[SQLALchemy] 세션(Session), 비동기 세션(Async Session) 그리고 scoped_session의 정리
1. SQLAlchemy의 세션(Session) 개념
- SQLAlchemy에서 세션은 데이터베이스와의 트랜잭션을 관리하는 객체이다.
- 세션은 데이터베이스 연결(Connection)을 유지하고, 쿼리를 실행하며, 변경된 데이터를 커밋(commit)하거나 롤백(rollback) 하는 역할을 한다.
2) 주요 역할
- 데이터 변경 추적 : add(), delete() 등을 통해 변경된 데이터를 추적
- 트랜잭션 관리 : commit() 또는 rollback() 을 사용해 데이터 변경 사항을 저장 또는 취소
- DB 연결 풀 관리 : 세션이 닫히면 내부적으로 커넥션 풀을 관리하여 성능 최적화
2. FastAPI에서 SQLAlchemy 세션 설정 방법
- FastAPI에서 SQLAlchemy를 사용할 때 세션을 안전하게 관리하는 방식은 다음과 같다.
1) 데이터베이스 설정 및 세션 팩토리 생성
- FastAPI에서 SQLAlchemy의 세션을 생성하려면 SessionLocal 을 사용하여 세션 팩토리를 설정한다.
1. database.py (데이터베이스 설정)
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker, declarative_base
# 데이터베이스 URL 설정
DATABASE_URL = "postgresql+psycopg2://user:password@localhost:5432/mydatabase"
# SQLAlchemy 엔진 생성 (연결 풀 포함)
engine = create_engine(DATABASE_URL, pool_size=10, max_overflow=20)
# 세션 팩토리 생성
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
# Base 클래스 생성 (모든 모델이 상속받음)
Base = declarative_base()
2) 의존성 주입을 통한 세션 관리
- FastAPI에서는 의존성 주입(Dependency Injection) 을 통해 요청(Request)별 세션을 관리한다.
1. dependencies.py (세션 종속성 설정)
- yield db 를 사용하면 FastAPI가 요청이 끝난 후 자동으로 세션을 닫음
- db.close() 는 세션을 닫고 커넥션 풀에 반환하여 성능 최적화
from fastapi import Depends
from sqlalchemy.orm import Session
from .database import SessionLocal
# 요청마다 새로운 세션을 생성하고, 요청 종료 시 닫음
def get_db():
db = SessionLocal()
try:
yield db # 호출한 곳에서 사용 가능
finally:
db.close() # 요청 종료 후 세션 닫기
3) 엔드포인트에서 세션 사용
- 이제 FastAPI 엔드포인트에서 get_db 의존성을 사용하여 SQLAlchemy 세션을 주입할 수 있다.
1. main.py (FastAPI 라우터에서 DB 사용)
- db : Session = Depends(get_db) : get_db() 함수를 통해 요청마다 새로운 세션을 주입받음
- 요청이 끝나면 세션이 자동으로 닫힘 (finally: db.close())
from fastapi import FastAPI, Depends
from sqlalchemy.orm import Session
from .dependencies import get_db
from .models import User
app = FastAPI()
@app.get("/users/{user_id}")
def read_user(user_id: int, db: Session = Depends(get_db)):
user = db.query(User).filter(User.id == user_id).first()
if user is None:
return {"message": "User not found"}
return user
3. FastAPI에서 세션 사용 시 주의할 점
1) autocommit=False, autoflush=False 의 의미
- 위에서 SessionLocal 을 설정할 때 autocommit=False, autoflush=False 옵션을 사용했다.
- autocommit=False → 명시적으로 commit() 해야 데이터가 저장된다. (트랜잭션 관리 용이)
- autoflush=False → flush() 가 자동으로 실행되지 않는다. (불필요한 쿼리 방지)
- 즉, commit() 을 직접 호출하여 트랜잭션을 명확하게 관리하는 것이 안전하다.
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
2) 비동기 지원 (async 세션 사용)
- FastAPI는 비동기(Async) 프레임워크이므로, async 방식의 SQLAlchemy 세션을 사용할 수도 있다.
1. database.py (비동기 세션 설정)
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession
from sqlalchemy.orm import sessionmaker, declarative_base
DATABASE_URL = "postgresql+asyncpg://user:password@localhost:5432/mydatabase"
async_engine = create_async_engine(DATABASE_URL, pool_size=10, max_overflow=20)
AsyncSessionLocal = sessionmaker(bind=async_engine, class_=AsyncSession, expire_on_commit=False)
Base = declarative_base()
2. dependencies.py (비동기 세션 의존성 주입)
- dependencies.py (비동기 세션 의존성 주입)async with 을 사용하면 세션이 자동으로 정리됨
- 비동기 함수에서 await db.execute() 형식으로 쿼리를 실행해야 함
from fastapi import Depends
from sqlalchemy.ext.asyncio import AsyncSession
from .database import AsyncSessionLocal
async def get_db():
async with AsyncSessionLocal() as db:
yield db
3. main.py (비동기 라우터)
- await db.execute(select(User).filter(User.id == user_id))
- 비동기 AsyncSession 은 await 키워드와 함께 사용해야 함
from fastapi import FastAPI, Depends
from sqlalchemy.ext.asyncio import AsyncSession
from .dependencies import get_db
from .models import User
from sqlalchemy.future import select
app = FastAPI()
@app.get("/users/{user_id}")
async def read_user(user_id: int, db: AsyncSession = Depends(get_db)):
result = await db.execute(select(User).filter(User.id == user_id))
user = result.scalar_one_or_none()
if user is None:
return {"message": "User not found"}
return user
4. SQLAlchemy Session과 AsyncSession 개요
- SQLAlchemy에서 데이터베이스와의 상호작용을 위해 Session과 AsyncSession을 사용한다.
- Session: 동기 방식으로 데이터베이스 작업을 처리한다.
- AsyncSession: 비동기 방식으로 데이터베이스 작업을 처리하여 FastAPI와 같은 비동기 웹 프레임워크에서 효율적으로 사용할 수 있다.
5. 데이터베이스 설정 및 엔진 생성
(1) 동기 방식 엔진 및 세션 설정
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
DATABASE_URL = "postgresql://user:password@localhost/dbname"
engine = create_engine(DATABASE_URL, echo=True)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
(2) 비동기 방식 엔진 및 세션 설정
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession
from sqlalchemy.orm import sessionmaker
ASYNC_DATABASE_URL = "postgresql+asyncpg://user:password@localhost/dbname"
async_engine = create_async_engine(ASYNC_DATABASE_URL, echo=True)
AsyncSessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=async_engine, class_=AsyncSession)
6. Session과 sessionmaker의 차이
1) Session 직접 사용
- 특징 : Session(bind=engine)을 통해 직접 세션을 생성하고 사용
- Session을 직접 사용하면 명시적으로 엔진을 바인딩해야 한다.
- 개별적인 세션을 직접 관리해야 하며, 여러 개의 세션을 생성할 경우 별도의 코드 처리가 필요하다.
- 주요 함수 및 옵션 :
- add(instance): 객체를 추가
- delete(instance): 객체를 삭제
- commit(): 트랜잭션 커밋
- rollback(): 트랜잭션 롤백
- close(): 세션 종료
- flush(): 변경 사항을 DB에 반영 (트랜잭션 커밋 없이 반영)
- 단점 : 세션이 여러 요청에서 공유될 수 있어 Thread-Safety 문제가 발생할 가능성이 있음
- 이 방식의 문제점 :
- session이 전역 변수로 사용되므로, 여러 요청이 동시에 발생하면 Thread-Safety 문제가 발생할 가능성이 있음
- 매 요청마다 세션을 새로 생성하지 않으므로 동시 요청 시 데이터 정합성 문제가 생길 수 있음
- FastAPI의 종속성 주입(Depends)을 활용할 수 없음
from fastapi import FastAPI, Depends
from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.orm import Session
from sqlalchemy.ext.declarative import declarative_base
# FastAPI 앱 생성
app = FastAPI()
# 데이터베이스 설정
DATABASE_URL = "sqlite:///./test.db"
engine = create_engine(DATABASE_URL, connect_args={"check_same_thread": False})
# ORM 모델 정의
Base = declarative_base()
class User(Base):
__tablename__ = "users"
id = Column(Integer, primary_key=True, index=True)
name = Column(String, index=True)
# 데이터베이스 테이블 생성
Base.metadata.create_all(bind=engine)
# 🚨 직접 세션을 생성하여 사용하는 방식
session = Session(bind=engine)
@app.get("/users_direct")
def get_users():
try:
users = session.query(User).all()
return users
finally:
session.close() # 수동으로 세션을 닫아야 함
2) sessionmaker를 사용하는 코드
- 특징: sessionmaker를 사용하여 요청마다 새로운 세션을 생성하고 Depends를 활용
- sessionmaker를 사용하면 세션을 더 쉽게 생성하고 관리할 수 있다.
- autocommit, autoflush 등의 기본 옵션을 설정할 수 있다.
- 주요 함수 및 옵션 :
- autocommit: 자동 커밋 활성화 여부 (기본값: False)
- autoflush: 자동 플러시 활성화 여부 (기본값: True)
- expire_on_commit: 커밋 후 객체 만료 여부 (기본값: True)
- 장점: 요청 단위로 세션을 관리할 수 있어 Thread-Safety가 보장됨
from fastapi import FastAPI, Depends
from sqlalchemy.orm import sessionmaker, Session
# FastAPI 앱 생성
app = FastAPI()
# 🚀 sessionmaker 사용하여 세션 팩토리 생성
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
# 요청마다 새로운 세션을 제공하는 의존성 함수
def get_db():
db = SessionLocal()
try:
yield db # 요청 처리 중에 사용할 세션을 반환
finally:
db.close() # 요청 완료 후 세션 닫기
@app.get("/users_sessionmaker")
def get_users(db: Session = Depends(get_db)):
return db.query(User).all()
3) 두 방식의 차이점
비교 항목 | Session 직접 사용 | sessionmaker 사용 |
세션 생성 방식 | session = Session(bind=engine) | SessionLocal = sessionmaker(bind=engine) 후 SessionLocal() 사용 |
세션 관리 | 전역 세션을 사용하므로 요청 간 공유될 가능성 있음 | 요청마다 독립적인 세션을 생성 |
Thread-Safety | ❌ 여러 요청이 동시에 들어올 경우 데이터 정합성 문제 발생 가능 | ✅ 요청마다 새로운 세션을 생성하여 Thread-Safety 보장 |
종속성 주입 (Depends) | ❌ 직접 session을 호출해야 함 | ✅ get_db()를 이용해 FastAPI의 Depends 활용 가능 |
세션 닫기 (.close()) | 직접 .close()를 호출해야 함 | get_db()에서 자동으로 관리 |
7. 동기식과 비동기식의 get_db 구현 방법
1) 동기(Sync) 방식의 get_db
- try...yield...finally 패턴을 사용해 세션을 안전하게 관리
- 요청이 성공적으로 끝나면 db.commit()을 호출하여 변경사항을 저장
- 예외 발생 시 db.rollback()을 수행하여 트랜잭션 안전성 유지
- finally:에서 db.close()를 호출하여 커넥션 누수 방지
from fastapi import Depends, HTTPException
from sqlalchemy.orm import sessionmaker, Session
from sqlalchemy.exc import SQLAlchemyError
from starlette.status import HTTP_500_INTERNAL_SERVER_ERROR
# SQLAlchemy 엔진 및 세션 설정
DATABASE_URL = "sqlite:///./test.db"
engine = create_engine(DATABASE_URL, connect_args={"check_same_thread": False})
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
# 🚀 동기 방식의 의존성 주입
def get_db():
db: Session = SessionLocal()
try:
yield db # 요청 처리 중에 사용할 세션 반환
db.commit() # 정상 요청이라면 커밋 수행
except SQLAlchemyError as e:
db.rollback() # 예외 발생 시 롤백 수행
raise HTTPException(status_code=HTTP_500_INTERNAL_SERVER_ERROR, detail=f"Database error: {str(e)}")
finally:
db.close() # 요청 완료 후 반드시 세션 닫기
2) 그렇다면 동기 방식에서 with를 사용할 방법이 전혀 없을까? - scoped_session
- 동기 방식에서도 with 문을 사용할 수는 있지만, 일반적인 SessionLocal() 방식에서는 불가능하다.
- 만약 동기 방식에서도 with 문을 사용하고 싶다면 scoped_session을 활용해야 하다.
from sqlalchemy.orm import scoped_session
# Scoped Session 설정
SessionLocal = scoped_session(sessionmaker(bind=engine, autocommit=False, autoflush=False))
def get_db():
with SessionLocal() as db: # scoped_session을 사용하면 가능
try:
yield db
db.commit()
except SQLAlchemyError as e:
db.rollback()
raise HTTPException(status_code=500, detail=f"Database error: {str(e)}")
1. scoped_session이란?
- scoped_session은 스레드 또는 특정 컨텍스트(예: 요청 단위)마다 고유한 세션을 제공하는 SQLAlchemy의 세션 관리 도구이다.
- sessionmaker()는 호출될 때마다 새로운 Session 인스턴스를 반환하지만, scoped_session()은 각 스레드(또는 컨텍스트)마다 하나의 Session을 유지하고 필요할 때 재사용한다.
- 즉, scoped_session을 사용하면 같은 스레드에서 여러 번 Session()을 호출해도 동일한 인스턴스를 반환한다.
- 주로 Flask, Celery, FastAPI 등의 웹 프레임워크에서 요청 단위의 세션 관리에 활용된다.
2. 기본적인 사용법 :
- SessionLocal = scoped_session(SessionFactory)
- 요청마다 새로운 세션을 제공하면서 같은 스레드에서는 동일한 세션을 유지
- SessionLocal()을 여러 번 호출해도 같은 요청 내에서는 같은 Session을 반환
- finally:에서 db.close()를 호출해 세션 누수를 방지
from sqlalchemy.orm import sessionmaker, scoped_session
from sqlalchemy import create_engine
# 데이터베이스 엔진 생성
DATABASE_URL = "sqlite:///./test.db"
engine = create_engine(DATABASE_URL, connect_args={"check_same_thread": False})
# sessionmaker 생성
SessionFactory = sessionmaker(bind=engine, autocommit=False, autoflush=False)
# scoped_session 설정 (스레드별 세션 관리)
SessionLocal = scoped_session(SessionFactory)
# 요청 단위로 사용되는 DB 세션 함수
def get_db():
db = SessionLocal()
try:
yield db
db.commit() # 정상적으로 처리되면 커밋
except Exception as e:
db.rollback() # 오류 발생 시 롤백
raise
finally:
db.close() # 요청이 끝나면 세션 닫기
3. scoped_session을 사용해야 하는 경우 :
- 멀티스레딩 환경 :
- scoped_session은 멀티스레딩 환경에서 각 스레드마다 독립적인 세션을 관리할 수 있도록 도와준다.
- 각 스레드는 서로 다른 세션을 가지므로 안전하게 병렬 처리 가능하다.
from threading import Thread
def db_task():
db = SessionLocal() # 각 스레드에서 동일한 SessionLocal()을 호출
print(f"Session ID: {id(db)}") # 각 스레드마다 다른 세션 ID 반환
db.close()
threads = [Thread(target=db_task) for _ in range(3)]
for t in threads:
t.start()
for t in threads:
t.join()
4. FastAPI와 같은 웹 프레임워크에서 요청 단위 세션 관리 :
- FastAPI의 Depends(get_db)를 활용하면 각 요청마다 고유한 세션을 제공할 수 있다.
- 요청이 끝나면 세션이 닫히므로 커넥션 누수를 방지할 수 있다.
from fastapi import FastAPI, Depends
from sqlalchemy.orm import Session
app = FastAPI()
@app.get("/")
def read_root(db: Session = Depends(get_db)):
result = db.execute("SELECT 'Hello, world!'").fetchone()
return {"message": result[0]}
5. scoped_session의 장점과 단점 :
- 장점 :
- 멀티스레딩에서 안전하게 세션 관리 (각 스레드마다 독립적인 세션 유지)
- FastAPI, Flask 등에서 요청 단위의 세션 유지 (요청이 끝나면 자동 정리 가능)
- 코드의 일관성 유지 (SessionLocal()을 여러 번 호출해도 같은 요청 내에서는 동일한 세션 반환`)
- 단점 :
- 비동기 환경에서는 적절하지 않음 (scoped_session은 동기 전용, 비동기 AsyncSession과 함께 사용할 수 없음)
- 세션 범위를 정확하게 설정해야 함 (clear()를 사용하지 않으면 스레드 간 세션이 꼬일 수도 있음)
- 비동기 환경에서는 scoped_session 대신 async with AsyncSessionLocal() as db:를 사용하는 것이 안전하다.
6. scoped_session에서 세션 수동 정리 (remove())
- scoped_session은 스레드나 요청이 종료될 때 remove()를 호출해야 안전하게 세션이 정리됨
from fastapi import Request
@app.middleware("http")
async def db_session_middleware(request: Request, call_next):
response = await call_next(request)
SessionLocal.remove() # 요청이 끝나면 세션 제거
return response
7. SessionLocal.remove()
- 사용 대상 : scoped_session 객체
- 기능: 현재 스레드 또는 요청과 연결된 세션을 제거하고, 이후 새로운 세션 요청이 오면 새로운 세션을 생성하도록 한다.
- 작동 방식: SessionLocal이 scoped_session을 사용할 경우, 내부적으로 Session.close()를 호출하고, 세션을 제거하여 메모리 누수를 방지한다.
- 예제 코드
from sqlalchemy.orm import sessionmaker, scoped_session
SessionLocal = scoped_session(sessionmaker(bind=engine))
# 요청이 끝난 후 세션 정리
SessionLocal.remove()
8. db.close()
- 사용 대상: 개별 세션 인스턴스 (Session 객체)
- 기능: 해당 db 세션을 직접 종료하여 연결을 정리함
- 작동 방식: 세션을 닫아 더 이상 사용할 수 없게 만듦 (해당 객체는 다시 사용할 수 없음)
- 예제 코드
from sqlalchemy.orm import sessionmaker
SessionLocal = sessionmaker(bind=engine)
db = SessionLocal()
# 세션 종료
db.close()
9. 차이점 요약
구분 | SessionLocal.remove() | db.close() |
대상 | scoped_session 객체 | 개별 Session 객체 |
효과 | 현재 스레드/요청과 연결된 세션을 제거하고 새 세션을 할당 가능 | 특정 세션 인스턴스를 닫음 (재사용 불가) |
내부 동작 | Session.close()를 호출하고 세션을 제거 | Session.close()만 호출 |
10. 언제 사용해야 할까?
- FastAPI 등 웹 애플리케이션에서 요청마다 새로운 세션을 생성하고 정리해야 할 경우:
- SessionLocal.remove()
- 특정한 세션을 직접 다룰 경우:
- db.close()
즉, 일반적으로 scoped_session을 사용할 때는 remove()를, 개별 세션을 사용할 때는 close()를 사용하면 된다.
11. scoped_session vs sessionmaker
비교 항목 | sessionmaker() | scoped_session() |
멀티스레드 지원 | ❌ (각 스레드가 직접 Session()을 생성해야 함) | ✅ (스레드별 세션 자동 관리) |
FastAPI 요청 단위 세션 관리 | 가능 (get_db()에서 직접 생성) | 가능 (get_db()에서 동일한 세션 재사용) |
동기/비동기 지원 | ✅ 동기 지원 (Session) | ❌ 동기 전용 (AsyncSession 지원 안 됨) |
세션 자동 정리 (remove()) | ❌ (close()를 직접 호출해야 함) | ✅ (remove()로 자동 정리 가능) |
12. 결론
- scoped_session은 멀티스레드 환경에서 안전하게 세션을 관리하는 도구
- FastAPI와 같은 웹 프레임워크에서 요청 단위의 세션 관리를 할 때 유용
- 같은 스레드에서 SessionLocal()을 여러 번 호출해도 동일한 세션을 반환하므로 관리가 편리
- 하지만, 비동기(AsyncSession) 환경에서는 scoped_session을 사용하면 안 됨! (async with 사용해야 함)
- FastAPI에서 동기 방식의 DB 관리가 필요하다면 scoped_session을 활용하는 것이 효과적입니다!
3) 비동기(Async) 방식의 get_db
- AsyncSessionLocal()을 async with 문으로 감싸 자동으로 커넥션을 닫음
- await db.commit() 및 await db.rollback()을 통해 비동기 방식으로 트랜잭션 관리
- 비동기 데이터베이스 드라이버 필요 (asyncpg, aiomysql 등)
from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine
from sqlalchemy.orm import sessionmaker
from fastapi import Depends, HTTPException
from sqlalchemy.exc import SQLAlchemyError
from starlette.status import HTTP_500_INTERNAL_SERVER_ERROR
# 비동기 데이터베이스 설정 (예: PostgreSQL + asyncpg)
ASYNC_DATABASE_URL = "postgresql+asyncpg://user:password@localhost/dbname"
async_engine = create_async_engine(ASYNC_DATABASE_URL, echo=True)
# 비동기 세션 팩토리
AsyncSessionLocal = sessionmaker(
bind=async_engine, class_=AsyncSession, expire_on_commit=False
)
# 🚀 비동기 방식의 의존성 주입
async def get_db():
async with AsyncSessionLocal() as db:
try:
yield db # 요청 처리 중에 사용할 세션 반환
await db.commit() # 정상 요청이라면 커밋 수행
except SQLAlchemyError as e:
await db.rollback() # 예외 발생 시 롤백 수행
raise HTTPException(status_code=HTTP_500_INTERNAL_SERVER_ERROR, detail=f"Database error: {str(e)}")
4) 비교: 동기 vs. 비동기
1. 동기 방식 (Session)
- Session은 컨텍스트 매니저(with 지원)가 아니라서 with 문을 사용할 수 없음
- 따라서 try...finally 블록을 사용해 .close()를 명시적으로 호출해야 함
- scoped_session을 사용하면 with 문을 사용할 수 있으나 일반적이지 않음
2. 비동기 방식 (AsyncSession)
- AsyncSession은 컨텍스트 매니저를 지원하므로 async with 문을 사용할 수 있음
- async with를 사용하면 세션이 자동으로 닫히므로 .close()가 필요 없음
- 결론적으로, 동기 방식에서는 try...finally로 명시적으로 db.close()를 호출하고, 비동기 방식에서는 async with로 자동으로 세션을 닫는 것이 가장 안전한 방법이다.
비교 항목 | 동기 (SessionLocal) | 비동기 (AsyncSessionLocal) |
세션 클래스 | Session | AsyncSession |
커넥션 유지 방식 | session.close() 필요 | async with 사용하여 자동 종료 |
커밋/롤백 | db.commit(), db.rollback() | await db.commit(), await db.rollback() |
예외 처리 | try...except SQLAlchemyError: | try...except SQLAlchemyError: |
트랜잭션 관리 | autocommit=False, autoflush=False로 관리 | expire_on_commit=False로 관리 |
비동기 지원 | ❌ | ✅ |
5) 동기 방식에서 with를 사용하지 않는 이유
- 동기 방식에서 with 문을 사용하지 않는 것은 SQLAlchemy의 Session 객체가 컨텍스트 매니저(__enter__() 및 __exit__())를 직접 구현하지 않았기 때문이다.
- 즉, Session은 with 문을 사용할 수 없는 구조이므로 finally:에서 .close()를 명시적으로 호출해야 한다.
6) 비동기 방식에서 close()가 필요 없는 이유
- 비동기 방식(AsyncSession)에서는 async with AsyncSessionLocal() as db: 구문을 사용했기 때문에 세션이 자동으로 닫힌다.
- async with 문은 비동기 컨텍스트 매니저로 동작하며, __aenter__()에서 세션을 생성하고, __aexit__()에서 세션을 닫아준다.
- 즉, async with를 사용하면 명시적으로 db.close()를 호출할 필요가 없다.
- 동기 방식에서는 finally: 블록에서 .close()를 명시적으로 호출해야 하지만, 비동기 방식은 이를 자동으로 처리합니다.
- reference :
https://docs.sqlalchemy.org/en/20/orm/session.html
Using the Session — SQLAlchemy 2.0 Documentation
docs.sqlalchemy.org
https://miintto.github.io/docs/python-sqlalchemy-session
SQLAlchemy의 세션 관리 - miintto.log
보통 Django를 벗어나서 독자적인 ORM이 없는 파이썬 프레임워크를 사용한다면 아마 거의 대부분은 SQLAlchemy를 채택하여 사용할 겁니다. 최근 FastAPI를 이용해 개발하면서 SQLAlchemy를 다루어 보았는
miintto.github.io
https://miintto.github.io/docs/python-sqlalchemy-asyncsession
Async 환경에서 SQLAlchemy 세션 관리 - miintto.log
이전에 SQLAlchemy의 세션 관리 포스트에서 SQLAlchemy 라이브러리 내부에서 세션의 작동 방식을 알아보았습니다. 하지만 해당 내용은 sync 환경에서만 유효하며, asyncio 기반으로 실행되는 경우에는 여
miintto.github.io
'SQLAlchemy' 카테고리의 다른 글
sqlalchemy의 declarative_base()를 fastapi에서 사용하는 이유 (0) | 2025.02.08 |
---|---|
[SQLALchemy] 트랜잭션(Transaction) 그리고 Database Lock (0) | 2025.02.04 |
[SQLALchemy] 비동기 함수, 비동기 Database 그리고 Pool의 정리 (0) | 2025.02.01 |
[SQLALchemy] 1:1, 1:N, N:M 관계에서 테이블 정의와 relationship의 활용 방법 (0) | 2025.02.01 |
[SQLALchemy] Alembic을 이용한 마이그레이션 관리 방법 (0) | 2025.01.31 |
댓글