Python 비동기 처리에서 asyncio.gather와 as_completed 선택 기준

문제 상황

외부 API 100개를 동시에 호출해서 데이터를 수집하는 작업이 있었다. 처음엔 asyncio.gather()를 사용했는데, 일부 API가 느리거나 타임아웃될 때 전체 응답을 기다려야 하는 문제가 있었다.

# 기존 코드
results = await asyncio.gather(*tasks)
# 가장 느린 작업이 끝날 때까지 대기

as_completed 도입

완료된 작업부터 처리하고 싶어서 asyncio.as_completed()로 변경했다.

for coro in asyncio.as_completed(tasks):
    try:
        result = await coro
        process_result(result)  # 완료되는 즉시 처리
    except Exception as e:
        logger.error(f"Task failed: {e}")

이렇게 하니 빠른 API 응답부터 바로 DB에 저장할 수 있어서 체감 속도가 개선되었다.

선택 기준

gather 사용:

  • 모든 결과가 필요할 때
  • 결과 순서가 중요할 때
  • 간단한 병렬 처리

as_completed 사용:

  • 완료된 것부터 처리해야 할 때
  • 진행률 표시가 필요할 때
  • 일부 실패를 허용해야 할 때
# gather with return_exceptions
results = await asyncio.gather(*tasks, return_exceptions=True)
for result in results:
    if isinstance(result, Exception):
        handle_error(result)

프로젝트에서는 as_completed로 변경 후 사용자에게 실시간으로 진행 상황을 보여줄 수 있게 되어 만족스러웠다.

Python 비동기 처리에서 asyncio.gather와 as_completed 선택 기준