티스토리 뷰

반응형

🚀 FastAPI 기반 로컬 LLM + RAG 챗봇 만들기 – FastAPI의 비동기(Async) 처리 방식

이번 글에서는 FastAPI의 비동기(Async) 처리 방식을 심층적으로 다룹니다.
비동기(Async) vs 동기(Sync) 차이 → FastAPI에서 async 및 await 사용법 → FastAPI의 Starlette 기반 비동기 구조 순서로 설명합니다.


📌 1. 동기(Synchronous) vs 비동기(Asynchronous) 개념

FastAPI는 비동기(Async) 기반의 프레임워크이며, 기존의 동기(Sync) 방식과 비교하면 성능과 응답 속도에서 큰 차이를 보입니다.

1️⃣ 동기(Sync) 방식이란?

동기(Synchronous) 방식은 요청이 순차적으로 실행되며, 하나의 요청이 완료될 때까지 다음 요청이 대기해야 합니다.

🔹 동기 방식 API 예제 (Flask)

from flask import Flask
import time

app = Flask(__name__)

@app.route("/sync")
def sync_endpoint():
    time.sleep(3)  # 3초 동안 대기
    return {"message": "Sync Response"}

💡 3초 동안 API가 응답을 기다리므로, 같은 서버에서 다른 요청을 동시에 처리할 수 없습니다.


2️⃣ 비동기(Async) 방식이란?

반응형

비동기(Asynchronous) 방식은 요청을 병렬로 처리할 수 있으며, 특정 요청이 지연되더라도 다른 요청을 동시에 처리할 수 있습니다.

🔹 비동기 방식 API 예제 (FastAPI)

from fastapi import FastAPI
import asyncio

app = FastAPI()

@app.get("/async")
async def async_endpoint():
    await asyncio.sleep(3)  # 3초 동안 비동기 대기
    return {"message": "Async Response"}

비동기 방식에서는 await를 사용하여 논블로킹 방식으로 API가 실행됩니다.
즉, 하나의 요청이 대기 상태라도 다른 요청이 즉시 처리될 수 있습니다.


📌 2. FastAPI에서 async 및 await 활용 방법

FastAPI에서 비동기 API를 작성하려면 async 키워드를 사용해야 합니다.
또한, 비동기 함수 내부에서는 await를 사용하여 논블로킹 방식으로 작업을 수행할 수 있습니다.

1️⃣ 동기(Sync) vs 비동기(Async) 비교

🔹 동기 방식

from fastapi import FastAPI
import time

app = FastAPI()

@app.get("/sync")
def sync_task():
    time.sleep(3)  # 동기 처리 (블로킹)
    return {"message": "Sync Task Completed"}

🔹 비동기 방식

from fastapi import FastAPI
import asyncio

app = FastAPI()

@app.get("/async")
async def async_task():
    await asyncio.sleep(3)  # 비동기 처리 (논블로킹)
    return {"message": "Async Task Completed"}

💡 동기 방식에서는 time.sleep()을 사용하고, 비동기 방식에서는 await asyncio.sleep()을 사용합니다.


2️⃣ async와 await의 역할

✅ async 키워드를 사용하면 해당 함수가 비동기 함수로 정의됩니다.
✅ await 키워드는 비동기 작업을 실행할 때 사용하며, 함수 실행이 블로킹되지 않도록 보장합니다.

🔹 비동기 데이터 처리 예제

from fastapi import FastAPI
import asyncio

app = FastAPI()

async def fetch_data():
    await asyncio.sleep(2)  # 2초 동안 데이터 처리 시뮬레이션
    return {"data": "Fetched data"}

@app.get("/fetch")
async def fetch_endpoint():
    data = await fetch_data()  # await 사용하여 비동기 함수 호출
    return data

await fetch_data()를 호출하면 fetch_data() 함수가 완료될 때까지 다른 요청을 동시에 처리할 수 있습니다.
FastAPI는 이러한 비동기 처리를 기본적으로 지원하므로 대규모 트래픽을 효과적으로 처리할 수 있습니다.


📌 3. FastAPI의 Starlette 기반 비동기 구조

FastAPI는 Starlette 프레임워크를 기반으로 동작하며, 비동기(Async) 및 이벤트 기반(ASGI) 서버를 지원합니다.

ASGI (Asynchronous Server Gateway Interface)

  • 기존 WSGI(Web Server Gateway Interface)보다 비동기 처리를 지원하는 API 서버 인터페이스
  • FastAPI는 ASGI 서버(Uvicorn)에서 실행되므로 비동기 요청을 효과적으로 처리할 수 있음

Uvicorn과 Starlette의 역할

  • Uvicorn: ASGI 서버로서 FastAPI 애플리케이션을 실행
  • Starlette: FastAPI의 핵심 기능(비동기 처리, 라우팅, 미들웨어 등) 제공

🔹 FastAPI + Uvicorn 서버 실행 예제

uvicorn main:app --host 0.0.0.0 --port 8000 --reload

Uvicorn은 FastAPI가 비동기 방식으로 동작할 수 있도록 지원하는 ASGI 서버입니다.


📌 4. FastAPI의 비동기 처리 성능 테스트

FastAPI가 비동기 방식으로 얼마나 빠르게 요청을 처리할 수 있는지 확인하기 위해 테스트를 진행해봅니다.

1️⃣ 비동기 API 성능 비교

import time
import asyncio
from fastapi import FastAPI

app = FastAPI()

@app.get("/sync")
def sync_task():
    time.sleep(3)  # 동기 처리 (블로킹)
    return {"message": "Sync Task Completed"}

@app.get("/async")
async def async_task():
    await asyncio.sleep(3)  # 비동기 처리 (논블로킹)
    return {"message": "Async Task Completed"}

2️⃣ Apache Benchmark (ab) 테스트 실행

# 동기(Sync) 방식 API 테스트
ab -n 10 -c 5 http://localhost:8000/sync

# 비동기(Async) 방식 API 테스트
ab -n 10 -c 5 http://localhost:8000/async

📌 결과 분석:

  • 동기(Sync) 방식에서는 요청이 하나씩 순차적으로 처리되므로 총 실행 시간이 길어짐
  • 비동기(Async) 방식에서는 요청이 병렬로 처리되므로 응답 속도가 훨씬 빠름

📌 5. 결론 및 다음 단계

FastAPI의 비동기(Async) 처리 방식이 동기(Sync) 방식보다 성능이 뛰어남을 확인했습니다!
FastAPI는 ASGI 서버(Uvicorn)와 Starlette 기반으로 비동기 처리를 최적화할 수 있습니다!

🚀 다음 글에서는 "2.1.3 FastAPI 설치 및 기본 실행"을 학습합니다!

※ 이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/07   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31
글 보관함
반응형