테이블을 나눴으면 이제 나눈 테이블들이 서로 어떻게 연결되는지를 따져야 한다. "한 회원이 주문을 몇 개나 할 수 있나?", "한 주문에 상품이 몇 개 들어갈 수 있나?" — 이런 질문이 바로 관계 차수(Cardinality)다. 테이블 간의 관계를 수량 관점에서 정의하는 것이다.
관계 차수는 세 가지다. 1:1, 1:N, N:M.
한 테이블의 행 하나가 다른 테이블의 행 하나와 정확히 대응되는 관계다.
회원과 회원 상세 정보를 예로 들면, 회원 한 명에게 상세 정보가 하나만 존재한다.

CREATE TABLE members (
member_id INT PRIMARY KEY AUTO_INCREMENT,
member_name VARCHAR(50) NOT NULL,
email VARCHAR(100) NOT NULL UNIQUE
);
CREATE TABLE member_profiles (
profile_id INT PRIMARY KEY AUTO_INCREMENT,
member_id INT NOT NULL UNIQUE, -- UNIQUE로 1:1 보장
address VARCHAR(200),
birth_date DATE,
FOREIGN KEY (member_id) REFERENCES members(member_id)
);
member_profiles.member_id에 UNIQUE가 붙어 있다. 같은 member_id가 두 번 들어올 수 없으니, 회원 한 명당 프로필이 하나뿐임을 DB 레벨에서 강제한다.
굳이 테이블을 나누는 이유는, 자주 쓰지 않는 컬럼(주소, 생년월일 등)을 메인 테이블과 분리해 조회 성능을 높이거나, 선택적으로 존재하는 정보를 별도로 관리하기 위해서다.
가장 흔한 관계다. 한 테이블의 행 하나가 다른 테이블의 행 여러 개와 연결된다.
회원 한 명이 주문을 여러 건 할 수 있다. 반대로 주문 하나는 한 명의 회원에게만 속한다. 이게 1:N이다.

CREATE TABLE members (
member_id INT PRIMARY KEY AUTO_INCREMENT,
member_name VARCHAR(50) NOT NULL
);
CREATE TABLE orders (
order_id INT PRIMARY KEY AUTO_INCREMENT,
member_id INT NOT NULL,
order_date DATE NOT NULL,
FOREIGN KEY (member_id) REFERENCES members(member_id)
);
members orders
----------- ----------------------------
member_id | member_name order_id | member_id | date
----------+------------ ---------+-----------+------
1 | 김민수 1 | 1 | 03-01
2 | 이지현 2 | 1 | 03-05
3 | 2 | 03-07
4 | 1 | 03-12
김민수(member_id=1)의 주문이 세 건이다. orders 테이블에 member_id를 외래 키로 두는 것만으로 1:N 관계가 만들어진다. "N쪽 테이블"이 외래 키를 가진다는 게 핵심이다.
양쪽 모두 여러 개와 연결될 수 있는 관계다. 한 주문에 상품이 여러 개 담길 수 있고, 한 상품은 여러 주문에 담길 수 있다. 이게 N:M이다.
N:M 관계는 두 테이블을 직접 연결할 수 없다. 외래 키를 어느 쪽에 두든 구조가 맞지 않는다. 이 문제를 해결하는 방법이 중간 테이블(Junction Table)이다.

CREATE TABLE orders (
order_id INT PRIMARY KEY AUTO_INCREMENT,
member_id INT NOT NULL,
order_date DATE NOT NULL,
FOREIGN KEY (member_id) REFERENCES members(member_id)
);
CREATE TABLE products (
product_id INT PRIMARY KEY AUTO_INCREMENT,
product_name VARCHAR(100) NOT NULL,
price INT NOT NULL
);
-- 중간 테이블
CREATE TABLE order_items (
order_id INT NOT NULL,
product_id INT NOT NULL,
quantity INT NOT NULL DEFAULT 1,
PRIMARY KEY (order_id, product_id),
FOREIGN KEY (order_id) REFERENCES orders(order_id),
FOREIGN KEY (product_id) REFERENCES products(product_id)
);
orders order_items products
-------- --------------------- ------------------
order_id order_id | product_id product_id | name
-------- ---------+----------- -----------+------
1 1 | 1 1 | 마우스
2 1 | 2 2 | 키보드
2 | 2
1번 주문에 마우스와 키보드가 담겼고, 2번 주문에도 키보드가 담겼다. 키보드(product_id=2)는 두 주문에 모두 연결돼 있다. 중간 테이블이 이 관계를 표현한다.
order_items의 PRIMARY KEY가 (order_id, product_id) 복합 기본 키인 점도 눈여겨볼 만하다. 같은 주문에 같은 상품이 두 번 들어가는 걸 막는다.
| 관계 | 설명 | 구현 방법 |
|---|---|---|
| 1:1 | 행 하나 ↔ 행 하나 | N쪽 FK에 UNIQUE 추가 |
| 1:N | 행 하나 ↔ 행 여러 개 | N쪽 테이블에 FK |
| N:M | 행 여러 개 ↔ 행 여러 개 | 중간 테이블(Junction Table) |
관계 차수를 정확히 파악하는 게 테이블 설계의 출발점이다. 관계를 잘못 파악하면 나중에 구조를 뒤집어야 하는 상황이 생긴다. "이 두 테이블이 서로 몇 개씩 연결될 수 있나?"를 먼저 따지고 설계를 시작하는 습관이 중요하다.