Skip to main content

Python FastAPI로 TodoApp API 만들기

오늘은 ChatGPT와 함께 Python FastAPI로 TodoApp API 만들기를 한번 해보겠습니다. 참고로 FastAPI 공식가이드도 첨부 합니다. 모르는 부분이나 TodoApp 외 궁금한 부분들은 공식 문서를 참고 하시기 바랍니다.

먼저 ChatGPT에게 아래와 같이 Python FastAPI로 TodoApp API를 만들어 달라고 요청 합니다.

ChatGPT프롬프트
I’m trying to build a simple todo webapp api, give me step by step instruction with code example
1) including init project, setup database
2) teck stack: python fastapi, sqlalchmey, mysql
3) features: list, add, update, delete

아래와 같이 ChatGPT가 답변을 해줍니다. 참고로 답변은 프롬프트 지니를 통해 번역된 결과 입니다.

먼저 아래와 같이 Python FastAPI로 TodoApp API 작성 하는 과정과 코드를 잘 설명해주고 있습니다. Python FastAPI로 TodoApp API 만들기 ChatGPT 답변 그리고 아래와 같이 폴더 구조까지 잘 설명해주고 있습니다. Python FastAPI로 TodoApp API 만들기 폴더 구조

그럼 ChatGPT 답변 내용을 가지고 FastAPI, SQLAlchemy 및 MySQL을 사용하여 간단한 ToDo API를 만들어보도록 하겠습니다.

1. 프로젝트를 초기화하고 종속성을 설치합니다.

프로젝트를 위한 새 디렉터리를 만들고 해당 디렉터리로 이동합니다.

mkdir todo-api
cd todo-api

가상 환경 생성 및 활성화:

python -m venv venv
source venv/bin/activate # On Windows, use `venv\Scripts\activate`

FastAPI, Uvicorn(ASGI 서버), SQLAlchemy 및 MySQL 커넥터를 설치합니다.

pip install fastapi uvicorn sqlalchemy pymysql

2. 데이터베이스를 설정합니다.

todo_db라는 이름의 MySQL 데이터베이스와 데이터베이스에 대한 액세스 권한이 있는 사용자를 생성합니다. 나중에 사용할 수 있도록 사용자 이름과 암호를 기억하십시오.

3. 프로젝트 구조를 생성합니다.

todo-api 디렉토리 안에 다음 파일과 폴더를 생성합니다.

.
├── app
│ ├── __init__.py
│ ├── main.py
│ ├── models.py
│ ├── schemas.py
│ └── crud.py
└── .env

4. 데이터베이스 액세스 구성:

.env 파일을 열고 다음을 추가합니다(username, password 및 hostname을 MySQL 자격 증명으로 대체).

DATABASE_URL=mysql+pymysql://username:password@hostname/todo_db

4. 데이터베이스 연결을 설정합니다.

app/init.py에서 다음 코드를 추가하여 .env 파일을 로드하고 데이터베이스 연결을 설정합니다.

app/__init__.py
from dotenv import load_dotenv
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
import os

load_dotenv()

DATABASE_URL = os.getenv("DATABASE_URL")
engine = create_engine(DATABASE_URL)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)

Base = declarative_base()

[참고] dotenv를 설치하지 않았다면 다음과 같이 설치합니다.

pip install python-dotenv

5. 모델, 스키마 및 CRUD 기능을 정의합니다.

app/models.py에서:

app/models.py
from . import Base
from sqlalchemy import Column, Integer, String, Boolean

class ToDoItem(Base):
__tablename__ = "todo_items"

id = Column(Integer, primary_key=True, index=True)
title = Column(String, index=True)
completed = Column(Boolean, default=False)

app/schemas.py에서:

app/schemas.py
from pydantic import BaseModel

class ToDoItemBase(BaseModel):
title: str
completed: bool

class ToDoItemCreate(ToDoItemBase):
pass

class ToDoItemUpdate(ToDoItemBase):
pass

class ToDoItem(ToDoItemBase):
id: int

class Config:
orm_mode = True

app/crud.py에서:

app/crud.py
from . import SessionLocal
from .models import ToDoItem
from .schemas import ToDoItemCreate, ToDoItemUpdate
from sqlalchemy.orm import Session

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

def get_todo_items(db: Session):
return db.query(ToDoItem).all()

def create_todo_item(db: Session, item: ToDoItemCreate):
new_item = ToDoItem(**item.dict())
db.add(new_item)
db.commit()
db.refresh(new_item)
return new_item

def update_todo_item(db: Session, item_id: int, item: ToDoItemUpdate):
db_item = db.query(ToDoItem).filter(ToDoItem.id == item_id).one()
for key, value in item.dict().items():
setattr(db_item, key, value)
db.commit()

def delete_todo_item(db: Session, item_id: int):
db_item = db.query(ToDoItem).filter(ToDoItem.id == item_id).one()
db.delete(db_item)
db.commit()

def get_todo_item(db: Session, item_id: int):
return db.query(ToDoItem).filter(ToDoItem.id == item_id).one()
  1. FastAPI 경로 설정:

app/main.py에서:

app/main.py
from fastapi import FastAPI, HTTPException, Depends
from .schemas import ToDoItem, ToDoItemCreate, ToDoItemUpdate
from .crud import get_db, get_todo_items, create_todo_item, update_todo_item, delete_todo_item, get_todo_item
from sqlalchemy.orm import Session

app = FastAPI()

@app.get("/todo/", response_model=list[ToDoItem])
def list_todo_items(db: Session = Depends(get_db)):
return get_todo_items(db)

@app.post("/todo/", response_model=ToDoItem)
def add_todo_item(item: ToDoItemCreate, db: Session = Depends(get_db)):
return create_todo_item(db, item)

@app.get("/todo/{item_id}", response_model=ToDoItem)
def read_todo_item(item_id: int, db: Session = Depends(get_db)):
item = get_todo_item(db, item_id)
if item is None:
raise HTTPException(status_code=404, detail="Item not found")
return item

@app.put("/todo/{item_id}", response_model=ToDoItem)
def update_todo_item(item_id: int, item: ToDoItemUpdate, db: Session = Depends(get_db)):
db_item = get_todo_item(db, item_id)
if db_item is None:
raise HTTPException(status_code=404, detail="Item not found")
return update_todo_item(db, item_id, item)

@app.delete("/todo/{item_id}")
def delete_todo_item(item_id: int, db: Session = Depends(get_db)):
db_item = get_todo_item(db, item_id)
if db_item is None:
raise HTTPException(status_code=404, detail="Item not found")
delete_todo_item(db, item_id)
return {"detail": "Item deleted successfully"}

8. 애플리케이션 생성 및 실행

앱을 실행하기 전에 다음 Python 스크립트를 실행하여 데이터베이스 테이블을 초기화해야 합니다.

init_db.py
from app import Base, engine
from app.models import ToDoItem
Base.metadata.create_all(bind=engine)

이제 다음을 명령을 사용하여 ToDo 웹앱 API를 실행할 수 있습니다.

$ uvicorn app.main:app --reload

또한 아래와 같이 FastAPI Swagger UI 기반의 API문서도 http://127.0.0.1:8000/docs 에서 확인 할수 있습니다.

Python FastAPI로 TodoApp API 개발 문서

서버 코드이다보니 TodoApp 페이지 작성 보다는 복잡한 과정이 있었는데요 개발 과정 들을 잘 설명 해주고 돌아가는 수준의 코드 작성 까지 잘 해주었던것 같습니다.

9. Trouble Shooting 과정

참고로 ChatGPT가 알려주었던 내용에서 동작 하지 않아 수정하였던 부분들도 정리를 해보았습니다. 잘 안될때 시도 하기에 좋은 방법이니 참고 하시면 좋을것 같습니다.

1) init_db.py 수정 하시

먼저 init_db.py에서 table을 생성 해주지 않았습니다. 그래서 아래와 같이 ChatGPT에게 요청을 해보았습니다.

ChatGPT프롬프트
init_db.py didn't create table with model file with above example.

아래와 같이 누락된게 있다고 설명을 잘 해주네요 Python FastAPI로 TodoApp API 만들기 Trouble Shooting 1

2) python init_db.py 오류 발생 해결

위의 가이드 대로 수정하고 돌렸더니 아래와 같은 오류가 발생을 했습니다.

sqlalchemy.exc.CompileError: (in table 'todo_items', column 'title'): VARCHAR requires a length on dialect mysql

그래서 아래와 같이 ChatGPT에게 오류 내용을 전달 해보았습니다.

ChatGPT프롬프트
(in table 'todo_items', column 'title'): VARCHAR requires a length on dialect mysql

아래와 같이 ChatGPT가 답변을 해주었습니다. Python FastAPI로 TodoApp API 만들기 Trouble Shooting 2

10. 마치며

이렇게 간단한 Python FastAPI로 TodoApp API를 만들어보았는데 도움이 되셨나요? 다음번에는 오늘 만든 API를 가지고 간단하게 AWS 인프라를 구축해보는 방법을 정리 해보도록 하겠습니다.

참고로 완성된 소스 코드는 아래 GitHub 링크에서 확인 하실수 있습니다.