// lab
FastAPI lifespan — 앱 수명과 리소스 정리를 한 자리에
- 백엔드를 FastAPI로 다루면서 정리한 앱 시작·종료 시점 처리 방식
- DB 커넥션 풀이나 모델 로딩처럼 한 번 만들고 끝까지 재사용해야 하는 자원을 어디에 두는가의 문제
- 정리 목적: lifespan이 컨텍스트 매니저와 같은 구조라는 걸 짚어두기
lifespan — yield 기준으로 앞뒤가 나뉜다
@asynccontextmanager
async def lifespan(app: FastAPI):
pool = await create_pool() # 앱 시작 시 1회
app.state.pool = pool
yield # ── 이 지점에서 앱이 요청을 받는다
await pool.close() # 앱 종료 직전 1회
app = FastAPI(lifespan=lifespan)yield이전 — 앱이 뜨기 전에 실행. 자원 확보yield이후 — 종료 직전에 실행. 자원 정리- 요청마다가 아니라 프로세스 수명당 한 번 실행됨
컨텍스트 매니저와 같은 모양
lifespan이 특별한 문법처럼 보이지만 구조는 컨텍스트 매니저 그대로.
# 클래스형 — 진입/이탈을 메서드로
class Resource:
def __enter__(self): ... # 블록 진입 시 초기화
def __exit__(self, *exc): ... # 블록 이탈 시 정리 (예외가 나도 실행)
with Resource() as r:
use(r)
# 데코레이터형 — yield 하나로 진입/이탈을 표현
@contextmanager
def resource():
r = acquire()
yield r
release(r)- 공통점: 정리 코드가 실행되는 것을 언어가 보장 — 중간에 예외가 나도 이탈 경로를 탄다
- 수동으로
try/finally를 흩어 놓는 것보다 누락 위험이 낮음
비동기 버전
- 비동기 환경에서는
__aenter__/__aexit__를 구현하거나@asynccontextmanager사용 - FastAPI lifespan이 비동기 컨텍스트 매니저를 그대로 받는 이유가 여기 있음
정리
- 자원의 수명 범위를 코드 구조로 표현 — 언제 만들고 언제 정리하는지가 한 함수 안에 보임
- 앱 수명이면 lifespan, 블록 수명이면
with. 같은 발상의 다른 축척
// 연결됨 (2)