다대다 관계 - 소개
다대다 관계 - 소개 (Many to Many - Intro)
우리는 데이터에서 일대다(One-to-Many) 관계를 다루는 법을 봤어요.
하지만 다대다(Many-to-Many) 관계는 어떻게 다룰까요?
함께 알아봐요. 🚀
출처: 공식문서
일대다에서 시작하기
익숙하고 더 단순한 일대다 옵션부터 시작할게요.
팀(team) 테이블 하나와 히어로(hero) 테이블 하나가 있고, 하나의 팀에 많은 히어로가 있을 수 있어요.
각 팀이 여러 히어로를 가질 수 있으니, team 테이블의 열들에 히어로 ID를 전부 다 넣을 순 없어요.
하지만 각 히어로는 한 팀에만 속할 수 있으니, 히어로 테이블에는 특정 팀(테이블 team의 특정 행)을 가리키는 단일 열이 있어요.
team 테이블은 이렇게 생겼어요:
| id | name | headquarters |
|---|---|---|
| 1 | Preventers | Sharp Tower |
| 2 | Z-Force | Sister Margaret's Bar |
!!! tip "팁"
다른 테이블을 가리키는 외래 키가 없다는 점을 눈여겨보세요.
그리고 hero 테이블은 이렇게 생겼어요:
| id | name | secret_name | age | team_id |
|---|---|---|---|---|
| 1 | Deadpond | Dive Wilson | null | 2 |
| 2 | Spider-Boy | Pedro Parqueador | null | 1 |
| 3 | Rusty-Man | Tommy Sharp | 48 | 1 |
hero 테이블의 team_id 열은 team 테이블에 있는 특정 팀의 ID를 가리켜요.
이렇게 각 hero를 team과 연결하는 거예요:
각 히어로는 하나의 연결만 가질 수 있어요. 하지만 각 팀은 많은 연결을 받을 수 있죠. 특히 Preventers 팀은 히어로가 둘이에요.
다대다 소개
그런데 Deadpond가 워낙 훌륭한 캐릭터라서, 새 Preventers 팀에도 영입됐다고 해 봅시다. 하지만 여전히 Z-Force 팀의 일원이기도 해요.
그러니 이제 많은 팀에 연결된 히어로가 필요해요. 그리고 각 팀도 여전히 많은 히어로를 받을 수 있어야 하죠. 즉 다대다 관계가 필요한 거예요.
잘 작동하지 않을 순진한 접근은 hero 테이블에 열을 더 추가하는 거예요. 열을 두 개 추가한다고 상상해 봐요. 이제 하나의 hero를 총 3개 팀까지는 연결할 수 있겠지만, 그 이상은 못 해요. 그러니 많은 팀을 지원하는 문제를 정말로 해결한 게 아니라, 아주 제한된 고정 개수만 지원한 거예요.
더 잘 할 수 있어요! 🤓
링크 테이블
hero 테이블과 team 테이블 사이의 연결을 나타내는 테이블을 하나 더 만들 수 있어요.
이 테이블이 담는 건 hero_id와 team_id 두 열뿐이에요.
두 열 모두 hero 테이블과 team 테이블의 특정 행 ID를 가리키는 외래 키예요.
이게 히어로-팀 연결을 나타낼 테니, 테이블 이름은 heroteamlink라고 하죠.
이렇게 생겼어요:
이제 hero 테이블에는 team_id 열이 없다는 점을 눈여겨보세요. 그 자리를 이 링크 테이블이 대신해요.
그리고 team 테이블도 이전과 마찬가지로 외래 키가 없어요.
구체적으로 새 링크 테이블 heroteamlink는 이러할 거예요:
| hero_id | team_id |
|---|---|
| 1 | 1 |
| 1 | 2 |
| 2 | 1 |
| 3 | 1 |
!!! note "참고"
이 **링크 테이블**을 부르는 다른 이름들이 있어요:
* association table
* secondary table
* junction table
* intermediate table
* join table
* through table
* relationship table
* connection table
저는 "링크 테이블(link table)"이라는 용어를 써요. 짧고, 이미 쓰고 있는 다른 용어(예: "relationship")와 부딪히지 않고, 어떻게 쓰는지 기억하기 쉽기 때문이에요.
링크 기본 키
좋아요, 두 열뿐인 링크 테이블이 생겼어요. 그런데 SQL 데이터베이스는 각 행이 그 테이블의 행을 고유하게 식별하는 기본 키를 가져야 한다고 요구한다는 거 기억나세요?
그럼 이 테이블의 기본 키는 뭘까요?
각 고유 행을 어떻게 식별할까요?
이 링크 테이블의 기본 키 역할을 할 열을 하나 더 추가해야 할까요? 아뇨! 그럴 필요 없어요. 👌
두 열 모두가 이 테이블 각 행의 기본 키예요(그리고 각 행은 그 두 열만 갖고 있죠). ✨
기본 키는 단일 테이블에서 특정 행을 고유하게 식별하는 방법이에요. 하지만 꼭 단일 열일 필요는 없어요.
기본 키는 테이블의 여러 열이 합쳐져서 그 테이블에서 고유한 그룹일 수 있어요.
위 테이블을 다시 보세요. 각 행이 hero_id와 team_id의 고유한 조합을 갖고 있죠?
기본 키는 중복될 수 없어요. 즉 hero와 team 사이의 링크가 중복될 수 없다는 뜻인데, 바로 우리가 원하는 거예요!
예를 들어 데이터베이스는 이제 이런 중복 행 오류를 막아줘요:
| hero_id | team_id |
|---|---|
| 1 | 1 |
| 1 | 2 |
| 2 | 1 |
| 3 | 1 |
| 3 🚨 | 1 🚨 |
히어로가 같은 팀에 두 번 속하는 건 말이 안 되잖아요, 그렇죠?
이제 두 열을 이 테이블의 기본 키로 쓰기만 하면, SQL이 hero와 team 사이의 링크가 중복되는 것을 막아 줘요. ✅
요약
소개인데 요약이 나오다니, 이상하네요... 뭐 어쩌겠어요. 🤷
이제 다대다 관계에 대한 이론과, SQL의 테이블로 그걸 해결하는 법을 알게 됐어요. 🤓
이제 그걸 다루는 SQL과 코드를 어떻게 쓰는지 확인해 볼게요. 🚀