models.py를 작성 후 1차 마이그레이션을 진행한 뒤 테이블 명중 1글자를 소문자에서 대문자로 변경할 일이 생겼다.
변경 후 하던대로 진행했을 뿐인데.
python manage.py makemigrations appname
python manage.py migrate
python manage.py runserver
NO SUCH TABLE '내가 만든 테이블명' 에러가 발생.
이것, 저것 해보다가 최종 해결 방법은 간단했지만, 중간 과정이 고생스러워서 기록한다.
1. 발생 원인
Django 마이그레이션 시스템에서 발생하는 OperationalError는 **애플리케이션의 마이그레이션 상태(State)**와 실제 데이터베이스 스키마(Schema) 간의 **동기화 실패(Desynchronization)**로 인해 발생.
Django는 데이터베이스의 형상 관리를 위해 다음 세 가지 요소를 유기적으로 일치시키는데, 이 중 하나라도 어긋나면 에러가 발생.
- 마이그레이션 파일 (Migration Files): 개발자가 작성한 모델 변경 사항을 코드로 정의한 명세서 (/migrations/*.py).
- 마이그레이션 기록 (Migration History): 데이터베이스 내 django_migrations 테이블에 저장된 적용 내역. (Django가 인지하는 현재 상태)
- 데이터베이스 스키마 (Database Schema): 실제 DBMS(SQLite, PostgreSQL 등)에 생성된 물리적인 테이블과 컬럼 구조.
2. 주요 에러 유형 및 발생 메커니즘
Case A. OperationalError: no such table
마이그레이션 기록상으로는 '적용 완료' 상태이나, 실제 물리 테이블이 존재하지 않는 경우.
- 상태 분석:
- Migration History: 해당 마이그레이션 파일이 적용(Applied)되었다고 기록됨.
- Actual Schema: 해당 테이블이 삭제되었거나 생성되지 않음.
- 발생 원인:
- 데이터베이스에 직접 접속(Shell, DB Tool 등)하여 SQL DROP TABLE 명령어로 테이블을 임의 삭제한 경우.
- migrate --fake 옵션을 사용하여 실제 테이블 생성 과정을 건너뛰고 기록만 남겼으나, 실제로는 테이블이 없었던 경우.
Case B. OperationalError: table "..." already exists
마이그레이션 기록상으로는 '미적용' 상태라 새로 생성을 시도했으나, 실제 물리 테이블이 이미 존재하는 경우입니다.
- 상태 분석:
- Migration History: 해당 마이그레이션 기록이 없거나 초기화됨 (Not Applied).
- Actual Schema: 과거에 생성된 테이블이 그대로 남아있음 (Zombie Table).
- 발생 원인:
- 가장 흔한 원인: 프로젝트 내 migrations 폴더의 파일들을 삭제(초기화)했으나, DB에 남아있는 실제 테이블을 삭제하지 않은 상태에서 다시 makemigrations 후 migrate를 시도할 때 발생.
- migrate --fake <app> zero 명령어로 기록(History)만 지우고, 실제 테이블(Schema)을 정리하지 않은 경우.
3. 근본적인 해결 전략: 동기화(Synchronization) 복구
세 가지 요소(파일, 기록, 스키마)의 상태를 다시 일치시키는 과정.
- 초기화 (Reset): 꼬여버린 마이그레이션 파일과 django_migrations 기록을 제거하여 상태를 '0(Zero)'로 초기화(__init__만 남기고 migrations 폴더 내 다른 파일 삭제).
- 잔재 제거 (Clean Up): 충돌을 유발하는 실제 DB 테이블을 DROP 하여 스키마 상태를 '0'으로 만듭니다.
- 재동기화 (Resync): 깨끗해진 상태에서 다시 설계도(Migration File)를 만들고, 이를 실행(Migrate)하여 기록과 스키마를 동시에 생성합니다.
나는 파이썬 기본 제공인 sqlite3 을 사용해 개발테스트 중이었기 때문에 철거 코드를 입력하여 처리했다.
1. shell 진입
python manage.py shell
2. 철거코드 입력
from django.db import connection
# 커서를 통해 직접 SQL 명령을 날려서 테이블을 날려버립니다.
with connection.cursor() as cursor:
# 혹시 있을지 모르는 3가지 테이블을 모두 삭제 시도합니다.
cursor.execute("DROP TABLE IF EXISTS gateways_gatewayconfig")
cursor.execute("DROP TABLE IF EXISTS gateways_provider")
cursor.execute("DROP TABLE IF EXISTS gateways_servicetype")
print("✅ 꼬인 테이블 삭제 완료! exit()를 입력해 나가세요.")
3. 나가기
exit()'알아두면 언젠간 유용할 몇 가지의 지식' 카테고리의 다른 글
| console 환경에서 git 병합 후 push (0) | 2026.01.11 |
|---|---|
| VS Code에서 ollama list 를 인식하지 못할 때 (0) | 2026.01.03 |
| Ollama Model 저장 경로 설정 방법 (0) | 2026.01.03 |
| pip install 을 사용해 설치했는데 인식하지 못할 때. (0) | 2025.12.23 |
| python 프로젝트 Git hub에 업로드 하기. (0) | 2025.12.01 |