Schema 구현 ( Pydantic 기반 )

현재 MSP 백엔드 프로젝트에서는 schemas 디렉터리를 통해 endpoint에서 요청받고, 응답할 데이터의 구조를 정의할 예정입니다. FastAPI에서 제공하는 OpenAPI 문서를 위해서입니다.
우선 해당 문서에서는 Login 기능에 관한 Schema 구현 및 endpoint 변경 내용만 작성하겠습니다.
schemas/user.py
from pydantic import BaseModel
class LoginRequest(BaseModel):
email: str
password: str
class LoginResponse(BaseModel):
message: str
role: str
email: str
name: str
로그인 기능에서 클라이언트에서 요청하는 데이터는 LoginRequest
로그인 기능에서 서버가 클라이언트에 응답하는 데이터는 LoginResponse
하나의 엔드포인트에 대하여 Request 클래스와 Response 클래스, 총 2개의 클래스가 필요합니다.
Login 엔드포인트
from fastapi import APIRouter, HTTPException, Request
from fastapi.responses import JSONResponse
from database.session import get_db_connection
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from psycopg2.extras import RealDictCursor
import smtplib
import core.config as config
from schemas.user import *
@user_router.post('/login', response_model=LoginResponse)
async def login(request: Request, body: LoginRequest):
email = body.email
password = body.password
if not email or not password:
raise HTTPException(status_code=400, detail="이메일과 비밀번호를 입력하세요.")
try:
conn = get_db_connection()
print("db_connected")
with conn:
with conn.cursor(cursor_factory=RealDictCursor) as cur:
cur.execute(
'SELECT * FROM user_table WHERE email = %s AND pw = %s ORDER BY email ASC',
(email, password)
)
user_data = cur.fetchone() # fetchall 대신 fetchone 사용
if not user_data:
return JSONResponse(content={'message': '회원정보가 없습니다.'}, status_code=404)
if user_data["role"] == "admin":
return JSONResponse(
content={
"message": "관리자님 반갑습니다.",
"role": "admin",
"email": user_data["email"],
"name" : user_data["name"]
},
status_code=200
)
elif user_data["role"] == "user":
return JSONResponse(
content={
"message": f"{user_data['name']}님 반갑습니다.",
"role": "user",
"email": user_data["email"],
"name": user_data["name"]
},
status_code=200
)
else:
return JSONResponse(content={'message': '역할 정보가 없습니다.'}, status_code=400)
except Exception as e:
print(f"에러 발생: {e}")
raise HTTPException(status_code=500, detail="서버 에러가 발생했습니다.")
위 코드는 전체적인 Login 엔드포인트 구현 코드입니다.
아래는 Schema 구현 후 엔드포인트 코드 작성시 공통적으로 필요한 내용들입니다.
from schemas.user import *
schemas 모듈에서 구현한 클래스들을 임포트합니다.
이미 schemas 모듈과 endpoints 디렉터리는 똑같이
project.py | provider.py | user.py 구조로 나뉘어져 있습니다.
Schemas의 user.py에서는 Endpoint의 user.py에서 필요한 클래스들만 보관 중이기에
import * 문으로 Schemas/user.py의 모든 클래스를 임포트해야 합니다.
@user_router.post('/login', response_model=LoginResponse)
async def login(request: LoginRequest):
email = request.email
password = request.password
그리고 response_model을 Schema에서 작성한 Response 클래스명을 입력해야 합니다.
또한 request도 LoginRequest로 설정합니다.
다음과 같이 Schema를 구현하고 endpoint를 구성하면,
이제 FastAPI에서 제공하는 OpenAPI의 기능을 활용할 수 있습니다.
Redoc
Redoc은 FastAPI에서 제공하는 API 문서입니다.
가독성이 좋은 디자인으로 API를 문서화해주며, 일부 기능을 테스트할 수 있게 해줍니다.
포트 5000에서 FastAPI가 실행된다는 가정 하에,
브라우저에서 위 주소를 입력하면 redoc 문서를 확인할 수 있습니다.
이 redoc 문서에서,
Schema를 구현하지 않은 엔드 포인트와 Schema를 제대로 구현한 엔드 포인트의 차이가 발생합니다.
Schema를 구현하지 않은 엔드포인트

Schema를 구현하지 않은 엔드포인트는 위 이미지와 같이,
Request Sample이 전혀 출력되지 않으며 Response Sample 또한 null로 출력됩니다.
미리 정의한 요청 및 응답 구조가 없기 때문입니다.
Schema를 구현한 엔드포인트

그러나 Schema를 제대로 구현한 엔드 포인트에서는 Request Sample과 Response Sample이 시각화됩니다.