
FastAPI를 사용하다 보면 반드시 마주치게 되는 키워드:
async / await
FastAPI에서 함수 만들 때 기억할 것
defawait가 필요한 라이브러리를 쓴다면 → async def둘은 섞어 써도 된다. 어차피 FastAPI가 알아서 잘 처리해줌.
👉 비동기를 “완벽히 이해한 뒤” 시작할 필요는 없다
👉 언제 쓰는지만 알면 충분하다
👉 “시간을 맞추지 않는다”는 의미다.
즉, 앞 작업이 끝나든 말든 다음 작업을 시작할 수 있다는 뜻
await는 영어 그대로 “기다리다”라는 의미다.
👉 비동기 흐름 중에서
👉 “이 결과는 받고 넘어가자”라고 표시하는 지점
import time
def task(name, seconds):
print(f"{name} 시작")
time.sleep(seconds)
print(f"{name} 완료")
start = time.time()
task("작업1", 1)
task("작업2", 1)
task("작업3", 1)
print(f"총 시간: {time.time() - start:.1f}초")
결과는 항상 같다.
총 시간: 3.0초
한 작업이 끝나야 다음 작업이 시작된다.
import asyncio
import time
async def task(name, seconds):
print(f"{name} 시작")
await asyncio.sleep(seconds)
print(f"{name} 완료")
async def main():
start = time.time()
await asyncio.gather(
task("작업1", 1),
task("작업2", 1),
task("작업3", 1),
)
print(f"총 시간: {time.time() - start:.1f}초")
asyncio.run(main())
결과는 이렇게 바뀐다.
총 시간: 1.0초
👉 같은 작업을 했는데 시간이 3배 차이난다
👉 비동기는 “빨리 계산하는 기술”이 아닌,
👉 기다리는 시간을 낭비하지 않는 기술이다
철수는 기다리는 시간 동안 아무것도 하지 않았다.
👉 같은 시간에 더 많은 일을 했다
| 구분 | 동기(Sync) | 비동기(Async) |
|---|---|---|
| 흐름 | 순차 실행 | 기다림 중 다른 작업 |
| 대기 시간 | 낭비됨 | 활용됨 |
| 웹 서버 | 비효율적 | 매우 적합 |
❗ 비동기는 “동시에 여러 계산”이 아니다
❗ 외부 응답을 기다리는 구조를 효율화하는 것이다
동시성과 병렬성은 해결하려는 문제가 다르다.
동시성은 이렇게 요약할 수 있다.
👉 “여러 일이 진행 중인 상태”
✔ 핵심은 기다리는 시간을 다른 일로 채우는 것
병렬성은 완전히 다른 문제를 푼다.
👉 “여러 일을 진짜로 동시에 처리”
✔ 핵심은 일손 자체를 늘리는 것
❗ 웹 서버에서 중요한 건 대부분 병렬성이 아니라 동시성이다
웹 서버는 대부분 이런 일을 한다.
이때 서버는 직접 일하지 않는다.
외부가 응답할 때까지 기다릴 뿐..
async def get_user_info(user_id):
user = await database.get_user(user_id)
return user
여기서 중요한 점:
DB가 일하는 동안 서버는 놀지 않는다👉다른 요청을 처리할 수 있다
👉 이것이 웹에서 동시성이 중요한 이유다
이번엔 기다림이 없다.
계산 자체가 오래 걸리는 작업이다.
def process_images(images):
chunk1 = images[0:25000]
chunk2 = images[25000:50000]
chunk3 = images[50000:75000]
chunk4 = images[75000:100000]
results = parallel_process([
chunk1,
chunk2,
chunk3,
chunk4
])
return results
이 경우엔:
👉 이건 비동기가 아니라 병렬 처리의 영역이다
언제 동시성을 쓰고,
그렇다면, 언제 병렬성을 써야 할까?
입출력을 기다리는 작업이다.
특징:
✅ 이런 작업엔 동시성(async)이 효과적
CPU가 계속 계산해야 하는 작업이다.
✅ 이런 작업엔 병렬성이 필요
FastAPI는 이 두 가지를 모두 잘 다룬다.
👉 그래서 FastAPI는
👉 일반 웹 API + ML API 모두에 적합하다
async def make_ramen_async():
return "라면 완성"
“이 함수는 중간에 기다릴 수 있다”
async def order_food():
food = await get_food_from_kitchen()
return food
await는 기다리는 지점 ❗ await는 async def 안에서만 사용 가능
@app.get("/hello")
def say_hello():
return {"message": "안녕하세요"}
✔ 가장 쉬움
✔ 대부분의 시작 단계에 충분
@app.get("/hello")
async def say_hello():
return {"message": "안녕하세요"}
✔ await가 필요할 때 사용 ✔ 비동기 라이브러리 사용 시 필수
| 상황 | 선택 |
|---|---|
| 잘 모르겠다 | def |
| 단순 로직 | def |
| await 필요한 라이브러리 | async def |
👉 FastAPI는 둘 다 알아서 처리한다