파이썬 FastAPI 실전 프로젝트 구현 (2) – 기능 보완 및 마무리
여러분, 프로젝트 마무리할 때 뭔가 찝찝하게 끝낸 적 있으시죠?
이번에는 FastAPI로 만든 API를 제대로 다듬고,
진짜 ‘완성된’ 느낌을 만들어봐요!
안녕하세요, 개발자 여러분 😊
드디어 FastAPI 실전 프로젝트의 마지막 단계에 도달했습니다.
앞서 API를 설계하고 기본적인 CRUD 기능을 구현했지만, 사실 프로젝트가 ‘완성됐다’고 말하기 위해서는 몇 가지 마무리 작업이 꼭 필요하죠.
예를 들어 빠진 기능을 채우거나, 리팩토링을 통해 코드 품질을 끌어올리고, 전체 테스트를 통해 문제가 없는지 꼼꼼히 검증하는 과정 말이에요.
이번 글에서는 Update/Delete API 구현, 리팩토링, 테스트 마무리, 추가 기능 구현까지 포함해서, 진짜 실전에 가까운 프로젝트 완성 과정을 함께 해볼 거예요.
이제 진짜 개발자 포트폴리오에 올릴 수 있는 API를 만들어볼 준비되셨나요? 😎 그럼 시작해볼게요!
목차
1. CRUD 기능 보완: Update/Delete 엔드포인트 구현 🛠️
1.1 글(Post) 및 할일(Todo) 수정 API 구현
이제 남은 CRUD 기능 중 '수정(Update)' 엔드포인트부터 완성해볼 차례입니다.
블로그 API와 Todo API 모두에 해당하는 기능으로, RESTful한 방식에 따라 PUT
메서드를 사용합니다.
FastAPI에서는 @router.put("/posts/{id}")
형식으로 경로를 선언하고, 입력 데이터는 schemas.PostUpdate
같은 Pydantic 모델을 사용해 받습니다.
- 수정 대상이 존재하지 않으면 404 Not Found
- 성공 시에는 수정된 객체를 JSON으로 반환
- 인증 기능이 있다면 작성자만 수정 가능하게 조건을 걸 수 있음 (지금은 생략)
예시 코드
@router.put("/posts/{id}")
def update_post(id: int, post_update: PostUpdate, db: Session = Depends(get_db)):
post = db.query(Post).filter(Post.id == id).first()
if not post:
raise HTTPException(status_code=404, detail="Post not found")
post.title = post_update.title
post.content = post_update.content
db.commit()
db.refresh(post)
return post
1.2 삭제(Delete) API 구현
삭제 기능은 프로젝트의 정돈을 위해 반드시 필요한 부분이에요.
블로그의 경우 글 삭제, Todo의 경우 할일 삭제가 이에 해당합니다.
완전 삭제 방식으로 구현하되, 보안이나 감사 로그가 필요한 경우에는 Soft Delete 방식도 고민해볼 수 있어요.
예시 코드
@router.delete("/todos/{id}", status_code=204)
def delete_todo(id: int, db: Session = Depends(get_db)):
todo = db.query(Todo).filter(Todo.id == id).first()
if not todo:
raise HTTPException(status_code=404, detail="Todo not found")
db.delete(todo)
db.commit()
return Response(status_code=204)
1.3 마무리 요약
- PUT 메서드로 수정 API를 추가한다.
- DELETE 메서드로 삭제 API를 완성한다.
- 없는 리소스에 접근 시 404 예외 처리를 꼼꼼히 해준다.
이제 CRUD의 4가지 기본 기능이 완성됐습니다.
이 다음은 조금 더 재미있는(?) 추가 기능 구현 시간입니다!
2. 주제별 추가 기능과 쿼리 개선 🎯
2.1 블로그 API – 사용자별 글 목록 및 검색 기능
블로그 API에선 기본적인 CRUD 외에도, 사용자별 글 목록이나 검색 기능처럼 실전에서 많이 쓰는 기능을 추가해보면 실력이 쑥쑥 자랍니다.
-
GET /users/{user_id}/posts
– 특정 유저가 작성한 글만 필터링 -
GET /posts?search=키워드
– 제목/내용에 포함된 키워드로 검색
쿼리 필터 예시
@router.get("/posts")
def list_posts(search: str = None, db: Session = Depends(get_db)):
query = db.query(Post)
if search:
query = query.filter(Post.title.contains(search))
return query.all()
2.2 Todo API – 완료 여부 필터링 및 정렬
Todo API에선 할 일의 완료 상태나 우선순위 정렬 기능을 추가하면 사용성이 훨씬 높아져요.
-
GET /todos?completed=true
– 완료된 항목만 필터링 -
GET /todos?sort=priority
– 우선순위 오름차순 정렬
정렬 필터 예시
@router.get("/todos")
def get_todos(completed: bool = None, sort: str = None, db: Session = Depends(get_db)):
query = db.query(Todo)
if completed is not None:
query = query.filter(Todo.done == completed)
if sort == "priority":
query = query.order_by(Todo.priority.asc())
return query.all()
2.3 마무리 팁 💡
이런 기능은 구현해보면 어렵지 않지만, 실제 API 사용 경험을 엄청나게 향상시켜줍니다.
쿼리 파라미터와 동적 필터링은 FastAPI와 SQLAlchemy를 익히는 데 정말 좋은 연습이 돼요!
꼭 필요한 핵심 기능 외에도 사용자가 편리하게 쓸 수 있는 부가 기능 몇 개만 추가해도, 프로젝트의 깊이가 확 달라진다는 거 잊지 마세요 😉
3. 코드 리팩토링과 공통 모듈 정리 📦
3.1 중복 로직 정리: get_object_or_404
FastAPI로 프로젝트를 하다 보면, 가장 자주 반복되는 패턴 중 하나가 바로 이거예요.
query.first()
로 객체를 가져오고 없으면 HTTPException(404)
을 던지는 코드!
매번 반복하지 말고, 다음과 같이 공통 헬퍼 함수로 만들어두면 가독성과 유지보수성이 확 올라갑니다.
def get_object_or_404(query, model_name: str = "Object"):
obj = query.first()
if not obj:
raise HTTPException(status_code=404, detail=f"{model_name} not found")
return obj
이제 이렇게 쓰면 됩니다:
post = get_object_or_404(db.query(Post).filter(Post.id == id), "Post")
3.2 인증/권한 검사 공통화
만약 로그인 인증 기능이 있다면, API마다 인증 정보를 검사하는 코드도 반복됩니다.
FastAPI는 Depends()를 이용해 공통 처리할 수 있어요.
def get_current_user(token: str = Depends(oauth2_scheme)):
payload = decode_token(token)
user = db.query(User).filter(User.id == payload["sub"]).first()
if not user:
raise HTTPException(status_code=401, detail="Invalid credentials")
return user
라우터에서는 이렇게 간단히 호출하면 되죠:
@router.get("/me/posts")
def my_posts(current_user: User = Depends(get_current_user)):
return current_user.posts
3.3 Swagger 문서화 향상
Swagger UI를 더 보기 좋게 꾸미고 싶다면, Pydantic 모델에 description
필드를 넣는 게 좋아요.
이게 곧 API 문서가 되거든요.
class PostCreate(BaseModel):
title: str = Field(..., description="게시글 제목")
content: str = Field(..., description="게시글 본문")
이렇게 하면 Swagger에서 각 필드 설명이 뜨고, 사용자나 동료 개발자에게도 친절한 API가 됩니다. 🧾
3.4 디버그 흔적 제거
그리고 가장 중요한 마무리 습관!
print
같은 디버깅 코드는 모두 제거해주세요.
콘솔에 찍히는 메시지는 실서비스에서 보안 위험이 될 수도 있고, 로그 관리도 어려워지니까요.
- print() 제거
- 테스트용 더미 코드 제거
깔끔한 코드는 실력의 증거입니다.
동료도, 미래의 나도 기뻐할 거예요. 😉
4. Swagger 기반 수동 테스트 🧪
4.1 Swagger UI에서 테스트 시나리오 따라가기
FastAPI의 강력한 무기 중 하나는 바로 자동 생성 API 문서, Swagger UI죠!
개발한 모든 엔드포인트를 웹 UI로 손쉽게 테스트할 수 있다는 점에서, 이건 정말 필수 기능이에요.
테스트를 시작할 땐, 가능한 실제 사용자 시나리오 기반으로 순서대로 실행해보는 게 좋아요.
예를 들어:
- 1️⃣ 사용자 생성 (POST /users)
- 2️⃣ 로그인 (만약 구현했다면)
- 3️⃣ 글 or 할일 생성
- 4️⃣ 목록 조회
- 5️⃣ 글/할일 수정
- 6️⃣ 삭제 요청
- 7️⃣ 삭제 후 목록 재조회
4.2 예외 상황도 꼭 테스트해보자!
정상 흐름만 테스트하면 부족해요.
진짜 완성도 높은 API는 경계 상황까지 잘 처리하는 경우죠.
꼭 체크해야 할 케이스 리스트 ✔️
- 존재하지 않는 ID로 요청했을 때 →
404 Not Found
잘 반환되는가? - 필수 값이 빠진 입력 →
422 Unprocessable Entity
나오는가? - 중복된 값 입력 → 에러 메시지가 친절한가?
이런 테스트는 Swagger UI에서 직접 해볼 수도 있지만, Postman이나 curl 같은 도구로 해보는 것도 좋은 연습이에요.
다양한 환경에서 동일한 API가 잘 작동하는지 확인할 수 있거든요.
4.3 마무리하며
직접 테스트해보면서 API 동작을 확인하는 건, 말 그대로 ‘현장감 있는 검증’입니다.
직접 손으로 다뤄보는 만큼, 놓쳤던 버그도 쉽게 발견되죠.
이제 우리 프로젝트도 한 단계 성숙해졌네요.
다음은 자동화 테스트로 더 철저하게 완성도를 높이는 시간입니다! 😎
5. pytest를 활용한 자동화 테스트 🔍
5.1 pytest 기본 구조와 테스트 함수 작성
FastAPI 프로젝트에선 pytest를 사용해 자동화 테스트를 작성하는 게 표준입니다.
기능 하나하나를 수동으로 확인할 수는 없으니, 테스트 코드를 작성해두면 나중에 기능을 수정하거나 리팩토링해도 안정성을 체크할 수 있어요.
예시 테스트 코드
from fastapi.testclient import TestClient
from app.main import app
client = TestClient(app)
def test_create_todo():
response = client.post("/todos", json={
"title": "테스트 할일",
"description": "자동화 테스트용"
})
assert response.status_code == 200
assert response.json()["title"] == "테스트 할일"
단순해 보이지만, POST 요청 → 응답 확인 → 예상 결과 비교까지 핵심 흐름이 모두 담겨 있어요.
5.2 테스트 커버리지 넓히기
단일 테스트로는 부족하죠.
아래 항목들을 테스트 목록에 꼭 포함시켜보세요:
- 목록 조회 (GET) 응답이 올바른지
- 수정/삭제 요청 시 상태코드 확인
- 없는 ID로 요청 시
404
테스트
5.3 테스트 실행 및 자동화 팁
터미널에서 다음 명령어를 입력하면 테스트가 실행됩니다.
pytest tests/
Tip: GitHub Actions 또는 GitLab CI와 연동하면 커밋할 때마다 자동으로 테스트가 돌아가요.
이것만 잘해도 실무에선 ‘코드 퀄리티 보장’으로 인정받습니다.
5.4 테스트 작성 못했다면?
사실 시간이 부족하거나 학습이 익숙하지 않다면, 모든 자동화 테스트를 작성하는 건 쉽지 않아요.
그럴 땐 수동 테스트와 로그 확인으로 충분히 대체 가능합니다.
하지만 이번 프로젝트가 끝나고 나면 꼭 pytest + FastAPI 조합으로 테스트를 구성해보세요.
다음 프로젝트에서는 코드 품질의 자신감이 달라질 거예요!
6. 프로젝트 마무리 및 다음 단계 제안 🚀
6.1 FastAPI 프로젝트 완성 축하합니다! 🎉
정말 고생 많으셨어요!
지금까지 FastAPI + SQLAlchemy를 활용해서 REST API를 설계하고, 구현하고, 테스트하고, 마무리까지 해냈습니다.
처음엔 생소하고 어렵게 느껴졌던 코드들도 이제는 익숙하게 다뤘을 거예요. 👏👏👏
6.2 포트폴리오로 남기는 법 💼
- GitHub에 코드 업로드: 기능별 커밋 기록은 매우 큰 가산점!
- README.md 작성: 사용 방법, 기능 목록, 설치 방법 포함하면 👍
- 시연 영상 or 이미지 첨부: 블로그나 유튜브 링크도 함께!
6.3 다음에 도전해볼 것들 ✨
이제 진짜 FastAPI를 익힌 셈이니까요, 다음 단계로 이런 걸 시도해보면 좋습니다:
- JWT 인증과 OAuth2 로그인 적용 (보안 강화)
- Docker로 서비스 배포 준비
- 프론트엔드 연동 (React, Vue 등으로 UI 구현)
6.4 참고 자료 📚
학습을 계속 이어가고 싶다면, 아래 자료들을 추천합니다:
FastAPI는 앞으로도 계속 성장할 프레임워크입니다.
꾸준히 공식 문서를 체크하고, 오픈소스 프로젝트에 기여해보는 것도 추천드려요!
마무리 🎁
지금까지 우리는 FastAPI를 활용한 실전 프로젝트를 단계별로 구축해왔고, 그 마지막 단계인 기능 보완과 테스트, 리팩토링까지 성공적으로 마무리했습니다.
이 과정을 통해 FastAPI의 기본 구조뿐 아니라 RESTful API 설계, ORM 연동, 예외 처리, 테스트 자동화에 이르기까지 백엔드 개발에서 꼭 필요한 스킬들을 하나씩 익혔어요.
특히 이번 프로젝트는 단순히 작동만 되는 코드가 아닌, 실제 서비스에 가까운 형태로 구현했다는 점에서 큰 의미가 있습니다.
지금까지 작성한 코드들은 포트폴리오로 활용할 수 있을 만큼 구조적이고 완성도가 높아졌습니다.
여기까지 따라오셨다면 정말 큰 박수를 드리고 싶어요. 👏👏👏
앞으로는 이 기반 위에 인증, 배포, 프론트엔드 연동 등 더 넓은 분야로 확장해보세요.
그리고 중요한 건 꾸준히 연습하고, 실제 프로젝트에 응용해보는 겁니다.
이제 여러분도 자신 있게 말할 수 있어요.
"FastAPI로 백엔드 개발할 줄 압니다!" 💪
🎯 이 글의 핵심 요약
- ✅ CRUD 완성: Update/Delete 엔드포인트 구현
- ✅ 사용자 중심 필터링, 검색 등 추가 기능
- ✅ 공통 함수 및 인증 구조 리팩토링
- ✅ Swagger를 통한 수동 테스트
- ✅ pytest 기반 자동화 테스트 도입
- ✅ 실무형 프로젝트 구조와 문서화
여기서 끝나지 않아요.
지금까지 쌓은 지식을 바탕으로 더 멋진 API, 더 나은 백엔드 시스템을 계속 만들어가시길 바랍니다.
여러분의 여정을 응원합니다! 🚀
'Python > Python 웹프로그래밍' 카테고리의 다른 글
[FastAPI-⑦] 파이썬 FastAPI 실전 프로젝트 (1) – 블로그 API/Todo API 설계 및 구현 (0) | 2025.04.16 |
---|---|
[FastAPI-⑥] 파이썬 FastAPI 예외 처리, 테스트 및 프로젝트 구조화 (0) | 2025.04.16 |
[FastAPI-⑤] 파이썬 FastAPI 고급 ORM – 관계 모델링과 다중 테이블 연동 (0) | 2025.04.16 |
[FastAPI-④] 파이썬 FastAPI 데이터베이스 연동 – SQLAlchemy ORM 시작 (0) | 2025.04.16 |
[FastAPI-③] 파이썬 FastAPI Pydantic을 통한 데이터 모델링과 검증 (0) | 2025.04.16 |