8/17(일) - RESTful API Endpoint 리스트업 및 FastAPI 코드 작성
저번시간 완성했던 API 명세서를 기반으로 BE 개발에 필요한 엔드포인트 정리부터 시작했다.
해당 리스트가 정리되면 이를 토대로 FastAPI용 코드를 작성할 계획이다.
RESTful API Endpoint Listup



📌 RESTful API Endpoint Listup 정리의 필요성
1. 팀원 간의 공통 이해 기반 마련
- 프론트엔드(FE), 백엔드(BE), 추천 시스템 등 파트별로 서로 약속된 통신 규약이 필요함.
- API 명세가 없으면 FE에서 어떤 URL로 요청해야 할지, 어떤 응답을 받을지 몰라서 구현 속도가 느려짐.
- 예: /api/v1/market/products 에서 어떤 파라미터를 받는지, 어떤 JSON 구조로 응답하는지 정리하면 FE에서 가짜 데이터(mock)로 먼저 화면을 개발할 수 있음.
2. 일관성 있는 구조 유지
- RESTful 설계 원칙을 따르려면 리소스 이름, 메서드(GET/POST/PUT/DELETE) 규칙이 일관되어야 함.
- 팀 내 각자 구현 시 혼동을 막음.
- 예: GET /users/{id} vs GET /userInfo?id=123 → 통일되지 않으면 나중에 유지보수 악몽 발생.
3. 디버깅 및 협업 효율성 증가
- 개발 중 오류가 생기면, API 리스트 문서를 보고 바로 요청/응답 형식을 확인 가능.
- Postman, Swagger 같은 API 테스트 도구에서 그대로 활용 가능 → QA 단계에서 시간 단축.
4. 백엔드-프론트엔드 연동 속도 향상
- BE API가 완성되기 전에도 FE는 Mock API로 화면을 구성할 수 있음.
- 즉, FE와 BE를 병렬로 개발할 수 있어 프로젝트 전체 속도가 빨라짐.
- 나중에 실제 API 연결만 바꿔주면 됨.
5. 유지보수 및 확장성 확보
- 서비스가 커질수록 API 엔드포인트가 많아지고 복잡해짐.
- 정리된 리스트가 있으면, 새 기능 추가나 리팩토링 시 기존 API와 충돌을 피할 수 있음.
- 새로운 팀원이 합류했을 때도 빠르게 이해 가능.
6. 발표 및 문서화 시 가독성 강화
- 졸업 프로젝트 발표나 보고서 제출 시, API Endpoint 리스트가 있으면 시스템 구조를 직관적으로 보여줌.
- "이 시스템은 어떤 기능을 제공하는지"를 한눈에 알 수 있어 평가자/교수님에게 어필 가능.
✅ 요약
RESTful API Endpoint Listup은 단순 문서가 아니라,
👉 팀 전체의 공통 언어이자 설계도 역할을 함.
👉 협업 효율을 높이고, FE/BE 연동 속도를 빠르게 하며, 유지보수에도 필수적임.
👉 최종적으로는 발표/보고서에서도 프로젝트의 체계성과 완성도를 보여주는 중요한 자료가 됨.
FastAPI code
# main.py
from typing import List, Optional
from fastapi import FastAPI, HTTPException, Body, Path, Query
from pydantic import BaseModel, Field
# --- Pydantic 모델 정의 ---
# 요청 및 응답 데이터 유효성 검사를 위해 사용됩니다.
# API 명세서에 맞춰 필요한 모델을 정의합니다.
# 회원
class UserCreate(BaseModel):
id: str
password: str
email: str
nickname: str
gender: Optional[str] = None
birthday: Optional[str] = None
class UserProfile(BaseModel):
id: str
email: str
nickname: str
gender: Optional[str] = None
birthday: Optional[str] = None
class UserLogin(BaseModel):
id: str
password: str
class Token(BaseModel):
message: str
token: str
data: dict
# 추천
class Recommendation(BaseModel):
title: str
score: float
distanceKm: float
reason: List[str]
class RecommendResponse(BaseModel):
message: str
data: dict
# 콘텐츠 (축제, 상품)
class Festival(BaseModel):
name: str
description: str
latitude: float
longitude: float
class Product(BaseModel):
name: str
price: int
description: str
image_url: str
# 사용자 상호작용
class Favorite(BaseModel):
item_id: str
class Review(BaseModel):
user_id: str
product_id: str
rating: int = Field(..., ge=1, le=5)
comment: str
# --- FastAPI 애플리케이션 초기화 ---
app = FastAPI(
title="소소행 API",
description="소도시 여행 추천 및 지역 콘텐츠 제공을 위한 RESTful API",
version="1.0.0"
)
# 임시 데이터베이스 (실제로는 DB 사용)
db_users = {}
db_festivals = {
"festival-001": Festival(name="논산딸기축제", description="맛있는 딸기 축제입니다.", latitude=36.1, longitude=127.1),
"festival-002": Festival(name="보령머드축제", description="머드 체험을 즐길 수 있습니다.", latitude=36.3, longitude=126.5),
}
db_products = {
"prod-001": Product(name="수제 막걸리", price=12000, description="정읍에서 직접 빚은 막걸리", image_url="http://example.com/img1.jpg"),
"prod-002": Product(name="전통 한지 부채", price=8000, description="수공예 한지 부채", image_url="http://example.com/img2.jpg"),
}
db_favorites = {}
# --- 회원 관리 엔드포인트 ---
@app.post("/users", tags=["회원 관리"])
async def signup(user: UserCreate):
"""
새로운 사용자 계정을 생성합니다.
"""
if user.id in db_users:
raise HTTPException(status_code=409, detail="이미 존재하는 사용자 ID입니다.")
db_users[user.id] = user
return {"message": "회원가입 성공", "data": {"id": user.id}}
@app.post("/auth/login", tags=["회원 관리"])
async def login(user: UserLogin):
"""
사용자 인증 및 토큰을 발급합니다.
"""
if user.id not in db_users or db_users[user.id].password != user.password:
raise HTTPException(status_code=401, detail="아이디 또는 비밀번호가 올바르지 않습니다.")
# 실제로는 JWT 토큰을 생성하여 반환합니다.
token = f"dummy_jwt_token_for_{user.id}"
return {"message": "로그인 성공", "token": token, "data": {"id": user.id}}
@app.get("/users/{user_id}", tags=["회원 관리"])
async def get_user_profile(user_id: str = Path(..., title="사용자 ID")):
"""
특정 사용자의 프로필 정보를 조회합니다.
"""
if user_id not in db_users:
raise HTTPException(status_code=404, detail="사용자를 찾을 수 없습니다.")
user_data = db_users[user_id]
return user_data
# --- 추천 및 콘텐츠 조회 엔드포인트 ---
@app.get("/recommend", tags=["추천 및 콘텐츠 조회"])
async def get_recommendations(
lat: float = Query(..., ge=-90, le=90, description="위도"),
lng: float = Query(..., ge=-180, le=180, description="경도"),
themes: Optional[str] = Query(None, description="테마 목록 (쉼표로 구분, 예: family,pet,nature)"),
dateFrom: Optional[str] = Query(None, description="시작 날짜 (YYYY-MM-DD)"),
dateTo: Optional[str] = Query(None, description="종료 날짜 (YYYY-MM-DD)"),
radiusKm: int = Query(50, ge=1, le=100, description="반경 (km)"),
limit: int = Query(20, ge=1, le=50, description="결과 수 제한"),
minPopularity: Optional[float] = Query(None, ge=0, description="최소 인기 점수")
):
"""
사용자 위치, 테마, 날짜, 거리 등 필터를 기반으로 콘텐츠를 추천합니다.
"""
# 실제 추천 로직 (캐시, TourAPI 연동, 스코어링 등)이 여기에 구현됩니다.
# 이 예시에서는 더미 데이터를 반환합니다.
return {
"message": "추천 리스트 조회 성공",
"data": {
"items": [
{
"title": "추천 아이템 1",
"score": 0.9,
"distanceKm": 5.2,
"reason": ["가족 친화적", "자연"]
},
{
"title": "추천 아이템 2",
"score": 0.8,
"distanceKm": 10.1,
"reason": ["자연경관"]
}
]
}
}
@app.get("/festivals", tags=["추천 및 콘텐츠 조회"])
async def get_festivals(
lat: Optional[float] = Query(None, description="위도"),
lng: Optional[float] = Query(None, description="경도")
):
"""
전체 축제 목록을 조회하며, 위치 기반 필터를 적용할 수 있습니다.
"""
# 이 예시에서는 모든 축제를 반환합니다.
return list(db_festivals.values())
@app.get("/festivals/{festival_id}", tags=["추천 및 콘텐츠 조회"])
async def get_festival_detail(festival_id: str = Path(..., title="축제 ID")):
"""
특정 축제의 상세 정보를 반환합니다.
"""
if festival_id not in db_festivals:
raise HTTPException(status_code=404, detail="해당 축제를 찾을 수 없습니다.")
return db_festivals[festival_id]
@app.get("/products", tags=["추천 및 콘텐츠 조회"])
async def get_products():
"""
마켓에 등록된 전체 상품 목록을 조회합니다.
"""
return list(db_products.values())
@app.get("/products/{product_id}", tags=["추천 및 콘텐츠 조회"])
async def get_product_detail(product_id: str = Path(..., title="상품 ID")):
"""
특정 상품의 상세 정보를 반환합니다.
"""
if product_id not in db_products:
raise HTTPException(status_code=404, detail="해당 상품을 찾을 수 없습니다.")
return db_products[product_id]
# --- 사용자 상호작용 엔드포인트 ---
@app.get("/users/{user_id}/favorites", tags=["사용자 상호작용"])
async def get_favorites(user_id: str = Path(..., title="사용자 ID")):
"""
사용자가 찜한 모든 항목(상품, 여행지 등)을 조회합니다.
"""
return db_favorites.get(user_id, [])
@app.post("/users/{user_id}/favorites/{item_id}", tags=["사용자 상호작용"])
async def add_favorite(
user_id: str = Path(..., title="사용자 ID"),
item_id: str = Path(..., title="찜할 아이템 ID")
):
"""
찜 목록에 특정 아이템을 추가합니다.
"""
if user_id not in db_favorites:
db_favorites[user_id] = []
if item_id not in db_favorites[user_id]:
db_favorites[user_id].append(item_id)
return {"message": "찜 목록 추가 성공"}
@app.delete("/users/{user_id}/favorites/{item_id}", tags=["사용자 상호작용"])
async def remove_favorite(
user_id: str = Path(..., title="사용자 ID"),
item_id: str = Path(..., title="삭제할 아이템 ID")
):
"""
찜 목록에서 특정 아이템을 삭제합니다.
"""
if user_id in db_favorites and item_id in db_favorites[user_id]:
db_favorites[user_id].remove(item_id)
return {"message": "찜 목록 삭제 성공"}
*깃허브 레포 구조
backend/
app/ # FastAPI 앱 소스코드
main.py # FastAPI 진입점 (app 객체 생성, 라우터 등록)
router/ # API 엔드포인트 라우터 모음
user_router.py # 사용자 회원가입/로그인/북마크 등 사용자 관련 API
recommend_router.py # 추천 시스템 관련 API (여행지/상품 추천)
festival_router.py # 축제/행사 정보 관련 API (TourAPI 연동)
market_router.py # 로컬 특산물 마켓 관련 API (상품, 가게)
common_router.py # 공통 엔드포인트 (health check 등)
services/ # 비즈니스 로직, DB 트랜잭션 처리
user_service.py # 사용자 CRUD 및 인증/보안 처리
recommend_service.py # 추천 모델 호출, 추천 결과 생성 로직
festival_service.py # 축제 데이터 처리, TourAPI 연동 로직
market_service.py # 마켓/상품 CRUD, 검색/필터 처리
common_service.py # DB 세션 의존성, 공통 유틸 서비스
models/ # SQLAlchemy 모델 및 Pydantic 스키마
user_models.py # 사용자 관련 테이블/스키마
recommend_models.py # 추천 시스템에 필요한 모델/스키마
festival_models.py # 축제/행사 관련 테이블/스키마
market_models.py # 마켓/상품/카테고리 관련 테이블/스키마
common_models.py # Base 클래스, TimestampMixin 등 공통 모델
core/ # 핵심 설정 및 인프라 레벨 모듈
config.py # 환경변수 설정 (pydantic-settings 등)
cache.py # Redis 캐시/세션 관리
database.py # DB 연결, 세션 로직
__init__.py # 패키지 초기화 파일
tests/ # 단위/통합 테스트 모음 (pytest)
recommend_test.py # 추천 API/서비스 테스트
festival_test.py # 축제 API/서비스 테스트
market_test.py # 마켓 API/서비스 테스트
tourapi_test.py # TourAPI 연동 테스트
data/ # 데이터셋 보관 (raw/processed)
raw/ # 원본 데이터 (크롤링/다운로드)
processed/ # 전처리된 데이터 (모델 학습용)
RecommendModels/ # 추천 시스템 모델/인덱스 파일
feature_store.parquet # 사용자/아이템 feature 저장소
nn_index.joblib # 최근접 이웃 검색용 인덱스
pyproject.toml # Poetry 설정 (패키지/빌드 관리)
requirements.txt # pip 기반 패키지 의존성 리스트
README.md # 프로젝트 개요 및 실행 방법 문서
'주전공 > 캡스톤디자인과창업프로젝트' 카테고리의 다른 글
| 여름방학 기록(6): 데이터베이스 초기화 | DB Schema 생성 (0) | 2025.08.24 |
|---|---|
| 여름방학 기록(5): FastAPI 백엔드 기본 개발환경 세팅 및 서버 띄우기 | 코드 실행 및 연동 1차 테스트 + Mock 실행 확인 (0) | 2025.08.18 |
| 여름방학 기록(3) : 깃허브 레포 생성 및 FE 개발 시작, 그리고 API 명세서 작성 | with React Native + Expo GO + Notion (0) | 2025.08.11 |
| 여름방학 기록(2) : React Native 개발 환경 구축 (0) | 2025.08.09 |
| 여름방학 기록(1) : 방학 개발계획 수립 및 피그마 UI 제작 (0) | 2025.08.04 |