본문 바로가기
AI/Python

FastAPI

by pjj11005 2025. 6. 9.

Python으로 빠르고 직관적인 API 서버를 만들고 싶다면, FastAPI는 최고의 선택지 중 하나이다. 이 글에서는 FastAPI의 주요 특징부터 기본 사용법, 그리고 다양한 입력 방식에 대해 예제와 함께 정리한다.


FastAPI란?

FastAPI는 Python 3.7+에서 사용할 수 있는 현대적인 웹 프레임워크로, 높은 성능과 생산성을 동시에 제공한다. Starlette(비동기 웹 프레임워크)와 Pydantic(데이터 검증 라이브러리)을 기반으로 만들어졌으며, Go나 Node.js 수준의 성능을 자랑한다.


FastAPI의 특징

  • 빠름: Starlette과 Pydantic 덕분에 NodeJS, Go와 대등한 수준의 고성능을 제공한다. 가장 빠른 Python 프레임워크 중 하나이다.
  • 생산성 증가: 기능 개발 속도가 200%~300%까지 빨라지고, 사람에 의한 에러 발생률은 40% 가까이 줄어든다.
  • 훌륭한 편집기 지원: 타입 힌트를 활용한 자동완성과 코드 분석 기능이 뛰어나 디버깅 시간이 줄어든다.
  • 간결함: 코드 중복을 줄이고, 매개변수 선언을 통해 다양한 기능을 처리할 수 있다.
  • 표준 기반 설계: OpenAPI(Swagger) 및 JSON Schema를 기반으로 문서화 및 API 설계가 가능하다.
  • 자동 문서화: 작성한 API는 자동으로 문서화되며, /docs, /redoc에서 바로 확인할 수 있다.

기본 코드 예제

from typing import Union
from fastapi import FastAPI

app = FastAPI()

@app.get('/')
def read_root():
    return {'Hello': 'World'}

@app.get('/items/{item_id}')
def read_item(item_id: int, q: Union[str, None] = None):
    return {'item_id': item_id, 'q': q}

경로 매개변수

경로 매개변수는 URL 경로 일부를 변수처럼 사용할 수 있는 기능이다. 필수로 입력되어야 하며, 타입 힌트를 통해 자동 검증도 가능하다.

기본 사용 예시

@app.get("/files/{file_path:path}")
async def read_file(file_path: str):
    return {"file_path": file_path}

숫자 검증과 순서

from fastapi import FastAPI, Path, Query
from typing import Union

app = FastAPI()

@app.get("/items/{item_id}")
async def read_items(
    item_id: int = Path(title="The ID of the item to get", ge=0, le=1000),
    q: Union[str, None] = Query(default=None, alias="item-query")
):
    results = {"item_id": item_id}
    if q:
        results.update({"q": q})
    return results
  • gt, ge, lt, le 등의 옵션으로 숫자 범위 검증이 가능하다.
  • 고정 경로보다 동적 경로가 아래에 위치해야 정상 작동한다.

쿼리 매개변수

경로 외에 URL에 포함되는 매개변수는 쿼리 매개변수라 한다. URL에서? key=value 형식으로 전달되며, &로 구분한다.

기본 예시

http://127.0.0.1:8000/items/?skip=0&limit=10
from fastapi import FastAPI, Query
from typing import Union

app = FastAPI()

@app.get("/items/")
async def read_items(q: Union[str, None] = Query(default=None, max_length=50)):
    return {"q": q}

다중 값과 리스트

from typing import List, Union
from fastapi import FastAPI, Query

app = FastAPI()

@app.get("/items/")
async def read_items(q: Union[List[str], None] = Query(default=None)):
    return {"q": q}

모델로 받기

from typing import Annotated, Literal
from fastapi import FastAPI, Query
from pydantic import BaseModel, Field

app = FastAPI()

class FilterParams(BaseModel):
    limit: int = Field(100, gt=0, le=100)
    offset: int = Field(0, ge=0)
    order_by: Literal["created_at", "updated_at"] = "created_at"
    tags: list[str] = []

@app.get("/items/")
async def read_items(filter_query: Annotated[FilterParams, Query()]):
    return filter_query

요청 본문 (Request Body)

요청 본문은 클라이언트가 서버로 데이터를 보낼 때 사용하는 영역으로, 주로 POST, PUT 요청에서 사용된다. FastAPI는 Pydantic 모델을 활용해 JSON 데이터를 자동으로 검증하고 파싱해준다.

기본 예시

from fastapi import FastAPI
from pydantic import BaseModel

class Item(BaseModel):
    name: str
    description: str | None = None
    price: float
    tax: float | None = None

app = FastAPI()

@app.post("/items/")
async def create_item(item: Item):
    item_dict = item.dict()
    if item.tax:
        item_dict["price_with_tax"] = item.price + item.tax
    return item_dict

경로 + 쿼리 + 본문을 동시에 받기

from fastapi import FastAPI, Path
from typing import Union
from pydantic import BaseModel

app = FastAPI()

class Item(BaseModel):
    name: str
    description: Union[str, None] = None
    price: float
    tax: Union[float, None] = None

@app.put("/items/{item_id}")
async def update_item(
    item_id: int = Path(title="The ID of the item to get", ge=0, le=1000),
    q: Union[str, None] = None,
    item: Union[Item, None] = None
):
    result = {"item_id": item_id}
    if q:
        result["q"] = q
    if item:
        result["item"] = item
    return result

중첩 모델 (Nested Models)

from typing import List, Set, Union
from fastapi import FastAPI
from pydantic import BaseModel, HttpUrl

app = FastAPI()

class Image(BaseModel):
    url: HttpUrl
    name: str

class Item(BaseModel):
    name: str
    description: Union[str, None] = None
    price: float
    tax: Union[float, None] = None
    tags: Set[str] = set()
    images: Union[List[Image], None] = None

class Offer(BaseModel):
    name: str
    description: Union[str, None] = None
    price: float
    items: List[Item]

@app.post("/offers/")
async def create_offer(offer: Offer):
    return offer

요청 예제 데이터 작성

from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI()

class Item(BaseModel):
    name: str
    description: str | None = None
    price: float
    tax: float | None = None

    model_config = {
        "json_schema_extra": {
            "examples": [
                {
                    "name": "Foo",
                    "description": "A very nice Item",
                    "price": 35.4,
                    "tax": 3.2,
                }
            ]
        }
    }

@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Item):
    return {"item_id": item_id, "item": item}

마무리

FastAPI는 빠르고 안정적인 API 서버를 구축하는 데 최적화된 프레임워크이다. 자동 문서화, 데이터 검증, 편리한 타입 선언 등 많은 장점을 제공하며, 특히 Python에 익숙한 개발자라면 빠르게 익히고 활용할 수 있다. 위 내용을 기반으로 작은 프로젝트부터 천천히 시작해 보자.


 

'AI > Python' 카테고리의 다른 글

비동기 처리  (2) 2025.07.03