글 목록으로 돌아가기

Jungle / Everyday

3/30 파이썬 비동기 프로그래밍

⚙️ 1. 비동기 함수 개념 정리 분류 함수/키워드 의미 (비유) 주요 역할 정의 async def 예약 가능한 함수 호출 즉시 실행되지 않고, 나중에 실행할 코루틴 객체를 생성합니다. 제어 await 기다리는 동안 양보 작업 완료를 기다리는 동안 이

임재환
임재환 2026년 3월 31일 · 3분 읽기 · 수정 2026년 4월 2일
3/30 파이썬 비동기 프로그래밍
이미지

⚙️ 1. 비동기 함수 개념 정리

분류 함수/키워드 의미 (비유) 주요 역할
정의 async def 예약 가능한 함수 호출 즉시 실행되지 않고, 나중에 실행할 코루틴 객체를 생성합니다.
제어 await 기다리는 동안 양보 작업 완료를 기다리는 동안 이벤트 루프에 제어권을 넘겨 다른 작업이 실행되게 합니다.
실행 asyncio.run() 엔진 시동 이벤트 루프를 생성하고 메인 코루틴을 실행한 뒤 안전하게 종료합니다.
조율 asyncio.gather() 동시 실행 여러 비동기 작업을 한꺼번에 시작하고, 모두 끝날 때까지 기다려 결과를 모읍니다.
조율 asyncio.as_completed() 빠른 순 처리 완료된 작업부터 순서대로 결과를 받을 수 있게 합니다.
관리 get_running_loop() 현재 루프 조회 현재 실행 중인 이벤트 루프 객체를 가져옵니다.
도구 httpx.AsyncClient() 비동기 브라우저 비동기 방식으로 HTTP 요청을 보낼 수 있게 해주는 클라이언트입니다.

💻 2. 실습 코드

import asyncio
import time
import requests
import httpx

URLS = [
    "https://www.google.com",
    "https://www.python.org",
    "https://www.github.com",
    "https://www.naver.com",
    "https://www.wikipedia.org"
] * 2

# --- [방법 1] 동기 방식: 하나씩 순서대로 실행 ---
def fetch_sync():
    print("동기(Sync) 방식 시작...")
    start_time = time.perf_counter()
    results = []

    for url in URLS:
        response = requests.get(url)
        results.append(response.status_code)
        print(f"[Sync] {url} 완료")

    end_time = time.perf_counter()
    return end_time - start_time

# --- [방법 2] 비동기 방식: 대기 시간에 다른 작업 수행 ---

# 2-1. 개별 URL을 처리하는 코루틴
async def fetch_async_url(client, url):
    response = await client.get(url)
    print(f"[Async] {url} 완료")
    return response.status_code

# 2-2. 여러 비동기 작업을 조율하는 메인 코루틴
async def fetch_async():
    print("\\n비동기(Async) 방식 시작...")
    start_time = time.perf_counter()

    async with httpx.AsyncClient() as client:
        tasks = [fetch_async_url(client, url) for url in URLS]
        await asyncio.gather(*tasks)

    end_time = time.perf_counter()
    return end_time - start_time

# --- 프로그램 실행 시작점 ---
if __name__ == "__main__":
    sync_duration = fetch_sync()
    async_duration = asyncio.run(fetch_async())

    print("\\n" + "=" * 30)
    print(f"동기 방식 소요 시간  : {sync_duration:.2f}초")
    print(f"비동기 방식 소요 시간: {async_duration:.2f}초")
    print(f"비동기가 {sync_duration / async_duration:.1f}배 더 빠릅니다!")
    print("=" * 30)

🧠 3. 비동기 vs 멀티스레딩

🔥 핵심 개념

  • 비동기 = 한 명의 작업자가 여러 작업을 번갈아 처리하는 방식
  • 멀티스레딩 = 여러 작업자가 동시에 작업을 처리하는 방식

📊 동시성 vs 병렬성

개념 설명
동시성 (Concurrency) 하나의 스레드가 여러 작업을 번갈아 수행하여 동시에 진행되는 것처럼 보이게 하는 방식
병렬성 (Parallelism) 여러 스레드나 여러 코어가 실제로 동시에 작업을 실행하는 방식

⚖️ Async vs Thread 비교

구분 비동기 (Asyncio) 멀티스레딩 (Threading)
스레드 개수 1개 (Single Thread) 여러 개 (Multiple Threads)
관리 주체 애플리케이션 / 이벤트 루프 운영체제
리소스 비용 낮음 높음
작업 전환 방식 await 지점에서 협력적으로 전환 운영체제 스케줄러가 강제로 전환
주요 강점 I/O 대기 시간을 효율적으로 활용 실제 병렬 처리 가능

❓ 왜 Python은 Async를 많이 사용할까?

파이썬에는 GIL(Global Interpreter Lock)이라는 제약이 있습니다.
이 때문에 멀티스레드를 사용하더라도 CPU 바운드 작업에서는 기대만큼 성능 향상이 크지 않을 수 있습니다.

하지만 웹 요청, 데이터베이스 쿼리, 파일 읽기/쓰기 같은 I/O 작업은 대부분의 시간이 "응답을 기다리는 시간"입니다.
비동기는 바로 이 대기 시간을 다른 작업으로 채우기 때문에, 적은 리소스로도 많은 작업을 효율적으로 처리할 수 있습니다.

🧾 4. 핵심 요약

  • async는 여러 일을 동시에 “보이게” 처리하는 동시성 모델이다.
  • await는 기다리는 동안 다른 작업에게 순서를 넘기는 핵심 지점이다.
  • 파이썬 비동기는 특히 네트워크, API 호출, DB 통신 같은 I/O 작업에서 강력하다.
  • CPU 연산이 많은 작업은 비동기보다 멀티프로세싱이 더 적합한 경우가 많다.

📚 5. 참고 자료