현대의 웹 애플리케이션 개발에서는 효율적이고, 반응성이 뛰어난 API 서버가 필수적입니다. FastAPI는 Python으로 작성된 빠르고 현대적인 웹 프레임워크로, 빠른 개발과 높은 성능을 자랑합니다. 이 글에서는 FastAPI를 사용하여 백엔드 서버를 구축하고, 데이터베이스를 조작하며, Done 리소스를 구현하는 방법에 대해 자세히 설명하겠습니다.
1. FastAPI란?
FastAPI는 Pydantic과 Starlette을 기반으로 한 고성능 웹 프레임워크로, Python에서 API를 구축하기 위한 최적의 선택입니다. FastAPI의 주요 특징은 다음과 같습니다:
- 자동 문서화: OpenAPI 및 Swagger UI를 사용하여 API 문서화를 자동으로 제공합니다.
- 타입 검사: Python 타입 힌트를 사용하여 코드의 가독성을 높이고 런타임 오류를 줄입니다.
- 비동기 지원: 비동기 프로그래밍을 지원하여 높은 성능을 발휘합니다.
- 유연성: RESTful API, GraphQL 등 다양한 API 디자인을 지원합니다.
2. FastAPI 설치하기
FastAPI를 사용하기 위해 먼저 FastAPI와 서버를 구동할 수 있는 Uvicorn을 설치합니다. 아래 명령어를 사용하여 설치할 수 있습니다:
pip install fastapi uvicorn
3. FastAPI 기본 구조
FastAPI 서버의 기본 구조는 다음과 같습니다. 아래 코드는 간단한 “Hello, World!” API를 구현한 예시입니다.
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
async def read_root():
return {"message": "Hello, World!"}
위의 코드를 main.py
라는 파일에 저장한 후, 다음 명령어로 서버를 실행할 수 있습니다:
uvicorn main:app --reload
서버가 실행되면 http://127.0.0.1:8000/로 접속하여 결과를 확인할 수 있습니다.
4. 데이터베이스 연결하기
이제 FastAPI와 데이터베이스를 연결해보겠습니다. 이번 예제에서는 SQLite 데이터베이스를 사용하여 Todo 리스트를 관리할 것입니다. 먼저, SQLAlchemy
와 databases
패키지를 설치합니다.
pip install sqlalchemy databases
4.1 데이터베이스 모델 정의하기
데이터베이스 모델을 정의하기 위해 SQLAlchemy의 ORM을 사용합니다. 아래는 Todo 모델을 정의하는 예시입니다.
from sqlalchemy import create_engine, Column, Integer, String, Boolean
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
DATABASE_URL = "sqlite:///./test.db"
engine = create_engine(DATABASE_URL)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
Base = declarative_base()
class Todo(Base):
__tablename__ = "todos"
id = Column(Integer, primary_key=True, index=True)
title = Column(String, index=True)
completed = Column(Boolean, default=False)
4.2 데이터베이스 초기화
데이터베이스를 초기화하기 위해 아래와 같은 코드를 추가합니다.
def init_db():
Base.metadata.create_all(bind=engine)
init_db()
5. CRUD 엔드포인트 구현하기
이제 Todo 리스트를 관리하기 위한 CRUD(Create, Read, Update, Delete) 엔드포인트를 구현하겠습니다.
5.1 Todo 생성하기
from fastapi import Depends, FastAPI
from sqlalchemy.orm import Session
app = FastAPI()
def get_db():
db = SessionLocal()
try:
yield db
finally:
db.close()
@app.post("/todos/", response_model=Todo)
async def create_todo(todo: Todo, db: Session = Depends(get_db)):
db.add(todo)
db.commit()
db.refresh(todo)
return todo
5.2 Todo 목록 조회하기
@app.get("/todos/", response_model=List[Todo])
async def read_todos(skip: int = 0, limit: int = 10, db: Session = Depends(get_db)):
todos = db.query(Todo).offset(skip).limit(limit).all()
return todos
5.3 Todo 수정하기
@app.put("/todos/{todo_id}", response_model=Todo)
async def update_todo(todo_id: int, todo: Todo, db: Session = Depends(get_db)):
todo_instance = db.query(Todo).filter(Todo.id == todo_id).first()
if todo_instance is None:
raise HTTPException(status_code=404, detail="Todo not found")
todo_instance.title = todo.title
todo_instance.completed = todo.completed
db.commit()
db.refresh(todo_instance)
return todo_instance
5.4 Todo 삭제하기
@app.delete("/todos/{todo_id}")
async def delete_todo(todo_id: int, db: Session = Depends(get_db)):
todo_instance = db.query(Todo).filter(Todo.id == todo_id).first()
if todo_instance is None:
raise HTTPException(status_code=404, detail="Todo not found")
db.delete(todo_instance)
db.commit()
return {"detail": "Todo deleted"}
6. Done 리소스 구현하기
이번에는 완료된 Todo를 관리하는 Done 리소스를 구현해보겠습니다. 아래와 같이 새로운 엔드포인트를 추가합니다.
6.1 Done 목록 조회하기
@app.get("/done/", response_model=List[Todo])
async def read_done_todos(db: Session = Depends(get_db)):
done_todos = db.query(Todo).filter(Todo.completed == True).all()
return done_todos
7. 클라이언트 테스트하기
이제 Postman 등의 클라이언트를 사용하여 엔드포인트를 테스트해볼 수 있습니다. 아래는 각 엔드포인트에 대한 간단한 테스트 예시입니다.
- POST /todos/: 새로운 Todo를 생성합니다.
- GET /todos/: 모든 Todo 목록을 조회합니다.
- PUT /todos/{todo_id}: 특정 Todo의 내용을 수정합니다.
- DELETE /todos/{todo_id}: 특정 Todo를 삭제합니다.
- GET /done/: 완료된 Todo 목록을 조회합니다.
8. 결론
이 글에서는 FastAPI를 사용하여 기본적인 CRUD API를 구축하고, 데이터베이스를 조작하는 방법에 대해 알아보았습니다. FastAPI는 간결한 문법과 뛰어난 성능으로 인해 현대 웹 애플리케이션 개발에 많은 도움이 됩니다. 더 나아가 부가적인 기능(예: JWT 인증, CORS 처리 등)을 추가하여 강력한 API 서버를 만들 수 있습니다.
FastAPI를 통해 여러분의 프로젝트에 더 많은 기능과 서비스를 추가해 보세요. Happy coding!