본문 바로가기

개발자 생활

FastAPI 연재 5편 — SQLModel + SQLite로 MVP DB “일단” 만들기

반응형

MVP에서는 DB를 빨리 붙여야 한다. 근데 또 나중에 바꿀 수도 있다.

그래서 내가 택한 조합은 이거.

  • SQLModel: Pydantic + SQLAlchemy 감성 합쳐진 ORM
  • SQLite: 설치 없이 파일로 끝, MVP 속도 최강

1) SQLite 파일 경로를 “정책”으로 만든다

대표 이미지 (SQLModel + SQLite)

내 설정은 기본으로 홈 디렉토리 아래에 DB를 만든다.

  • ~/.doubles/server/doubles.db

이걸 코드로 만들면 대충 이런 느낌.

def get_default_database_path() -> Path:
    return Path.home().joinpath(".doubles", "server", "doubles.db")

def build_sqlite_url(path: Path) -> str:
    return f"sqlite:///{path.resolve()}"

장점이 뭐냐면:

  • 로컬에서 어디서 실행하든 DB 위치가 예측 가능
  • 도커에서는 DOUBLES_DATABASE_URL로 완전히 갈아끼울 수 있음

2) SQLite는 디렉토리가 없으면 터진다 → 미리 만들어주기

이거 은근히 자주 맞는 함정이다.

그래서 엔진 만들기 전에 DB 디렉토리를 만들어준다.

def _prepare_sqlite_directory(database_url: str) -> None:
    if not database_url.startswith("sqlite:///"):
        return
    database_path = Path(database_url.removeprefix("sqlite:///"))
    database_path.parent.mkdir(parents=True, exist_ok=True)

3) 엔진/Settings 캐시를 같이 쓰면 깔끔하다

Settings는 캐시(lru_cache), 엔진도 캐시(lru_cache)로 맞춰두면 “프로세스 생명주기” 관점에서 자연스럽다.

@lru_cache
def _get_engine_for_url(database_url: str) -> Engine:
    _prepare_sqlite_directory(database_url)
    return create_engine(database_url, connect_args={"check_same_thread": False})

SQLite에서 check_same_thread=False는 FastAPI 같은 웹앱에서 자주 필요한 세팅이라 같이 기억해두면 좋다.


4) 모델 설계: JSON 컬럼이 MVP에서는 꽤 쓸모 있다

“DB 경로 정책” 개념 이미지

Diary 모델에는 이런 데이터가 들어간다.

  • 동선(place_visits): 리스트/딕셔너리
  • 사진 EXIF(photos_exif): 리스트/딕셔너리
  • AI 결과(photo_descriptions): 리스트/딕셔너리

MVP에서는 RDB 정규화보다 “일단 쌓고 기능 만들기”가 급할 때가 많다.
그래서 JSON 컬럼이 꽤 편했다.

place_visits: list[dict[str, Any]] = Field(
    default_factory=list,
    sa_column=Column(JSON, nullable=False, default=[]),
)

단, 이건 나중에 확장하면 구조 바꿀 수도 있다. (MVP니까… ㅎㅎ)


실습: DB가 자동으로 만들어지는지 확인

서버를 띄우고 /api/v1/diaries를 한 번 호출해보자.

curl -sS "http://127.0.0.1:8000/api/v1/diaries"

여기서 중요한 건 “응답이 뭐냐”보다, 앱 시작 시점에 테이블이 생성되어 오류 없이 돌아가느냐다.


마무리

SQLModel + SQLite 조합은 “빠르게 시작하고, 나중에 갈아끼우기”에 좋다.
다음 편에서는 multipart/form-data로 Form + File을 같이 받으면서 검증을 어떻게 했는지 본다. (여기부터 진짜 실전 느낌)


참고

반응형