python_fastapi

[FastApi]간단한 Todo 리스트 API 구현

알세지 2024. 5. 28. 01:14

간단한 Todo 리스트 API 구현

1. 프로젝트 설정

필요한 라이브러리 설치

pip install fastapi uvicorn

프로젝트 파일 구조

.
├── main.py
└── requirements.txt

2. FastAPI 서버 코드 작성

main.py 파일 내용

from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from typing import List

app = FastAPI()

class Todo(BaseModel):
    id: int
    title: str
    description: str = None
    completed: bool = False

todos = []

@app.post("/todos/", response_model=Todo)
def create_todo(todo: Todo):
    for t in todos:
        if t.id == todo.id:
            raise HTTPException(status_code=400, detail="Todo with this ID already exists")
    todos.append(todo)
    return todo

@app.get("/todos/", response_model=List[Todo])
def read_todos():
    return todos

@app.delete("/todos/{todo_id}")
def delete_todo(todo_id: int):
    for t in todos:
        if t.id == todo_id:
            todos.remove(t)
            return {"message": "Todo deleted successfully"}
    raise HTTPException(status_code=404, detail="Todo not found")

3. FastAPI 서버 실행

uvicorn main:app --reload

4. 발생한 문제와 해결 방법

문제 1: 404 Not Found

  • 원인: 브라우저에서 http://127.0.0.1:8000으로 접속하면 기본 경로("/")에 대한 처리가 없기 때문입니다.
  • 해결 방법: 기본 경로("/")에 HTML 파일을 제공하도록 설정.

문제 2: CORS (Cross-Origin Resource Sharing)

  • 원인: file:/// 프로토콜을 사용하여 로컬 파일을 열 때 CORS 정책에 의해 교차 출원 요청이 차단됨.
  • 해결 방법: FastAPI 서버에 CORS 설정을 추가하여 CORS 문제 해결.
from fastapi.middleware.cors import CORSMiddleware

app = FastAPI()

origins = [
    "http://localhost",
    "http://127.0.0.1:8000"
]

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

문제 3: OPTIONS /todos/ HTTP/1.1 405 Method Not Allowed

  • 원인: 브라우저가 CORS 프리플라이트 요청을 보내는데 서버에서 이를 처리하지 않아서 발생.
  • 해결 방법: CORS 설정 추가로 해결.

문제 4: HTML 파일을 file:/// 프로토콜로 열 때 CORS 문제

  • 원인: 로컬 파일을 직접 열 때 CORS 정책에 의해 API 요청이 차단됨.
  • 해결 방법: FastAPI 서버에서 HTML 파일을 제공하도록 설정.
@app.get("/", response_class=HTMLResponse)
def read_root():
    with open("index.html") as f:
        return HTMLResponse(content=f.read(), status_code=200)

5. HTML 파일 작성

index.html 파일 내용

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Todo List</title>
</head>
<body>
    <h1>Todo List</h1>
    <form id="todo-form">
        <label for="id">ID:</label><br>
        <input type="number" id="id" name="id" required><br>
        <label for="title">Title:</label><br>
        <input type="text" id="title" name="title" required><br>
        <label for="description">Description:</label><br>
        <input type="text" id="description" name="description"><br>
        <label for="completed">Completed:</label><br>
        <input type="checkbox" id="completed" name="completed"><br><br>
        <input type="submit" value="Add Todo">
    </form>

    <script>
        document.getElementById('todo-form').addEventListener('submit', async function(event) {
            event.preventDefault();

            const id = document.getElementById('id').value;
            const title = document.getElementById('title').value;
            const description = document.getElementById('description').value;
            const completed = document.getElementById('completed').checked;

            const todo = {
                id: parseInt(id),
                title: title,
                description: description,
                completed: completed
            };

            try {
                const response = await fetch('http://127.0.0.1:8000/todos/', {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json'
                    },
                    body: JSON.stringify(todo)
                });

                if (!response.ok) {
                    throw new Error('Network response was not ok');
                }

                const data = await response.json();
                console.log('Todo added:', data);
            } catch (error) {
                console.error('There was a problem with the fetch operation:', error);
            }
        });
    </script>
</body>
</html>

6. 결과 확인

브라우저에서 http://127.0.0.1:8000으로 접속하여 할 일을 추가하고, API가 제대로 작동하는지 확인합니다.


이와 같이 간단한 Todo 리스트 API를 FastAPI로 구현하고, 발생한 문제들을 해결하였습니다. 추가적인 문제가 발생하거나 다른 기능을 구현하고 싶다면 언제든지 말씀해 주세요! 다음 문제로 진행할 준비가 되시면 알려주세요.