고급 웹프로그래밍

FastAPI(models)

rabbit-jun 2025. 4. 2. 19:58

아래의 코드를 설명하기 앞서 전체적인 흐름을 알고가자.

  1. 클라이언트가 POST /tags 요청을 보낸다
  2. Tag에 id와 tag 그리고 datetime과 secret이 담긴 객체가 생성된다
  3. 이렇게 만든 Tag객체를 services.create_tag(tag)에 인자로 보낸다.
  4. services에서 정의한대로 tag_list에 클라이언트가 보낸 id와 tag가 딕셔너리 형태로 저장된다.
  5. 클라이언트가 GET/tags/{id} 요청을 보낸다
  6. 클라이언트가 보낸 id가 services.get_tag(id)의 인자로 넣어진다
  7. create_tag에 의해 만들어진 list에서 클라이언트가 만든 id와 GET 요청으로 보낸 id가 같으면 Tag 인스턴스 생성
  8. 이 인스턴스에서 TagOut을 반환한다 했으니 TagOut에 정의한 데이터들만 Tag에서 반환

 

models.py

from datetime import datetime
from pydantic import BaseModel

class Tag(BaseModel):
    id: int
    tag: str
    created_at: datetime  
    secret: str

class TagIn(BaseModel):
    id: int
    tag: str

 class TagOut(BaseModel):
    id: int
    tag: str
    created_at: datetime   
  • Tag : 서버 내부에서 사용하는 전체 데이터 구조
  • TagIn : 클라이언트가 요청 시 제공해야 하는 데이터 구조
  • TagOut : 클라이언트가 값을 받을 때 datetime도 받을 수 있게 만든 구조
  • 'BaseModel`: 데이터를 다룰 수 있는 객체
    • 자동 json 파싱
    • 타입 검사(ex. ``tag: str`이면 str만 받는다)
    • 문서화 (/docs)
    • 데이터 검증 (값이 빠졌거나, 잘못된 형식이면 자동 오류 발생)

 

services.py

import datetime
from models import Tag
from fastapi import HTTPException

tag_list={}

def create_tag(tag: Tag) -> Tag:
    tag_list[tag.id]= tag.tag
    return tag

def get_tag(id: int) -> Tag:
    for k,v in tag_list.items():
        if k == id:
            return Tag(id= k, 
               tag=v, 
               created_at= datetime.datetime.now(),
               secret="secret"
    )

    raise HTTPException(status_code=404, detail="Tag not found")
  • create_tag : 실제 저장 로직이 들어가는 자리
  • get_tag : 예시 데이터를 반환하는 함수

 

main.py

from models import Tag,TagIn
import services
import datetime

@app.post("/tags")
def create_tag(tag_in: TagIn) -> TagIn:
    tag: Tag = Tag(
        id=tag_in.id,
        tag=tag_in.tag,
        created_at=datetime.datetime.now(),
        secret="a"
    )
    services.create_tag(tag)
    return tag_in

@app.get("/tags/{id}")
def get_tag(id: int) -> TagOut:
    tag: Tag = services.get_tag(id)
    return tag # Tag 객체에서 TagOut이 요청하는 데이터를 자동으로 추출해서 반환(TagOut이 Tag의 서브셋이라 가능)
  • tag_in: TagIn : 요청 본문을 TagIn 모델로 파싱함 (id, tag만 있음)
  • -> TagIn: 응답으로 TagIn 형식만 클라이언트에게 전달
  • 내부에서는 TagIn + 추가정보 -> Tag 객체 생성
  • services.create_tag(tag): 저장 또는 가공 로직 호출
  • return tag_in: 민감 정보(secret 등)를 숨기고 클라이언트에게 요청값 그대로 반환

 

데이터를 만들고 가져오는 예시

 

 

질문

1. TagOut이 Tag의 서브셋인지는 자동으로 판단하나요?

  • FastAPI가 Tag와 같은 변수명을 쓰는 TagOut을 서브셋으로 인식

 

2. services.create_tag(tag) 에서 객체를 인자로 받았는데 이거 그냥 쓰면 안되나?

def create_tag(tag: Tag) -> Tag:
    tag_list[tag.id] = tag
    return tag


def get_tag(id: int) -> Tag:
    tag = tag_list.get(id)
    if not tag:
        raise HTTPException(status_code=404, detail="Tag not found")
    return tag

이렇게 하면 객체를 통으로 가져다 쓸 수 있다

반응형