📌 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
  • 전체
    오늘
    어제
    • 분류 전체보기 (758) N
      • Python (32)
      • 프로젝트 (82) 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)
  • 블로그 메뉴

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

  • 공지사항

  • 인기 글

  • 태그

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

  • 최근 글

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

티스토리툴바