이번 포스트에서는
FastAPI의 개념부터 Path Parameter와 Query Parameter를 이용해 간단한 API를 만드는 흐름까지 다뤄보았습니다.
FastAPI란?
FastAPI는 Python 기반 고성능 웹 API 프레임워크입니다.
가장 큰 장점은 이름처럼 '빠르다(Fast)'는 것과, 코드를 작성할 때 변수의 타입을 미리 정해두는 타입 힌트 기능을 사용하면 데이터 검증과 문서 작성이 자동으로 된다는 점입니다.
FastAPI는 파이썬의 타입 힌트를 적극적으로 활용합니다. 예를 들어, user_id: int라고 함수에 지정하면, 사용자가 user_id 자리에 숫자가 아닌 문자('abc')를 보내면 FastAPI가 자동으로 에러를 처리해 줍니다. 개발자가 직접 검증 코드를 짤 필요가 없어서 편리합니다.
주요 특징
- 빠른 성능: Starlette 기반입니다.
- 타입 힌트 기반 자동 검증: 타입 힌트로 입력값 검증이 자동으로 동작합니다.
- 자동 API 문서: Swagger 문서가 자동으로 생성됩니다.
주요 용도
- 백엔드 API 서버 구축
- AI 또는 ML 모델을 API로 서빙할 때 사용
Django vs Flask vs FastAPI:
- Django: 기능이 너무 많아서 배우기 어렵고(러닝 커브가 높음), 큰 프로젝트에 적합함
- Flask: 아주 가벼워서 작은 프로젝트에 좋음. 하지만 기능이 적어 필요한 것을 직접 만들어야 함.
- FastAPI: 빠르고, API 서버와 AI 모델 서빙에 특화되어 있어 요즘 많이 사용됨.
개발 환경 준비
Python 버전
Python **3.10+** 사용을 권장합니다.
가상환경 생성
python3.13 -m venv .venv
가상환경 활성화
macOS
source .venv/bin/activate
Windows
.venv\Scripts\activate
FastAPI 설치
pip install "fastapi[standard]"
FastAPI 기본 구조
FastAPI는 FastAPI()로 앱을 만들고 데코레이터로 라우트를 등록합니다.
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def root():
return {"message": "Hello FastAPI"}
기본 구조의 이해: FastAPI 서버를 시작하는 가장 기본적인 형태입니다.
- from fastapi import FastAPI: FastAPI 기능을 가져옵니다.
- app = FastAPI(): 서버 애플리케이션 객체를 만듭니다.
- @app.get("/"): / 경로에 GET 요청이 들어오면 바로 아래에 있는 함수(root)를 실행하라는 뜻입니다.
- return {"message": "Hello FastAPI"}: 함수가 실행된 후, 이 딕셔너리(key: value 형태)를 JSON 형태의 HTTP 응답으로 클라이언트에게 돌려줍니다.
💡FastAPI 서버 실행 시 지피티 등 다양하게 이용하다보면 다음과 같은 다양한 명령을 보게 됩니다.
fastapi dev 000:app
fastapi dev -e 000:app
fastapi dev 000.py
대체 이게 무슨 차이가 있는 애들일까요? 아래에서 알아보았습니다.
FastAPI 실행의 기본 원리
FastAPI 서버 실행의 핵심은 Python 파일 안에 있는 app 객체를 서버에 전달하는 것입니다.
# 000.py
from fastapi import FastAPI
app = FastAPI()
이때 FastAPI는 다음 형식을 기대합니다.
파일이름 : 앱객체이름
정석적인 실행 방식은 다음과 같습니다.
fastapi dev 000:app
000.py 파일 안에 정의된 app 객체를 개발 서버로 실행하라는 의미
이 명령은 FastAPI 개발 서버를 실행하며, 코드 변경 시 자동 재시작 기능이 포함된 기본 개발 모드입니다.
-e 옵션의 의미
-e 옵션은 FastAPI의 환경 변수 로딩 및 개발 편의 모드를 활성화하는 옵션입니다.
fastapi dev -e 000:app
주요 기능
- 코드 변경 사항을 즉시 반영하는 안정적인 자동 리로드
- 개발 환경에 최적화된 실행
- (선택적) .env 파일이 있을 경우 자동 로딩
000.py 방식이 동작하는 이유
fastapi dev 000.py
이는 FastAPI CLI의 편의 기능 때문입니다.
FastAPI는 내부적으로 다음과 같이 추정하여 실행합니다.
000.py → 000:app
즉 000.py 방식은 축약형, 000:app 방식은 정석 문법입니다.
가끔 실습을 진행하다보면 :app 은 안 되는데 .py는 실행이 될 때가 있습니다.
이 현상은 FastAPI CLI의 동작 방식 차이 때문입니다.
.py 방식은 FastAPI가 "추측"해 주는 모드입니다
.py 로 실행되면 FastAPI는 다음 과정을 자동으로 수행합니다.
- 000.py 파일을 찾습니다.
- 파일을 import 합니다.
- 그 안에서 FastAPI 객체(app)를 자동으로 탐색합니다.
- 발견되면 해당 객체를 서버로 실행합니다.
.py 방식은 FastAPI가 내부에서 "이 파일 안에 app이 있겠지?" 하고 알아서 찾아 주는 모드입니다.
그래서 경로나 구조가 조금 틀려도 실행이 되는 경우가 많습니다.
그에 반해 :app 방식은 정석 문법이며 추측이 전혀 없습니다
이 방식은 FastAPI에게 정확히 <"000" 이라는 모듈 안에서 "app" 이라는 객체를 정확히 찾아 실행하라> 라고 요구합니다.
따라서 다음 중 하나라도 어긋나면 바로 실패합니다.
| 실패 원인 | 설명 |
| 파일 위치 | 현재 디렉토리에 000.py 가 없는 경우 |
| 실행 위치 | 터미널 위치가 파일이 있는 폴더가 아닌 경우 |
| 패키지 구조 | 폴더 구조로 인해 import 경로가 달라진 경우 |
| 객체 이름 | FastAPI 객체 이름이 app 이 아닌 경우 |
| 모듈 충돌 | 동일한 이름의 폴더 또는 모듈이 존재하는 경우 |
실습을 하다보면 실습 파일이 계속 늘어나고, 파일명을 변경한다던가 하는 이유로
:app 방식은 실패할 수도 있고 이런 차이가 있다는 것을 알 수 있었습니다.🍀
아래와 같이 표로 간략하게 정리해봤습니다.
| 실행 명령 | 의미 |
| fastapi dev 000:app | FastAPI 정석 실행 방식 |
| fastapi dev -e 000:app | 정석 방식 + 환경변수 자동 로딩 |
| fastapi dev 000.py | CLI 편의 기능으로 동작하는 축약형 |
데코레이터 개념과 FastAPI에서의 역할
데코레이터란
함수를 감싸서 원래 함수의 동작 전후에 공통 로직을 추가하는 문법입니다.
중복 코드를 줄이고 선언적으로 기능을 표현하는 데 사용합니다.
예시는 다음과 같습니다.
def my_decorator(func):
def wrapper(*args, **kwargs):
print("before")
result = func(*args, **kwargs)
print("after")
return result
return wrapper
@my_decorator
def hello():
print("hello")
FastAPI에서 데코레이터 역할
FastAPI의 @app.get() 같은 데코레이터는 함수를 HTTP 엔드포인트로 등록합니다.
예를 들어 GET / 요청이 오면 root() 함수가 실행됩니다.
@app.get("/")
def root():
return {"message": "Hello FastAPI"}
자동 API 문서
FastAPI는 API 문서를 자동 생성합니다.
- Swagger UI: http://localhost:8000/docs
- Redoc: http://localhost:8000/redoc
Path Parameter
Path Parameter는 URL 경로 자체에 포함되는 값입니다.
주로 리소스를 식별할 때 사용합니다.
예시는 다음과 같습니다.
- /users/3
- /items/abc
{user_id} 를 경로에서 추출해 함수 인자로 받습니다.
user_id: int 같은 타입 힌트로 자동 검증이 동작합니다.
@app.get("/users/{user_id}")
def get_user(user_id: int):
return {"user_id": user_id}
/users/abc처럼 타입이 맞지 않으면 422 에러로 검증 실패가 자동 처리됩니다.
Swagger 문서에도 타입 정보가 자동 반영됩니다.
또 Path 값에 조건과 설명을 붙일 수 있는데요.
- ge=1은 1 이상만 허용합니다.
- description은 Swagger에 설명을 표시합니다.
- ...는 필수값을 의미합니다.
from fastapi import Path
@app.get("/users/{user_id}")
def get_user(user_id: int = Path(..., ge=1, description="유저 ID (1 이상)")):
return {"user_id": user_id}
실습을 해보겠습니다!
요구사항
- GET /items/{item_id}
- 예시 입력: /items/10
- 예시 응답: {"item_id": 10}
정답 예시
@app.get("/items/{item_id}")
def get_item(item_id: int):
return {"item_id": item_id}
Query Parameter
Query Parameter는 URL 뒤에 ?key=value 형태로 붙는 값입니다.
필터링, 정렬, 페이지네이션에 자주 사용합니다.
예시
/search?q=fastapi&limit=10
- q는 필수입니다. 기본값이 없습니다.
- limit은 선택입니다. 기본값이 10입니다.
@app.get("/search")
def search(q: str, limit: int = 10):
return {"q": q, "limit": limit}
Query에는 조건을 걸 수 있습니다.
- min_length, max_length는 문자열 길이 제한입니다.
- ge, le는 숫자 범위 제한입니다.
from fastapi import Query
@app.get("/search")
def search(
q: str = Query(..., min_length=2, max_length=30),
limit: int = Query(10, ge=1, le=100),
):
return {"q": q, "limit": limit}
Path + Query 같이 쓰기
원칙은 다음과 같습니다.
- 리소스 식별은 Path입니다.
- 옵션은 Query입니다.
- URL 경로 상에 존재하면 Path입니다.
- 존재하지 않으면 Query입니다.
예시로 /users/3/posts?limit=5가 제시 되었을 때 아래와 같이 쓸 수 있습니다.
@app.get("/users/{user_id}/posts")
def list_posts(user_id: int, limit: int = 10):
return {"user_id": user_id, "limit": limit}
이것도 실습을 해보겠습니다.
요구사항
- GET /products/search?q=apple&limit=5
- 응답: {"q": "apple", "limit": 5}
정답 예시
@app.get("/products/search")
def product_search(q: str, limit: int = 10):
return {"q": q, "limit": limit}'[오즈코딩스쿨] AI 헬스케어 > 🏄🏻 FastAPI 활용 인공지능 모델 서빙' 카테고리의 다른 글
| [FastAPI 4일차] 동기와 비동기, asyncio (3) | 2026.01.16 |
|---|---|
| [FastAPI 2일차] Type Hints, 상태 코드, 에러 처리 (1) | 2026.01.15 |