본문 바로가기
django

모델링과 마이그레이션 (3)

by shinminkyoung 2025. 1. 17.

2.4 마이그레이션

  • 장고에서 모델링하면 SQL(DDL)로 해당 모델 기반의 플랜을 작성해줌
    • DDL (데이터 정의어)
      • SQL 중에서 데이터베이스를 정의하는 문법
      • CREATE, ALTER, DROP, TRUNCATE 등
  • 장고에서는 이 작업을 마이그레이션 또는 DB 마이그레이션이라고 부름
  • 장고에서는 DB 마이그레이션을 하기 위한 다음과 같은 명령어를 제공
    • 마이그레이션
      • 컴퓨터 분야에서는 보통 시스템의 변화 또는 시스템의 이동을 의미
      • 데이터베이스의 구조 변화를 의미
      • 데이터베이스가 가지고 있는 데이터에 일괄적인 변화를 주는 작업
      • ex. 2년 이상 로그인하지 않은 회원을 휴면 계정으로 처리하는 데이터 마이그레이션
    • 종류
      • python manage.py makemigrations
      • python manage.py sqlmigrate study_example_app 0001 # {장고 프로젝트 이름} {마이그레이션 파일 번호}
      • python manage.py showmigrations
      • python manage.py migrate

2.4.1 makemigrations

<장고에게 DDL을 자문 받는 명령어>

  • 장고 프로젝트의 migrations 폴더의 하위 파일들과 models.py와의 차이를 비교하는 명령어
  • 이전에 수행된 migrations 폴더의 하위 파일을 전부 읽어서 현재 models.py에 존재하는 모델과 비교해서 차이가 있는지 검사하고 만약 차이가 있다면 이를 일치시키기 위해 새로운 마이그레이션 파일을 생성
  • 이 안에는 models.py와 migrations 정보를 일치시키기 위한 DDL이 포함되어 있음
  • 여기서 주의해야할 점은 이 DDL은 장고가 제안해주는 정보일 뿐이지 완벽하지 않을 수 있음
  • makemigrations는 마치 개발자가 장고라는 이름을 가진 DBA에게 DDL 수행 계획을 자문하는 것과 같은 역할
  • makemigrations를 수행했을 때 생성되는 00xx_auto_xxxxx.py 파일이 장고라는 DBA에게 자문으로 얻은 DDL 수행 계획인 것

*makemigrations를 수행할 때마다 각 장고 앱에서 모델 변경 사항이 발견되면 1개의 마이그레이션 파일이 생성됨

  • 하지만, 장고는 무수한 if-else 문으로 도배된 DBA일 뿐임
  • 장고가 제안한 DDL은 개발자가 살펴보고 적절한지 판단해야 함
  • 장고가 제안한 DDL은 데이터베이스에 즉시 반영되지 않게 설계되어 있음

2.4.2 Operations

<장고 마이그레이션 모듈이 가지고 있는 명령어>

  • 장고가 가지고 있는 Operation의 종류로는 여러 가지가 있음
  • 모든 것을 일일이 분석하는 것은 불필요
  • dependencies란 마이그레이션 파일이 수행되려면 반드시 dependencies에 언급된 마이그레이션 파일이 먼저 수행되어야 한다는 제약을 의미함
  • dependencies= [ ('study_example_app', '0001_initial'), ]
  • operation 사용 예시
    1. CreateModel
      • 장고 모델에 명시된 옵션 값을 토대로 테이블을 생성하는 DDL을 만들어줌
      -- 위 옵션 값을 가진 CreateModel Operation은 아래와 같은 DDL을 만들어준다.
      
      Create TABLE "b_model" (
      			"id" serial NOT NULL PRIMARY KEY,
      			"b_field" varchar(16) NOT NULL,
      			"b_int_field" integer NOT NULL
      );
      
    2. migrations.CreateModel( name='Bmodel', fields=[ ('id', models.AutoField( auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('b_field', models.CharField(max_length=16)), ('b_int_field', models.IntegerField(default=3)), ], options={ 'db_table' : 'b_model', }, ),
    3. AddField
      • AddField로 생성된 DDL
      -- 위 옵션 값을 가진 AddField Operation은 아래와 같은 DDL을 만들어준다.
      
      ALTER TABLE "b_model" ADD COLUMN "a_111_field" varchar(32) DEFAULT 'aa' NOT NULL;
      ALTER TABLE "b_model" ALTER COLUMN "a_111_field" DROP DEFAULT;
      
      • CreateModel이 깔끔하게 1개의 DDL을 만들어준 것과 달리
      • AddField는 DDL이 하나 더 생성되어있음
    4. migrations.AddField( model_name='amodel', name='a_111_field', field=models.fields.CharField( default='aa', max_length=32 ), ),
    • 장고 필드에 default=’aa’라는 옵션을 부여했지만 왜 2번째 DDL을 추가해서 굳이 DROP DEFAULT를 하는 것인가?DROP DEFAULT: 칼럼에 부여된 default=’aa’ 옵션을 제거하는 DDL
    • → 장고 ORM의 특징으로 연결
    • 장고 마이그레이션은 SQL의 DEFAULT 옵션을 사용하지 않음
    • 장고 ORM은 데이터에 대한 제어권을 장고가 전부 가지고 있기를 원함
    • ADDFiled가 전달하고자 하는 내용
      1. makemigrations는 장고가 수행할 DDL 계획을 제안해주는 작업
        • ADDField에서 DEFAULT 옵션이 드롭되는 것처럼 장고가 원하는 방식대로 DDL을 계획
      2. makemigrations로 생성된 마이그레이션 파일이 그 결과물이고 항상 개발자가 기대하는 DDL이 수행되는지 알 수 없기 때문에 개발자는 생성된 마이그레이션 파일을 직접 읽어보고 문제없는지 판단해야함
      3. 의도하지 않는 DDL이 마이그레이션 파일 내에 계획되어 있다면 이를 커스터마이징 해야 함

2.4.3 sqlmigrate

<마이그레이션 수행 계획 검토(출력) 명령어)>

  • makemigrate를 사용해서 장고에게 DDL 수행 계획 파일을 받았다면 이제 마이그레이션 파일을 검토해야 함
  • 앞에서 언급한 것처럼 마이그레이션 Operation들이 수행하는 SQL을 전부 외우는 것은 불필요
  • sqlmigrate 명령어는 각 마이그레이션 파일이 수행될 때 발생하는 DDL을 출력해서 개발자에게 보여주는 역할
  • sqlmigrate 명령어 사용법
  • python manage.py sqlmigrate {장고 앱 이름} {마이그레이션 파일 번호}
  • sqlmigrate에서 사용 가능한 옵션
    • - - backwards
    • 장고의 마이그레이션은 migrate라는 명령어로 수행되는데 - - backwards로 롤백을 수행할 수 있음
    • 특정 마이그레이션 파일 수행으로 인해 시스템에 문제가 생겼을 때 데이터베이스를 원상 복구하는 것이 가능함
    • 이 옵션을 부여하면 롤백 시 발생하는 DDL을 출력

2.4.4 migrate

<실제 데이터베이스에 마이그레이션을 반영하는 명령어>

  • makemigrations를 사용해서 마이그레이션 파일을 생성하고 필요하다면 이를 커스터마이징 해야 함
  • sqlmigrate를 사용해서 데이터베이스에서 수행될 DDL을 확인했다면
  • 이제는 실제로 데이터베이스에 반영해야함
  • migrate는 이름 그대로 데이터베이스에 마이그레이션 파일을 반영
  • migrate 명령어 사용법
  • python mange.py migrate {장고 앱 이름} {마이그레이션 파일 번호}
  • migrate는 마이그레이션 파일 단위로 수행이 가능
  • 만약 {장고 앱 이름}만 명시하고 {마이그레이션 파일 번호}를 명시하지 않았다면
    • 해당 장고 앱에 존재하는 아직 수행되지 않은 모든 마이그레이션 파일을 수행해서 데이터베이스에 반영
  • 만약 {장고 앱 이름}을 명시하지 않고 migrate를 수행한다면
    • 해당 장고 프로젝트에 존재하는 아직 수행되지 않은 모든 마이그레이션 파일을 수행해서 데이터베이스에 반영
  • migrate에서 사용 가능한 옵션
        • fake: 이 옵션이 부여되면 migrate 수행 시 실제 데이터베이스에 DDL을 반영하지 않고 수행 완료 처리.
      • 왜 이런 옵션이 존재하는가?
      • → 장고는 자기 자신만 데이터베이스를 완전히 제어할 수 있는 능력을 가지고 있지만 실제 시스템의 데이터베이스에는 장고 이외에 다양한 시스템이 붙어 있는 경우가 많음
          • fake 옵션을 사용해야 하는 상황 예시
          • 장고의 제어 범위 밖에서 (예: DBA가 직접 수행) DDL이 반영되었고 이것을 장고에 마이그레이션 이력으로 기록해야 하는 경우
          • 조직의 정책이 데이터베이스에 대한 제어권을 DBA가 주도하는 방향으로 운영되어서 모든 마이그레이션 파일을 - - fake 처리 해줘야 하는 경우
          • 시스템 성능에 큰 영향을 줄 수 있는 DDL Optimizing과 분할 수행이 필요한 경우
          • PostrageSQL에는 DDL 수행 시 하나라도 실패하면 데이터베이스가 알아서 롤백해주는 기능이 존재하지만 MySQL의 경우 이러한 기능이 없음. 따라서 특정 마이그레이션 파일이 수행되다가 중간에 에러가 발생한다면 해당 마이그레이션 파일을 - - fake 처리해주고 데이터베이스에 접근해서 나머지 DDL을 직접 수행해야함
  • 마이그레이션 파일 수행 중 에러 발생 시 🚨
    • 개발자라면 이른바 삽질을 해봐야 한다..
    • 또는 이러한 상황을 최대한 방지하기 위해 MySQL보다는 PostgreSQL을 사용하는 것을 추천
    • PostgreSQL은 DDL 수행 시 마이그레이션 파일 단위로 트랜잭션을 보장
    • → migrate가 수행 중 실패하더라도 문제를 수정하고 실패한 마이그레이션 파일을 재수행할 수 있음
    1. —plan: migrate 수행 계획을 출력해줌.
      • sqlmigrate와 차이점
        • sqlmigrate: DDL을 직접 출력
        • migrate - - plan: 장고 operation의 수행 계획을 출력
      • 수행 예시
      • python manage.py migrate study_example_app --plan
      • 거의 사용되지 않는 명령어

2.4.5 showmigrations

<마이그레이션 이력 조회하기>

  • migrate 명령어를 수행하기 전이나 수행한 이후 지금까지 수행한 마이그레이션 이력을 확인하고 싶을 때 사용
  • 지금까지 수행된 마이그레이션 파일과 아직 실행되지 않은 마이그레이션 파일을 검토해주는 역할
  • 수행 예시
  • python mange.py showmigrations
  • 명령어 수행 시 출력되는 결과에서 X 표시가 되지 않은 마이그레이션 파일은 아직 수행되지 않은 파일이라는 의미
  • showmigrations로 migrate를 수행하면 study_example_app의 002 파일이 데이터베이스에 반영될 것이라는 예측을 할 수 있음
  • showmigrations과 sqlmigrate는 단순 조회 용이기 때문에 여러 번 수행해도 시스템에 변화를 주지 않음

2.4.6 squashmigrations

<마이그레이션 이력 통합하기>

  • 장고 프로젝트를 오랜 기간 운영하다 보면 마이그레이션 파일이 너무 많이 쌓이게 됨
  • 굳이 알지 않아도 되는 정보도 존재
  • 이때 squashmigrations을 사용
  • 여러 개의 마이그레이션 파일을 1개의 마이그레이션 파일로 합쳐주는 명령어
  • 명령어 사용법
    • 특정 장고 앱에 존재하는 마이그레이션 파일을 1부터 2까지 1개의 마이그레이션 파일로 만듦
  • python manage.py squashmigrations {장고 앱 이름} {마이그레이션 파일 번호 1} {마이그레이션 파일 번호 2}
  • sqashmigrations에서 사용 가능한 옵션
        • squashed -name
        • 해당 옵션과 함께 문자열을 부여하면 (squshmigrations - - squashed - name squashed_file) 합쳐진 마이그레이션 파일 이름으로 사용됨

2.4.7 커스텀 마이그레이션 파일 작성하기

  1. 데이터 마이그레이션
  2. 마이그레이션 오버라이딩

'django' 카테고리의 다른 글

모델링과 마이그레이션 (2)  (2) 2025.01.15
모델링과 마이그레이션 (1)  (2) 2025.01.15
장고에 대하여  (4) 2025.01.07
3 - ORM과 Django Rest Framework (1)  (1) 2024.05.23
2 - Django Template과 Model  (3) 2024.05.22