이 영역을 누르면 첫 페이지로 이동
시간의화살 블로그의 첫 페이지로 이동

시간의화살

페이지 맨 위로 올라가기

시간의화살

행복하세요

[FastAPI] SQLAlchemy

  • 2023.11.06 00:38
  • 낙서장

 

 

 

SQLAlchemy는 파이썬의 ORM 기술으로 자바 진영의 JPA와 유사한 부분이 많다.

 

 

JPA의 영속성 컨텍스트와 1차 캐시 : SQLAlchemy의 Session객체

N+1 문제를 해결하기 위한 JPA의 fetch 속성 : SQLAlchemy의 joinedload(), subqueryload()

JPA의 @Entity : SQLAlchemy의 declarative_base() 

@ManyToOne, @OneToMany : relationship()

 

이렇듯 같은 ORM 기술이다 보니 비슷한 개념을 공유하고 있어 JPA에 익숙하다면 SQLAlchemy도 어렵지 않게 적응할 수 있다.

 

 

Core

SQLAlchemy의 Core는 데이터베이스별 SQL과 스키마 정의를 위한 시스템으로, SQL 대신 Python코드로 데이터베이스를 조작하는 도구를 포함한다.

 

Engine : Dialect와 Connection Pool을 포함한 데이터베이스와의 연결을 관리한다.

Dialect : MySQL, PostgreSQL 등 여러 데이터베이스별로 특화된 Dialect가 있으며 각 데이터베이스와 통신하는 방법을 정의한다.

Connection Pool : 데이터베이스 연결을 재사용 할 수 있게 해 연결 관련 오버헤드를 줄인다.

Metadata : 데이터베이스 스키마를 정의하고 DDL 명령어를 생성한다.

 

 

ORM

ORM은 파이썬 객체와 데이터베이스 테이블을 매핑하는 시스템으로 SQL 작업을 추상화한다.

 

Session : 변화 추적, 트랜잭션 관리, 객체 로딩 등 데이터베이스와의 전반적인 통신을 제어한다.

Declarative Base : 테이블과 클래스 매핑을 선언적으로 정의한다.

Query : 데이터베이스 쿼리를 구성할 때 사용되는 객체로 Session을 통해 생성되며 여러 필터링 메서드를 제공해 복잡한 쿼리를 간단하게 작성할 수 있다. (JPA의 QueryDSL과 유사하다)

 

 

 

SQLALCHEMY_DATABASE_URL = 'sqlite:///./blog_api.db'

engine = create_engine(SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False})

SessionLocal = sessionmaker(bind=engine, autocommit=False, autoflush=False)

Base = declarative_base()


def get_db():
    db = SessionLocal()
    try:
        yield db
    finally:
        db.close()

 

 

 

SQLite 데이터베이스를 FastAPI에서 사용하는 예시이다.

 

create_engine 함수로 데이터베이스와의 연결을 관리하는 엔진 객체를 생성한다.

sessionmaker 함수는 데이터베이스 세션을 생성하는 팩토리로 여기서는 자동 커밋과 플러시를 사용하지 않아 트랜잭션을 더 세밀하게 조정한다.

declarative_base는 모든 데이터베이스 테이블의 기본 클래스를 생성해 Base클래스는 ORM을 사용해 테이블과 파이썬 클래스를 매핑하는 구조를 제공한다

 

get_db 함수는 FastAPI의 의존성 주입 시스템에 사용돼 요청에 대해 새로운 데이터베이스 세션을 생성하고 처리가 완료된 후 세션을 닫는다.

 

 

class DbPost(Base):
    __tablename__ = "post"
    id = Column(Integer, primary_key=True, index=True)
    image_url = Column(String)
    title = Column(String)
    content = Column(String)
    creator = Column(String)
    timestamp = Column(DateTime)

 

 

Base를 상속받은 클래스는 ORM 모델 기반 클래스로 작동한다.

__tablename__ 부분으로 클래스가 매핑될 데이터베이스 테이블의 이름을 알려주고, Column 객체로 데이터베이스 테이블의 각 열을 나타낸다.

 

 

class PostBase(BaseModel):
    image_url: str
    title: str
    creator: str


class PostDisplay(BaseModel):
    id: int
    image_url: str
    title: str
    content: str
    creator: str
    timestamp: datetime

    class Config():
        orm_mode = True

 

 

Pydantic 모델으로 데이터 검증과 설정 관리를 수행한다.

 

PostBase는 클라이언트로부터 데이터를 받아 새로운 게시물을 데이터베이스에 생성할 때 본문을 검증할 때 사용되고,

PostDisplay는 클라이언트에게 데이터를 반환할 때 응답 본문의 스키마를 정의한다.

 

orm_mode 설정으로 SQLAlchemy 객체의 데이터를 직접 읽어 Pydnatic 모델에 할당한다.

 

DbPost 객체는 JPA에서 @Entity로 정의하는 객체라고 할 수 있고, PostBase와 PostDisplay는 DTO라고 할 수 있다.

SRP원칙, 보안, 데이터 유효성 검증, 성능 최적화를 위해 이렇게 엔티티와 DTO를 나눠서 분리한다.

 

 

 

@router.post('')
def create(request: PostBase, db: Session = Depends(get_db)):
    return db_post.create(db, request)

def create(db: Session, request: PostBase):
    new_post = DbPost(
        image_url=request.image_url,
        title=request.title,
        content=request.content,
        creator=request.creator,
        timestamp=datetime.datetime.now()
    )
    db.add(new_post)
    db.commit()
    db.refresh(new_post)

    return new_post

 

 

엔드포인트에서 데이터베이스를 사용하는 부분이다.

 

FastAPI에서는 Depends로 의존성 주입을 구현한다.

재사용 가능한 데이터베이스 연결 로직을 함수로 분리해 Depends를 통해 의존성으로 주입받아 사용한다.

 

스프링은 ApplicationContext가 스프링 빈들을 직접 싱글톤으로 관리하고, @Autowired 같은 애너테이션으로 컨테이너에서 싱글톤으로 관리되는 빈들을 주입한다.

 

FastAPI에서의 의존성 주입은 좀 다르다.

 

Depends를 사용해 의존성 주입을 구현하면 코드를 읽는 사람에게 해당 매개변수가 외부 의존성임을 명확히 알려줘 가독성을 향상시키고, 의존성 내에서 또 다른 의존성을 선언하는 것 처럼 복잡한 의존성 체인을 구성할 수 있다. 

 

이 외에도 특정 기능을 모듈로 분리해 모듈성과 유지보수성을 향상시키는 등 여러 이점을 제공하니... Depends를 쓰던 안 쓰던 런타임에 호출되는 동작의 차이는 없지만 되도록이면 Depends를 명시적으로 사용하자. 

 

 

 

반응형
저작자표시 (새창열림)

'낙서장' 카테고리의 다른 글

FastAPI에서의 동시성 처리  (1) 2023.11.29
[FastAPI] 요청과 응답  (0) 2023.11.02
[CSS] Selector  (0) 2022.12.08
[HTML] Media  (0) 2022.12.02
[HTML] Graphics  (0) 2022.12.01

댓글

이 글 공유하기

  • 구독하기

    구독하기

  • 카카오톡

    카카오톡

  • 라인

    라인

  • 트위터

    트위터

  • Facebook

    Facebook

  • 카카오스토리

    카카오스토리

  • 밴드

    밴드

  • 네이버 블로그

    네이버 블로그

  • Pocket

    Pocket

  • Evernote

    Evernote

다른 글

  • FastAPI에서의 동시성 처리

    FastAPI에서의 동시성 처리

    2023.11.29
  • [FastAPI] 요청과 응답

    [FastAPI] 요청과 응답

    2023.11.02
  • [CSS] Selector

    [CSS] Selector

    2022.12.08
  • [HTML] Media

    [HTML] Media

    2022.12.02
다른 글 더 둘러보기

정보

시간의화살 블로그의 첫 페이지로 이동

시간의화살

  • 시간의화살의 첫 페이지로 이동

검색

방문자

  • 전체 방문자
  • 오늘
  • 어제

카테고리

  • 분류 전체보기 (606) N
    • Algorithm (205)
      • Data Structure (5)
      • Theory && Tip (33)
      • Baekjoon (166)
      • ALGOSPOT (1)
    • Spring (123)
      • Spring (28)
      • Spring Web MVC (20)
      • Spring Database (14)
      • Spring Boot (6)
      • Spring 3.1 (11)
      • Spring Batch (6)
      • Spring Security (16)
      • JPA (12)
      • Spring Data JPA (5)
      • QueryDSL (4)
      • eGovFramework (1)
    • Programming Language (74)
      • Java (19)
      • JavaScript (15)
      • C (25)
      • C++ (12)
      • Python (1)
      • PHP (2)
    • Computer Science (69) N
      • Operating System (18)
      • Computer Network (17) N
      • System Programming (22)
      • Universial Programming Lang.. (8)
      • Computer Architecture (4)
    • Database (21)
      • Database (7)
      • MySQL (3)
      • Oracle (3)
      • Redis (5)
      • Elasticsearch (3)
    • DevOps (20)
      • Docker && Kubernetes (8)
      • Jenkins (4)
      • Github Actions (0)
      • Amazon Web Service (8)
    • Machine Learning (28)
      • AI Introduction (28)
    • Mobile (28)
      • Android (21)
      • Flutter (7)
    • Solutions (13)
    • Life Logs (0)
    • 낙서장 (25)

최근 글

나의 외부 링크

메뉴

  • 홈

정보

13months의 시간의화살

시간의화살

13months

블로그 구독하기

  • 구독하기
  • RSS 피드

티스토리

  • 티스토리 홈
  • 이 블로그 관리하기
  • 글쓰기
Powered by Tistory / Kakao. Copyright © 13months.

티스토리툴바