FastAPI | Pydantic에서 snake_case ↔︎ camelCase 변환 삽질 기록

Faithful Dev·2025년 6월 30일
0

셀파트너랩스

목록 보기
4/6

문제 상황

FastAPI와 Pydantic을 사용해서 API를 만들던 중,,,
프론트엔드와의 협업을 위해 응답(JSON)은 camelCase로,
파이썬 내부에서는 snake_case로 리팩토링을 하던 중이었다.
Pydantic alias_generator 기능을 활용해 BaseModel을 상속한 CamelModel을 만들어 사용.

from pydantic import BaseModel

def to_camel(string:str) -> str:
    parts = string.split('_')
    return parts[0] + ''.join(word.capitalize() for word in parts[1:])

class CamelModel(BaseModel):
    class Config:
        orm_mode = True
        allow_population_by_field_name = True
        alias_generator = to_camel

이렇게 하면 snake_case로 작성한 필드가 응답에서 자동으로 camelCase로 변환되어 나가야 하는데,,,


500 에러가...

API를 호출했더니 아래와 같은 500 Internal Server Error 발생..

pydantic_core._pydantic_core.ValidationError: 7 validation errors for SumingData
sumingField
    Field required [type=missing, input_value={'example_field': 'value', ...}, input_type=dict]
...

분명 suming_field 등 snake_case로 값을 넘겼는데, pydantic이 camelCase(sumingField) 필드를 못찾겠다고 에러를 낸다.
리팩토링 전에는 동작하던 코드라 신입의 눈물...
고친 게 이것 뿐이라 분명 camelCase랑 snake_case 사이의 문제인 건 확실한데 뭐가 문제냐고 ㅠㅠ


원인 분석

  • pydantic의 alias_generator 는 출력 시에는 camelCase로 변환해주지만,
  • 입력 시에는 기본적으로 snake_case로 값을 받아야 한다.
  • 그런데 pydantic v2에서는 설정 방식이 바뀌어서,
    allow_population_by_field_name 대신 populate_by_name을 써야 하고,
    Config 대신 model_config를 써야 한단다.

pydantic v1과 v2의 차이

버전설정 방법
v1class Config: ... allow_population_by_field_name = True
v2model_config = { "populate_by_name": True }

해결 방법

pydantic v1

class CamelModel(BaseModel):
    class Config:
     	orm_mode = True
        allow_population_by_field_name = True
        alias_generator = to_camel

pydantic v2

class CamelModel(BaseModel):
	model_config = {
    	"orm_mode": True,
        "populate_by_name": True,
        "alias_generator": to_camel,
	}
  • populate_by_name=True가 있어야 snake_case로도 값을 받을 수 있다.
  • alias_generator는 camelCase로 변환해서 응답에 사용한다.

결론

  • pydantic에서 snake_case ↔︎ camelCase 변환하려면 alias_generator를 활용하면 된다.
  • 입력도 snake_case로 받고 싶으면
    • v1: allow_population_by_field_name = True
    • v2: populate_by_name = True
  • pydantic 버전에 따라 설정법이 다르니 꼭 확인하자!

삽질에서 얻은 교훈

  • 공식 문서와 마이그레이션 가이드를 꼭 읽자.
  • 에러 메시지를 끝까지 읽고, 필드명이 어떻게 매핑되는지 꼼꼼히 확인하자.
  • 기존 코드 리팩토링은 생각보다 훠어어어얼씬 더 까다롭다.
    (입사 전에는 리팩토링 무조건 필요하다고 생각했는데, 왜 회사들에서 리팩토링을 잘 안한다고 하는지 알 것 같다.ㅎ)
profile
Turning Vision into Reality.

0개의 댓글