2025/10/01 FastAPI -3

김기훈·2025년 9월 30일

TIL

목록 보기
30/191

습관 만들기

  • 시작전에 전체 테스트 한번 돌려보는 습관 기르기

API Spec만들기

API 스펙(spec) : API가 어떻게 동작하는지에 대한 “계약서”(실무에서 구현보다 스펙을 먼저 작성 하는게 좋음)

  • 어떤 URL(path) 에 어떤 HTTP 메서드(GET, POST, PUT, DELETE) 를 써야 하는지,
  • 요청(Request) 시 어떤 데이터(body, query, header) 를 보내야 하는지,
  • 응답(Response)이 어떤 형식(JSON, 상태코드, 필드 구조) 으로 오는지를 정리한 문서.

main 구분


uvicorn

  • FastAPI 서버 실행기(엔진)
    • FastAPI는 웹 프레임워크일 뿐, 직접 실행할 수 있는 게 아님.
      • ASGI 서버(uvicorn) 위에서 돌아가야 요청을 처리할 수 있다.
  • uvicorn main:app --reload
    • main:app : main.py 안에 있는 app = FastAPI() 객체를 실행한다는 뜻
    • --reload : 코드 수정하면 서버 자동으로 다시 시작 (개발용 필수)
  • 동작 흐름
    • uvicorn이 켜진다 → FastAPI 앱을 불러온다 → 클라이언트가 http://localhost:8000/items/1 요청 → uvicorn이 요청을 받아서 → FastAPI 함수(@app.get)로 전달 → FastAPI가 응답을 만들어서 → 다시 uvicorn이 클라이언트에게 반환

직렬화 / 역직렬화

서버와 클라이언트는 JSON, XML 같은 텍스트 형식으로 주고받음 : 직렬화 없으면 주고받기 X
파일 저장: 메모리 안 객체는 그냥 저장 불가능 → 직렬화해서 파일에 씀.
캐싱/DB 저장: 객체 그대로 저장 불가 → 직렬화 필요.

  • 직렬화(Serialization)

    • 메모리에 있는 객체(파이썬 dict, list, 클래스 인스턴스 등)저장하거나 전송할 수 있는 형식(문자열, 바이트)으로 바꾸는 과정
      • Python의 dict → JSON 문자열
      • Python 객체 → 바이트 스트림
      • 메모리 안 자료 → 파일로 저장 / 네트워크로 전송 가능
    • “컴퓨터 안 복잡한 구조 → 단순한 문자열/바이트” 로 바꾸는 것
  • 역직렬화(Deserialization)

    • 저장된 JSON 문자열이나 바이트 데이터를 다시 원래 Python 객체로 되돌리는 과정

orjson

  • orjson은 JSON을 위한 Python용 빠르고 정확한 JSON 라이브러리
    • 다른 라이브러리 보다 정확도가 높다
    • dataclass , datetime , numpy , UUID 인스턴스를 기본적으로 직렬화
  • 설치

orjson 주요 기능

  • JSONEncodeError , Type is not JSON serializable: ...
    • 지원되지 않는 유형에서 발생: 이 문제를 해결하기 위해서는 default를 지정해야함

fastapi 실습

router 생성

  • APIRouter : 라우터 객체
    • prefix : URL 앞부분을 미리 정해두는 값
      • /v1/edgedb/meetings 아래의 모든 엔드포인트가 이 라우터에 속함
    • tags=["Meeting"]
      • Swagger 문서에서 이 API 그룹을 "Meeting" 이라는 이름으로 묶어 보여줌


DTO

  • data를 전달하기 위한 목적으로 생성한 객체를 의미
    • dto 는 오직 데이터를 “전달”만 해야 하며, 데이터를 수정, 추가, 삭제하면 안됨
  • pydantic basemodel 을 상속하는 CreateMeetingResponse 가 현재 dto

DTO 대신 Dict를 사용

  • dict일 경우 실수로 키를 추가하거나 누락해도 오류를 잡아내기 쉽지 않음

식별자

Final

  • 재할당을 막고 mutable한걸 immutable로 변경시키지는 못한다.


Base62/64

  • 정수를 Base62 문자열로 바꾸는 클래스
import string
from typing import Final, ClassVar

class Base62:
    BASE: Final[ClassVar[str]] = string.ascii_letters + string.digits
    BASE_LEN: Final[ClassVar[int]] = len(BASE)

    @classmethod
    def encode(cls, num: int) -> str:
        if num < 0:
            raise ValueError(f"{cls}.encode() needs positive integer but you passed: {num}")

        if num == 0:
            return cls.BASE[0]

        result = []
        while num:
            num, remainder = divmod(num, cls.BASE_LEN)
            result.append(cls.BASE[remainder])
        return "".join(result)

class Base62:
    BASE: Final[ClassVar[str]] = string.ascii_letters + string.digits
    BASE_LEN: Final[ClassVar[int]] = len(BASE)
  • BASE : a~z,A~Z,0~9 : 62개 이기 때문에 Base62
  • ClassVar[str] : 타입 힌트중의 하나로 클래스 변수임을 명시하기 위하여 사용
    • 타입 힌트는 없어도 상관은 없지만 인스턴스 변수로 오해받을 수 있다.
    • str로 이 값의 타입은 문자열이라는것을 알린다.
    • mypy같은 타입체커가 ClassVar을 보고 이건 클래스 변수니까 self로 접근하지 마라 라고 알려줌
    • Final : 재할당 금지

    @classmethod
    def encode(cls, num: int) -> str:
  • @classmethod = 데코레이터 : 클래스 메서드를 정의할 때 사용
    • 첫 번째 인자가 cls (즉, 클래스 자체).
    • 클래스 변수(BASE, BASE_LEN처럼 ClassVar)에 접근가능
    • 인스턴스를 만들지 않고도 클래스명.method() 형태로 호출 가능.
  • Base62.encode(12345) 처럼 바로 호출 가능.
    • 데코레이터가 없었으면 cls가 전부 self로 바뀜
    • encoder = Base62() 이렇게 인스턴스 생성하고 print(encoder.encode(12345)) 이렇게 사용

        if num < 0:
            raise ValueError(f"{cls}.encode() needs positive integer but you passed: {num}")

        if num == 0:
            return cls.BASE[0]
  • num < 0 → 예외 발생시킴. (음수는 인코딩 불가) / num == 0 → BASE[0] 반환 (즉 'a')

result = []
while num:
    num, remainder = divmod(num, cls.BASE_LEN)
    result.append(cls.BASE[remainder])
return "".join(result)
  • while num: : num이 0이 아닐 동안 반복한다.(사실상 while num != 0: 과 같음)
  • divmod(num, cls.BASE_LEN) : num을 62로 나눈 몫(num)과 나머지(remainder)를 동시에 구함.
  • Base62.encode(62) 일 경우
    • 1바퀴: num, remainder = divmod(62, 62) (1,0) → 'a' 추가
    • 2바퀴: num, remainder = divmod(1, 62) (0,1) → 'b' 추가
      • 결과 : ab

디버깅

프로그램에서 발생하는 오류(bug)를 찾아내고, 그 원인을 파악해서 수정하는 과정


Deterministic

Base62 연산은 “결정적”(deterministic) / 결정적: 같은 입력을 하면 항상 같은 결과가 나온다는 뜻


sqids

Sqids는 숫자로부터 짧은 고유 식별자를 생성할 수 있는 오픈 소스 라이브러리

profile
안녕하세요.

0개의 댓글