프로그래머가 되는 꿈
FastAPI를 사용한 파이썬 웹 개발(CHAPTER 2) 본문

FastAPI를 사용한 파이썬 웹 개발(CHAPTER 2)
2.1 FastAPI의 라우팅 (FastAPI 라우팅(Routing)과 HTTP 메서드 정리)
웹 애플리케이션에서 클라이언트(Client) 는 서버에 HTTP 요청(Request) 을 보내고, 서버는 이에 대한 응답(Response) 을 반환한다.
이때 요청의 목적에 따라 서로 다른 HTTP 메서드를 사용한다.
HTTP 요청 메서드란?
HTTP 메서드는 서버에 어떤 작업을 요청하는지를 나타내는 식별자이며, 상황에 따라 적절한 메서드를 사용해야 한다.
주요 HTTP 메서드는 다음과 같다.
- GET: 데이터 조회
- POST: 새로운 데이터 생성
- PUT: 기존 데이터 생성 또는 수정
- DELETE: 데이터 삭제
(이 외에도 PATCH 등 다양한 메서드가 존재한다.)
라우트(Route)와 라우팅(Routing)
FastAPI에서는 이러한 HTTP 요청을 라우트(Route) 라는 개념으로 관리한다.
- 라우트(Route)
→ “어떤 URL로 어떤 HTTP 메서드 요청이 들어왔을 때, 어떤 함수가 실행될지” 를 정의한 것 - 라우팅(Routing)
→ 들어온 요청을 적절한 라우트와 함수로 연결하는 과정
라우트 처리기(Route Handler)
라우트에는 요청을 실제로 처리하는 함수가 연결된다.
이 함수를 라우트 처리기(Route Handler) 라고 한다.
- 서버로 전달된 요청을 처리하는 함수
- 예: 요청을 받아 데이터베이스에서 특정 데이터를 조회하거나 저장하는 함수
HTTP 메서드별 사용 목적 정리
| GET | 데이터를 읽거나 검색할 때 사용 |
| POST | 새로운 리소스(데이터)를 생성 |
| PUT | 리소스를 생성하거나 수정 |
| DELETE | 지정된 리소스를 삭제 |
FastAPI 라우팅 기본 예제
FastAPI에서는 FastAPI() 인스턴스를 생성하고, 데코레이터를 사용해 라우트를 정의한다.

- / 경로로 GET 요청이 들어오면 welcome() 함수가 실행된다.
- 반환값은 JSON 형태의 응답으로 클라이언트에 전달된다.
서버 실행
FastAPI 애플리케이션은 uvicorn을 통해 실행된다.

- api: 파일 이름
- app: FastAPI 인스턴스
- uvicorn은 하나의 엔트리 포인트만 실행할 수 있다.
FastAPI 인스턴스의 한계
FastAPI() 인스턴스를 직접 사용한 라우팅 방식은
단일 라우트 구조의 간단한 애플리케이션에 적합하다.
- 라우트가 많아질 경우 관리가 어려움
- 하나의 FastAPI 인스턴스만으로는 구조적인 분리가 힘듦
APIRouter를 사용하는 이유
이 문제를 해결하기 위해 FastAPI는 APIRouter 클래스를 제공한다.
- 여러 개의 라우트를 모듈 단위로 분리 가능
- 다중 라우팅 구조 구현 가능
- 코드의 가독성과 유지보수성 향상
📌 개념 정리
- FastAPI 인스턴스: 단일 라우팅을 위한 경로 처리 클래스
- APIRouter 클래스: 다중 라우팅을 위한 경로 처리 클래스
2.2 APIRouter 클래스를 사용한 라우팅 (FastAPI 기본 라우팅과 APIRouter의 필요성)
처음에는 FastAPI() 인스턴스를 사용해 간단한 라우트를 정의했다. 이 방식은 구조가 단순한 애플리케이션에는 적합하지만, 기능이 많아질수록 하나의 파일에 모든 라우트를 작성하는 것은 관리하기 어려워진다.
이 문제를 해결하기 위해 APIRouter 클래스를 사용했다.
- 기능 단위로 라우트를 분리할 수 있음
- 파일 구조가 명확해지고 유지보수가 쉬워짐
- 여러 라우트를 하나의 FastAPI 애플리케이션에 연결 가능
이를 활용해 todo 기능 전용 라우트를 만들고, 메인 애플리케이션에서 include_router()를 사용해 외부로 공개했다.
2.3 pydantic 모델을 사용한 요청 바디 검증 (Pydantic 모델을 활용한 요청 바디 검증 정리)
FastAPI에서는 pydantic 모델을 사용해 요청 바디(Request Body)를 검증(validation) 할 수 있다.
이는 서버로 전달되는 데이터가 정의된 형식과 타입을 따르는지 확인하는 중요한 기능으로, 잘못된 요청이나 악의적인 입력을 사전에 차단하여 서버의 안정성과 보안성을 높여준다.
모델(Model)이란?
FastAPI에서 모델이란 데이터가 어떤 구조로 전달되고 처리되어야 하는지를 정의한 구조화된 클래스를 의미한다.
모델은 모두 pydantic의 BaseModel 클래스를 상속받아 생성된다.
Pydantic이란?
pydantic은 파이썬의 타입 어노테이션(Type Annotation) 을 기반으로 데이터를 검증하는 라이브러리이며, FastAPI에서 클래스를 이용해 요청과 응답 데이터를 다룰 때 핵심적으로 사용된다.
pydantic의 주요 역할은 다음과 같다.
- 데이터 타입 자동 검증
(예: int가 와야 하는 곳에 str이 오면 오류 발생) - 복잡한 데이터 구조를 명확하게 분리하고 관리
타입 어노테이션(Type Annotation)
타입 어노테이션이란 파이썬 코드에서 변수, 함수 인자, 반환 값의 기대되는 데이터 타입을 명시적으로 선언하는 방법이다.
자주 사용하는 타입은 다음과 같다.
- int, str, list, tuple, dict, set, bool
Pydantic 모델 예제

이 모델은 네 개의 필드만 허용하며, 정의되지 않은 필드나 잘못된 타입의 값이 들어오면 자동으로 오류가 발생한다.
기존 방식의 한계
todo 애플리케이션에서 요청 바디를 단순히 dict로 받을 경우 다음과 같은 문제가 있다.

- 빈 딕셔너리를 보내도 오류가 발생하지 않음
- 잘못된 구조의 데이터도 그대로 처리됨
즉, 요청 데이터의 형태를 강제할 수 없다.
Pydantic 모델로 요청 바디 검증하기
요청 바디에 필요한 데이터만 허용하려면 모델을 정의하면 된다.
model.py

이 모델은 다음 두 필드만 허용한다.
- id: 정수형
- item: 문자열형
todo.py

요청 바디의 타입을 dict에서 Todo 모델로 변경하면,
모델에 정의된 구조와 타입이 자동으로 검증된다.
검증 결과
- 필수 필드(id, item)가 누락되면 자동으로 오류 발생
- 타입이 맞지 않으면 요청 자체가 거부됨
- 모델과 일치하는 데이터만 정상 처리됨
이를 통해 의도하지 않은 데이터 처리와 런타임 오류를 미리 방지할 수 있다.
중첩 모델(Nested Model)
pydantic 모델은 모델 안에 또 다른 모델을 포함하는 중첩 구조도 지원한다.

요청 데이터는 다음과 같은 형태가 된다.

정리
pydantic 모델을 사용하면 요청 바디의 구조와 타입을 명확히 제한할 수 있다.
이를 통해 서버의 안정성을 높이고, 잘못된 데이터로 인한 오류를 사전에 방지할 수 있다.
모델은 FastAPI 전반에서 계속 사용되는 핵심 개념이므로 충분히 이해하고 넘어가야 한다.
다음 단계에서는 경로 매개변수(Path Parameter) 와 쿼리 매개변수(Query Parameter) 를 살펴본다.
2.4 경로 매개변수와 쿼리 매개변수 (경로 매개변수와 쿼리 매개변수 이해하기)
CHAPTER 2에서는 특정 데이터를 지정해 조회하는 방법도 함께 다뤘다.
- 경로 매개변수(Path Parameter)
URL 경로 자체에 포함되는 값으로, 특정 리소스를 식별할 때 사용한다.
예를 들어 /todo/1은 ID가 1인 todo를 요청하는 의미다.
FastAPI의 Path 클래스를 사용하면 경로 매개변수에 대한 설명을 추가하고, 값의 범위 검증까지 가능하다. 이 정보는 자동 문서화에도 그대로 반영된다.
- 쿼리 매개변수(Query Parameter)
URL 뒤에 ?를 붙여 전달되는 선택 값으로, 검색이나 필터링 조건에 주로 사용된다.
2.5 요청 바디 (요청 바디와 FastAPI 자동 문서화)
POST나 PUT 요청에서는 요청 바디(Request Body) 를 통해 데이터를 서버로 전달한다. FastAPI는 요청 바디, 라우트 정보, pydantic 모델을 기반으로 API 문서를 자동 생성해준다.
- /docs → Swagger UI
- /redoc → ReDoc
FastAPI 자동 문서화
FastAPI는 모델의 JSON 스키마 정의를 생성하고 라우트, 요청 바디의 유형, 경로 및 쿼리 매개변수, 응답 모델 등을 자동으로 문서화한다. 문서는 다음 두 가지 유형으로 제공된다.
- 스웨거
- ReDoc
스웨거
인터랙티브 문서(사용자가 실행할 수 있는 문서)를 제공하여 API를 테스트할 수 있도록 돕는다.
스웨거 문서를 보려면 애플리케이션 주소의 끝에 /docs를 붙이면 된다.
브라우저를 열고 http://127.0.0.1:8000/docs에 접속하면 아래와 같은 화면을 볼 수 있다.

ReDoc
모델, 라우트, API에 관한 정보를 더 직관적이고 상세하게 전달한다.
애플리케이션 주소 끝에 /redoc을 추가하면 ReDoc 문서를 볼 수 있다.
스웨거 문서와 마찬가지로 브라우저를 열고 http://127.0.0.1:8000/redoc에 접속하면 아래와 같은 화면을 볼 수 있다.

2.6 간단한 CRUD 애플리케이션 개발 (CRUD 기능을 갖춘 todo 애플리케이션 완성)
마지막으로 todo 애플리케이션에 CRUD 기능을 모두 구현했다.
- CREATE: todo 추가
- READ: 전체 조회 및 단일 조회
- UPDATE: todo 내용 수정
- DELETE: todo 삭제
이 과정을 통해 FastAPI에서
- 라우트 정의
- 요청 바디 검증
- 경로 매개변수 처리
- 데이터 수정 및 삭제 흐름
까지 전반적인 API 개발 흐름을 직접 경험할 수 있었다.
---
앞서 todo 아이템을 추가하고 추출할 수 있는 라우트를 만들었다. 이번에는 기존 아이템을 변경하거나 삭제하는 라우트를 추가해볼 것이다. 다음 단계를 따라 실습해보자.
1. UPDATE 라우트의 요청 바디용 모델을 model.py에 추가한다.
class TodoItem(BaseModel):
item: str
class Config:
schema_extra = {
"example":{
"item": "Read the next chapter of the book."
}
}
2. todo를 변경하기 위한 라우트를 todo.py에 추가한다.
from fastapi import APIRouter, Path
from model import Todo, TodoItem
todo_router = APIRouter()
todo_list = []
@todo_router.post("/todo")
async def add_todo(todo: Todo) -> dict:
todo_list.append(todo)
return {
"message": "Todo added successfully."
}
@todo_router.get("/todo")
async def retrieve_todos() -> dict:
return {
"todos": todo_list
}
@todo_router.get("/todo/{todo_id}")
async def get_single_todo(todo_id: int) -> dict:
for todo in todo_list:
if todo.id == todo_id:
return {
"todo": todo
}
return {
"message": "Todo with supplied ID doesn't exist."
}
@todo_router.put("/todo/{todo_id}")
async def update_todo(todo_data: TodoItem, todo_id: int = Path(..., title="The ID of the todo to be updated.")) -> dict:
for todo in todo_list:
if todo.id == todo_id:
todo.item = todo_data.item
return {
"message": "Todo updated successfully."
}
return {
"message": "Todo with supplied ID doesn't exist."
}
3. 새로 추가한 라우트를 테스트해보자. 먼저 신규 todo 아이템을 추가한다.


4. PUT 요청을 보내서 추가한 아이템을 변경해보자.

5. 실제로 아이템이 변경됐는지 확인해보자.


todo 아이템이 성공적으로 변경된 것을 확인할 수 있다.
6. todo.py에 삭제를 위한 DELETE 라우트를 추가해보자.
@todo_router.delete("/todo/{todo_id}")
async def delete_single_todo(todo_id: int) -> dict:
for index in range(len(todo_list)):
todo = todo_list[index]
if todo.id == todo_id:
todo_list.pop(index)
return {
"message": "Todo deleted successfully."
}
return {
"message": "Todo with supplied ID doesn't exist."
}
@todo_router.delete("/todo")
async def delete_all_todo() -> dict:
todo_list.clear()
return {
"message": "Todos deleted successfully."
}
7. 추가한 DELETE 라우트를 테스트해보자. 먼저 신규 todo 아이템을 추가한다.


8. 이제 추가한 todo 아이템을 삭제해보자.


9. GET 요청을 사용해서 삭제한 아이템이 추출되는지 확인해보자.


/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\



[정리하기]
CHAPTER 2를 학습하면서 FastAPI에서 라우팅이 단순히 URL을 연결하는 기능이 아니라, 애플리케이션 전체 구조를 설계하는 핵심 요소라는 것을 느꼈다. 특히 APIRouter를 사용해 라우트를 기능별로 분리하고 메인 FastAPI 인스턴스와 연결하는 과정이 인상적이었고, 실제로 규모가 커질수록 이런 구조가 왜 필요한지도 자연스럽게 이해할 수 있었다.
또한 pydantic 모델을 사용해 요청 바디를 검증하는 과정을 통해, 잘못된 데이터가 서버로 전달되는 것을 사전에 막을 수 있다는 점이 인상 깊었다. 단순히 기능이 동작하는 것에서 끝나는 것이 아니라, 안정성과 신뢰성을 고려한 API 설계의 중요성을 체감할 수 있었다.
마지막으로 경로 매개변수와 쿼리 매개변수를 활용해 CRUD 애플리케이션을 완성하면서, HTTP 메서드와 라우팅, 모델이 서로 어떻게 연결되어 동작하는지 전체 흐름을 이해할 수 있었다. 이번 CHAPTER를 통해 FastAPI로 API를 구현하는 기본 틀을 확실히 잡을 수 있었고, 다음 CHAPTER에서 다룰 응답 처리와 오류 관리에 대한 내용도 더 잘 이해할 수 있을 것이라는 기대가 생겼다.
🌱 배운 점
- FastAPI는 라우팅 + 검증 + 문서화를 하나의 흐름으로 제공한다.
- APIRouter를 활용한 구조화는 유지보수성과 확장성에 매우 중요하다.
- REST API 설계 시 HTTP 메서드의 역할을 명확히 구분해야 한다.
- 자동 문서화는 협업과 테스트 효율을 크게 높여준다.
✨ 정리
본 프로젝트를 통해
FastAPI 기반 백엔드 API의 전체 흐름을 이해하고 직접 구현했으며,
구조적인 라우팅 설계와 데이터 검증의 중요성을 체감할 수 있었다.
이는 이후 캡스톤 프로젝트 및 실무형 백엔드 개발로 확장 가능한 기반이 되었다.
'백엔드 (Back-end)' 카테고리의 다른 글
| FastAPI를 사용한 파이썬 웹 개발(CHAPTER 6) (0) | 2025.12.27 |
|---|---|
| FastAPI를 사용한 파이썬 웹 개발(CHAPTER 5) (0) | 2025.12.20 |
| FastAPI를 사용한 파이썬 웹 개발(CHAPTER 3) (0) | 2025.12.20 |
| FastAPI를 사용한 파이썬 웹 개발(CHAPTER 4) (0) | 2025.12.20 |
| FastAPI를 사용한 파이썬 웹 개발(CHAPTER 1) (1) | 2025.12.20 |