FastAPI: Pydantic from_attribute, model_validate

임동혁 Ldhbenecia·2025년 2월 13일

FastAPI

목록 보기
1/2
post-thumbnail

개요

Spring Boot에서는 Entity를 DTO로 변환할 때 Builder 패턴이나 팩토리 메서드 패턴을 활용하여 변환 메서드를 직접 구현하는 것이 일반적이다.

하지만 FastAPI에서는 이러한 변환 과정을 간결하게 처리할 수 있는 내장 기능이 제공된다.

  • Field(from_attribute=True)를 활용하여 ORM 객체를 Pydantic 모델로 자동 변환
  • model_validate()를 사용하여 데이터를 검증하며 DTO로 변환

이번 글에서는 FastAPI에서 ORM을 DTO로 변환하는 방법과 장점에 대해 알아본다.

  • Spring Boot 방식과 FastAPI 방식 비교
    • toDto() 같은 변환 메서드를 직접 구현해야 하는 Spring Boot 방식과
    • FastAPI(Pydantic)의 modl_validate(), from_attribute=True를 활용한 간단한 변환 방식 비교
  • ORM을 직접 반환하는 경우와 변환하는 경우 차이점
    • FastAPI에서는 Pydantic 모델을 이용하여 변환하는 것이 일반적이며,
    • 직접 ORM을 반환하는 경우의 장단점(예: SQLAlchemy ORM 객체의 lazy loading 문제 등)
  • FastAPI에서 권장되는 변환 방법
    • Field(from_attribute=True)를 활용한 방법
    • model_validate()를 활용한 방법
    • 위 두 가지를 결합하여 ORM에서 DTO로 변환하는 최적화된 방식

1. Spring Boot vs FastAPI: Entity → DTO 변환 방식

Spring Boot에서는 데이터 변환을 직접 수행해야 한다.

FastAPI는 Pydantic의 기능을 활용하여 한 줄로 변환이 가능하다.

✅ Spring Boot 방식 (Builder 패턴 또는 팩토리 메서드)

@Getter
@AllArgsConstructor
@Builder
public class UserDto {
    private Long id;
    private String username;
    private String email;

    public static UserDto fromEntity(UserEntity user) {
        return UserDto.builder()
            .id(user.getId())
            .username(user.getUsername())
            .email(user.getEmail())
            .build();
    }
}
  • UserDto.fromEntity(userEntity)를 직접 호출해야 변환이 가능

✅ FastAPI 방식 (Field(from_attribute=True))

FastAPI에서는 Pydantic의 Field(from_attribute=True)를 사용하여 ORM을 Schema(Dto)로 변환할 수 있다.

from_attributePydantic v2에서 도입된 기능으로, 모델 필드를 변환할 때 사용된다.

특히, FastAPI에서 ORM 모델을 Pydantic 모델로 변환할 때 유용하다.

  • ORM 모델의 필드를 Pydantic 모델로 변환할 때 사용
  • Field(from_attribute=True)를 사용하면, Pydantic이 SQLAlchemy ORM 객체에서 해당 필드를 자동으로 가져와 변환
  • Config.from_attributes = True를 설정하면, 모델 전체에서 자동으로 적용
from pydantic import BaseModel, Field
from sqlalchemy.orm import declarative_base
from sqlalchemy import Column, Integer, String

Base = declarative_base()

# SQLAlchemy ORM 모델
class UserORM(Base):
    __tablename__ = "users"
    id = Column(Integer, primary_key=True, index=True)
    username = Column(String, unique=True, index=True)
    email = Column(String, unique=True, index=True)

# Pydantic 모델
class UserSchema(BaseModel):
    id: int = Field(from_attribute=True)
    username: str = Field(from_attribute=True)
    email: str = Field(from_attribute=True)

    class Config:
        from_attributes = True  # 전체 모델에서 사용 가능

✅ FastAPI 방식 (model_validate())

변환 코드 없이 한 줄로 ORM을 DTO로 변환 가능

from pydantic import BaseModel

class UserSchema(BaseModel):
    id: int
    username: str
    email: str

# dict -> Pydantic 모델 변환
user_data = {"id": 1, "username": "fastapi_user", "email": "user@example.com"}
user = UserSchema.model_validate(user_data)

print(user)
# UserSchema(id=1, username='fastapi_user', email='user@example.com')

model_validate()Pydantic v2에서 제공하는 객체 검증 메서드이다.

데이터가 Pydantic 모델과 일치하는지 검증하고, 자동 변환을 수행할 수 있다.

model_validate()의 역할

  • dict, ORM 객체, JSON 등 다양한 데이터 유형을 Pydantic 모델 인스턴스로 변환
  • UserSchema(**data)처럼 직접 인스턴스를 생성하는 것과 동일하지만, 더 유연하고 안전
  • FastAPI에서 요청 데이터를 검증할 때 유용

2. ORM을 직접 반환하는 경우 vs Schema로 변환하는 경우

FastAPI에서 SQLAlchemy ORM 객체를 직접 반환하는 것은 비효율적일 수 있음

❌ ORM 객체를 직접 반환할 경우 (비추천)

@app.get("/users/{user_id}")
async def get_user(user_id: int, db: Session = Depends(get_db)):
    user = db.query(UserORM).filter(UserORM.id == user_id).first()
    return user  # ❌ ORM 객체 반환 (비효율적)

⚠️ 문제점

  • FastAPI는 자동으로 JSON 직렬화하지만, ORM 객체는 dict가 아님.
  • SQLAlchemy의 lazy loading 문제가 발생할 수 있음.

✅ Pydantic Schema로 변환 후 반환 (권장)

@app.get("/users/{user_id}", response_model=UserSchema)
async def get_user(user_id: int, db: Session = Depends(get_db)):
    user = db.query(UserORM).filter(UserORM.id == user_id).first()
    return UserSchema.model_validate(user)  # DTO 변환 후 반환

이점

  • ORM 객체의 lazy loading 문제 방지
  • DTO를 이용해 불필요한 필드 제거 가능
  • 한 줄로 변환 가능

3. from_attribute + model_validate 같이 사용하기

이 두 개를 같이 사용하면, ORM 모델에서 Pydantic 모델로 변환하면서 데이터를 검증할 수 있다.

# ORM 객체 생성
user_orm = UserORM(id=1, username="fastapi_user", email="user@example.com")

# Pydantic 모델로 변환 (ORM 객체 검증)
user_schema = UserSchema.model_validate(user_orm)

print(user_schema)
# UserSchema(id=1, username='fastapi_user', email='user@example.com')
  • from_attribute 덕분에 ORM 모델에서 데이터를 자동으로 매핑
  • model_validate()를 사용해 데이터 검증 및 변환

🔥 정리

Spring Boot 방식FastAPI 방식
toDto() 변환 메서드 필요model_validate() 한 줄 변환
Builder 패턴, 팩토리 메서드 사용Field(from_attribute=True) 사용
직접 DTO 객체를 생성해야 함ORM을 자동으로 Pydantic 모델로 변환 가능
Lazy loading 문제 해결 필요Pydantic이 변환 처리

기능설명
from_attributeSQLAlchemy ORM 객체에서 Pydantic 모델로 데이터 변환
model_validate()딕셔너리 또는 ORM 객체를 Pydantic 모델로 변환 및 검증

🎯 결론

Spring Boot에서는 DTO 변환을 직접 해야 하지만, FastAPI는 ORM → DTO 변환을 자동화하는 기능이 내장되어 있어 훨씬 간결하게 구현할 수 있음

profile
지극히 평범한 공대생

0개의 댓글