FastAPI 서버개발, FastAPI 애플리케이션 구조화, 이벤트 플래너 애플리케이션 개발

FastAPI는 Python으로 작성된 현대적인 웹 프레임워크로, 빠르고 효율적인 API를 구축하는 데 최적화되어 있습니다. 이 글에서는 FastAPI를 사용해 간단한 이벤트 플래너 애플리케이션을 개발하는 과정을 상세히 설명하겠습니다. 이 과정은 FastAPI 서버의 구조화, RESTful API 설계, 데이터베이스 연동, 인증 및 권한 부여 등을 포함합니다.

FastAPI 소개

FastAPI는 다음과 같은 특징을 가지고 있습니다:

  • ⚡ 신속한 성능: Starlette로 구축된 비동기 기반이므로 매우 빠릅니다.
  • 🔄 자동 문서화: Swagger UI와 ReDoc을 사용하여 API 문서를 자동 생성합니다.
  • 📦 타입 힌팅: Python 타입 힌트를 사용하여 코드 품질과 가독성을 높입니다.
  • 🔒 보안 & 인증: OAuth2와 JWT를 통해 강력한 인증과 인가 기능을 제공합니다.

환경 설정

FastAPI 애플리케이션을 개발하기 위해 필요한 기본 환경을 설정해보겠습니다. 먼저, FastAPI와 Uvicorn을 설치해야 합니다.

pip install fastapi uvicorn

프로젝트 구조화

이벤트 플래너 애플리케이션의 코드를 구조화하는 방법은 다음과 같습니다:


event_planner/
├── app/
│   ├── main.py
│   ├── models.py
│   ├── schemas.py
│   ├── database.py
│   └── routes/
│       └── events.py
└── requirements.txt

1. main.py

FastAPI 애플리케이션의 엔트리 포인트인 main.py 파일에서는 FastAPI 인스턴스를 생성하고, 중간웨어 및 라우터를 설정합니다.

from fastapi import FastAPI
from .routes import events

app = FastAPI()

@app.get("/")
async def read_root():
    return {"message": "이벤트 플래너 API에 오신 것을 환영합니다!"}

app.include_router(events.router)

2. models.py

models.py 파일은 SQLAlchemy 데이터 모델을 정의합니다. 이벤트 플래너 애플리케이션에서는 이벤트에 대한 기본적인 모델을 설정합니다.

from sqlalchemy import Column, Integer, String
from .database import Base

class Event(Base):
    __tablename__ = "events"
    
    id = Column(Integer, primary_key=True, index=True)
    title = Column(String, index=True)
    description = Column(String)
    location = Column(String)
    time = Column(String)

3. schemas.py

schemas.py에서는 Pydantic을 사용하여 데이터 검증 및 직렬화를 합니다. 이 파일은 API의 요청 바디와 응답 모델을 정의합니다.

from pydantic import BaseModel

class EventBase(BaseModel):
    title: str
    description: str
    location: str
    time: str

class EventCreate(EventBase):
    pass

class Event(EventBase):
    id: int

    class Config:
        orm_mode = True

4. database.py

database.py에서는 데이터베이스 연결을 설정하고 세션을 관리합니다. SQLAlchemy를 통한 데이터베이스 설정을 진행합니다.

from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker

SQLALCHEMY_DATABASE_URL = "sqlite:///./events.db"

engine = create_engine(SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False})
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)

Base = declarative_base()

5. routes/events.py

이벤트 관련 API 엔드포인트를 담당하는 events.py 파일에서는 CRUD 기능을 작성합니다.

from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.orm import Session
from .. import models, schemas
from ..database import SessionLocal

router = APIRouter()

# 의존성 주입을 위한 함수
def get_db():
    db = SessionLocal()
    try:
        yield db
    finally:
        db.close()

@router.post("/events/", response_model=schemas.Event)
async def create_event(event: schemas.EventCreate, db: Session = Depends(get_db)):
    db_event = models.Event(**event.dict())
    db.add(db_event)
    db.commit()
    db.refresh(db_event)
    return db_event

@router.get("/events/{event_id}", response_model=schemas.Event)
async def read_event(event_id: int, db: Session = Depends(get_db)):
    db_event = db.query(models.Event).filter(models.Event.id == event_id).first()
    if db_event is None:
        raise HTTPException(status_code=404, detail="이벤트를 찾을 수 없습니다.")
    return db_event

@router.get("/events/", response_model=list[schemas.Event])
async def read_events(skip: int = 0, limit: int = 10, db: Session = Depends(get_db)):
    events = db.query(models.Event).offset(skip).limit(limit).all()
    return events

FastAPI 애플리케이션 실행

모든 설정이 완료되면 Uvicorn을 통해 애플리케이션을 실행할 수 있습니다.

uvicorn app.main:app --reload

브라우저에서 http://127.0.0.1:8000/docs를 열어 자동 생성된 API 문서와 Swagger UI를 확인하며 API를 테스트할 수 있습니다.

데이터베이스 설정

SQLite 데이터베이스를 사용할 경우, 데이터베이스를 초기화하고 테이블을 생성해야 합니다. 다음 코드를 main.py에 추가하여 처음 실행할 때 테이블을 생성합니다.

from fastapi import FastAPI
from .database import engine, Base

# DB 초기화
Base.metadata.create_all(bind=engine)

인증 및 권한 부여

이번 애플리케이션에서는 간단한 사용자 인증을 추가할 수 있습니다. FastAPI는 OAuth2와 JWT를 지원하므로, 이를 이용해 보호된 엔드포인트를 만들 수 있습니다. 예를 들어, 이벤트 삭제 엔드포인트에 인증을 추가하는 방식으로 접근할 수 있습니다.

from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
from fastapi import Depends
from .. import models, schemas
import bcrypt

oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")

def fake_hash_password(password: str):
    return "fakehashed" + password

@router.post("/token")
async def login(form_data: OAuth2PasswordRequestForm = Depends()):
    user = db.query(models.User).filter(models.User.username == form_data.username).first()
    if not user or not bcrypt.checkpw(form_data.password.encode('utf-8'), user.hashed_password.encode('utf-8')):
        raise HTTPException(status_code=400, detail="잘못된 사용자명 또는 비밀번호")
    return {"access_token": user.username, "token_type": "bearer"}

결론

이러한 단계를 통해 FastAPI와 SQLAlchemy를 활용하여 이벤트 플래너 애플리케이션의 기본 구조를 설정했습니다. 이 애플리케이션에서 더 발전된 기능을 추가해보며 FastAPI의 다양한 특징을 경험할 수 있습니다. FastAPI의 문서화와 비동기 처리가 효율적이기 때문에, 복잡한 웹 애플리케이션 개발의 도전 과제를 쉽게 극복할 수 있습니다. 이 프로젝트를 통해 FastAPI의 실제 사용 사례를 접해보길 바랍니다!