📌 다대다(N:M) 관계: ManyToManyField 사용 이유와 작동 방식 ⚙️
다대다 관계는 하나의 테이블의 여러 레코드가 다른 테이블의 여러 레코드와 연결될 수 있는 복잡한 관계입니다. 이 관계를 효율적으로 관리하기 위해 Django에서는 ManyToManyField를 제공하며, 이는 내부적으로 ForeignKey를 사용하지만 개발자가 직접 이를 다룰 필요가 없도록 추상화되어 있습니다.
1. 다대다(N:M) 관계의 특징
- 여러 레코드 연결: 하나의 테이블의 레코드가 다른 테이블의 여러 레코드와 연결될 수 있습니다.
- 중간 테이블 필요: 다대다 관계를 표현하기 위해서는 중간 테이블이 필요합니다. 중간 테이블은 두 테이블의 기본 키를 외래 키로 가지며, 두 테이블 간의 연결 정보를 저장합니다.
- 복잡한 관계: 직접
ForeignKey만으로는 다대다 관계를 표현하기 어렵고, 중간 테이블을 직접 관리해야 하므로 복잡도가 높아집니다.
2. ManyToManyField의 역할
- 다대다 관계 추상화:
ManyToManyField는 다대다 관계를 추상화하여 개발자가 복잡한 중간 테이블 관리를 직접 하지 않고, 다대다 관계를 간편하게 정의하고 관리할 수 있도록 해줍니다. - 자동 중간 테이블 생성:
ManyToManyField를 사용하면 Django는 자동으로 중간 테이블을 생성하고 관리합니다. 개발자는 중간 테이블에 대한 걱정 없이 다대다 관계를 표현하고, 관련 데이터를 쉽게 접근할 수 있습니다. - ORM 지원: Django ORM은
ManyToManyField를 통해 생성된 관계 데이터를 쉽게 접근하고 조작할 수 있는 기능을 제공합니다.
3. ForeignKey를 직접 사용하지 않는 이유
- 복잡성 증가:
ForeignKey만으로는 다대다 관계를 표현하려면 중간 테이블을 직접 생성하고 관리해야 합니다. 이는 코드 복잡성을 증가시키고, 유지보수를 어렵게 만듭니다. - ORM 비효율:
ForeignKey를 직접 사용하면 Django ORM의 편리한 기능을 제대로 활용하기 어렵습니다. 예를 들어, 관계된 데이터를 쉽게 가져오거나, 관계를 편리하게 조작하는 기능을 사용할 수 없습니다. - 코드 가독성 저하: 다대다 관계를
ForeignKey만으로 구현하면 코드가 복잡해지고, 가독성이 떨어집니다.
4. ManyToManyField의 사용 예시
from django.db import models
class Tag(models.Model):
name = models.CharField(max_length=100, unique=True)
class Article(models.Model):
title = models.CharField(max_length=200)
content = models.TextField()
# ManyToManyField 필드: 게시글과 태그 간의 다대다 관계 설정
tags = models.ManyToManyField(
Tag, related_name="articles"
)
ManyToManyField정의:Article모델에서tags필드를ManyToManyField로 정의하여Tag모델과 다대다 관계를 설정합니다.- 중간 테이블 자동 생성: Django는
article_tags라는 중간 테이블을 자동으로 생성하고 관리합니다. 개발자는 이 테이블을 직접 다룰 필요가 없습니다. - 데이터 접근: Django ORM을 통해
article.tags.all()또는tag.articles.all()과 같이 편리하게 관련 데이터를 가져올 수 있습니다.
5. 결론: ManyToManyField, 다대다 관계의 편리한 해결책 💡
ManyToManyField는 다대다 관계를 보다 쉽고 편리하게 구현할 수 있도록 Django에서 제공하는 필드 타입입니다. 내부적으로는 ForeignKey를 사용하여 중간 테이블을 관리하지만, 개발자는 직접 이 테이블을 다룰 필요 없이 다대다 관계를 추상화된 형태로 관리할 수 있습니다. 따라서 다대다 관계를 표현할 때는 ForeignKey를 직접 사용하는 것보다 ManyToManyField를 사용하는 것이 훨씬 효율적이고 편리합니다.
📌 다대다(N:M) 관계 예시 추가: 작성자, 좋아요, 게시글
- 다대다(N:M) 관계: 작성자, 좋아요, 게시글
- 개념: 작성자(Author)는 여러 게시글(Article)을 작성할 수 있고, 하나의 게시글은 여러 작성자에게 '좋아요'를 받을 수 있는 관계입니다. 또한 한 명의 사용자는 여러 게시글에 좋아요를 누를 수 있는 관계를 의미합니다. 이는 여러 사람이 여러 게시글에 좋아요를 누를 수 있는 상황과 같습니다.
- 구현:
Article모델과Author모델에 각각ManyToManyField를 추가하여 다대다 관계를 설정합니다. 게시글을 작성하는 작성자와 게시글에 좋아요를 누르는 사용자가 구분되어야 하므로 다음과 같이Article모델과Author모델에ManyToManyField를 추가하고 좋아요를 누르는 사용자를 저장할 별도 모델을 추가해서 표현합니다.
from django.db import models
class Author(models.Model):
name = models.CharField(max_length=100)
def __str__(self):
return self.name
class Article(models.Model):
title = models.CharField(max_length=200)
content = models.TextField()
# Article 모델의 authors 필드는 Author 모델과 다대다 관계 설정
authors = models.ManyToManyField(
Author, related_name="articles", through='ArticleAuthor'
)
# Article 모델의 like_users 필드는 User 모델과 다대다 관계 설정
like_users = models.ManyToManyField(
'User', related_name="like_articles"
)
def __str__(self):
return self.title
class User(models.Model):
username = models.CharField(max_length=100, unique=True)
def __str__(self):
return self.username
class ArticleAuthor(models.Model):
author = models.ForeignKey(Author, on_delete=models.CASCADE)
article = models.ForeignKey(Article, on_delete=models.CASCADE)
class Meta:
unique_together = ('author', 'article')
- 설명:
Article모델의authors필드는Author모델과 다대다 관계를 설정하며 중간 테이블로ArticleAuthor모델을 사용합니다.ArticleAuthor는article필드와author필드로 다대다 관계를 명시적으로 나타냅니다. 또한 특정 작성자가 특정 게시글을 한 번만 작성할 수 있도록 유일성 제약 조건을 추가했습니다.Article모델의like_users필드는User모델과 다대다 관계를 설정합니다.ManyToManyField를 사용하면 Django는 자동으로 중간 테이블을 생성하고 관리하여 다대다 관계를 편리하게 표현할 수 있도록 도와줍니다. 즉 게시글과 좋아요를 누른 사용자 목록을 연결합니다.- 위 코드에서는 사용자의 좋아요 정보를 저장할
User모델을 추가하였습니다.
'Python > Django' 카테고리의 다른 글
| Django AUTH USER 사용자 모델 (2) | 2025.01.08 |
|---|---|
| Django 워크플로우 정리 (CRUD, 로그인 기능까지) (0) | 2025.01.08 |
| [TIL] ForeignKey 보충 (코드예시) (0) | 2025.01.08 |
| [TIL] Django Model, foreignkey와 migration (0) | 2025.01.07 |
| [TIL] 프레임워크에 대해 (3) | 2025.01.06 |