관계
고친 사람 github-actions[bot]
관계는 둘이 서로 어떻게 이어져 있는지를 말해 줍니다. 데이터 모델링에서는 고객과 주문처럼 두 종류의 데이터가 이어진 방식을 가리킵니다. 그런데 관계형 데이터베이스라는 이름 속의 관계는 이어짐이 아니라 표 하나를 가리킵니다. 같은 낱말이 두 뜻으로 쓰여서 어느 쪽 이야기인지부터 가려야 합니다.
쉽고 빠른 이해
무슨 일을 하는 말인가 — 두 데이터가 어떻게 이어져 있는지를 적어 둡니다. 쇼핑몰이라면 「고객이 주문을 한다」가 관계입니다. 고객 한 명은 주문을 여럿 할 수 있습니다. 주문 하나는 고객 한 명의 것입니다.
왜 적어 두나 — 이어짐을 안 적어 두면 「이 주문은 누가 했나」에 답할 길이 없습니다. 관계를 먼저 정해야 표를 어떻게 나누고 무엇으로 이을지가 정해집니다.
어떻게 도나
- 다룰 대상을 고객·주문·상품처럼 나눕니다
- 둘씩 짝지어 어떻게 이어지는지, 몇 대 몇인지 적습니다
- 표로 옮길 때는 상대의 번호를 적는 칸을 두어 그 이어짐을 남깁니다
헷갈리는 점 — 「관계형 데이터베이스」의 관계는 이 이어짐이 아닙니다. 거기서는 표 하나를 관계라고 부릅니다.
대가 — 관계를 따라 나눈 데이터는 한 번에 읽으려 해도 여러 표를 이어 붙여야 합니다. 업무 규칙이 바뀌어 몇 대 몇이 달라지면 표를 다시 나누고 쌓인 데이터까지 옮겨야 합니다.
상세
이 절은 먼저 「관계」가 가리키는 뜻들을 표 하나로 가릅니다. 그다음 백엔드 개발자가 가장 자주 만나는 뜻, 데이터 모델링의 관계를 쇼핑몰의 고객·주문·상품으로 따라갑니다. 끝에서는 관계형 데이터베이스의 「관계」가 왜 표 하나를 가리키는지 보고, 어느 뜻인지 가르는 단서를 모읍니다.
관계가 가리키는 뜻들
맥락마다 관계가 무엇을 가리키는지 영어 이름과 함께 모았습니다.
| 맥락 | 관계가 가리키는 것 | 영어 이름 | 예 |
|---|---|---|---|
| 데이터 모델링 | 두 종류의 데이터가 서로 이어진 방식 | relationship | 고객이 주문을 한다 |
| [[객체 지향 프로그래밍 | 객체 지향]] 코드 | 한 객체가 다른 객체를 가리키는 연결 | association |
| 일반 기술 문서 | 한쪽이 다른 쪽과 맞물리는 방식 | relationship | 시각과 초 값의 관계 · 알림 사이의 의존 관계 |
| 관계형 데이터베이스 | 같은 열을 가진 행들의 모음, 곧 표 하나 | relation | 고객 표 |
| 수학 | 조건을 만족하는 짝들의 모음 | relation | 「보다 작다」를 만족하는 수의 짝 |
위의 셋은 영어로 relationship·association, 아래 둘은 relation 입니다. 위의 셋은 둘 사이의 이어짐을 말합니다. 아래 둘은 짝이나 행을 모아 둔 덩어리 하나를 말합니다.
한국어는 이 둘을 모두 관계라고 부릅니다. 그래서 헷갈림이 생깁니다.
엔티티와 관계
데이터 모델링은 담을 데이터를 어떤 덩어리로 나누고 어떻게 이을지 정하는 일입니다. 나눈 덩어리 하나하나를 엔티티라고 부릅니다. 쇼핑몰이라면 고객·주문·상품이 엔티티입니다.
엔티티만 정해서는 부족합니다. 주문 목록만 있으면 「이 주문은 누가 했나」에 답할 수 없습니다. 그래서 엔티티끼리 어떻게 이어지는지도 함께 정합니다. 이 이어짐이 데이터 모델링에서 말하는 관계입니다.
관계에는 보통 동사로 이름을 붙입니다. 고객은 주문을 「한다」. 주문은 상품을 「담는다」. 이름을 소리 내 읽으면 요구사항 문장이 됩니다. 그래서 모델이 요구사항과 맞는지 바로 견줘 볼 수 있습니다.
몇 대 몇으로 이어지나
관계에는 수가 붙습니다. 고객 한 명이 주문을 몇 개까지 할 수 있는지, 주문 하나가 고객 몇 명의 것인지가 그 수입니다. 이 수를 관계의 카디널리티라고 부릅니다. 흔히 1:N 처럼 적습니다.
| 종류 | 적는 법 | 뜻 | 예 |
|---|---|---|---|
| 일대일 | 1:1 | 양쪽 모두 상대가 하나뿐 | 회원과 회원 프로필 |
| 일대다 | 1:N | 한쪽 하나가 다른 쪽 여럿과 이어짐 | 고객과 주문 |
| 다대다 | N:M | 양쪽 모두 상대가 여럿 | 주문과 상품 |
같은 두 엔티티라도 업무 규칙에 따라 몇 대 몇이 달라집니다. 여러 사람이 주문 하나를 함께 내는 서비스라면 고객과 주문은 다대다가 됩니다. 그래서 카디널리티는 쌓인 데이터를 세어 얻는 값이 아니라 요구사항에서 정하는 값입니다. 규칙이 바뀌어 일대다가 다대다가 되면 표를 다시 나누고 쌓인 데이터까지 옮겨야 합니다.
수와 함께 「상대가 없어도 되나」도 정합니다. 주문은 고객 없이 생길 수 없습니다. 고객은 주문을 한 번도 안 해도 고객입니다.
관계를 그린 그림
엔티티와 관계를 그린 그림을 ER(Entity-Relationship, 엔티티-관계) 다이어그램이라고 부릅니다. 아래는 쇼핑몰의 세 엔티티와 두 관계를 그린 것입니다.
erDiagram
direction TB
고객 ||--o{ 주문 : "한다"
주문 }o--|{ 상품 : "담는다"
선 양 끝의 기호가 앞 소절에서 본 두 가지를 나타냅니다. 세 갈래로 벌어진 끝은 「여럿」, 세로 막대는 「하나」, 동그라미는 「없음」입니다. 끝마다 기호가 둘씩 붙어 가장 적을 때와 가장 많을 때를 함께 보입니다. 엔티티 바로 옆 기호가 가장 많을 때, 선 가운데 쪽 기호가 가장 적을 때입니다.
첫 선은 이렇게 읽습니다. 고객 쪽 끝은 막대 둘이라 적어도 하나, 많아야 하나입니다. 주문 하나에는 고객이 꼭 한 명 있다는 뜻입니다. 주문 쪽 끝은 동그라미와 세 갈래라 고객 한 명의 주문은 없을 수도 있고 여럿일 수도 있습니다.
둘째 선도 같은 방법으로 읽습니다. 상품 쪽 끝은 막대와 세 갈래라 주문 하나에는 상품이 적어도 하나 들어갑니다. 주문 쪽 끝은 동그라미와 세 갈래라 상품 하나는 한 번도 안 팔렸을 수도 있고 주문 여럿에 들어갔을 수도 있습니다.
표로 옮긴 관계
그림 위의 선은 데이터베이스에 그대로 담을 수 없습니다. 담으려면 선 하나를 표 안의 값으로 바꿔야 합니다. 이 소절은 몇 대 몇마다 그 방법이 어떻게 갈리는지 봅니다.
먼저 번호가 필요합니다. 표에서 행 하나를 콕 집어 가리키는 값을 기본 키라고 부릅니다. 고객 표라면 고객마다 겹치지 않게 매긴 고객번호가 기본 키입니다.
일대다는 「여럿」 쪽 표에 「하나」 쪽의 기본 키를 적는 열을 하나 둡니다. 다른 표의 기본 키를 적어 두는 이 열을 외래 키라고 부릅니다. 고객과 주문이라면 주문 표에 고객번호 열을 둡니다.
먼저 고객 표입니다.
| 고객번호 | 이름 |
|---|---|
| 1 | 김하나 |
| 2 | 이두리 |
다음은 주문 표입니다. 주문마다 고객번호 열이 붙어 있습니다.
| 주문번호 | 고객번호 |
|---|---|
| 101 | 1 |
| 102 | 1 |
| 103 | 2 |
주문 101 과 102 는 고객번호가 1 이라 김하나의 주문입니다. 고객 표에는 주문을 적는 칸이 없습니다. 관계는 주문 표의 고객번호 열에만 남습니다.
외래 키를 「하나」 쪽에 두지 않는 데는 까닭이 있습니다. 고객 표에 주문번호를 적으려면 김하나의 칸 하나에 101 과 102 를 함께 넣어야 합니다. 관계형 데이터베이스는 칸 하나에 값 하나만 넣도록 표를 짭니다. 그래서 값이 하나로 정해지는 「여럿」 쪽이 번호를 적습니다.
일대일은 어느 쪽에든 외래 키를 둘 수 있습니다. 대신 그 열에 같은 값이 두 번 들어가지 못하게 막아야 합니다. 안 막으면 회원 한 명에게 프로필이 둘 붙어 일대다가 됩니다. 이렇게 막는 규칙이 유니크 제약입니다.
다대다를 푸는 연결 표
다대다는 양쪽 어디에도 외래 키를 둘 수 없습니다. 주문 하나에는 상품이 여럿입니다. 상품 하나도 주문 여럿에 들어갑니다. 그래서 어느 쪽 칸에 적어도 값이 여럿이 됩니다. 그래서 두 표 사이에 표를 하나 더 둡니다.
이 표를 연결 테이블이라고 부릅니다. 쇼핑몰이라면 주문항목 표가 그 일을 맡습니다. 주문항목의 한 행은 「어느 주문에 어느 상품이 몇 개」를 적습니다.
| 주문번호 | 상품번호 | 수량 |
|---|---|---|
| 101 | 7 | 2 |
| 101 | 9 | 1 |
| 102 | 7 | 1 |
주문 101 은 상품 7 과 9 를 담았습니다. 상품 7 은 주문 101 과 102 에 모두 들어 있습니다. 한 행에는 번호가 하나씩만 있으므로 칸 하나에 값이 여럿 들어갈 일이 없습니다.
erDiagram
direction TB
주문 ||--|{ 주문항목 : "담는다"
상품 ||--o{ 주문항목 : "들어간다"
그림으로 보면 다대다 하나가 일대다 둘로 풀렸습니다. 주문 하나에 주문항목이 여럿, 상품 하나에 주문항목이 여럿입니다. 수량처럼 관계 자체에 붙는 값도 이 연결 표가 담습니다.
관계를 따라 읽기
표로 나눈 데이터를 다시 모으려면 관계를 거꾸로 따라갑니다. 「주문 101 은 누가 했나」에 답하려면 먼저 주문 행의 고객번호를 읽습니다. 그 번호로 고객 표에서 행을 찾으면 답이 나옵니다. 두 표를 이렇게 이어 읽는 연산이 조인입니다.
SELECT 고객.이름
FROM 주문
JOIN 고객
ON 고객.고객번호 = 주문.고객번호
WHERE 주문.주문번호 = 101; -- 김하나
JOIN ... ON 줄이 외래 키를 따라가는 부분입니다. 주문 101 의 고객번호 1 이 고객 표의 1 번 행과 맞물려 이름이 나옵니다.
표 밖의 관계
표를 쓰지 않는 저장소도 관계를 적습니다. 문서 데이터베이스는 데이터를 문서 한 덩어리씩 담습니다. 이때 관계를 적는 방법이 둘입니다.
하나는 주문 문서 안에 상품 목록을 함께 넣는 것입니다. 한 번에 읽혀서 조인이 필요 없습니다.
다른 하나는 고객번호만 적어 두고 필요할 때 따로 찾아오는 것입니다. 외래 키와 같은 방식입니다. 어느 쪽이든 모델에서 정한 관계는 같습니다. 적는 방법만 다릅니다.
코드 속의 관계
객체 지향 코드에서는 관계가 필드 하나로 나타납니다. 주문 클래스가 고객 객체를 가리키는 필드를 가지면 둘은 이어져 있습니다. 이런 이어짐을 영어로 association, 곧 연관이라고 부릅니다.
데이터 모델링의 관계와 같은 이어짐을 코드로 옮긴 것입니다. 코드에서는 필드가 상대를 가리킵니다. 표에서는 외래 키가 상대를 가리킵니다. 둘 사이를 오가며 바꿔 주는 도구가 ORM(Object-Relational Mapping, 객체-관계 매핑)입니다.
관계형 데이터베이스의 「관계」
「관계형」이라는 이름을 들으면 표끼리 이어져 있어서 붙은 이름처럼 들립니다. 그렇지 않습니다. 이 이름 속의 관계는 표 하나를 가리킵니다. 이 소절은 그 뜻이 수학에서 왔다는 것을 작은 표 하나로 보입니다.
수학에서 관계는 어떤 조건을 만족하는 짝들의 모음입니다. 순서가 정해진 짝을 순서쌍이라고 부릅니다. 1·2·3 에서 「왼쪽이 오른쪽보다 작다」를 만족하는 순서쌍은 (1, 2) · (1, 3) · (2, 3) 셋입니다. 이 셋의 모음이 「보다 작다」라는 관계입니다.
| 작은 수 | 큰 수 |
|---|---|
| 1 | 2 |
| 1 | 3 |
| 2 | 3 |
순서쌍을 한 줄에 하나씩 적으니 표가 되었습니다. 관계형 데이터베이스가 따르는 설계 이론을 관계형 모델이라고 부릅니다. 관계형 모델은 이 생각을 데이터에 가져왔습니다.
두 값의 짝 대신 여러 값을 묶은 줄을 씁니다. 같은 모양의 줄들을 모은 것을 관계라고 부릅니다.
그 줄 하나를 튜플이라고 부릅니다. 흔히 말하는 표의 행입니다. 줄 안의 칸마다 붙은 이름은 속성이라고 부릅니다. 표의 열 이름에 해당합니다.
flowchart TD
subgraph M["데이터 모델링의 관계 · 둘을 잇는 선"]
A[고객] -->|한다| B[주문]
end
subgraph R["관계형 데이터베이스의 관계 · 표 하나"]
C["고객 표 · 고객번호와 이름을 묶은 줄들"]
end
M ~~~ R
그래서 앞에서 본 고객 표도 그 자체로 관계 하나입니다. 외래 키가 하나도 없는 표 한 장짜리 데이터베이스도 관계형입니다. 이 뜻일 때는 데이터 모델링의 관계와 섞이지 않게 「릴레이션」이라고 소리 나는 대로 부르는 일이 많습니다.
「객체-관계 매핑」의 관계도 이쪽 뜻입니다. ORM 은 객체를 관계형 데이터베이스의 표(릴레이션)에 옮기는 도구라서 그런 이름이 붙었습니다.
여러 분야 문서의 관계
기술 문서는 관계를 따로 정의하지 않고 낱말 뜻 그대로 쓰기도 합니다. 「A 와 B 의 관계」는 한쪽을 알 때 다른 쪽을 어떻게 알아내는지를 말합니다. 유닉스 시간(정해 둔 기준 시각부터 센 초 값)과 실제 시각의 관계라고 하면 초 값 하나에서 지금 시각을 구하는 규칙을 가리킵니다.
「의존 관계」도 자주 나옵니다. 한쪽이 다른 쪽에 기대고 있어서 그쪽이 멈추면 함께 영향을 받는 사이를 말합니다. 데이터베이스 서버를 쓰는 서비스는 그 서버에 의존하는 관계입니다.
장애를 감시하는 도구가 보내는 알림에서 이 관계가 쓰입니다. 데이터베이스 서버가 멈추면 그 서버의 알림이 먼저 뜹니다. 이어서 그 서버를 쓰는 서비스들의 알림이 줄줄이 뜹니다.
뒤의 알림들은 첫 알림에 의존하는 관계입니다. 그래서 원인인 첫 알림 하나만 보내고 나머지는 거를 수 있습니다.
이 쓰임에는 엔티티·표·외래 키 같은 말이 따라오지 않습니다. 그런 말이 없으면 대개 이 뜻입니다.
어느 뜻인지 가르는 단서
글에서 관계를 만나면 함께 나온 낱말을 보면 됩니다. 아래 표는 자주 같이 나오는 낱말과 그때의 뜻입니다.
| 함께 나오는 말 | 뜻 |
|---|---|
| 엔티티 · 일대다 · 다대다 · ER 다이어그램 | 데이터 모델링의 관계 |
| 외래 키 · 연결 테이블 · 조인 | 데이터 모델링의 관계를 표로 옮긴 것 |
| 필드 · 객체 · 연관 | 코드 속의 관계 |
| 튜플 · 속성 · 릴레이션 · 관계형 모델 | 표 하나를 가리키는 관계 |
| 집합 · 순서쌍 · 「보다 작다」 같은 조건 | 수학의 관계 |
| 의존 · 비례 · 「A 와 B 의」 | 낱말 뜻 그대로의 관계 |
관련 항목
관계와 함께 데이터 모델을 이루는 구성 요소
엔티티 · 속성 · 카디널리티 · ER 다이어그램 · 개체 관계 모델 · 개념 모델 · 논리 모델 · 데이터 모델링
관계의 하위 종류
일대일 관계 · 일대다 관계 · 다대다 관계 · 자기 참조 관계
관계를 표로 옮길 때 쓰는 키와 제약
기본 키 · 외래 키 · 유니크 제약 · 연결 테이블 · 참조 무결성 · 제약 조건
관계를 따라 데이터를 읽는 연산과 그 함정
조인 · 질의 · 서브쿼리 · N+1 문제 · 지연 로딩
관계를 어디에 둘지 가르는 설계 기법
관계를 표 없이 적는 저장 방식
문서 데이터베이스 · 그래프 데이터베이스 · NoSQL
관계를 코드의 객체로 옮기는 도구와 표기
ORM · 객체 지향 프로그래밍 · UML · 클래스 다이어그램 · 연관
관계를 표 하나로 보는 관계형 모델의 용어
관계형 모델 · 관계형 데이터베이스 · 릴레이션 · 튜플 · 행 · 열 · 관계 대수
관계형 모델의 관계가 비롯된 수학 개념
관계라는 이름이 붙은 다른 분야의 용어
의존성 · 관계 기반 접근 제어 · happened-before 관계
다른 이름: relationship · relation