Notice
Recent Posts
Recent Comments
Link
반응형
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- add_subgraph
- adaptive_rag
- Docker
- langgraph
- tool_calls
- rag
- chat_history
- fastapi
- 강화학습의 수학적 기초와 알고리듬 이해
- subgraph
- 추천시스템
- agenticrag
- conditional_edges
- Ai
- update_state
- LangChain
- REACT
- 강화학습의 수학적 기초와 알고리듬의 이해
- 밑바닥부터 시작하는 딥러닝
- summarize_chat_history
- toolnode
- langgrpah
- tool_call_chunks
- removemessage
- RecSys
- 밑바닥부터시작하는딥러닝 #딥러닝 #머신러닝 #신경망
- pinecone
- Python
- 강화학습
- rl
Archives
- Today
- Total
타임트리
[FastAPI] 동기, 비동기 테스트 본문
FastAPI에서 알아보는 동기와 비동기 처리의 차이
FastAPI를 통해 동기(Synchronous)와 비동기(Asynchronous) 처리의 차이점에 대해 알아보자. 실제 코드 예제와 함께 이 두 가지 처리 방식의 동작 원리를 자세히 살펴본다.
동기와 비동기의 기본 개념
동기 처리 (Synchronous)
- 여러 개의 스레드를 사용하여 작업을 병렬(Parallelism)로 처리
- 각 요청마다 새로운 스레드가 할당됨
→ FastAPI에서는def
로 정의하면 호출 시 내부적으로 ThreadPoolExecutor를 활용해 관리되어 여러 스레드에 동시 처리 가능 (병렬성)
비동기 처리 (Asynchronous)
- 단일 스레드에서 이벤트 루프를 통해 동시성(Concurrency)을 구현
- I/O 작업 중에 다른 작업을 처리할 수 있음
- CPU 자원을 효율적으로 사용
코드로 보는 동기와 비동기 처리
비동기 처리 예제
import asyncio
import threading
from fastapi import FastAPI
app = FastAPI()
async def io_task():
await asyncio.sleep(5)
return {"status": "io_task completed"}
@app.get("/task")
async def task():
print(f"... task 호출 [Thread-{threading.get_ident()}]")
result = await io_task()
return result
asyncio.sleep()
는 CPU를 블로킹하지 않고 다른 작업을 수행할 수 있게 한다.
uvicorn main:app --workers=1
로 하나의 워커 프로세스를 띄우고, 아래처럼 5개의 요청을 보내보면 5개의 요청이 모두 같은 스레드에서 실행되며 (동일 스레드 내 이벤트 루프), 비동기 방식으로 처리되고 있다.
time (curl http://127.0.0.1:8000/task & curl http://127.0.0.1:8000/task & curl http://127.0.0.1:8000/task & curl http://127.0.0.1:8000/task & curl http://127.0.0.1:8000/task)
... run_task 호출 [Thread-139642321622080]
... run_task 호출 [Thread-139642321622080]
... run_task 호출 [Thread-139642321622080]
... run_task 호출 [Thread-139642321622080]
... run_task 호출 [Thread-139642321622080]
{"status":"task completed"}{"status":"task completed"}{"status":"task completed"}{"status":"task completed"}{"status":"task completed"}( curl http://127.0.0.1:8000/task & curl http://127.0.0.1:8000/task & curl &) 0.00s user 0.00s system 0% cpu 5.006 total
동기 처리 예제
@app.get("/task")
def run_task():
print(f"... task 호출 [Thread-{threading.get_ident()}]")
time.sleep(5)
return {"status": "task completed"}
반대로 위의 코드에서는 time.sleep(5)가 CPU를 블로킹한다.
비동기 예제와 마찬가지로 uvicorn main:app --workers=1
로 하나의 워커 프로세스를 띄우고, 아래처럼 5개의 요청을 보내보면 5개의 요청이 모두 다른 스레드에서 실행되는 걸 확인할 수 있다.
time (curl http://127.0.0.1:8000/task & curl http://127.0.0.1:8000/task & curl http://127.0.0.1:8000/task & curl http://127.0.0.1:8000/task & curl http://127.0.0.1:8000/task)
... run_task 호출 [Thread-140385687238208]
... run_task 호출 [Thread-140385678845504]
... run_task 호출 [Thread-140385670452800]
... run_task 호출 [Thread-140385662060096]
... run_task 호출 [Thread-140385653667392]
{"status":"task completed"}{"status":"task completed"}{"status":"task completed"}{"status":"task completed"}( curl http://127.0.0.1:8000/task & curl http://127.0.0.1:8000/task & curl &) 0.00s user 0.00s system 0% cpu 5.011 total
성능 차이와 사용 시나리오
비동기 처리가 유리한 경우
- I/O 바운드 작업이 많은 경우
- 데이터베이스 쿼리
- 외부 API 호출
- 파일 읽기/쓰기
- 동시에 많은 연결을 처리해야 하는 경우
- 메모리 사용량을 최소화해야 하는 경우
동기 처리가 유리한 경우
- CPU 바운드 작업이 많은 경우
- 개별 요청의 처리 시간이 매우 짧은 경우
결론
비동기 처리는 이벤트 루프를 통한 동시성을 제공하여 I/O 바운드 작업에서 뛰어난 성능을 보여준다. 반면 동기 처리는 여러 스레드를 통한 병렬 처리로 CPU 바운드 작업에서 장점을 가집니다. 따라서 FastAPI 애플리케이션을 구현할 때 CPU 바운드와 I/O 바운드를 잘 구분하고 상황에 맞게 코드를 작성하는 게 중요하다.
'Today I Learned > 동시성 프로그래밍' 카테고리의 다른 글
[Python] Multi-Threading, Multi-Processing, GIL (0) | 2024.05.26 |
---|---|
[Python] 동시성(concurrency)와 병렬성(parallelism) (0) | 2024.05.26 |
[Python] 프로그램, 프로세스와 스레드 (0) | 2024.05.26 |
[Python] 파이썬 코루틴 (0) | 2024.05.26 |
[Python] 동기와 비동기 (0) | 2024.05.26 |