에듀테크 프로젝트 대시보드
async vs sync — 동시성 모델
선택을 잘못하면 성능이 오히려 나빠집니다. 핵심은 '이벤트 루프를 블로킹하지 마라'.
| 선언 | 실행 위치 | 쓸 때 |
|---|---|---|
async def | 이벤트 루프에서 직접 | 내부가 전부 await 가능한 비동기 I/O |
def | 외부 스레드풀(anyio) | 동기 DB 드라이버, requests, 파일 I/O, 무거운 CPU |
import time, requests
@app.get("/bad")
async def bad():
time.sleep(3) # 이벤트 루프 전체가 3초 멈춤
r = requests.get("https://...") # 동기 HTTP — 역시 블로킹
return r.json()
# -> 이 3초 동안 서버가 다른 요청을 하나도 처리 못 함import asyncio, httpx
@app.get("/good")
async def good():
await asyncio.sleep(3)
async with httpx.AsyncClient() as client:
r = await client.get("https://...")
return r.json()@app.get("/also-good")
def also_good():
r = requests.get("https://...") # 스레드풀에서 실행되므로 OK
return r.json()from fastapi.concurrency import run_in_threadpool
@app.get("/mix")
async def mix():
data = await run_in_threadpool(heavy_sync_parse, big_blob)
return dataimport asyncio
@app.get("/dashboard")
async def dashboard():
users, orders, stats = await asyncio.gather(
fetch_users(), fetch_orders(), fetch_stats(),
)
return {"users": users, "orders": orders, "stats": stats}