관계 차수

mskimdev·2026년 4월 17일

MySQL

목록 보기
12/20
post-thumbnail

관계 차수 (Cardinality)

테이블을 나눴으면 이제 나눈 테이블들이 서로 어떻게 연결되는지를 따져야 한다. "한 회원이 주문을 몇 개나 할 수 있나?", "한 주문에 상품이 몇 개 들어갈 수 있나?" — 이런 질문이 바로 관계 차수(Cardinality)다. 테이블 간의 관계를 수량 관점에서 정의하는 것이다.

관계 차수는 세 가지다. 1:1, 1:N, N:M.


관계 차수의 종류

1:1 (일대일)

한 테이블의 행 하나가 다른 테이블의 행 하나와 정확히 대응되는 관계다.

회원과 회원 상세 정보를 예로 들면, 회원 한 명에게 상세 정보가 하나만 존재한다.

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_idUNIQUE가 붙어 있다. 같은 member_id가 두 번 들어올 수 없으니, 회원 한 명당 프로필이 하나뿐임을 DB 레벨에서 강제한다.

굳이 테이블을 나누는 이유는, 자주 쓰지 않는 컬럼(주소, 생년월일 등)을 메인 테이블과 분리해 조회 성능을 높이거나, 선택적으로 존재하는 정보를 별도로 관리하기 위해서다.

1:N (일대다)

가장 흔한 관계다. 한 테이블의 행 하나가 다른 테이블의 행 여러 개와 연결된다.

회원 한 명이 주문을 여러 건 할 수 있다. 반대로 주문 하나는 한 명의 회원에게만 속한다. 이게 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이다.

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)

관계 차수를 정확히 파악하는 게 테이블 설계의 출발점이다. 관계를 잘못 파악하면 나중에 구조를 뒤집어야 하는 상황이 생긴다. "이 두 테이블이 서로 몇 개씩 연결될 수 있나?"를 먼저 따지고 설계를 시작하는 습관이 중요하다.

profile
<- 개발 공부하는 나

0개의 댓글