[Python] Validation의 필요성과 Pydantic

changhwan·2021년 12월 26일
2

Python

목록 보기
1/1
post-thumbnail

이 글은 Enterprise Application을 Python으로 개발할 때, Data Validation을 어떻게 보장할지 다루는 글 입니다.


Validation의 필요성

먼저 Validation 이야기를 해보자!! Validation은 ‘확인’, ‘검증’ 이라는 뜻을 가졌다. 즉, 유효성 검사를 위한 오브젝트이다.

서버는 서버로 들어오는 수많은 데이터를 믿을 수 있을까? 아니면 믿어야 할까?? 나는 개인적으로 믿지 못하고 믿어서도 안된다고 생각하며 어떤 원인에 의해서든 잘못된 데이터가 들어올 확률은 아주 높다고 생각한다. 특히, null able한 언어에서는 null 값에 대해선 최소한의 방어코드는 반드시 필요하다고 생각한다.

물론 Data를 보내는 Client측에서도 데이터 검증을 하겠지만 서버는 방어적 스탠스를 취하는 것이 좋기 때문에 송,수신 측 모두 Validation Check는 필수라고 생각한다.

Validation Check는 위의 예시처럼 Client에서 보내는 Data 검증에만 해당하지 않는다. Python과 같은 동적 타이핑을 지원하는 언어는 계층간 이동에 사용되는 dto class에 대해서도 검증이 필요하며 Dto Data Type를 보장하기 위해선 Validator가 필요하다.



Pydantic Overview

Pydantic 공식 Document에서는 아래와 같이 Pydantic을 소개하고 있다.

Data validation and setting management using python type annoations pydatin enforeces type hints at runtime, and provides user friendly erros when data is invalid.
Define how data should be in pure, canonical python; validate it with pydantic

"데이터 유효성 검사 및 설정이 관리를 하며 런타임에 Type hinting을 적용하여 데이터가 유효하지 않을 때 사용자 친화적인 오류를 제공하는 모듈로, 순수하고 표준적인 데이터를 정의할 수 있다." 라고 소개하고 있다.



Pydantic이 필요한 이유

Validation이 왜 필요한지는 어느정도 설명이 되었다고 생각하지만 조금 더 자세히 알아보자

a. Validation Check

  • 동적 타이핑 언어인 Python에는 어떻게 Validation Check를 할 수 있을까? 아마 가장 기초적인 방법은 type() 메서드를 이용해서 체크할 수 있겠다.
  • e.g
    if type("name") is str:
       return True
    else:
       return False

하지만 Validation을 해야할 모든 로직에 위와 같은 코드가 들어가면 method의 복잡도 올라가고 ‘단일 책임 원칙’도 지켜지지 못한다. 물론 util package로 Validator를 만드는 방법도 있겠지만 이렇게 되면 우리가 테스트 혹은 관리해야할 코드가 많아지는 것이기 때문에 추천하지 않는다.


b. Parsing

아래와 같이 Sign Up Request JSON에서 age가 문자열로 들어왔다고 생각해보자

signUpDto = {
  "name": "Blue"
  "age": "27"
}

회원가입 로직 에서는 문자열이 아닌 정수형 데이터가 필요하다. 이때 pydatic을 사용하지 않는다면 매번 문자열을 정수형으로 타입 캐스팅이 발생한다. Client에서 보내는 데이터를 기본적으로 믿지 않는 방어적 스탠스 때문에 매번 타입 캐스팅을 한다는 것 또한 복잡도가 높아지는 원인이 될 것이다.

그래서 이러한 점들을 해소해줄 Pydantic이라는 Module를 소개한다.



How to using pydantic

  1. install pydantic
  2. extend pydantic.BaseModel

이 글에선 Install 방법에 대해선 다루지 않겠다 공식문서에 잘 나왔으니 참고하자!

BaseModel을 상속받자.

Python Class가 pydantic의 기능을 사용하기 위해선 BaseModel을 상속받아야 한다.

e.g

from pydantic import BaseModel

class Item(BaseModel):
    id: int
    name: str
    code: str

BaseModel을 상속받은 Item Class 기본 생성자를 사용할 수 없다. 기본 생성자를 호출한다면 pydantic이 ValidationError를 뱉을 것이다.


인스턴스 생성

pydantic model은 생성할 때 생성자에 “멤버변수” = “값” 으로 어떤 멤버변수에 어떤 값을 넣는다는 것을 명시해야 한다.

e.g

from pydantic import BaseModel

class Item(BaseModel):
    id: int
    name: str
    code: str

item = Item(
    id = 12,
    name = "Blue",
    code = "A-123"
)

>>> id=12 name='Blue' code='A-123'

만약 특정 멤버 변수에 대해서 값이 빠진다면 ValueError 발생하기 때문에 null 값을 방지할 수 있다.


Parsing 확인

위에서 Pydantic Parsing을 지원한다고 했습니다. 지금 Item 생성 코드를 보면 id = 12 로 정수형 데이터가 들어오고 있지만 만약 id = “12”와 같이 문자형 데이터를 주입한다면 어떻게 될까??

e.g

class Item(BaseModel):
    id: int
    name: str
    code: str

item = Item(
    id = "12",
    name = "Blue",
    code = "A-123"
)

assert isinstance(item.id, int)

print(isinstance(item.id, int))
print(item.dict())

>>> True
>>> {'id': 12, 'name': 'Blue', 'code': 'A-123'}

결과는 문자열 데이터를 넣었지만 정수형 데이터로 자동으로 파싱해준다. 따라서 우리는 더 이상 parsing 문제에 대한 고민을 하지 않고 비즈니스 로직 개발에 집중할 수 있게 된다.



BaseModel Properties

BaseModel의 Properties는 정말 여러가지 있기 때문에 모두 소개하는 것은 힘들고 내가 생각하는 유용한 사례를 소개한다.

dict()

파이썬은 기본적으로 클래스가 강제되는 언어가 아니기에 dict Type의 활용도가 높은 언어라고 생각한다.

따라서 Object를 dict로 변환 해주는 것은 유용하다. 나는 주로 ReponseModel을 json으로 Parsing 하지 않고 dict()를 사용하여 Dict Tpye으로 내려주는 방법을 선호한다.

그 이유는 역시 json library에 대한 의존성을 떨어트리기 위해서 이기도 하며, json dump 과정에서 한글 인코딩 문제를 신경쓰지 않아도 되기 때문이다.

e.g

class ResponseModel(BaseModel):
    class Data(BaseModel):
	"""
	필드 값은 생략
	"""
data: Data


class Controller:
    def get(self):
        return ResponseModel.Data().dict()


마무리

지금까지 Python에서 Validation을 어떻게 보장할지에 대해서 정리 해봤다. 백엔드 개발에서 엔터프라이즈급 서비스로 갈 수록 서버의 안정성은 중요한 포인트이며 이를 위한 기본 중에 기본이라고 할 수 있는게 Validation Check이다.

이러한 needs 비단 나만의 needs가 아니였기 때문에 Pydantic이란 멋진 라이브러리가 존재한다.

오늘은 왜 Validation Check가 필요한지 그리고 기본적인 사용법에 대해서 정리했고 다음에는 Error Handling과 그 밖에 Validation 검증 로직을 처리할 수 있는 @validator 에 대해서 정리할 예정이다.

profile
Junior Backend Developer

0개의 댓글