[TIL] Flask 프로젝트를 FastAPI로 이관하기(3)

RE_BROTHER·2026년 7월 27일

FastAPI-migration

목록 보기
3/7

실제 FastAPI 이관 작업

1. 실제 마이그레이션 시작

2편까지는 FastAPI로 전환하려는 이유와 작업 순서를 정리했다. 이번 글부터는 실제 코드에서 어떤 부분을 변경했는지 정리해보려고 한다.

이번 작업에서는 Flask 앱을 바로 삭제하지 않고, 기존 Flask 앱은 실행 가능한 상태로 유지하면서 별도의 FastAPI 앱을 추가했다. 이렇게 하면 기존 기능을 참고하면서 API를 하나씩 옮길 수 있고, 문제가 생겼을 때 비교할 수 있는 기준도 남는다.

2. FastAPI 앱 엔트리포인트 추가

FastAPI 앱은 fastapi_app/main.py에서 생성하고, 외부 ASGI 서버가 사용할 수 있도록 asgi.py에서 앱을 노출했다.

from fastapi_app.main import app

로컬에서는 다음과 같이 실행할 수 있다.

uvicorn asgi:app --reload

기존 Flask의 run.py는 바로 삭제하지 않고 호환 실행 경로로 남겨두었다.

3. 설정 로더 분리

기존 Flask 앱은 app.config을 통해 환경변수와 설정값을 전달받았다. FastAPI에서도 같은 설정을 사용해야 하므로 환경변수 로딩 결과를 AppSettings 객체로 분리했다.

Flask는 이 객체를 app.config으로 변환하고, FastAPI는 app.state.settings에 보관하도록 했다. 이 방식으로 설정 로딩과 프레임워크별 앱 초기화를 나눌 수 있었다.

4. Repository provider 이관

기존 프로젝트에는 SQLite와 D1을 분기하는 repository/provider 구조가 이미 있었다. 이 구조를 활용해 FastAPI에서는 요청의 dependency로 repository provider를 받도록 구성했다.

FastAPI Request
  -> dependency
  -> repository provider
      -> SQLite repository
      -> D1 repository

Flask에서만 사용할 수 있었던 provider 생성 로직은 공용 runtime provider로 옮겼다. 이후 Flask 호환 경로도 같은 builder를 사용하도록 변경해 두 런타임의 저장소 선택 로직을 통합했다.

5. 주요 API 이관

기능별로 FastAPI router를 분리했다.

  • 대시보드
  • 문서
  • 에셋
  • WBS
  • 일정
  • 멤버
  • 페이지뷰 로그

문서와 에셋 API는 목록·상세·생성·수정·삭제뿐만 아니라 폴더, 태그, 일괄 처리, 업로드·다운로드까지 함께 이관해야 했다.

6. Flask app context 의존성 줄이기

실제 작업에서 가장 시간이 많이 걸린 부분은 Flask decorator를 FastAPI decorator로 바꾸는 일이 아니었다. current_app, g, Flask 전역 설정에 숨어 있던 의존성을 찾아내는 일이 더 중요했다.

DB 연결, storage 설정, 로그 파일 경로를 명시적인 설정 기반 함수로 분리했다. FastAPI는 lifespan에서 연결을 만들고, Flask 호환 함수는 기존 app context에서 동작하도록 유지했다.

7. 파일 처리 이관

파일 업로드는 UploadFile의 stream을 사용하고, local/R2 분기는 storage 계층에서 담당하도록 했다. 라우터에서는 업로드 결과로 object key, 공개 URL, content type, size, checksum을 받아 repository에 메타데이터를 저장한다.

다운로드는 파일 바이트와 Content-Disposition 헤더를 FastAPI Response로 반환하도록 변경했다. 이 덕분에 파일을 브라우저에서 열어버리는 대신 다운로드 응답으로 제어할 수 있었다.

8. 현재까지의 결과

현재 FastAPI는 핵심 API와 프론트엔드 진입 라우팅을 직접 처리할 수 있다. Flask는 아직 제거하지 않았지만, run.py와 기존 blueprint를 호환 경로로 두고 공용 계층부터 Flask 의존성을 줄인 상태다.

다음 글에서는 Docker와 운영 배포 구조, Cloudflare D1/R2 연결, 그리고 Cloudflare Worker를 메인 애플리케이션으로 사용하지 않으면서 Container를 연결하는 방법을 정리할 예정이다.

profile
@github https://github.com/jhpark-jarvis

0개의 댓글