FastAPI 응답을 camelCase로: Pydantic CamelModel 하나로 Next.js 필드명 통일
Pydantic to_camel alias 생성기를 베이스 모델에 한 번 걸어 FastAPI 응답을 camelCase로 바꾸고, Next.js 컴포넌트에서 변환 유틸을 지우는 방법을 정리했어요.
Next.js 화면에서 data.monthly_payment와 form.monthlyPayment가 한 컴포넌트에 섞여 있으면 손이 자꾸 멈춰요. API 응답은 snake_case, 리액트 쪽은 camelCase가 관습이라 어느 쪽 이름을 쓸지 매번 고민하게 되거든요. 라이프케어로그 플랜 시리즈를 만들면서 저도 똑같이 겪었고, 결국 프론트에서 변환 함수를 지우는 쪽으로 정리했어요.
프론트에서 변환하면 생기는 일
처음엔 fetch 뒤에 toCamel() 유틸을 끼워 넣었어요. 직접 만들어 보니 문제가 두 가지였어요. 타입이 실제 JSON과 어긋나서 as 캐스팅이 늘어나고, 중첩 객체나 배열이 들어오면 변환 함수가 재귀를 타면서 조용히 필드를 놓쳤어요. 응답 스키마가 바뀔 때마다 백엔드·유틸·타입 세 곳을 같이 고쳐야 하니 화면 작업 속도가 그만큼 느려졌고요.
백엔드 쪽은 모델 하나면 끝나요
Pydantic v2에는 to_camel alias 생성기가 들어 있어요. 이걸 베이스 모델에 한 번만 걸어 두면 돼요.
from pydantic import BaseModel, ConfigDict
from pydantic.alias_generators import to_camel
class CamelModel(BaseModel):
model_config = ConfigDict(alias_generator=to_camel, populate_by_name=True)
class LoanResult(CamelModel):
monthly_payment: int
total_interest: int설정은 3줄, 파일은 1개예요. 이후 응답 모델은 BaseModel 대신 CamelModel을 상속하기만 하면 되고, 파이썬 코드 안에서는 여전히 snake_case로 필드를 다뤄요. FastAPI는 응답을 직렬화할 때 alias를 기본으로 쓰니 클라이언트에는 monthlyPayment로 나가요. 요청도 마찬가지예요. alias 기준으로 파싱하니 프론트가 camelCase로 보내면 그대로 받고, populate_by_name=True 덕분에 서버 내부 테스트에서 snake_case로 넣어도 돼요.
화면 코드가 이렇게 줄어요
적용해 봤더니 컴포넌트에서 사라진 게 세 가지였어요. 변환 유틸 import, 응답 타입의 as 캐스팅, 그리고 camelCase 강제 lint 규칙을 피하려고 달아 두던 예외 주석이요.
type LoanResult = { monthlyPayment: number; totalInterest: number };
export function LoanSummary({ result }: { result: LoanResult }) {
return (
<dl>
<dt>월 상환액</dt>
<dd>{result.monthlyPayment.toLocaleString()}원</dd>
<dt>총 이자</dt>
<dd>{result.totalInterest.toLocaleString()}원</dd>
</dl>
);
}타입이 JSON과 1:1로 맞으니 React Query의 select에서 이름을 바꿔 줄 이유도 없어졌어요. 폼도 편해져요. 입력 필드 name을 camelCase로 두고 그대로 POST하면 서버가 받아 주니, 제출 직전에 키를 바꾸는 코드가 필요 없어요. 플랜씨(plan-c) 대출이자 계산기처럼 결과 필드가 많은 화면일수록 이 차이가 크게 느껴져요.
놓치기 쉬운 두 가지
테스트해 보면 model_dump()는 기본이 snake_case라는 점에 걸려요. 서버 코드 안에서 dict로 꺼내 프론트에 넘기는 경로가 있다면 by_alias=True를 붙여야 해요. 응답 모델을 거치는 라우터는 신경 쓸 필요 없지만, 웹소켓이나 백그라운드 작업에서 직접 JSON을 만드는 곳은 한 번 훑어보는 게 좋아요.
OpenAPI 스키마도 alias 이름으로 나가요. 그래서 스키마에서 타입을 생성하는 도구를 돌려 보니 camelCase 타입이 바로 나왔고, 위에서 손으로 적은 LoanResult 타입도 생성 결과로 교체할 수 있었어요. 백엔드 모델 1개, 프론트 타입 생성 1회. 이 2단계로 바꾸는 데 10분 정도 걸렸고, 이름 때문에 리뷰에서 오가던 댓글이 그 뒤로 사라졌어요.
관련 글
댓글
아직 댓글이 없어요. 첫 댓글을 남겨주세요.