Python/FastAPI / / 2023. 1. 5. 22:26

FastAPI 알아보기 - Schema 다루기 혹은 DTO, Entity, DAO 등

So What is DTO, VO, Entity, Domain, Model?

 

DTO, 풀어 쓰자면 Data Transfer Object이다. 직역하자면, "정보 전송 객체"인데, 사실 이렇게 말하면 이해하기가 어려울 수 있다. 잘 풀어보면 계층 간 데이터 전송을 위해 도메인 모델 대신 사용되는 객체라고 보면 된다. 이런 DTO는 파이썬, C++, 자바와 같이 object-oriented programming (OOP) 언어에서 사용된다. 

 

그렇다면 여러분들은 다양하게 들어봤을 것이다, DTO, VO, Entity, Domain, Model 등등이다. 이것들에 대해 간단하게 이야기해보려고 한다.

 

  • Entity : 엔티티의 경우 ID로 구성된 class이다. Entity의 경우 실제 DataBase와 1:1로 매핑되는 클래스이다. DB의 테이블 내에 존재하는 속성만을 가져야 한다. 
  • DTO (Data Transfer Object) : 레이어 사이의 네트워크를 통해 보낼 데이터를 매핑하는 클래스이다. 즉 DB에서 데이터를 얻어 Service나 Controller등으로 보낼 때 사용하는 객체이다.
  • VO (Value Object) : DTO가 레이어 간의 통신 용도로 오고가는 객체이면, VO는 Read Only이며 특정한 비즈니스 값을 담는 객체이다. 
  • DAO (Data Access Object) : 실제로 DB에 접근하는 객체이다. 서비스와 DB를 연결하는 고리의 역할을 한다.

 

사실 위의 예제는 Java의 Spring에 적용되는 예제가 많다. Python에서 DTO를 주로 어떻게 구현하는지를 알아볼 것인데, 가장 심플한 방법은 Dictionary를 사용하는 것이다. 그 외에도 다양한 방법이 있다. 일단 다음과 같은 방식으로 DTO를 파이썬에서도 정의할 수 있다.

 

dataclasses

  • Python 3.7부터 추가되었다.
  • @dataclass 데코레이터를 통해 만들 수 있으며, 설정시 __init__, __repr__그리고 __eq__가 설정된다.
from dataclasses import dataclass

@dataclass
class UserDTO:
	name: str
    	email: str
    	password: str
    
user_dto = UserDTO(
	name="Kani",
    	email="Kani@email.com",
    	password="123456"
)

@dataclass를 통해 만들어진 __repr__ 메소드의 경우 클래스 이름, 필드 이름들 그리고 필드 데이터를 표시해준다.

@dataclass를 통해 만들어진 __eq__ 메소드의 경우 클래스 튜플을 비교해서 현재 인자와 다른 인자가 같은 필드 값을 가지고 있는 지를 비교해준다.

 

NamedTuples

  • 일반 튜플의 서브 클래스이며, 파이썬 3.0부터 소개되었다.
  • Python 3.5부터 도입된 타입 힌팅기능 부터 나중에 Python 3.6부터 강화된 변수 어노테이션 문법이 있다.

 

TypedDicts

  • Python 3.8부터 도입되었다

이렇게 파이썬 기본 라이브러리를 이용해서 DTO를 설정할 수 있는 것을 알았다. 이제 본격적으로 Pydantic을 이용해서 FastAPI의 Schema를 설정해 보려고 한다.

 

Creating Schemas in FastAPI by using Pydantic

기본적인 틀은 다음과 같다.

 

from pydantic import BaseModel

class User(BaseModel):
	name: str
    email: str
    password: str

위의 경우처럼 pydantic에서 import한 BaseModel을 상속하게 된다. 그러면 이제 일반적인 파이썬 타입 힌팅 기능을 사용해서 기대되는 필드를 정의해줄 수 있다. 그러면 다음과 같이 데이터를 넣을 수도 있다.

이렇게 Pydantic을 이용해서 얻을 수 있는 장점은 다음과 같다.

  • 새로운 micro-language를 배울 필요가 없다.
  • "리퀘스트와 리스폰스에 데이터에 대한 검증"에 대한 이점
  • 복잡한 데이터 구조에 대한 검증
  • 확장성 - 커스텀 데이터 타입들을 만들 수 있다
  • 파이썬 데이터 클래스와 같이 사용할 수 있다.
 

GitHub - KaniKim/VueFast: Vue.js version 3 with FastAPI

Vue.js version 3 with FastAPI. Contribute to KaniKim/VueFast development by creating an account on GitHub.

github.com

그럼 본격적으로 위의 내가 작성한 코드에서 어떻게 Pydantic이 사용되는지 알아보려고 한다.

위의 코드가 어떻게 작동되는지 하나씩 설명해 보겠다.

 

  1. 이 router.post의 endpoint는 "/api/user/"가 된다. 이때 이 Post 메소드는 성공할 경우 HTTP_201_Created를 반환하며, 동시에 UserResponse에 맞춰서 반환한다. 
  2. user_info를 통해 UserRequest에 맞는 형식의 데이터를 받아들인다. 이때 이 값이 None일 경우는 일단 None으로 기본 설정을 해 두었다.
  3. 만약 위의 EmailStr에 안맞는 값이 들어올 경우 값이 반환되면서 에러가 반환된다. 그 외의 경우에는 잘 들어가서 유저를 만들게 된다.

만약 실제로 email을 엉망으로 쓰면 어떻게 될까? 다음과 같이 된다.

 

오른쪽에 보면 "value is not a valid email address"로 나온다. 즉 제대로 된 이메일 형식이 아니라서 에러를 뿜은 것이다.

 

이렇듯 위의 예시처럼 Pydantic의 강력한 Request, Response 검증을 통해 손쉽게 서버를 유지보수할 수 있다는 장점이 있다.

 

 

728x90
반응형
  • 네이버 블로그 공유
  • 네이버 밴드 공유
  • 페이스북 공유
  • 카카오스토리 공유