FastAPI에서 백그라운드 태스크 처리 시 예외 처리 문제

문제 상황

이메일 발송 같은 부가 작업을 BackgroundTasks로 처리하고 있었는데, 간헐적으로 메일이 누락되는 이슈가 발생했다. 로그를 확인해도 에러가 기록되지 않아서 원인 파악이 어려웠다.

@app.post("/users")
async def create_user(user: UserCreate, background_tasks: BackgroundTasks):
    new_user = await user_service.create(user)
    background_tasks.add_task(send_welcome_email, new_user.email)
    return new_user

원인

FastAPI의 백그라운드 태스크는 응답이 클라이언트에게 전달된 후 실행된다. 이 과정에서 발생하는 예외는 요청 컨텍스트 밖이라 일반적인 exception handler로 잡히지 않는다.

해결

백그라운드 태스크 함수 내부에 try-except를 추가하고 로깅을 명시적으로 처리했다.

import logging

logger = logging.getLogger(__name__)

async def send_welcome_email(email: str):
    try:
        await email_service.send(
            to=email,
            template="welcome",
            context={"email": email}
        )
        logger.info(f"Welcome email sent to {email}")
    except Exception as e:
        logger.error(f"Failed to send welcome email to {email}: {str(e)}", exc_info=True)

추가로 Sentry 같은 모니터링 도구를 사용한다면 백그라운드 태스크에도 명시적으로 context를 전달해야 한다.

from sentry_sdk import capture_exception

async def send_welcome_email(email: str):
    try:
        await email_service.send(to=email, template="welcome")
    except Exception as e:
        capture_exception(e)
        logger.error(f"Email send failed: {email}")

중요한 작업이라면 Celery나 Redis Queue 같은 별도의 태스크 큐를 고려하는 것도 방법이다. 재시도 로직이나 실패 추적이 필요한 경우 BackgroundTasks는 한계가 있다.