커넥션 풀의 연결(Connection Checkout)은 쿼리가 실행되는 순간이 아니라, with Session() 또는 async with AsyncSession() 블록에 진입해서 데이터베이스에 실제 요청을 보내거나 응답을 받는 순간(session.execute(), session.select(), …)(ref1)부터 with 블록을 나갈 때까지 계속 점유된다. with Session 컨텍스트가 열리자마자 바로 커넥션 풀을 점유하는 것은 아니지만, 최악의 경우 with 블록의 범위가 곧 커넥션의 점유 범위가 될 수 있다.

def problematic_sync_function():
    with Session() as session:
        # 1. 커넥션을 빌리고 DB 작업 수행
        stmt = select(User).where(User.id == 1)
        user = session.query(User).filter_by(id=1).one()

        # 2. 이 5초 동안 DB 커넥션과 작업자(Worker)를 모두 점유함!
        response = requests.get("<https://slow-api.com/process>")  # 5초 소요
        user.external_data = response.json()

        session.commit()
    # 커넥션 반납

따라서 영속성 관련 함수(레포지토리 메서드)를 데코레이팅 패턴으로 감싸면 깜빡하고 세션을 닫지 않을 위험은 많이 줄어들지만, 한편으론 커넥션 풀이 정말 필요한 때만 사용되지는 않을 수 있다. 위와 같은 코드는 첫 번째 DB 호출 이후 함수가 종료되기 전까지 session.close()가 불가능하다. 이렇게 하나의 영속성 함수 내에서 DB와 상관없는 I/O 바운드 작업이 존재하여 최적화가 필요하다면, 아래와 같이 DB 입출력 부분에만 컨텍스트 매니저를 사용하여 불필요한 부분에 DB 커넥션을 반납하라.

def recommended_sync_function():
    user_id = 1

    with Session() as session:
        user = session.query(User).filter_by(id=user_id).one()
    # 커넥션 반납

    # 이 동안에는 DB 커넥션을 점유하지 않음
    response = requests.get("<https://slow-api.com/process>") # 5초 소요
    external_data = response.json()

    with Session() as session:
        user = session.query(User).filter_by(id=user_id).one()
        user.external_data = external_data
        session.commit()
    # 커넥션 반납

parse me : 언젠가 이 글에 쓰이면 좋을 것 같은 재료을 보관해 두는 영역입니다.

  1. None

from : 과거의 어떤 원자적 생각이 이 생각을 만들었는지 연결하고 설명합니다.

  1. DI는 “소스코드 입장”에서 논리적으로 모든 의존성이 컨테이너로 향하도록 하고, 컨테이너에서 의존성을 중앙화된 방식으로 관리할 수 있다는 장점 때문에 사용한다.
  2. bc1.1_1. title: 데이터베이스 응답은 빠른 속도가 중요하므로, 연결을 끊어버리면 매번 TCP 핸드셰이크와 DB 핸드셰이크를 다시 해야 한다는 문제가 있다. 그래서 전송 계층으로 HTTP이 상태 유지가 기본인 TCP 프로토콜에 의존하고, 커넥션 풀을 이용해 한 번 맺어둔 TCP 연결을 재사용한다.
  3. 클린 아키텍처를 유지하며 FastAPI 코드 작성을 LLM에게 위임하기 위한 프롬프트

supplementary : 어떤 새로운 생각이 이 문서에 작성된 생각을 뒷받침하는지 연결합니다.

  1. None

opposite : 어떤 새로운 생각이 이 문서에 작성된 생각과 대조되는지 연결합니다.

  1. None