본문 바로가기
Python/Django

[TIL] Django Model, foreignkey와 migration

by 좌우지간에 2025. 1. 7.

📌 Django 모델과 ForeignKey, 그리고 마이그레이션 (최종 정리) 🧐

Django는 웹 애플리케이션 개발을 쉽게 해주는 강력한 프레임워크입니다. 그중에서도 모델(Model)은 데이터베이스와 상호작용하는 핵심 요소입니다. 오늘은 모델의 ForeignKey 필드와 마이그레이션 과정을 자세히 알아보겠습니다.

 

1. ForeignKey 란 무엇일까요? 🔗

  • ForeignKey 의 개념
    • 관계형 데이터베이스(RDBMS)에서 테이블 간의 관계를 정의하는 데 사용되는 필드입니다.
      • 단순히 참조만 하는 것이 아니라, 테이블 간의 관계(Relationship)를 설정하는 것이 핵심입니다.
    • '외래 키'라고도 불리며, 다른 테이블의 특정 레코드를 참조하는 역할을 합니다.
    • 예시: 블로그 게시글(Post) 테이블이 작성자(Author) 테이블의 특정 작성자를 참조하는 경우.

 

from django.db import models

class Author(models.Model):
    name = models.CharField(max_length=100)

    def __str__(self):
        return self.name

class Post(models.Model):
    title = models.CharField(max_length=200)
    content = models.TextField()
    author = models.ForeignKey(Author, on_delete=models.CASCADE)  # ForeignKey 사용

    def __str__(self):
        return self.title

 

  • Django 모델에서 ForeignKey 사용 예시 
    • author = models.ForeignKey(Author, on_delete=models.CASCADE): Post 모델의 author 필드는 Author 모델의 특정 레코드를 참조하는 ForeignKey입니다.
    • on_delete=models.CASCADE: 참조하는 Author 레코드가 삭제될 때, 해당 Author를 참조하는 모든 Post 레코드를 함께 삭제합니다. (CASCADE 외에 다양한 옵션이 존재합니다.)
      • CASCADE: 연결된 모든 레코드 삭제
      • PROTECT: 연결된 레코드가 있을 경우, 삭제 불가
      • SET_NULL: 연결된 레코드가 삭제될 때, 외래 키를 NULL로 설정
      • SET_DEFAULT: 연결된 레코드가 삭제될 때, 외래 키를 기본값으로 설정
      • DO_NOTHING: 연결된 레코드가 삭제되어도 아무런 조치 취하지 않음 (권장하지 않음)
      • 필요에 따라 적절한 옵션을 선택해야 합니다.

 

  • RDBMS (관계형 데이터베이스) 란?
    • 데이터를 테이블 형태로 저장하고, 테이블 간의 관계(Relationship)를 설정하여 데이터를 효율적으로 관리하는 데이터베이스 시스템입니다.
      • 단순히 데이터를 저장하는 것뿐만 아니라, 데이터 간의 관계를 통해 좀 더 복잡하고 효율적인 데이터 관리가 가능합니다.
    • MySQL, PostgreSQL, SQLite 등이 있습니다.

 

2. 마이그레이션 (Migration) 이란 무엇일까요? ⚙️

  • 마이그레이션의 정의
    • Django 모델을 변경했을 때, 변경 사항을 데이터베이스 스키마에 반영하는 과정입니다.
      • 모델 변경은 코드 상의 변경이며, 데이터베이스에도 해당 변경 사항을 적용해야 합니다.
    • Django는 모델 변경 사항을 마이그레이션 파일로 관리하며, 이를 통해 데이터베이스 스키마를 체계적으로 관리할 수 있습니다.
      • 마이그레이션 파일은 일종의 데이터베이스 변경 이력이며, 이를 통해 언제든지 데이터베이스 스키마를 원하는 상태로 변경할 수 있습니다.

 

  • 마이그레이션 관련 주요 명령어
    1. python manage.py makemigrations 앱이름/:
      • 앱 이름을 지정하는 이유: Django 프로젝트는 여러 앱으로 구성될 수 있습니다. 각 앱은 독립적인 기능을 수행하며, 데이터베이스 모델도 별도로 관리해야 합니다. 앱 이름을 지정함으로써, 특정 앱의 모델 변경 사항에 대한 마이그레이션 파일을 생성할 수 있습니다. 실수로 다른 앱의 모델을 건드리는 것을 방지하고, 마이그레이션 관리를 효율적으로 할 수 있습니다.
      • 실수 방지: makemigrations를 실행할 때 앱 이름을 지정하지 않으면, 모든 앱의 변경사항이 하나의 마이그레이션 파일에 포함될 수 있습니다. 이는 충돌과 오류를 유발할 수 있으므로 앱별로 관리하는 것이 필수적입니다.
      • 예시: python manage.py makemigrations blog/ (blog 앱에 대한 새로운 마이그레이션 파일 생성)

 

2.  **`python manage.py migrate 앱이름/`:**

    *   `makemigrations`로 생성된 **마이그레이션 파일에 정의된 변경 사항을 실제 데이터베이스에 적용**하는 명령어입니다.
    *   앱 이름을 지정하여 특정 앱의 마이그레이션만 적용하거나, 앱 이름을 생략하여 모든 앱의 마이그레이션을 적용할 수 있습니다.
    *   **앱별 관리:** `migrate` 역시 앱 이름을 지정하여 **각 앱의 마이그레이션을 독립적으로 적용**할 수 있습니다.
    *   **예시:** `python manage.py migrate blog/` (blog 앱에 대한 **마이그레이션 적용**)

 

  • 데이터베이스 테이블:
    • 마이그레이션을 적용하면, 데이터베이스에 모델에 해당하는 테이블과 관계가 생성됩니다.
    • 테이블 이름은 기본적으로 앱이름_모델이름 형식으로 생성됩니다. (예: blog_post, blog_author)

 

3. 마이그레이션 실수 대처법 🚨

  • 마이그레이션 실수로 인한 문제점
    • 데이터베이스 스키마가 원하지 않는 형태로 변경되어 오류가 발생할 수 있습니다.
    • 데이터 손실 및 불일치의 위험이 있습니다.

 

  • 마이그레이션 실수 대처 방법
    1. SQLite 데이터베이스 삭제는 최후의 수단! ❌:
      • SQLite 데이터베이스를 삭제하고 다시 만들면, 기존 데이터가 모두 손실되므로 절대로 해서는 안 됩니다.
        • 주의: 개발 환경에서는 SQLite를 사용하기도 하지만, 실제 서비스 환경에서는 다른 데이터베이스 시스템 (MySQL, PostgreSQL 등)을 사용하는 것이 일반적입니다.

 

2.  **이전 마이그레이션으로 되돌리기 (Rollback) ⏪:**
    *   실수로 잘못된 마이그레이션을 적용했다면, **특정 마이그레이션 시점으로 데이터베이스를 되돌릴 수 있습니다**.
    *   **예시:** `0002` 마이그레이션 적용 후 `0003`을 적용했는데, `0003`에 문제가 있다면, `python manage.py migrate 앱이름/ 0002` 명령어를 실행하여 **`0002` 마이그레이션이 적용된 상태로 데이터베이스를 되돌릴 수 있습니다**.
        *   **주의:** 마이그레이션 되돌리기는 데이터 구조를 이전 상태로 돌리는 것이므로, **데이터 손실이 발생할 수 있습니다**.
    *   `0003` 파일 자체는 삭제되지 않고 그대로 남아있습니다. (마이그레이션 이력을 관리하기 위함)

 

4. 마이그레이션 파일 예시 📝

# 0001_initial.py (최초 마이그레이션)
from django.db import migrations, models

class Migration(migrations.Migration):

    initial = True

    dependencies = [
    ]

    operations = [
        migrations.CreateModel(
            name='Author',
            fields=[
                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('name', models.CharField(max_length=100)),
            ],
        ),
        migrations.CreateModel(
            name='Post',
            fields=[
                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('title', models.CharField(max_length=200)),
                ('content', models.TextField()),
                ('author', models.ForeignKey(on_delete=models.CASCADE, to='blog.Author')),
            ],
        ),
    ]

 

5. 마무리 및 추가 정보 💡

  • Django 모델의 ForeignKey는 RDBMS에서 테이블 간의 관계를 정의하고 관리하는 데 중요한 역할을 합니다.
    • 단순히 데이터를 참조하는 것 이상의 의미를 가지며, 데이터 무결성을 유지하는 데도 중요한 역할을 합니다.
  • 마이그레이션은 데이터베이스 스키마를 안전하고 체계적으로 관리하는 데 필수적인 과정입니다.
    • 마이그레이션 파일 관리는 데이터베이스 스키마를 일관성 있게 유지하고, 변경 사항을 추적하는 데 도움이 됩니다.
  • 앱 이름을 지정하여 마이그레이션을 관리하는 것은 필수이며, 오류를 줄이고 개발 효율성을 높일 수 있습니다.
  • 마이그레이션 실수 시, 이전 마이그레이션으로 되돌리는 방법을 사용하면 데이터 손실을 어느 정도 방지할 수 있지만, 데이터 손실 가능성을 항상 인지하고 있어야 합니다.
    • 마이그레이션을 적용하기 전에는 반드시 백업을 하는 것이 중요합니다.