본문 바로가기
Programming/Django

🗄️ Django & SQL에서의 CASCADE와 NOT NULL 이해하기

by Mandy's 2025. 8. 5.

1. CASCADE란?

CASCADE는 외래 키(Foreign Key) 제약 조건에서 부모 객체가 삭제될 때, 자식 객체를 어떻게 처리할지를 결정하는 옵션 중 하나입니다.

특히 on_delete=models.CASCADE부모가 삭제되면 해당 부모를 참조하는 모든 자식도 함께 삭제하라는 의미입니다.


📌 Django 예시

from django.db import models

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

class Book(models.Model):
    author = models.ForeignKey(
        Author,
        on_delete=models.CASCADE  # 부모 Author 삭제 시 Book도 삭제
    )
    title = models.CharField(max_length=200)

동작 예시

# 부모 생성
a = Author.objects.create(name="김민주")
Book.objects.create(author=a, title="Django 입문")
Book.objects.create(author=a, title="Python 심화")

# 부모 삭제
a.delete()

# 결과: a가 참조하던 Book들도 자동 삭제됨
Book.objects.all()  # → 빈 QuerySet

📌 SQL 예시

CREATE TABLE author (
    id SERIAL PRIMARY KEY,
    name VARCHAR(100) NOT NULL
);

CREATE TABLE book (
    id SERIAL PRIMARY KEY,
    author_id INTEGER REFERENCES author(id) ON DELETE CASCADE,
    title VARCHAR(200) NOT NULL
);
  • ON DELETE CASCADE가 부모 삭제 시 자식 행 삭제를 보장합니다.

💡 CASCADE 주의점

  • 의도치 않은 대량 삭제 위험이 있음 → 테스트 환경에서 꼭 확인
  • 중요 데이터는 PROTECT, SET_NULL 등 다른 옵션 고려 가능

2. NOT NULL이란?

NOT NULL은 컬럼이 NULL 값을 가질 수 없도록 하는 제약 조건입니다.
즉, 해당 필드는 항상 값이 있어야 함을 의미합니다.


📌 Django 예시

class Author(models.Model):
    name = models.CharField(max_length=100, null=False)  # 기본값: null=False
    birth_year = models.IntegerField(null=True)  # NULL 허용

동작 예시

# name은 null=False이므로 값이 없으면 에러 발생
Author.objects.create()  
# → IntegrityError: NOT NULL constraint failed: author.name

# birth_year는 NULL 허용
Author.objects.create(name="김민주", birth_year=None)  # 정상 저장

📌 SQL 예시

CREATE TABLE author (
    id SERIAL PRIMARY KEY,
    name VARCHAR(100) NOT NULL,
    birth_year INTEGER NULL
);
  • NOT NULL이 붙은 컬럼은 INSERT 시 반드시 값이 필요합니다.

3. CASCADE + NOT NULL 함께 쓰기

실무에서 자주 보이는 패턴은 외래 키를 NOT NULL로 두고, CASCADE 삭제를 설정하는 경우입니다.
즉, 자식 객체는 반드시 부모를 가져야 하고, 부모 삭제 시 자식도 함께 삭제됩니다.


📌 Django 예시

class Book(models.Model):
    author = models.ForeignKey(
        Author,
        on_delete=models.CASCADE,
        null=False  # 부모 없이 존재 불가
    )
    title = models.CharField(max_length=200, null=False)

4. 마무리

  • CASCADE: 부모 삭제 → 자식 자동 삭제
  • NOT NULL: 해당 필드에 NULL 저장 불가
  • 둘을 함께 쓰면 데이터 무결성을 보장하면서 참조 무효 데이터를 방지

💡 추천 참고자료