본문 바로가기
C.W.K.
Stream
Lesson 05 of 05 · published

비동기·스레드·프로세스를 고르는 질문

~15 min · picking, io-bound, cpu-bound, patterns

Level 0호기심
0 XP0/93 lessons0/23 achievements
0/100 XP to next level100 XP to go0% complete

네트워크·DB처럼 I/O를 기다리고 라이브러리가 비동기를 지원하면 asyncio, 동기 I/O만 제공하면 스레드, 오래 계산하는 Python CPU 작업이면 프로세스를 먼저 생각해.

비동기 코드에서 짧은 동기 I/O는 asyncio.to_thread로 보내 이벤트 루프를 막지 않고, CPU 계산은 프로세스 풀로 넘겨. 중요한 건 “끝까지 비동기”라는 구호가 아니라 어디가 얼마나 막히는지 측정하고 그 경계를 명시하는 거야.

자유 스레딩 Python이 널리 기본이 되면 CPU 선택은 달라질 수 있지만, 현재 일반 빌드에서는 GIL을 전제로 해.

Code

I/O 작업에는 asyncio·python
import asyncio
import aiohttp                         # async HTTP 클라이언트

async def fetch(session, url):
    async with session.get(url) as resp:
        return await resp.text()

async def fetch_all(urls):
    async with aiohttp.ClientSession() as session:
        return await asyncio.gather(*(fetch(session, u) for u in urls))

# (데모만 — asyncio.run(fetch_all(urls)) 로 실행)
# 수백 동시 fetch, 단일 스레드, 한 이벤트 루프
CPU 작업에는 프로세스·python
from concurrent.futures import ProcessPoolExecutor

def heavy_compute(n):
    total = 0
    for i in range(n):
        total += i * i
    return total

if __name__ == '__main__':
    with ProcessPoolExecutor() as pool:
        results = list(pool.map(heavy_compute, [10**7] * 4))
        print(results)
# 4 코어 실제 병렬 사용, GIL 제약 없음
비동기 흐름에서 CPU 계산 넘기기·python
import asyncio

def heavy_compute(n):                  # sync, CPU 바운드
    total = 0
    for i in range(n):
        total += i * i
    return total

async def main():
    # 이벤트 루프 안 막게 스레드 (또는 프로세스) 로 offload
    result = await asyncio.to_thread(heavy_compute, 10_000_000)
    print(result)

asyncio.run(main())

# 프로세스 레벨엔 — loop.run_in_executor(ProcessPoolExecutor(), fn, *args)
스레드가 맞는 동기 I/O 경계·python
# threading 이 이기는 특정 케이스:
# - sync 라이브러리 사용해야 (async 버전 없음)
# - 지금 async 로 리팩터 안 하는 중
# - 작업이 I/O 바운드
#
# 예 — sync 만인 legacy DB 드라이버.
# asyncio.to_thread 또는 ThreadPoolExecutor 로 감싸.
#
# threading을 무턱대고 기본값으로 삼지 마 — 사람들 가정보다 적은 경우에 답.
# asyncio 가 거의 모든 현대 I/O 라이브러리 지원,
# threading 은 갭 메우기.

External links

Exercise

100개 웹 페이지, 1000개 이미지 크기 변경, 수천 웹소켓, 비동기 FastAPI 안의 동기 DB 호출, 캐시 없는 피보나치라는 다섯 상황에 asyncio·스레드·프로세스 중 하나를 고르고 이유를 한 문장씩 써.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.