피드로 돌아가기
Dev.toBackend
원문 읽기
Fake Async 탈피를 통한 응답 속도 3배 개선 및 메모리 28% 절감
From ThreadPoolExecutor to httpx AsyncClient: True Async Refactoring
AI 요약
Context
ThreadPoolExecutor를 활용해 동기 호출을 비동기로 래핑한 Fake Async 구조로 인한 확장성 저하 발생. Thread 기반의 동시성 제어로 인해 요청 수 증가 시 Thread Overhead 증가 및 메모리 사용량 급증이라는 병목 지점 확인.
Technical Solution
- ThreadPoolExecutor를 제거하고 Native Async I/O를 지원하는 httpx AsyncClient 도입
- Lazy Loading 패턴을 적용한 Client 초기화 구조로 불필요한 리소스 할당 방지
- httpx.Limits 설정을 통한 Max Connection 및 Keep-alive Connection의 정밀한 제어
- Async Context Manager 구현을 통한 HTTP Connection의 안정적인 생명주기 관리
- 루프 기반의 run_in_executor 방식에서 Event Loop 기반의 Non-blocking I/O 모델로 전환
Impact
- 평균 응답 속도: 450ms에서 150ms로 3배 단축
- 메모리 사용량: 250MB에서 180MB로 약 28% 감소
- 동시 처리 용량: 3개에서 10개 요청으로 3.3배 증가
- 100개 동시 요청 처리 시간: 15초에서 5초로 3배 단축
Key Takeaway
동기 라이브러리를 Thread Pool로 감싸는 방식은 임시방편일 뿐이며, 고성능 I/O 바운드 서비스에서는 설계 단계부터 Async-first 관점의 Native Async Client 채택이 필수적임.
실천 포인트
1. 코드 내 loop.run_in_executor 또는 ThreadPoolExecutor 사용 여부 전수 조사
2. I/O 집중 작업 시 requests 대신 httpx나 aiohttp 같은 Non-blocking 라이브러리 검토
3. Connection Pooling 설정(Max Connections, Keep-alive)이 인프라 환경에 최적화되었는지 검증
4. Client 객체의 생명주기 관리를 위해 Async Context Manager 적용 여부 확인