lifecarelog
프론트엔드

FastAPI 응답을 camelCase로: Pydantic CamelModel 하나로 Next.js 필드명 통일

Pydantic to_camel alias 생성기를 베이스 모델에 한 번 걸어 FastAPI 응답을 camelCase로 바꾸고, Next.js 컴포넌트에서 변환 유틸을 지우는 방법을 정리했어요.

5분 읽기

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로 넣어도 돼요.

snake_case 모델 정의CamelModel 상속응답 JSON camelCaseNext.js 컴포넌트에서 그대로 사용

화면 코드가 이렇게 줄어요

적용해 봤더니 컴포넌트에서 사라진 게 세 가지였어요. 변환 유틸 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분 정도 걸렸고, 이름 때문에 리뷰에서 오가던 댓글이 그 뒤로 사라졌어요.

#FastAPI#Pydantic#Next.js#TypeScript

라이프케어로그 서비스가 궁금하신가요?

AI 기반 건강·일정·재활 관리 앱을 직접 써보세요.

서비스 살펴보기

관련 글

댓글

아직 댓글이 없어요. 첫 댓글을 남겨주세요.