SQLAlchemy |
<colbgcolor=#fff,#1f2023><colcolor=#3EB049> 창시자 | Michael Bayer[1] |
출시일 | 2006년 02월 14일[2] |
최신 버전 | v2.0.41# |
유형 | 데이터베이스 ORM[3] |
사용 언어 | Python |
공식 웹사이트 | 공식 사이트 공식 문서 깃허브 |
1. 개요
#!syntax sh
# SQLAlchemy 설치 (pip)
pip install SQLAlchemy
# 비동기 extra를 함께 설치하는 경우
pip install "SQLAlchemy[asyncio]"
SQLAlchemy는 Python의 데이터베이스 라이브러리로, SQL과 데이터베이스 작업을 파이썬 객체를 통해 조작할 수 있게 한다. 단순한 데이터베이스 연결부터 복잡한 객체-관계 매핑까지 다양한 수준의 추상화를 제공한다.
Django 프레임워크에 내장된 Django ORM과 비교했을 때, SQLAlchemy는 프레임워크에 종속되지 않는 독립적인 라이브러리로서, 더 낮은 수준의 데이터베이스 제어와 높은 유연성을 제공한다. Django ORM이 웹 프레임워크의 일부로 통합되어 있어 빠른 개발에 유리하다면, SQLAlchemy는 어떤 파이썬 프로젝트에서도 사용할 수 있으며, 복잡하거나 특수한 데이터베이스 요구사항에 더 잘 대응할 수 있다.
2. 특성
- 유연성: ORM 레이어와 Core 레이어를 제공하여, 필요에 따라 선택하거나 조합해서 사용할 수 있다.
- 성능: 저수준의 데이터베이스 통신을 처리하며, 필요에 따라 쿼리를 직접 작성할 수도 있어 성능 최적화에 유리하다.
- 다양한 데이터베이스 지원: PostgreSQL, MySQL, SQLite 등 다양한 데이터베이스를 지원한다.[4][5]
3. 구성 요소
3.1. Core
SQLAlchemy Core는 데이터베이스 스키마를 표현하고 쿼리 생성 및 실행하는 저수준의 기능을 제공한다. 데이터베이스 연결 풀, 트랜잭션 관리, 스키마 정의[6], SQL 표현식 구성 등의 기능을 포함한다. ORM을 사용하지 않고 순수하게 쿼리를 Python 코드로 작성하고 실행해야 할 때 유용하다.3.2. ORM
SQLAlchemy ORM은 파이썬 클래스를 데이터베이스 테이블과 매핑하여 객체 지향적인 방식으로 데이터베이스를 조작할 수 있게 해준다. 데이터베이스의 레코드를 Python 객체로, 필드를 객체의 속성으로 매핑한다. 이를 통해 쿼리를 직접 작성하는 대신 Python 객체를 다루듯이 데이터를 조회, 생성, 수정, 삭제할 수 있다. 또한 복잡한 관계[7] 매핑 및 로딩 전략 설정[8] 등 강력한 기능을 제공한다.4. 사용 방법
4.1. 1.x 스타일
1.x 버전에서는 주로 declarative_base를 사용하여 모델 클래스의 베이스를 만들고, 클래스 속성으로 Column 객체를 직접 할당하는 방식으로 모델을 정의했다.#!syntax python
from sqlalchemy import Column, Float, Integer, String
from sqlalchemy.orm import declarative_base
Base = declarative_base()
class User(Base):
__tablename__ = "users"
id = Column(Integer, primary_key=True)
name = Column(String, nullable=False)
value = Column(Float, default=None, nullable=True)
데이터를 조회할 때는 주로 session.query를 사용했다.
#!syntax python
# User 모델이 정의되어 있고, users 테이블이 생성되어 있다고 가정
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
engine = create_engine("sqlite:///:memory:")
Session = sessionmaker(bind=engine)
with Session() as session:
for user in session.query(User):
print(user)
4.2. 2.0 스타일
2.0에서는 Python의 타입 힌트, Mapped, mapped_column을 활용하는 새로운 선언적 매핑 스타일을 도입했다.#!syntax python
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, sessionmaker
class Base(DeclarativeBase):
pass
class User(Base):
__tablename__ = "users"
id: Mapped[int] = mapped_column(primary_key=True)
name: Mapped[str]
value: Mapped[float | None] = mapped_column(default=None)
데이터를 조회할 때는 select와 session.scalars를 사용하여 ORM 객체를 조회한다.[9]
#!syntax python
# User 모델이 정의되어 있고, users 테이블이 생성되어 있다고 가정
from sqlalchemy import create_engine, select
from sqlalchemy.orm import sessionmaker
engine = create_engine("sqlite:///:memory:")
Session = sessionmaker(bind=engine)
with Session() as session:
for user in session.scalars(select(User)):
print(user)
2.0문법을 사용할 경우 pyright와 같은 정적 분석기가 ORM 객체의 각 속성에 대한 타입을 정확하게 추론하므로, IDE를 사용할 때 생산성이 크게 향상된다.[10][11]
[1] 현재는 커뮤니티 주도로 개발이 이뤄지고 있다.[2] pypi 릴리즈 기준[3] Object-Relational Mapper[4] Dialect라는 객체로 각 데이터베이스에 대한 프로토콜을 구현했다.[5] 현존하는 거의 모든 데이터베이스에 대해 지원한다.[6] 테이블, 컬럼 등[7] 일대일, 일대다, 다대다[8] selectinload, joinedload[9] execute가 반환하는 Result객체의 scalars 메소드를 호출한 것과 동일하다.[10] User.id를 예시로, 모델 클래스의 속성은 InstrumentedAttribute\[int\]로 추론하고, 조회한 모델 객체의 속성은 int로 추론한다.[11] 1.4버전 사용자를 위한 스텁 라이브러리가 있지만 불완전하며, 2.0출시 이후 개발이 중단되었다.