본문 바로가기
카테고리 없음

다대다(N:M) 관계를 연결 테이블로 어떻게 구현할까?

by whereisco 2023. 1. 17.

개요

팀 프로젝트를 진행하며, 다대다 관계를 설계해야 하는 상황이 발생했습니다. 다대다 관계를 적용하기 전에, 현재 프로젝트 내에서 설계해야 하는 상황을 예시로 들며 이 관계가 정말 합리적인지 알아보고 싶었습니다. 이번 포스팅을 통해, 다대다 관계가 무엇이고, 이를 활용하여 프로젝트 내에서 다대다 설계를 진행하는 것이 올바른지 공부해 보도록 하겠습니다.

현재 프로젝트 상황

현재 프로젝트 주제를 먼저 간단히 언급하고 넘어가면, 개발자 챌린지 서비스를 만들고 있습니다.

챌린저스와 같이 여러 유저가 하나의 공통된 챌린지에 참여하고, 서로 인증하는 방식의 시스템이라고 생각하시면 편할 것 같습니다.

프로젝트를 설계하며, 다대다 관계가 필요하다고 생각했던 부분은 바로 User와 Challenge 간의 관계입니다. 

하나의 유저는 여러 챌린지에도 참여할 수 있고, 한 챌린지는 여러 유저를 수용할 수 있다고 생각했기 때문입니다. 

다대다 관계

두 개 테이블이 서로의 행에 대해 여러개로 연관되어 있는 상태를 다대다 관계라고 합니다.

위에서 언급한 것을 한번 더 언급하자면, 한 명의 유저는 여러 챌린지를 참여하고, 한 챌린지는 여러 유저를 수용합니다. 와 같은 관계를 다대다 관계라고 할 수 있죠.

다대다(M:N) 관계 구현 하기

논리적으로 다대다 관계 표현은 가능하지만, 2개 테이블로 구현하는 것은 불가능합니다.

다대다 관계를 실제로 구현하기 위해서는 각 테이블의 PK를 외래키로 참조하고 있는 연결 테이블(매핑 테이블)을 사용해야 합니다.

예를 들어, ‘철민’이라는 유저는 ‘JPA 완강하기’, ‘1일 1 알고리즘 챌린지’, ‘1일 1 커밋’ 3가지의 챌린지에 참여하고 있고, ‘JPA 완강하기’라는 챌린지는 ‘철민’, ‘길동’, ‘길자’라는 유저를 수용하고 있습니다.

위의 상황을 이용해, 데이터를 테이블에 입력하면 아래와 같이 저장될 것입니다.

User

유저id(PK) 유저 이름
1 철민
2 길동
3 길자

Challenge_User - 연결 테이블 (매핑 테이블)

id(PK) 유저id(FK) 챌린지id(FK)
1 1 1
2 1 2
3 1 3
4 2 1
5 3 1

Challenge

챌린지id(PK) 챌린지 이름
1 JPA 완강하기
2 1일 1 알고리즘 챌린지
3 1일 1 커밋 운동
  • 만약, 철민이가 참여하고 있는 챌린지를 알고 싶다면, 철민이의 유저 id, 즉 1을 조건문으로 Challenge_User 테이블을 조회합니다.
  • 만약, 길동이가 참여하고 있는 챌린지를 알고 싶다면, 민지의 유저 id, 즉 2를 조건문으로 Challenge_User 테이블을 조회합니다.
  • 만약, 길동이가 1일 1 알고리즘 챌린지에 참여한다면, 길동이의 유저 id, 2와 1일 1 알고리즘 챌린지의 id, 2를 Challenge_User 테이블에 삽입합니다. 

TIP : 테이블 간 관계를 이해하기 어려운 분들에게

  1. 관계를 생각할 때, 테이블로 생각하지 말고, 한 행을 기준으로 생각해야 합니다.
    • 그러므로, 테이블 명도 유저 목록, 챌린지 목록이 아닌, 한 행을 대표할 수 있는 이름인 유저와 챌린지로 해야 합니다.
  2. 논리적으로 생각할 땐, 연결(매핑) 테이블은 생각하지 않습니다.
    • 철민이의 유저 id는 Challenge_User 테이블에 여러 개 존재한다. (X)
    • 철민이는 ‘jpa 완강하기’, ‘1일 1 알고리즘’, ‘1일 1 커밋 운동’ 챌린지에 참여한다. (0)
  3. 항상 일대다 기준으로 생각합니다. 다대일보다 직관적으로 이해하기 쉽습니다.
    • 철민(1)이는 여러 챌린지(N)에 참여한다. (0)
    • jpa 완강하기, 1일 1 알고리즘, 1일 1 커밋운동 챌린지는 철민이를 수용한다.(X)

출처

https://siyoon210.tistory.com/26