0Pricing
Python Academy · 강의

프로덕션 환경의 비동기 입출력 패턴

HTTP 클라이언트, 큐 및 실제 파이프라인에 asyncio를 적용합니다.

프로덕션 환경의 비동기 입출력 패턴은(는) CoddyKit의 무료 Python Academy 강의입니다. 이것은 4개 중 4번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 Python Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. Python Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

이벤트 루프 모범 사례

항상 asyncio.run()을 단일 진입점으로 사용하세요. 동기 코드와 비동기 코드를 부주의하게 섞지 말고, 긴 CPU 작업으로 이벤트 루프를 절대 차단하지 마세요.

import asyncio

async def main():
    # Never: time.sleep() — blocks the event loop
    # Always: await asyncio.sleep()
    await asyncio.sleep(1)

asyncio.run(main())

연결 풀 사용

요청마다 새 연결을 여는 대신 연결을 재사용하세요. asyncpg와 aiohttp 같은 라이브러리는 기본 제공 연결 풀을 제공합니다.

# pip install asyncpg
import asyncpg, asyncio

async def main():
    pool = await asyncpg.create_pool(
        dsn="postgresql://user:pass@host/db",
        min_size=5, max_size=20
    )
    async with pool.acquire() as conn:
        row = await conn.fetchrow("SELECT 1")
    await pool.close()

asyncio.Queue를 사용하는 생산자-소비자

asyncio.Queue는 동시에 실행되는 생산자와 소비자를 작업 단위로 분리합니다.

import asyncio

async def producer(q):
    for i in range(5):
        await q.put(i)
        await asyncio.sleep(0.5)
    await q.put(None)  # sentinel

async def consumer(q):
    while (item := await q.get()) is not None:
        print(f"processing {item}")
        q.task_done()

async def main():
    q = asyncio.Queue()
    await asyncio.gather(producer(q), consumer(q))

asyncio.run(main())

Semaphore를 사용한 속도 제한

외부 API에 과도한 부하를 주거나 속도 제한에 걸리지 않도록 외부로 보내는 동시 요청 수를 제한하세요.

import asyncio, aiohttp

SEM = asyncio.Semaphore(10)  # 10 concurrent requests max

async def fetch(session, url):
    async with SEM:
        async with session.get(url) as r:
            return await r.json()

async def main(urls):
    async with aiohttp.ClientSession() as s:
        return await asyncio.gather(*[fetch(s, u) for u in urls])

지수 백오프를 사용한 재시도

재시도 가능한 작업을 백오프 로직으로 감싸 일시적인 실패를 우아하게 처리하세요.

import asyncio

async def retry(coro_fn, retries=3, base=1):
    for attempt in range(retries):
        try:
            return await coro_fn()
        except Exception as e:
            if attempt == retries - 1: raise
            delay = base * 2 ** attempt
            await asyncio.sleep(delay)

정상 종료

장시간 실행되는 작업에서 asyncio.CancelledError를 처리하고 OS 신호를 다뤄 깔끔하게 종료하세요.

import asyncio, signal

async def server():
    stop = asyncio.Event()
    loop = asyncio.get_running_loop()
    loop.add_signal_handler(signal.SIGINT, stop.set)
    await stop.wait()
    print("Shutting down gracefully")

응답 스트리밍

비동기 제너레이터를 사용하면 대규모 응답을 메모리에 전부 불러오지 않고 스트리밍할 수 있습니다.

import asyncio, aiohttp

async def stream(url):
    async with aiohttp.ClientSession() as s:
        async with s.get(url) as r:
            async for chunk in r.content.iter_chunked(4096):
                process(chunk)

async def process(chunk):
    await asyncio.sleep(0)
    print(len(chunk), "bytes")

FastAPI의 백그라운드 작업

FastAPI의 BackgroundTasks는 응답이 전송된 후 실행되도록 작업을 대기열에 넣어 엔드포인트를 빠르게 유지합니다.

from fastapi import FastAPI, BackgroundTasks

app = FastAPI()

def send_email(to: str, body: str):
    # heavy synchronous work
    pass

@app.post("/register")
async def register(email: str, bg: BackgroundTasks):
    bg.add_task(send_email, email, "Welcome!")
    return {"status": "registered"}

하트비트 패턴

create_task를 사용해 주 서버 루프와 함께 주기적인 백그라운드 작업을 실행하세요.

import asyncio

async def heartbeat():
    while True:
        print("alive")
        await asyncio.sleep(30)

async def main():
    asyncio.create_task(heartbeat())
    await serve_forever()

비동기 코드 프로파일링

비동기 코드를 인식하는 프로파일링에는 yappi 또는 py-spy를 사용하세요. 느린 콜백 경고를 확인하려면 asyncio 디버그 모드를 활성화하세요.

# Enable debug to catch slow callbacks:
# asyncio.run(main(), debug=True)

# PYTHONASYNCIODEBUG=1 python server.py
# logs: Executing <Task coroutine=...> took 0.150 seconds

일반적인 문제 피하기

핵심 규칙은 다음과 같습니다. 이벤트 루프에서 차단 코드를 절대 호출하지 말고, 코루틴은 항상 기다리며, 종료할 때 작업을 취소하고, 연결 풀을 사용하며, Semaphore로 동시성을 제한하세요.

import asyncio

async def bad():
    import time
    time.sleep(2)        # blocks the entire event loop!

async def good():
    await asyncio.sleep(2)  # yields control

빠른 확인

동시에 실행되는 생산자와 소비자를 분리하는 asyncio 기본 요소는 무엇입니까?

복습

실제 운영 환경의 비동기 패턴에서는 연결 풀을 사용하고, Semaphore로 동시성을 제어하며, 재시도 및 백오프를 구현하고, 대규모 데이터를 스트리밍하고, 신호를 받으면 정상적으로 종료하며, create_task로 주기적인 작업을 실행하세요.

자주 묻는 질문

“프로덕션 환경의 비동기 입출력 패턴” 강의는 무료인가요?

네 — “프로덕션 환경의 비동기 입출력 패턴” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 Python Academy 강의 전체를 잠금 해제할 수 있습니다. Python Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

“프로덕션 환경의 비동기 입출력 패턴”에서 뭘 배우나요?

HTTP 클라이언트, 큐 및 실제 파이프라인에 asyncio를 적용합니다. 브라우저에서 직접 실행하는 실습 코드로 Python Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.

Python Academy을(를) 시작하는 데 경험이 필요한가요?

사전 경험은 필요하지 않습니다. CoddyKit의 Python Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 4번째 강의입니다.

“프로덕션 환경의 비동기 입출력 패턴” 강의는 얼마나 걸리나요?

대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.

이 Python Academy 강의에서 코드를 작성하고 실행할 수 있나요?

네. 모든 Python Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.

이 강의의 모든 강의

  1. 코루틴과 이벤트 루프
  2. await, 작업 및 수집
  3. 비동기 컨텍스트 관리자와 반복자
  4. 프로덕션 환경의 비동기 입출력 패턴
← Python Academy(으)로 돌아가기