FastAPI #1 MariaDB, DB Migration, Swagger UI

FastAPI #1 MariaDB, DB Migration, Swagger UI #

#2025-09-17


1. 실습 내용 #

#1 maria db container 띄우기

# 1. conda 가상환경 생성
$ conda create -n demo-app python=3.11
$ conda activate demo-app

# 2. 작업 위치
# mariadb_tmplt 디렉토리를 다운받고 압축 해제함
$ pwd
/Users/yshmbid/Documents/home/github/MLops/mariadb_tmplt
$ ls
conf.d          data            env             maria_db.yaml

# 3. Docker Compose로 MariaDB 실행
$ docker compose -p maria_db -f maria_db.yaml up -d

# 4. 컨테이너가 잘떴는지확인
$ docker ps | grep mariadb
ae333f330cc4   mariadb:10.5.18     "docker-entrypoint.s…"   4 minutes ago   Up 4 minutes   0.0.0.0:3379->3306/tcp           maria_db-sqldb-1
  • docker desktop에서도 확인
image

#

#2 db connection

  • vscode에서 database client extension 열고 create connection
image

#

cf) 컨테이너 기반 실습 환경을 구성하는 이유와 장점

  • 컨테이너 기반 실습 환경을 구성하는 이유
    • 목적1: 모두가 똑같은 환경에서 실습을 하기 위해
      • 내부에서 설치된 라이브러리 버전이나 운영체제 차이 때문에 동일한 python-app.py를 실행해도 실행이안대거나 오류가날수있다.
      • Docker 컨테이너라는 상자 안에 Python 실행 환경을 일정하게 담아두고 Mac이든 Windows든 그 상자를 똑같이 실행시키면 누구든 동일한 환경에서 같은 결과를 낼수있으니까 환경 차이로 인한 오류가 없어진다
    • 목적2: 작업 환경을 제한
      • 단순히 Python 코드만 실행하는 것이 아니라 데이터베이스(DBMS)까지 연결해야 할 때가 많은데 오픈소스 데이터베이스인 MySQL이나 MariaDB 같은 프로그램을 직접 로컬에 설치할 수도 있지만 얘네는 운영체제에 따라 설치 과정이 복잡하고 하드웨어 자원에 의존적이라 충돌이나 오류가 발생하기 쉬운프로그램들이다.
      • Docker 컨테이너를 사용하면 데이터베이스를 별도의 격리된 공간에서 실행할 수 있다. FastAPI를 실행하는 컨테이너 하나, MySQL을 실행하는 컨테이너 하나를 띄워두고, 이 둘을 내부 네트워크로 연결해주는 식으로 작업하면 데이터베이스나 Python 실행 환경이 호스트 컴퓨터 전체를 더럽히지 않고, 필요 없을 때 컨테이너만 지우면 깨끗하게 정리된다.

#

#3

# 5. 필요 패키지 설치
pip install fastapi "uvicorn[standard]"
pip install -r pjt-requirements.txt

# 6. 실행 위치
$ pwd
/Users/yshmbid/Documents/home/github/MLops/skala-fastapi-rpt
$ ls
api                     container               pjt-main.py             pjt-requirements.txt    test-requirements.txt

# 7. uvicorn 실행
$ uvicorn api.main:app --host 127.0.0.1 --port 8001 --reload
INFO:     Will watch for changes in these directories: ['/Users/yshmbid/Documents/home/github/MLops/skala-fastapi-rpt']
INFO:     Uvicorn running on http://127.0.0.1:8001 (Press CTRL+C to quit)
INFO:     Started reloader process [84071] using WatchFiles
INFO:     Started server process [84076]
INFO:     Waiting for application startup.
INFO:     Application startup complete.
  • uvicorn
    • uvicorn을 실행해 fastapi 앱을 실행한다.
    • api 서버가 실행되면 브라우저에서 127.0.0.1:8001로 접속하면 서버가 응답을 돌려줄수있다.
  • swagger ui
    • api를만들면 기능이 코드안에 가려져있어서 어떤 요청을 보내야 하고 어떤 응답이 돌아오는지 알기 어려운데
    • swagger ui가 있으면 내가만든 fast api 서버가 swagger ui를 통해 “이런 엔드포인트들이 있습니다, 이런 식으로 요청을 보내면 되고, 이런 응답이 옵니다”를 자동으로 보여준다.
    • ui 화면에서 실제 api 요청도 보낼수있다.

#

#4

  • routers/task_a.py → done_crud 임포트 및 done 여부 확인 부분 수정
  • routers/done_a.py → DoneResponse 반환 시 done 필드 제거
  • cruds/task_a.py → get_tasks_with_done, update_task에서 Done 여부 올바르게 체크
  • schemas/task_a.py → done 필드 반드시 포함
  • schemas/done_a.py → DoneResponse 정의 필요 (예: class DoneResponse(BaseModel): id: int)
# 8. 실행위치
$ pwd
/Users/yshmbid/Documents/home/github/MLops/skala-fastapi-rpt

# 9. DB 마이그레이션 실행
$ python -m api.migrate_db_a
2025-09-17 12:08:44,735 INFO sqlalchemy.engine.Engine SELECT DATABASE()
2025-09-17 12:08:44,736 INFO sqlalchemy.engine.Engine [raw sql] ()
2025-09-17 12:08:44,740 INFO sqlalchemy.engine.Engine SELECT @@sql_mode
2025-09-17 12:08:44,740 INFO sqlalchemy.engine.Engine [raw sql] ()
2025-09-17 12:08:44,741 INFO sqlalchemy.engine.Engine SELECT @@lower_case_table_names
2025-09-17 12:08:44,741 INFO sqlalchemy.engine.Engine [raw sql] ()
2025-09-17 12:08:44,745 INFO sqlalchemy.engine.Engine BEGIN (implicit)
2025-09-17 12:08:44,745 INFO sqlalchemy.engine.Engine DESCRIBE `demo`.`tasks`
2025-09-17 12:08:44,745 INFO sqlalchemy.engine.Engine [raw sql] ()
2025-09-17 12:08:44,772 INFO sqlalchemy.engine.Engine DESCRIBE `demo`.`dones`
2025-09-17 12:08:44,772 INFO sqlalchemy.engine.Engine [raw sql] ()
2025-09-17 12:08:44,780 INFO sqlalchemy.engine.Engine DESCRIBE `demo`.`tasks`
2025-09-17 12:08:44,780 INFO sqlalchemy.engine.Engine [raw sql] ()
2025-09-17 12:08:44,785 INFO sqlalchemy.engine.Engine DESCRIBE `demo`.`dones`
2025-09-17 12:08:44,785 INFO sqlalchemy.engine.Engine [raw sql] ()
2025-09-17 12:08:44,792 INFO sqlalchemy.engine.Engine 
CREATE TABLE tasks (
        id INTEGER NOT NULL AUTO_INCREMENT, 
        title VARCHAR(1024), 
        PRIMARY KEY (id)
)


2025-09-17 12:08:44,792 INFO sqlalchemy.engine.Engine [no key 0.00017s] ()
2025-09-17 12:08:44,811 INFO sqlalchemy.engine.Engine 
CREATE TABLE dones (
        id INTEGER NOT NULL, 
        PRIMARY KEY (id), 
        FOREIGN KEY(id) REFERENCES tasks (id)
)


2025-09-17 12:08:44,811 INFO sqlalchemy.engine.Engine [no key 0.00013s] ()
2025-09-17 12:08:44,822 INFO sqlalchemy.engine.Engine COMMIT

# 10. fastapi 서버 실행해서 확인
$ uvicorn api.main:app --host 127.0.0.1 --port 8001 --reload
INFO:     Will watch for changes in these directories: ['/Users/yshmbid/Documents/home/github/MLops/skala-fastapi-rpt']
INFO:     Uvicorn running on http://127.0.0.1:8001 (Press CTRL+C to quit)
INFO:     Started reloader process [13839] using WatchFiles
INFO:     Started server process [13867]
INFO:     Waiting for application startup.
INFO:     Application startup complete.
INFO:     127.0.0.1:60547 - "GET / HTTP/1.1" 200 OK
INFO:     127.0.0.1:60547 - "GET /favicon.ico HTTP/1.1" 200 OK
INFO:     127.0.0.1:60550 - "GET /docs HTTP/1.1" 200 OK
INFO:     127.0.0.1:60550 - "GET /openapi.json HTTP/1.1" 200 OK
INFO:     127.0.0.1:60551 - "GET /static/favicon.ico HTTP/1.1" 200 OK
2025-09-17 12:10:21,548 INFO sqlalchemy.engine.Engine SELECT DATABASE()
2025-09-17 12:10:21,551 INFO sqlalchemy.engine.Engine [raw sql] ()
2025-09-17 12:10:21,554 INFO sqlalchemy.engine.Engine SELECT @@sql_mode
2025-09-17 12:10:21,554 INFO sqlalchemy.engine.Engine [raw sql] ()
2025-09-17 12:10:21,554 INFO sqlalchemy.engine.Engine SELECT @@lower_case_table_names
2025-09-17 12:10:21,554 INFO sqlalchemy.engine.Engine [raw sql] ()
2025-09-17 12:10:21,556 INFO sqlalchemy.engine.Engine BEGIN (implicit)
2025-09-17 12:10:21,564 INFO sqlalchemy.engine.Engine SELECT tasks.id, tasks.title, dones.id IS NOT NULL AS done 
FROM tasks LEFT OUTER JOIN dones ON tasks.id = dones.id
2025-09-17 12:10:21,564 INFO sqlalchemy.engine.Engine [generated in 0.00024s] ()
2025-09-17 12:10:21,571 INFO sqlalchemy.engine.Engine COMMIT
[✅ COMMIT 완료]
INFO:     127.0.0.1:60554 - "GET /tasks HTTP/1.1" 200 OK

cf2

SELECT tasks.id, tasks.title, dones.id IS NOT NULL AS done 
FROM tasks LEFT OUTER JOIN dones ON tasks.id = dones.id

SQLAlchemy 로그 해석?

  • tasks와 dones 테이블을 조인해서 각 할 일이 완료되었는지 여부(done)를 계산
  • FastAPI가 JSON으로 가공해 클라이언트에 반환.

#

cf3

swagger ui에서 확인

image

#

#5 실습정리

가상환경 만들기?

  • source ./demo-app/bin/activate
  • 나는 어케하는지몰라서 그냥 conda환경만들엇는데 갠찮겠지..

필요 패키지 설치

  • pip install fastapi “uvicorn[standard]”
  • pip install sqlalchemy aiomysql pymysql greenlet

PathOperation 함수는 경로동작 함수

  • 모듈 임포트하는 모든 경로에, __init__.py 만든다

#

2. 개념 #

  • 목적
    • Docker 컨테이너(MariaDB), SQLAlchemy, FastAPI, Uvicorn을 활용해 동일한 데이터베이스 환경에서 FastAPI 서버를 구축하고 Swagger UI를 통해 API 동작을 확인하는 것

#

  • 구현
    • 컨테이너 실행(Docker + MariaDB): Docker Compose를 이용해 MariaDB 컨테이너를 띄우고, 로컬 환경과 독립된 동일한 DB 환경을 구성함
    • DB 연결(Database Client + SQLAlchemy): VS Code Database Client Extension과 SQLAlchemy를 통해 MariaDB에 연결해 테이블을 조회하고 쿼리를 실행함
    • FastAPI 서버 실행(Uvicorn + FastAPI): FastAPI 앱을 uvicorn으로 구동하여 API 서버를 실행하고, 로컬 브라우저에서 엔드포인트에 접근 가능하게 함
    • Swagger UI 확인(Swagger UI): 자동 문서화된 API 명세서를 통해 엔드포인트 구조와 요청/응답을 직관적으로 확인하고 직접 API 요청을 테스트함
    • DB 마이그레이션(SQLAlchemy ORM): migrate_db_a 모듈을 실행해 tasks/dones 테이블을 자동 생성하고, 조인 쿼리를 통해 완료 여부를 조회하도록 구현함
    • 라우터 및 스키마 수정(FastAPI routers/schemas): routers, cruds, schemas 모듈을 수정하여 done 여부를 올바르게 반영하고 DoneResponse를 정의하여 API 응답 형식을 보장함

#

  • 의문점1
    • (MariaDB를 로컬 운영체제에 직접 깔지 않고) Docker Compose를 이용해 MariaDB 컨테이너를 띄운 이유?
  • 답1
    • mariadb같은 db를 로컬 환경에 깔려고 하면 운영체제마다 설치 방법도 다르고 버전 호환 문제도 많아서 똑같은 코드를 실행해도 어떤 컴퓨터에서는 잘 되고 다른 컴퓨터에서는 에러가 날수있다.
    • 이때 docker에 mariadb를 세팅된 상태로 담아두고 돌리면 2가지 이점이 있는데
      • 맥이든 서버가 리눅스든 상관없이 항상 동일한 MariaDB 환경이 보장되고
      • 삭제할때 컨테이너만 지우면 깨끗하게 정리돼서 추후 호환문제가 발생하는것도 방지할수있다.
  • 의문점2
    • db를 왜 로컬환경에 설치하는가? db가 무엇인가?
  • 답2
    • db는 많은 양의 데이터를 체계적으로 관리하고 동시에 여러 사용자가 빠르게 조회할 수 있도록 도와주는 시스템.
    • 엑셀 파일처럼 몇 줄짜리 데이터만 다룰 거라면 굳이 DB가 필요 없지만
      • 웹 서비스나 API 서버를 만든다고 하면?
        • 예를 들어 할 일 관리 앱을 만든다고 하면
        • 사용자가 추가한 작업들을 어딘가에 저장해 두었다가 나중에 다시 보여줘야하는데
        • 만약 메모리에만 저장하면 서버가 꺼지는 순간 다 사라지고 파일로 저장하면 여러 사람이 동시에 접속해서 데이터를 읽고 쓰기 시작하면 꼬일수있다 그래서 신뢰성 있게 “데이터를 관리"할 수 있는 db가 필요하다!
  • 의문점3
    • “데이터를 관리"한다란?
  • 답3
    • 서비스를 구동하면 데이터가 들어오니까 데이터를 저장하고 조회하고 해야한다.

#

  • 의문점4
    • VS Code Database Client Extension과 SQLAlchemy가 각각 하는일이 무엇인가?
  • 답4
    • vscode db client extension을 쓰면
      • vs code를 통해서 db에 들어있는 테이블이랑 적재된 데이터를 볼수있고
      • db에 쿼리문을 입력해서 결과를 볼수있고
      • 구조를 시각적으로 확인할수도있다.
      • 즉 db 상태를 빠르게확인하고 단순한수준의 조작을 할수있다.
    • sql alchemy를 쓰면
      • 파이썬 객체와 데이터베이스 테이블을 연결할수있다.
  • 의문점5
    • SQLAlchemy 의 기본 뼈대 Engine + Base + Session?
  • 답5 #

#