[FastAPI] 'Unknown Column' 에서 Alembic 사용법 (SQLAlchemy 스키마 동기화)
Language/Python

[FastAPI] 'Unknown Column' 에서 Alembic 사용법 (SQLAlchemy 스키마 동기화)

뉴비뉴 2025. 6. 15.

 안녕하세요.

 

FastAPI와 SQLAlchemy로 구현 된 서비스에서 코드를 수정하던 중 (pymysql.error.OperationalError) (1054, "Unknown column '..' in 'field list'") 오류와 그 해결 과정을 공유하려고 합니다.

 

참고로 Django 개발자였고 Django 는 makemigrations, migrate 명령어로 DB 스키마 동기화가 편리했지만, FastAPI의 경우 처음 사용하는 웹 프레임워크이다 보니까 아무것도 모르는 상태에서 Alembic 을 발견 했습니다.

추측

"FastAPI와 SQLAlchemy 로 AWS RDS 까지 구축된 상황에서 데이터베이스 스키마가 동기화가 안되어 있다" 라는 걸 봤을 때 전 개발자는 초기에 DB 를 개발하고 AWS RDS 를 만들어 한번 배포를 했을 겁니다. 하지만 배포하고 나서 DB 스키마는 수 많은 수정/삭제가 되었을 것이고, 그 결과 'Unknown Column' 에러가 발생하지 않았을까 싶습니다.

 


문제

코드와 현실(AWS RDS DB)의 불일치

class User(Base):
    __tablename__ = 'users'
    
    # 새로 추가한 필드
    point = Column(Numeric(10, 2), nullable=True, default=0.00, comment='보유중인 포인트')
    # (pymysql.err.OperationalError) (1054, "Unknown column 'users.point' in 'field list'")

 

위 코드와 에러를 봤을 때 코드는 업데이트되었지만, 실제 데이터베이스는 DB 스키마 동기화가 안되고 있었습니다.

Alembic 이란?

SQLAlchemy를 위한 데이터베이스 마이그레이션 도구입니다. SQLAlchemy 모델(코드)과 실제 데이터베이스 스키마를 비교하여, 그 차이점을 적용하는 SQL 스크립트를 자동으로 생성하고 실행해주는 도구

Alembic 도입 및 설정하기

1. Alembic 설치

poetry add alembic

2. Alembic 초기화

프로젝트 최상위 디렉토리에서 아래 명령어를 실행하여 Alembic 설정 파일을 생성합니다.

alembic init alembic

alembic.ini 파일과 alembic 디렉토리가 생성됩니다.

3. Alembic 설정 수정

1) alembic.ini 파일 수정

  • DB 연결 정보
# alembic.ini

[alembic]
# ...
script_location = alembic

# sqlalchemy.url 값을 실제 DB URI로 교체합니다.
# .env 파일에서 이 값을 관리하는 것이 좋습니다.
sqlalchemy.url = mysql+pymysql://user:password@host/db_name

2) alembic/env.py

  • 모델 파일 수정
  • 어떤 모델의 변경사항을 추적해야 하는지 알려주고, 환경 변수를 읽을 수 있도록 설정합니다.
  • from app.db.models.user import User 코드는 프로젝트의 모든 모델을 import 해주어야 Alembic이 인식합니다.
# alembic/env.py

from logging.config import fileConfig
from sqlalchemy import engine_from_config
from sqlalchemy import pool
from alembic import context

# ==========================================================
# [수정 1] 우리 프로젝트의 Base 객체와 모든 모델 클래스를 import
# ==========================================================
from app.config.db import Base
# 아래에 프로젝트의 모든 모델을 import 해주어야 Alembic이 인식합니다.
from app.db.models.user import User
# ... (다른 모델들도 모두 추가)
# ----------------------------------------------------------

config = context.config

if config.config_file_name is not None:
    fileConfig(config.config_file_name)

# ==========================================================
# [수정 2] target_metadata를 우리 프로젝트의 Base.metadata로 설정
# ==========================================================
# 원래: target_metadata = None
# 수정 후:
target_metadata = Base.metadata
# ----------------------------------------------------------


def run_migrations_online() -> None:
    # ... (이하 코드는 그대로)

마이그레이션 실행

4. 마이그레이션 스크립트 자동 생성

터미널에서 아래 명령어를 실행하여 코드와 DB의 차이점을 감지하고, "작업 지시서"를 만듭니다.

alembic revision --autogenerate -m "User 모델에 point 필드 등 추가"

성공적으로 실행되면, 아래 메시지가 보입니다.

INFO  [alembic.autogenerate.compare] Detected added column 'users.point'
INFO  [alembic.autogenerate.compare] Detected added column 'users.total_challenge_amount'
...
Generating /path/to/project/alembic/versions/xxxx_...py ...  done

Alembic이 users 테이블에 point 컬럼이 없다는 것을 정확히 찾았습니다.

5. 데이터베이스에 변경사항 적용

alembic upgrade head

터미널에 Running upgrade ... 메시지가 뜨고, alembic/versions/...py 파일을 보면 아래 사진과 같이 업그레이드 및 다운그레이드 된 정보가 나와 있습니다.

또 DB 툴로 users 테이블을 확인하면 스키마 동기화가 잘 된 것을 확인할 수 있습니다.

결론

  1. 체계적인 DB 변경 이력 관리: alembic/versions 디렉토리에 모든 변경 이력이 코드로 남습니다.
  2. 팀 협업 효율 증가: 누가 어떤 스키마를 변경했는지 명확하게 추적할 수 있습니다.

초기 설정이 번거로울 수 있지만, 한번 구축해두면 개발 경험의 질을 수직으로 상승시켜 줍니다. FastAPI와 SQLAlchemy를 사용하신다면, Alembic은 선택이 아닌 필수라고 말씀드리고 싶습니다.

댓글

💲 추천 글