Python 비동기 요청 처리 시 메모리 누수 해결

문제 상황

재택근무 체제로 전환하면서 사내 대시보드 API를 FastAPI로 마이그레이션했다. 외부 API 호출이 많은 서비스인데, 운영 중 메모리 사용량이 계속 증가하는 현상이 발견됐다.

원인 파악

각 엔드포인트에서 aiohttp.ClientSession을 매번 생성하고 있었지만, 명시적으로 닫지 않고 있었다.

# 문제가 있던 코드
@app.get("/external-data")
async def get_data():
    session = aiohttp.ClientSession()
    async with session.get("https://api.example.com") as resp:
        data = await resp.json()
    return data  # session이 닫히지 않음

해결 방법

FastAPI의 의존성 주입을 활용해 세션 라이프사이클을 관리하도록 수정했다.

from contextlib import asynccontextmanager

# 전역 세션 관리
class HTTPClient:
    session: aiohttp.ClientSession = None
    
    async def start(self):
        self.session = aiohttp.ClientSession()
    
    async def stop(self):
        await self.session.close()

http_client = HTTPClient()

@app.on_event("startup")
async def startup():
    await http_client.start()

@app.on_event("shutdown")
async def shutdown():
    await http_client.stop()

@app.get("/external-data")
async def get_data():
    async with http_client.session.get("https://api.example.com") as resp:
        return await resp.json()

결과

메모리 사용량이 안정화되었고, 세션 재사용으로 인해 커넥션 풀링 효과까지 얻었다. 응답 속도도 평균 30% 개선됐다.

교훈

비동기 리소스는 반드시 명시적으로 정리해야 한다. FastAPI의 라이프사이클 이벤트를 적극 활용하면 이런 문제를 예방할 수 있다.

Python 비동기 요청 처리 시 메모리 누수 해결