FastAPI - FastAPI 유효성검사 Pydantic Validator 사용해서 데이터 유효성 검사하기

프로필 사진mingke

FastAPI Logo

목차

소개

Pydantic은 Python용 데이터 유효성 검사 라이브러리입니다. FastAPI에서 많이 사용됩니다. Pydantic은 데이터 모델을 정의하고 해당 모델의 유효성을 검사할 수 있습니다. Pydantic을 사용하면 더욱 안전하고 효율적인 API 개발이 가능합니다. Pydantic은 Rust로 개발되어 빠르고 타입 안정성이 뛰어납니다. (저도 언젠간 Rust로 Python 라이브러리 만들어보고 싶은 꿈이..)
오늘은 Pydantic Validator를 사용하여 데이터를 유효성 검사 하는 법을 알아보겠습니다.

사용법

validator를 사용하기 전에 모델 정의를 해야합니다. 현재 사용하고 있는 버젼은 다음과 같습니다. 거의 2버젼을 사용하고 있겠죠? 1버젼과는 사용법이 다릅니다.

  • Pydantic 2.5.2
# 예시
from pydantic import BaseModel, field_validator
 
class Model(BaseModel):
    a: int
	b: int
 
	@field_validator("a")
	@classmethod
    def check_a(cls, v):
        if v < 0:
            raise ValueError("a 는 0 보다 큽니다.")
        return v

field_validator

field_validator는 특정 필드에 대해 유효성 검사를 하고 데코레이터로 사용합니다. validation 로직이 담긴 함수를 작성하고 field_validator로 감싸주면 입력을 받을 때 validation을 실행합니다. 위 예시에서는 a 필드에 대한 유효성 검사를 실행합니다.

주의해야할 점은 python의 classmethod로 작성해야한다는 점입니다. 데코데이터 순서가 틀리거나 classmethod를 사용하지 않으면 validator가 동작하지 않으니 주의해야합니다.

여러 필드를 같은 로직으로 유효성 검사를 하고 싶으면 다음과 같이 사용하면 됩니다. 다음과 같이 사용하면 a, b필드 모두 유효성 검사를 합니다.

class Model(BaseModel):
    a: int
    b: int
 
    @field_validator("a","b")
    @classmethod
    def check(cls, v):
        if v < 0:
            raise ValueError(f"{v} 는 0 보다 큽니다.")
        return v

유효성 검사에 실패하면 아래와 같은 응답을 반환합니다.

{
  "detail": [
    {
      "type": "value_error",
      "loc": ["body", "a"],
      "msg": "Value error, -1 는 0 보다 큽니다.",
      "input": -1,
      "ctx": {
        "error": {}
      },
      "url": "https://errors.pydantic.dev/2.4/v/value_error"
    },
    {
      "type": "value_error",
      "loc": ["body", "b"],
      "msg": "Value error, -1 는 0 보다 큽니다.",
      "input": -1,
      "ctx": {
        "error": {}
      },
      "url": "https://errors.pydantic.dev/2.4/v/value_error"
    }
  ]
}

다음과 같이 다른 필드값과 비교할 수 도 있습니다. values는 ValidationInfo객체이며 data 속성에 다른 필드값을 가지고 있습니다. 하지만 이렇게 비교하는 방법말고 model_validator를 사용하여 다른 필드값과 비교하는 방법도 있습니다.

class Model(BaseModel):
    a: int
    b: int
 
    @field_validator("b")
    @classmethod
    def check_ab(cls, v, values):
        if v < values.data["a"]:
            raise ValueError("a는 b보다 작아야 합니다.")

model_validator

model_validator는 모델 전체에 대해서 유효성 검사를 진행합니다. 이전 버젼에서는 root_validator를 사용했었는데 deprecated되었습니다.

data는 python dict로 생성되고 그 안에 필드 값들이 key:value로 담겨있습니다.

class Model(BaseModel):
    a: int
    b: int
 
    @model_validator(mode="before")
    @classmethod
    def check_sum(cls, data):
        if data["a"] + data["b"] > 10:
            raise ValueError(f'{data["a"]} + {data["b"]} 는 10 보다 작습니다.')
        return data

mode 에는 before, after, wrap이 있습니다만 보통은 before를 많이 사용합니다. before는 pydantic 모델이 파싱되기 전에 필드값 검사를 하고 after는 파싱후에 검사합니다.

오늘은 FastAPI에서 유효성 검증에 사용되는 Pydantic validator를 알아봤습니다.