파이썬 FastAPI 기초 가이드: 비동기 REST API 서버 만들기

FastAPI로 파이썬 비동기 REST API 서버를 만들고 GET·POST 경로, 파라미터와 요청 본문 검증, 응답 모델, 오류 처리, 자동 문서와 운영 배포 전 확인사항을 구현하는 방법을 설명합니다.

본문 상단 광고 구역 (승인 후 자동 노출됩니다)
파이썬 FastAPI 비동기 REST API 서버 기초 대표 이미지
FastAPI를 활용한 비동기 REST API 서버 구축 기초 가이드

FastAPI는 파이썬 타입 힌트로 요청값을 검증하고 OpenAPI 문서를 자동 생성하는 REST API 프레임워크입니다. 기본 서버는 몇 줄로 실행할 수 있지만, 실제 서비스에는 오류 처리·응답 모델·보안·배포 설정이 추가로 필요합니다. 이 글에서는 로컬 개발 서버를 만들고 GET·POST 엔드포인트를 테스트하는 가장 짧은 흐름부터 비동기 함수 선택 기준까지 설명합니다.

FastAPI 공식 첫 단계 확인하기

핵심 요약

  • FastAPI() 인스턴스를 만들고 데코레이터로 경로와 HTTP 메서드를 연결합니다.
  • 개발 환경에서는 fastapi dev 또는 Uvicorn으로 앱을 실행합니다.
  • 경로·쿼리·요청 본문은 타입 힌트와 Pydantic 모델을 통해 검증됩니다.
  • /docs/redoc에서 자동 생성된 API 문서를 확인할 수 있습니다.
  • 대기 시간이 있는 비동기 라이브러리는 async def, 동기 라이브러리는 일반 def를 선택합니다.

FastAPI 설치와 첫 서버 실행

가상환경을 만든 뒤 FastAPI를 설치합니다. 공식 문서의 현재 CLI 흐름을 사용하려면 표준 의존성을 포함한 설치 옵션을 사용할 수 있습니다. 프로젝트 요구사항에 맞춰 버전을 고정하고, 개발용과 운영용 의존성을 구분하는 편이 안전합니다.

python -m venv .venv

# Windows PowerShell
.venv\Scripts\Activate.ps1

pip install "fastapi[standard]"

프로젝트 폴더에 main.py를 만들고 아래 코드를 저장합니다. FastAPI 인스턴스가 애플리케이션의 중심이며, 경로 데코레이터 아래의 함수가 요청을 처리합니다.

from fastapi import FastAPI

app = FastAPI(title="상품 API", version="1.0.0")

@app.get("/")
async def root():
    return {"message": "API is running"}

개발 서버는 프로젝트 위치에서 fastapi dev main.py로 실행할 수 있습니다. 환경에 따라 uvicorn main:app --reload를 사용할 수도 있습니다. 여기서 main은 파일명, app은 FastAPI 인스턴스 변수명입니다.

fastapi dev main.py

# 또는
uvicorn main:app --reload

브라우저에서 http://127.0.0.1:8000/에 접속해 JSON이 나오면 첫 서버가 동작한 것입니다. --reload는 파일 변경을 감지해 개발 서버를 재시작하는 옵션이므로 운영 환경에서는 그대로 사용하지 않습니다.

GET 엔드포인트와 HTTP 메서드

@app.get(), @app.post(), @app.put(), @app.delete() 같은 데코레이터가 경로와 HTTP 메서드를 함수에 연결합니다. 일반적으로 GET은 조회, POST는 생성, PUT은 전체 수정, PATCH는 일부 수정, DELETE는 삭제 용도로 사용합니다.

메서드 대표 용도 예시 경로
GET 목록·상세 조회 /items, /items/10
POST 새 자원 생성 /items
PUT 자원 전체 교체 /items/10
PATCH 일부 필드 수정 /items/10
DELETE 자원 삭제 /items/10

메서드 의미가 프레임워크에 의해 강제되는 것은 아니지만, 관례를 따르면 API 소비자가 동작을 예상하기 쉽고 문서도 명확해집니다. 동일한 경로라도 HTTP 메서드가 다르면 별도 엔드포인트로 처리할 수 있습니다.

경로 파라미터와 쿼리 파라미터

경로 문자열의 중괄호와 함수 인수 이름을 일치시키면 경로 파라미터가 됩니다. 함수 인수에 타입을 선언하면 FastAPI가 변환과 검증을 수행합니다. 경로에 포함되지 않은 단순 인수는 일반적으로 쿼리 파라미터로 해석됩니다.

from fastapi import FastAPI, Query

app = FastAPI()

@app.get("/items/{item_id}")
async def read_item(
    item_id: int,
    keyword: str | None = None,
    limit: int = Query(default=10, ge=1, le=100),
):
    return {
        "item_id": item_id,
        "keyword": keyword,
        "limit": limit,
    }

/items/abc처럼 정수로 바꿀 수 없는 값을 보내면 검증 오류 응답이 생성됩니다. Query()를 사용하면 최소·최대값, 문자열 길이와 설명 같은 조건을 추가할 수 있습니다. 페이지 크기처럼 서버 부하에 영향을 주는 값은 상한을 반드시 두는 것이 좋습니다.

Pydantic 모델로 POST 요청 본문 받기

JSON 요청 본문은 Pydantic 모델로 선언합니다. FastAPI는 본문을 읽어 모델에 맞게 검증하고, 타입이 맞지 않거나 필수 필드가 빠지면 요청 처리 함수가 실행되기 전에 오류를 반환합니다.

from pydantic import BaseModel, Field

class ItemCreate(BaseModel):
    name: str = Field(min_length=2, max_length=100)
    price: int = Field(gt=0)
    description: str | None = None
    in_stock: bool = True

@app.post("/items", status_code=201)
async def create_item(item: ItemCreate):
    data = item.model_dump()
    return {"id": 1, **data}

이 예제는 학습을 위해 고정 ID를 반환합니다. 실제 서비스에서는 데이터베이스 저장, 중복 검사, 트랜잭션과 오류 처리가 필요합니다. 입력 모델과 출력 모델을 분리하면 내부 필드나 민감정보가 응답에 실수로 포함되는 일을 줄일 수 있습니다.

응답 모델과 HTTPException 오류 처리

response_model을 지정하면 반환 데이터를 선언된 스키마로 검증하고 필터링하며 문서에 반영할 수 있습니다. 찾을 수 없는 자원이나 권한 문제처럼 정상 흐름이 아닌 경우에는 HTTPException으로 적절한 상태 코드와 메시지를 반환합니다.

from fastapi import HTTPException

class ItemResponse(BaseModel):
    id: int
    name: str
    price: int

items = {
    1: {"id": 1, "name": "키보드", "price": 59000}
}

@app.get("/items/{item_id}", response_model=ItemResponse)
async def get_item(item_id: int):
    item = items.get(item_id)
    if item is None:
        raise HTTPException(status_code=404, detail="상품을 찾을 수 없습니다.")
    return item

오류 메시지에 데이터베이스 쿼리, 파일 경로, 비밀키 같은 내부 정보를 포함하지 마세요. 서버 로그에는 원인을 남기되 외부 응답에는 문제 해결에 필요한 범위의 정보만 제공해야 합니다.

async def와 일반 def 선택 기준

FastAPI 함수에 무조건 async def를 붙인다고 모든 코드가 빨라지는 것은 아닙니다. 호출하는 라이브러리가 await를 지원하고 네트워크·파일·데이터베이스 응답을 기다리는 작업이라면 비동기 함수가 적합합니다. 반면 동기 방식으로만 동작하는 라이브러리를 호출한다면 일반 def를 사용하는 것이 안전할 수 있습니다.

작업 권장 출발점 주의사항
비동기 HTTP·DB 클라이언트 async defawait 호출 전 구간이 비동기인지 확인
동기 DB·파일 라이브러리 일반 def 이벤트 루프를 막지 않도록 구성
무거운 CPU 계산 별도 작업 큐·프로세스 검토 async만으로 CPU 병렬화되지 않음

async def 안에서 오래 걸리는 동기 함수를 직접 실행하면 다른 요청 처리까지 지연될 수 있습니다. 사용 중인 라이브러리의 공식 문서에서 비동기 지원 여부를 먼저 확인하고, 부하 테스트를 통해 실제 응답성을 검증하세요.

Swagger UI와 OpenAPI 문서 확인

개발 서버가 실행되면 기본적으로 /docs에서 Swagger UI, /redoc에서 대체 문서 화면을 볼 수 있습니다. 경로·파라미터·요청 모델·응답 모델 정보가 OpenAPI 스키마에 반영되어 브라우저에서 직접 요청을 시험할 수 있습니다.

  • http://127.0.0.1:8000/docs: 대화형 Swagger UI
  • http://127.0.0.1:8000/redoc: 읽기 중심 ReDoc
  • http://127.0.0.1:8000/openapi.json: 원본 OpenAPI JSON

자동 문서는 코드와 API 계약을 맞추는 데 도움이 되지만 설명, 예시, 상태 코드와 오류 응답을 명확하게 작성해야 실제 사용자에게 유용합니다. 운영 환경에서 문서 경로를 공개할지는 서비스 정책과 보안 요구에 따라 결정하세요.

운영 배포 전에 확인할 사항

로컬 서버가 작동한다고 운영 준비가 끝난 것은 아닙니다. 개발용 재로더를 끄고, 환경변수로 비밀값을 관리하며, HTTPS 종료·프록시 헤더·프로세스 수·로그·모니터링·헬스체크와 배포 전략을 설계해야 합니다.

  • 비밀키와 데이터베이스 주소를 코드에 직접 작성하지 않습니다.
  • CORS는 필요한 출처만 허용하고 와일드카드를 습관적으로 사용하지 않습니다.
  • 인증과 권한 검사를 엔드포인트별로 일관되게 적용합니다.
  • 요청 크기, 업로드 크기, 페이지 크기와 처리 시간을 제한합니다.
  • 운영 서버의 워커 수는 CPU·메모리·트래픽 특성에 맞춰 시험합니다.
  • 데이터베이스 연결과 외부 API 호출에 타임아웃을 설정합니다.
  • 구조화 로그와 오류 추적, 상태 확인 경로를 준비합니다.

실수 방지 체크리스트

  • main:app에서 파일명과 인스턴스명이 맞는지 확인합니다.
  • 개발용 --reload를 운영에서 사용하지 않습니다.
  • 경로 파라미터 이름과 함수 인수 이름을 일치시킵니다.
  • 입력 모델과 출력 모델을 분리해 민감정보 노출을 막습니다.
  • 페이지 크기와 문자열 길이 등 입력 상한을 설정합니다.
  • 동기 라이브러리를 async def 안에서 장시간 실행하지 않습니다.
  • 404·409·422·500 등 상태 코드를 상황에 맞게 구분합니다.
  • 환경변수와 비밀정보가 로그에 출력되지 않게 합니다.
  • /docs에서 성공·실패 요청을 모두 시험합니다.

자주 묻는 질문

1. FastAPI만 설치하면 서버가 실행되나요?

ASGI 서버가 필요합니다. 표준 설치 옵션을 사용하면 필요한 실행 도구가 함께 설치될 수 있으며, Uvicorn을 별도로 설치해 실행할 수도 있습니다.

2. Flask와 문법이 많이 다른가요?

경로 데코레이터는 익숙할 수 있지만 FastAPI는 타입 힌트, Pydantic 검증, 비동기 처리와 OpenAPI 통합을 중심으로 설계됐습니다.

3. 모든 경로 함수를 async def로 써야 하나요?

아닙니다. 호출하는 라이브러리가 비동기인지 동기인지에 따라 async def와 일반 def를 선택합니다.

4. 요청 본문이 잘못되면 직접 검사해야 하나요?

Pydantic 모델과 제약조건으로 선언하면 FastAPI가 요청 처리 전에 검증합니다. 업무 규칙은 별도 검증과 서비스 계층 로직이 필요할 수 있습니다.

5. /docs는 직접 만들어야 하나요?

기본 설정에서는 OpenAPI 스키마를 기반으로 Swagger UI가 자동 제공됩니다. 제목, 설명, 모델과 응답 정보를 충실히 선언해야 문서 품질이 좋아집니다.

6. 데이터베이스는 무엇을 써야 하나요?

FastAPI가 특정 데이터베이스를 강제하지 않습니다. 동기·비동기 드라이버, 트랜잭션 요구, 운영 환경과 팀 경험을 기준으로 선택하세요.

7. CORS 오류는 왜 발생하나요?

브라우저의 출처 정책 때문에 프런트엔드와 API의 출처가 다를 때 발생할 수 있습니다. 허용할 출처·메서드·헤더를 명시적으로 설정해야 합니다.

8. 배포할 때 127.0.0.1만 사용해도 되나요?

127.0.0.1은 로컬 인터페이스입니다. 컨테이너나 외부 접근 환경에서는 바인딩 주소와 리버스 프록시 구성을 배포 방식에 맞춰 설정해야 합니다.

9. CPU를 많이 쓰는 작업도 FastAPI에서 바로 처리하나요?

무거운 CPU 작업은 요청 처리 프로세스를 막을 수 있습니다. 별도 작업 큐, 워커 또는 프로세스 분리를 검토하세요.

10. 5분이면 운영 API까지 완성할 수 있나요?

기본 서버와 엔드포인트는 빠르게 만들 수 있지만 운영 서비스에는 인증, 데이터베이스, 테스트, 보안, 관측성과 배포 설정이 추가로 필요합니다.

공식 출처

공식 문서 확인일: 2026년 8월 29일

본문 하단 광고 구역