본문 바로가기
IT & TECH/개발기록

[프로젝트] PC 자산관리 프로그램 개발기 #5 : FastAPI의 문지기, Pydantic으로 데이터 검증 시스템 구축하기 (ORM vs Schema 완벽 정리)

by codenplay 2026. 1. 2.

FastAPI의 문지기, Pydantic으로 데이터 검증 시스템 구축하기 (ORM vs Schema 완벽 정리)
FastAPI의 문지기, Pydantic으로 데이터 검증 시스템 구축하기 (ORM vs Schema 완벽 정리)

1. 서론: DB 연결은 끝났다, 이제 '검문소'를 세울 차례

지난 포스팅에서 우리는 사내 시스템의 심장인 오라클 데이터베이스(Oracle 11g)와 FastAPI를 연동하는 데 성공했습니다. (database.py 설정 완료) 이제 고속도로는 뚫렸으니 데이터를 주고받기만 하면 될까요? 절대 아닙니다.

 

사용자(프론트엔드)가 자산 가격(Price) 칸에 숫자가 아닌 "백만원"이라는 한글을 적어서 보낸다면 어떻게 될까요? 혹은 필수 입력값인 '사번'을 빼먹고 보낸다면요? DB는 에러를 뿜어내고 시스템은 멈출 수 있습니다.

 

그래서 우리는 DB 앞에 깐깐한 문지기를 하나 세워야 합니다. 들어오는 데이터가 올바른지 검사하고, 나가는 데이터를 예쁘게 포장해 주는 역할. 바로 FastAPI의 꽃, Pydantic(파이단틱)을 이용한 스키마(Schema) 정의 단계입니다.


2. 개념 잡기: SQLAlchemy(모델) vs Pydantic(스키마)

FastAPI를 처음 접하는 분들이 가장 헷갈려 하는 것이 바로 models.py와 schemas.py의 차이입니다. 둘 다 데이터의 생김새를 정의하지만, 그 목적과 활동 영역이 완전히 다릅니다.

 

이 차이를 명확히 이해해야 프로젝트가 꼬이지 않습니다.

[표] 모델(Model) vs 스키마(Schema) 비교

구분 SQLAlchemy 모델 (models.py) Pydantic 스키마 (schemas.py)
핵심 역할 데이터베이스(DB)의 테이블 정의 API 요청/응답(Request/Response) 정의
활동 영역 서버 ↔ DB 사이 (백엔드 내부) 클라이언트 ↔ 서버 사이 (입출력)
주요 기능 컬럼 타입, 관계(FK), 테이블 옵션 설정 데이터 유효성 검증(Validation), 필터링
비유 실제 물건이 보관되는 '창고' 물건을 들이고 내보낼 때 쓰는 '주문서'

💡 요약: DB에 테이블을 만들 때는 SQLAlchemy를 쓰고, API로 데이터를 주고받을 때는 Pydantic을 씁니다.

 


3. 프로젝트 구조 및 준비

본격적인 코딩에 앞서, 프로젝트 폴더 구조를 다시 한번 점검합니다. 체계적인 관리를 위해 파일들을 분리하는 것이 좋습니다.

📂 my_asset_project
├── 📄 main.py        (앱 실행 파일)
├── 📄 database.py    (DB 접속 설정)
├── 📄 models.py      (DB 테이블 정의 - 지난 시간 완료)
└── 📄 schemas.py     (★ 오늘 만들 파일 - 데이터 검증)

가상환경이 켜진 상태에서 pydantic 라이브러리가 설치되어 있어야 합니다. (FastAPI 설치 시 보통 같이 설치되지만, 혹시 모르니 확인해 주세요.)

pip install pydantic

4. 실전 구현: schemas.py 작성하기

이제 schemas.py 파일을 생성하고, 우리 프로젝트인 'PC 자산관리'에 필요한 데이터 규칙을 정의해 보겠습니다. 우리가 관리할 데이터는 자산명, 모델명, 구매일, 가격, 지급상태 등입니다.

from pydantic import BaseModel, Field
from typing import Optional
from datetime import date

# ==========================================
# 1. 공통 속성 정의 (Base)
# ==========================================
# 데이터를 생성할 때(Create)나 조회할 때(Read) 공통적으로 들어가는 필드입니다.
# 상속을 통해 코드 중복을 줄입니다.
class PCAssetBase(BaseModel):
    asset_name: str = Field(..., title="자산명", max_length=50) # ...은 필수값 의미
    model_name: str = Field(..., title="모델명", max_length=100)
    manufacturer: Optional[str] = None # 제조사는 비워둘 수 있음 (선택 사항)
    
    # 0보다 큰 값만 받도록 검증 가능 (Pydantic의 강력한 기능)
    price: int = Field(gt=0, description="가격은 0원 이상이어야 합니다.")
    
    buy_date: date  # 날짜 형식 자동 검증 (2024-01-01 형식)

# ==========================================
# 2. 데이터 생성용 스키마 (Create)
# ==========================================
# 클라이언트(사용자)가 데이터를 보낼 때 검증하는 규격입니다.
# Base 클래스를 상속받으므로 위 내용이 그대로 포함됩니다.
class PCAssetCreate(PCAssetBase):
    pass 
    # 추가로 필요한 필드가 있다면 여기에 작성 (예: 비밀번호 등)

# ==========================================
# 3. 데이터 응답용 스키마 (Response)
# ==========================================
# 사용자에게 데이터를 보여줄 때 사용하는 규격입니다.
# DB에 저장된 ID(PK)나 생성일시 같은 시스템 정보는 여기서 추가됩니다.
class PCAsset(PCAssetBase):
    id: int            # DB에서 자동 생성된 고유 번호
    is_active: bool    # 사용 가능 여부
    
    # [중요] Pydantic V2 설정 (구 orm_mode = True)
    # 이것을 설정해야 SQLAlchemy 객체(DB 데이터)를 Pydantic 모델로 변환할 수 있습니다.
    class Config:
        from_attributes = True

🔍 코드 뜯어보기 (핵심 포인트)

  1. BaseModel 상속: 모든 Pydantic 스키마는 BaseModel을 상속받아야 작동합니다.
  2. Field(...): 단순한 타입 지정뿐만 아니라, max_length(최대 길이), gt(Greater Than, 값 크기 제한) 같은 상세한 제약 조건을 걸 수 있습니다. 이게 바로 '문지기' 역할입니다.
  3. from_attributes = True: 아주 중요합니다. 데이터베이스에서 꺼내온 데이터는 '객체' 형태인데, 이를 Pydantic이 이해할 수 있는 'JSON(딕셔너리)' 형태로 읽으려면 이 옵션이 필수입니다. (Pydantic V1에서는 orm_mode라고 불렸습니다.)

5. 왜 Pydantic을 써야 하는가? (장점 분석)

실무에서 Pydantic을 적용했을 때 얻을 수 있는 이점은 명확합니다.

  • 자동 데이터 변환 (Parsing): 사용자가 id="123"이라고 문자열로 보내도, 스키마에 id: int라고 되어 있으면 알아서 숫자 123으로 바꿔줍니다. 개발자가 일일이 형 변환을 할 필요가 없습니다.
  • 친절한 에러 메시지: 데이터 형식이 틀리면, "Internal Server Error" 같은 불친절한 메시지 대신 "price 필드는 숫자여야 합니다"라고 구체적인 JSON 에러를 자동으로 리턴해 줍니다. 프론트엔드 개발자와 싸울 일이 줄어듭니다.
  • IDE 자동완성 지원: 파이썬의 타입 힌트(Type Hint)를 기반으로 하므로, VS Code 같은 에디터에서 자동완성 기능이 완벽하게 지원됩니다. 오타로 인한 버그가 획기적으로 줄어듭니다.

6. 마치며: 뼈대 완성, 이제 살을 붙이자

오늘은 사내 시스템 개발의 네 번째 단계로, 데이터의 입출력 규칙(Schema)을 완벽하게 정의했습니다.

  1. DB 연결 (database.py)
  2. 테이블 정의 (models.py)
  3. 검증 규칙 정의 (schemas.py)

이제 준비운동은 모두 끝났습니다. 다음 시간에는 이 모든 조각을 합쳐서, 실제로 데이터를 DB에 넣고(Create), 조회하고(Read), 수정하는(Update) CRUD API 로직(main.py)을 구현해 보겠습니다.

 

드디어 다음 편부터, 우리가 만든 시스템이 살아서 움직이는 모습을 볼 수 있습니다. 기대해 주세요!

 

[함께 보면 좋은 글]

2025.12.28 - [IT & TECH/개발기록] - [프로젝트] PC 자산관리 개발기 #4 : FastAPI와 오라클 11g 연동! (cx_Oracle 말고 python-oracledb 쓰세요)

 

2025.12.03 - [IT & TECH/개발기록] - [프로젝트] PC 자산관리 프로그램 개발기 #3 : 왜 FastAPI인가? & 파이썬 가상환경 구축 완벽 가이드

 

[프로젝트] PC 자산관리 프로그램 개발기 #3 : 왜 FastAPI인가? & 파이썬 가상환경 구축 완벽 가이드

1. 지난 이야기 & 시작하며지난 시간까지 VMware에 윈도우 서버를 올리고, 원격 데스크톱(RDP) 포트까지 열었습니다. (이제 서버 준비는 끝났네요!)이제 본격적으로 엑셀을 대체할 'PC 자산관리 시스

codenplay.tistory.com