📌 Django에서의 팔로우 기능 모델링 완전 정복

2025. 5. 16. 11:47·기술블로그-Django편

📌 Django에서의 팔로우 기능 모델링 완전 정복

✅ 1. 핵심 개념 정리

용어 설명

팔로잉 내가 누군가를 따라가는 것 (내가 팔로우하는 사람들)
팔로워 나를 따라오는 사람들 (나를 팔로우하는 사람들)
ManyToManyField N:N 관계 (예: 유저끼리 서로 팔로우할 수 있음)
through 모델 중간에 관계를 직접 조절할 수 있는 연결 테이블
symmetrical=False “a가 b를 팔로우”는 “b가 a를 팔로우”를 의미하지 않음 (단방향 관계)

🧱 2. 전체 구조 및 모델 설명

👤 User 모델 분석

class User(AbstractBaseUser):
    email = models.EmailField(verbose_name='email', unique=True)
    is_active = models.BooleanField(default=False)
    is_admin = models.BooleanField(default=False)
    nickname = models.CharField('nickname', max_length=20, unique=True)

    following = models.ManyToManyField(
        'self',
        symmetrical=False,
        related_name='followers',
        through='UserFollowing',
        through_fields=('from_user', 'to_user')
    )

✨ 필드 설명:

  • 'self': 같은 모델(User) 간 연결
  • symmetrical=False: 단방향 팔로우
  • related_name='followers': 나를 팔로우하는 유저를 조회하는 역참조 필드
  • through='UserFollowing': 중간 모델을 명시적으로 사용
  • through_fields: 어떤 필드가 어떤 방향인지 명시

🧩 UserFollowing 중간 모델

class UserFollowing(TimestampModel):
    to_user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='user_followers')
    from_user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='user_following')

    class Meta:
        unique_together = ('to_user', 'from_user')

✔️ 핵심 개념 정리:

  • to_user: 팔로우 당하는 대상
  • from_user: 팔로우 하는 사람
  • unique_together: 같은 유저에게 중복 팔로우 방지

🧪 3. 예제 흐름 시뮬레이션

admin = User.objects.get(email='admin@admin.com')
student = User.objects.first()
UserFollowing.objects.create(to_user=admin, from_user=student)

➡️ 결과: student가 admin을 팔로우함

🧪 4. ORM 명령어 예시로 보는 실제 활용

목적 ORM 코드 설명

admin이 팔로우한 사람들 admin.following.all() 내가 팔로우한 유저 목록
admin을 팔로우한 사람들 admin.followers.all() 나를 팔로우한 유저 목록
팔로우 추가 admin.following.add(other_user) 내부적으로 UserFollowing 생성됨
팔로우 제거 admin.following.remove(other_user) 내부적으로 UserFollowing 삭제됨

⚠️ through 모델을 명시한 경우에는 .add()와 .remove()가 동작하지 않을 수 있어 직접 중간 테이블에 조작 필요

📊 ERD 구조 시각화

User ---< UserFollowing >--- User
   ↑          ↕             ↓
 from_user   중간 테이블    to_user

➡️ UserFollowing이 from_user → to_user로 단방향 연결하는 구조

⚠️ 주의사항 & 팁

항목 내용

중복 방지 unique_together로 중복 팔로우 방지
자기자신 팔로우 방지 from_user != to_user 조건 추천
related_name 쿼리에서 매우 유용함 (ex. user.followers.all())
symmetrical=False 트위터식 단방향 팔로우 구현 가능

✅ 요약

키워드 설명

ManyToManyField('self', symmetrical=False) 유저 → 유저 단방향 관계
through='UserFollowing' 중간 테이블로 관계 직접 설정
related_name 관계 접근 시 직관적인 이름 사용 가능 (예: 팔로워, 팔로잉)

 

🔍 질문 핵심 요약

Q. User 모델에는 following = models.ManyToManyField(...) 한 줄만 정의되어 있는데, 왜 u.followers.count() 같은 반대 방향도 되는 걸까?

✅ 핵심 포인트: related_name 덕분입니다

following = models.ManyToManyField(
    'self',
    symmetrical=False,
    related_name='followers',
    through='UserFollowing',
    through_fields=('from_user', 'to_user')
)

➡️ 여기서 related_name='followers' 이 부분이 바로 핵심입니다.

💡 어떻게 작동하냐면?

접근 표현식 의미 실제 필드 기준
u.following.all() u가 팔로우한 사람들 from_user = u
u.followers.all() u를 팔로우한 사람들 to_user = u ← related_name='followers' 덕분

🔁 정리하자면:

방향 필드 정의 위치 ORM 접근 방식 설명
내가 팔로우한 사람 직접 정의한 following u.following.all() 내가 누굴 팔로우함
나를 팔로우한 사람 related_name='followers' u.followers.all() 누가 나를 팔로우함

✅ 그래서 다음도 가능합니다:

u.followers.count()   # 나를 팔로우하는 사람 수
u.following.count()   # 내가 팔로우한 사람 수

➡️ 모두 ManyToMany 관계에서 자동 제공되는 쿼리셋 기능 덕분입니다.

🔧 만약 related_name을 지정하지 않았다면? Django는 기본값으로 _set 형식을 제공합니다.

# related_name='followers'를 안썼다면?
u.userfollowing_set.all()

➡️ 읽기 어렵고 비직관적이기 때문에 related_name 설정은 꼭 해주는 게 좋습니다

🧠 요약

질문 답변
왜 followers, following 둘 다 쓸 수 있나요? related_name 덕분입니다
following만 정의했는데? related_name='followers'가 역방향 필드를 자동 생성해줍니다
둘 다 ManyToManyField인가요? 실제로는 following만 정의된 것이고, 반대는 related_name으로 연결된 것입니다

'기술블로그-Django편' 카테고리의 다른 글

📌 Django ORM - get_or_create 완전 정복  (0) 2025.05.16
📌 Django 클래스 기반 뷰(CBV)의 흐름 완전 이해 + AJAX 연동 설명  (0) 2025.05.16
🧠 Django에서 name=name 의미 완전 정리하기  (0) 2025.05.15
🔍 Django의 object vs objects 완전 정리!  (0) 2025.05.15
🔍 Django REST Framework - GenericAPIView란?  (0) 2025.05.15
'기술블로그-Django편' 카테고리의 다른 글
  • 📌 Django ORM - get_or_create 완전 정복
  • 📌 Django 클래스 기반 뷰(CBV)의 흐름 완전 이해 + AJAX 연동 설명
  • 🧠 Django에서 name=name 의미 완전 정리하기
  • 🔍 Django의 object vs objects 완전 정리!
Chansman
Chansman
안녕하세요! 코딩을 시작한 지 얼마 되지 않은 초보 개발자 찬스맨입니다. 이 블로그는 제 학습 기록을 남기고, 다양한 코딩 실습을 통해 성장하는 과정을 공유하려고 합니다. 초보자의 눈높이에 맞춘 실습과 팁, 그리고 개발하면서 겪은 어려움과 해결 과정을 솔직하게 풀어내려 합니다. 함께 성장하는 개발자 커뮤니티가 되기를 바랍니다.
  • Chansman
    찬스맨의 프로그래밍 스토리
    Chansman
  • 전체
    오늘
    어제
    • 분류 전체보기 (744) N
      • Python (32)
      • 프로젝트 (68) N
      • 과제 (25)
      • Database (40)
      • 멘토링 (11)
      • 특강 (37)
      • 기술블로그 (41)
      • 기술블로그-Fastapi편 (33)
      • 기술블로그-Django편 (153)
      • 기술블로그-Flask편 (36)
      • AI 분석 (5)
      • HTML & CSS (31)
      • JavaScript (17)
      • AWS_Cloud (21)
      • 웹스크래핑과 데이터 수집 (14)
      • Flask (42)
      • Django (77)
      • Fastapi (16)
      • 연예 (14) N
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    life reflection
    americanlaw
    classaction
    btsjungkook
    urbantrends
    trumpmuskclash
    livebroadcast
    btscomeback
    homebartrend
    뷔
    college reunions
    btsdischarge
    remittance
    americaparty
    self-growth
    youngprofessionals
    travel ban
    newpoliticalparty
    global politics
    titaniumcase
    chinanightlife
    basalcellcarcinoma
    gpterror
    smartphonedurability
    hotcoffeecase
    RM
    btsreunion
    chatgpterror
    bts
    lawsuitculture
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
Chansman
📌 Django에서의 팔로우 기능 모델링 완전 정복
상단으로

티스토리툴바