C.W.K.
Stream
Lesson 01 of 10 · published

왜 Async — Event Loop 문제

~12 min · async, event-loop, asyncio

Level 0Scout
0 XP0/80 lessons0/10 achievements
0/120 XP to next level120 XP to go0% complete

Blocking 호출이 cooperative scheduling 죽임

Python asyncio 가 기본값으로 single thread 위 모든 거 실행. 한 task 가 I/O 대기 (DB read, HTTP 요청) 면 event loop 가 다른 task 실행. 그게 전체 전제.

함정: asyncioawait 할 때만 wait 봐. Disk 에서 200ms block 하는 sync 호출이 200ms 동안 event loop 통째로 freeze — 다른 모든 request, 다른 모든 task, 다른 모든 websocket frame.

평범한 sqlite3.connect(...) + conn.execute(...) 가 sync C 호출. Async 웹 앱 안에서 모든 DB query 가 event loop 멈춤. 유저 한 명이면 상관 X. 동시 100 명이면 무너져.

해법 둘:

  • aiosqlite — SQLite 를 백그라운드 thread 에서 실행 + async execute/fetchone/등 노출. Await 가 DB 호출이 thread 위 도는 동안 event loop 양보.
  • asyncio.to_thread — sync 호출 수동 offload. 되긴 하는데 aiosqlite 의 connection-management 다시 발명.
Self-reference: 피파 backend (backend/store/conversations.py) 가 정확히 이 이유로 aiosqlite 사용. Claude SSE streaming 이 conversation 영속화 동안 event loop 양보 계속해야 함; sync write 면 UI 에 보이게 stutter.

Code

Async loop 에 blocking 이 뭐 하나·python
import asyncio, sqlite3, time

async def heartbeat():
    while True:
        print('tick', time.strftime('%H:%M:%S'))
        await asyncio.sleep(0.1)

async def slow_sync_query():
    conn = sqlite3.connect('big.db')
    conn.execute('SELECT count(*) FROM huge_table').fetchone()  # event loop block

async def main():
    heart = asyncio.create_task(heartbeat())
    await slow_sync_query()    # 호출 동안 heartbeat freeze
    heart.cancel()

asyncio.run(main())

External links

Exercise

Freeze 재현: tiny FastAPI/aiohttp 서버에 endpoint 둘 — 하나는 느린 sync SQLite query, 다른 하나는 즉각 async 응답. 느린 endpoint 에 동시 request 보내고 빠른 거 latency 어떻게 degrade 하는지 측정. 그 다음 느린 endpoint 를 aiosqlite 로 swap, 재측정.

Progress

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

댓글 0

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

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