FastAPI로 REST API 만들기 – 초보자도 쉽게 따라하는 완벽 가이드

FastAPI로 REST API 만들기 – 초보자도 쉽게 따라하는 완벽 가이드

1. 도입 – 학습 목표 및 필요성

FastAPI로 REST API 만들기는 현대적인 웹 개발에서 필수적인 기술입니다. FastAPI는 Python으로 고성능 API를 빠르게 구축할 수 있는 최신 웹 프레임워크로, 자동 문서화, 타입 힌팅, 비동기 처리 등의 강력한 기능을 제공합니다. 이 튜토리얼에서는 FastAPI의 기본 개념부터 실전 구현까지 단계별로 학습하여, 실무에서 바로 활용할 수 있는 REST API를 만드는 방법을 마스터하게 됩니다. 초보자도 쉽게 따라할 수 있도록 상세한 코드 예제와 설명을 제공하며, 데이터베이스 연동, 인증, 에러 핸들링 등 실무 필수 기능까지 다룹니다.

2. 기본 개념 설명

FastAPI란? FastAPI는 Starlette와 Pydantic을 기반으로 한 고성능 Python 웹 프레임워크입니다. NodeJS나 Go와 비슷한 수준의 높은 성능을 자랑하며, Python 3.6+의 타입 힌팅을 적극 활용합니다.

주요 특징:

  • 빠른 개발 속도: 코드 작성량이 적고 직관적인 문법으로 개발 시간을 40-60% 단축
  • 자동 문서화: Swagger UI와 ReDoc을 통한 대화형 API 문서 자동 생성
  • 타입 안정성: Pydantic을 통한 데이터 검증 및 직렬화
  • 비동기 지원: async/await를 통한 고성능 비동기 처리
  • 표준 준수: OpenAPI와 JSON Schema 표준 완벽 지원

REST API란? REST(Representational State Transfer)는 HTTP 프로토콜을 기반으로 자원을 정의하고 처리하는 아키텍처 스타일입니다. GET, POST, PUT, DELETE 등의 HTTP 메소드를 사용하여 CRUD 작업을 수행합니다.

3. 단계별 구현 가이드

Step 1: 환경 설정

먼저 Python 3.7 이상이 설치되어 있는지 확인하고, 가상환경을 생성합니다.

# 가상환경 생성
python -m venv venv

# 가상환경 활성화 (Windows)
venv\Scripts\activate

# 가상환경 활성화 (Mac/Linux)
source venv/bin/activate

필요한 패키지를 설치합니다.

# FastAPI와 ASGI 서버 설치
pip install fastapi uvicorn[standard]

# 추가 패키지 설치
pip install pydantic sqlalchemy

Step 2: 기본 API 서버 생성

프로젝트 폴더를 만들고 main.py 파일을 생성합니다. 가장 간단한 FastAPI 애플리케이션부터 시작합니다.

from fastapi import FastAPI

app = FastAPI()

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

서버를 실행합니다.

# 서버 실행
uvicorn main:app --reload

# --reload 옵션은 코드 변경 시 자동 재시작

브라우저에서 http://localhost:8000 으로 접속하면 JSON 응답을 확인할 수 있고, http://localhost:8000/docs 에서 자동 생성된 API 문서를 볼 수 있습니다.

Step 3: 데이터 모델 정의

Pydantic을 사용하여 요청/응답 데이터 모델을 정의합니다. 이를 통해 자동 검증과 문서화가 가능합니다.

from pydantic import BaseModel, Field
from typing import Optional

class Item(BaseModel):
    id: Optional[int] = None
    name: str = Field(..., min_length=1, max_length=100)
    description: Optional[str] = Field(None, max_length=500)
    price: float = Field(..., gt=0)
    is_active: bool = True

class ItemCreate(BaseModel):
    name: str
    description: Optional[str] = None
    price: float
    is_active: bool = True

Step 4: CRUD 엔드포인트 구현

Create, Read, Update, Delete 기능을 가진 완전한 REST API를 구현합니다.

from fastapi import FastAPI, HTTPException, status
from typing import List

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

# 임시 데이터베이스 (실제로는 DB 사용)
items_db = {}
item_id_counter = 1

@app.post("/items/", response_model=Item, status_code=status.HTTP_201_CREATED)
def create_item(item: ItemCreate):
    global item_id_counter
    new_item = Item(id=item_id_counter, **item.dict())
    items_db[item_id_counter] = new_item
    item_id_counter += 1
    return new_item

@app.get("/items/", response_model=List[Item])
def read_items(skip: int = 0, limit: int = 10):
    items = list(items_db.values())
    return items[skip:skip+limit]

@app.get("/items/{item_id}", response_model=Item)
def read_item(item_id: int):
    if item_id not in items_db:
        raise HTTPException(status_code=404, detail="Item not found")
    return items_db[item_id]

@app.put("/items/{item_id}", response_model=Item)
def update_item(item_id: int, item: ItemCreate):
    if item_id not in items_db:
        raise HTTPException(status_code=404, detail="Item not found")
    updated_item = Item(id=item_id, **item.dict())
    items_db[item_id] = updated_item
    return updated_item

@app.delete("/items/{item_id}", status_code=status.HTTP_204_NO_CONTENT)
def delete_item(item_id: int):
    if item_id not in items_db:
        raise HTTPException(status_code=404, detail="Item not found")
    del items_db[item_id]
    return None

Step 5: 쿼리 파라미터와 검증

URL 파라미터, 쿼리 파라미터, 요청 본문을 조합하여 복잡한 API를 구현할 수 있습니다.

from fastapi import Query

@app.get("/search/")
def search_items(
    q: str = Query(..., min_length=3, max_length=50),
    min_price: Optional[float] = Query(None, ge=0),
    max_price: Optional[float] = Query(None, ge=0),
    is_active: bool = Query(True)
):
    results = []
    for item in items_db.values():
        if q.lower() in item.name.lower():
            if min_price and item.price < min_price:
                continue
            if max_price and item.price > max_price:
                continue
            if item.is_active != is_active:
                continue
            results.append(item)
    return results

4. 실제 코드 예제와 설명

완전한 예제: 사용자 인증이 포함된 Todo API

실무에서 자주 사용되는 JWT 인증과 데이터베이스 연동을 포함한 완전한 예제입니다.

from fastapi import FastAPI, Depends, HTTPException, status
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
from pydantic import BaseModel
from typing import List, Optional
from datetime import datetime

app = FastAPI()
security = HTTPBearer()

# 데이터 모델
class TodoCreate(BaseModel):
    title: str
    description: Optional[str] = None
    completed: bool = False

class Todo(BaseModel):
    id: int
    title: str
    description: Optional[str]
    completed: bool
    created_at: datetime
    user_id: str

# 간단한 인증 함수
def verify_token(credentials: HTTPAuthorizationCredentials = Depends(security)):
    token = credentials.credentials
    # 실제로는 JWT 검증 로직 구현
    if token != "secret-token":
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Invalid authentication credentials"
        )
    return "user123"  # 실제로는 토큰에서 추출한 user_id

# 임시 데이터베이스
todos_db = {}
todo_id_counter = 1

@app.post("/todos/", response_model=Todo, status_code=status.HTTP_201_CREATED)
def create_todo(
    todo: TodoCreate,
    user_id: str = Depends(verify_token)
):
    global todo_id_counter
    new_todo = Todo(
        id=todo_id_counter,
        **todo.dict(),
        created_at=datetime.now(),
        user_id=user_id
    )
    todos_db[todo_id_counter] = new_todo
    todo_id_counter += 1
    return new_todo

@app.get("/todos/", response_model=List[Todo])
def get_todos(user_id: str = Depends(verify_token)):
    return [todo for todo in todos_db.values() if todo.user_id == user_id]

@app.patch("/todos/{todo_id}/complete")
def complete_todo(
    todo_id: int,
    user_id: str = Depends(verify_token)
):
    if todo_id not in todos_db:
        raise HTTPException(status_code=404, detail="Todo not found")
    todo = todos_db[todo_id]
    if todo.user_id != user_id:
        raise HTTPException(status_code=403, detail="Not authorized")
    todo.completed = True
    return todo

코드 설명:

  • HTTPBearer: Bearer 토큰 인증 스키마 제공
  • Depends: 의존성 주입을 통한 인증 로직 재사용
  • status_code: 명시적인 HTTP 상태 코드 설정
  • HTTPException: 에러 응답 처리

5. 고급 활용 방법

5.1 미들웨어 추가

요청/응답 처리 파이프라인에 로깅, CORS 등을 추가할 수 있습니다.

from fastapi.middleware.cors import CORSMiddleware
import time

app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

@app.middleware("http")
async def add_process_time_header(request, call_next):
    start_time = time.time()
    response = await call_next(request)
    process_time = time.time() - start_time
    response.headers["X-Process-Time"] = str(process_time)
    return response

5.2 백그라운드 태스크

이메일 발송 등 비동기 작업을 백그라운드에서 처리할 수 있습니다.

from fastapi import BackgroundTasks

def send_notification(email: str, message: str):
    # 이메일 발송 로직
    print(f"Sending to {email}: {message}")

@app.post("/notify/")
def create_notification(
    email: str,
    background_tasks: BackgroundTasks
):
    background_tasks.add_task(send_notification, email, "Task created")
    return {"message": "Notification will be sent"}

5.3 데이터베이스 연동

SQLAlchemy를 사용한 실제 데이터베이스 연동 예제입니다.

from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker, Session

DATABASE_URL = "sqlite:///./app.db"
engine = create_engine(DATABASE_URL)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
Base = declarative_base()

class ItemModel(Base):
    __tablename__ = "items"
    id = Column(Integer, primary_key=True, index=True)
    name = Column(String, index=True)
    price = Column(Integer)

def get_db():
    db = SessionLocal()
    try:
        yield db
    finally:
        db.close()

@app.get("/db-items/")
def get_db_items(db: Session = Depends(get_db)):
    return db.query(ItemModel).all()

6. 마무리 및 추가 학습 자료

이 가이드를 통해 FastAPI로 REST API 만들기의 기본부터 고급 기능까지 학습했습니다. FastAPI는 강력하면서도 사용하기 쉬운 프레임워크로, 실무 프로젝트에 바로 적용할 수 있습니다. 다음 단계로는 실제 프로덕션 환경 배포, 테스트 작성, Docker 컨테이너화 등을 학습하는 것을 추천합니다.

추가 학습 자료:

  • 공식 문서: https://fastapi.tiangolo.com/
  • FastAPI GitHub: https://github.com/tiangolo/fastapi
  • Pydantic 문서: https://pydantic-docs.helpmanual.io/
  • SQLAlchemy 튜토리얼: https://docs.sqlalchemy.org/

실습을 통해 배운 내용을 내 프로젝트에 적용해보세요. 작은 API부터 시작하여 점차 복잡한 기능을 추가하면서 실력을 향상시킬 수 있습니다. FastAPI 커뮤니티도 활발하므로 궁금한 점이 있으면 공식 Discord나 GitHub Discussions를 활용하세요!

📚 함께 읽으면 좋은 글

1

FastAPI로 REST API 만들기 – 초보자도 쉽게 따라하는 완벽 가이드

📂 Python 튜토리얼
📅 2025. 10. 1.
🎯 FastAPI로 REST API 만들기

2

FastAPI로 REST API 만들기 – 초보자도 쉽게 따라하는 완벽 가이드

📂 Python 튜토리얼
📅 2025. 9. 30.
🎯 FastAPI로 REST API 만들기

3

Python 자동화 스크립트 작성하기 – 초보자도 쉽게 따라하는 완벽 가이드

📂 Python 튜토리얼
📅 2025. 10. 18.
🎯 Python 자동화 스크립트 작성하기

4

Python 머신러닝 라이브러리 활용법 – 초보자도 쉽게 따라하는 완벽 가이드

📂 Python 튜토리얼
📅 2025. 10. 18.
🎯 Python 머신러닝 라이브러리 활용법

5

Python 웹 스크래핑 완벽 가이드 – 초보자도 쉽게 따라하는 완벽 가이드

📂 Python 튜토리얼
📅 2025. 10. 17.
🎯 Python 웹 스크래핑 완벽 가이드

💡 위 글들을 통해 더 깊이 있는 정보를 얻어보세요!

📢 이 글이 도움되셨나요? 공유해주세요!

여러분의 공유 한 번이 더 많은 사람들에게 도움이 됩니다 ✨

🔥 공유할 때마다 블로그 성장에 큰 힘이 됩니다! 감사합니다 🙏

💬 여러분의 소중한 의견을 들려주세요!

FastAPI로 REST API 만들기에 대한 여러분만의 경험이나 노하우가 있으시나요?

💡
유용한 정보 공유

궁금한 점 질문

🤝
경험담 나누기

👍
의견 표현하기

⭐ 모든 댓글은 24시간 내에 답변드리며, 여러분의 의견이 다른 독자들에게 큰 도움이 됩니다!
🎯 건설적인 의견과 경험 공유를 환영합니다 ✨

🔔 블로그 구독하고 최신 글을 받아보세요!

📚
다양한 주제
17개 카테고리

정기 업데이트
하루 3회 발행

🎯
실용적 정보
바로 적용 가능

💡
최신 트렌드
2025년 기준

🌟 Python 튜토리얼부터 다양한 실생활 정보까지!
매일 새로운 유용한 콘텐츠를 만나보세요 ✨

📧 RSS 구독 | 🔖 북마크 추가 | 📱 모바일 앱 알림 설정
지금 구독하고 놓치는 정보 없이 업데이트 받아보세요!

답글 남기기