2026년 10월에 내용을 보강했습니다. 기호를 읽는 법, 식별/비식별 관계의 차이, 관계별 DDL, 다대다(N:N) 해소 방법을 추가했습니다.

ERD(Entity Relationship Diagram)에서 엔티티 사이를 잇는 선은 두 가지를 동시에 말해 줍니다.

  1. 선의 모양(실선/점선): 부모의 키가 자식에서 어떤 역할을 하는가 → 식별 / 비식별 관계
  2. 선 끝의 기호: 한쪽이 다른 쪽과 몇 개 대응되는가 → 관계의 종류(카디널리티)

이 글에서는 SHOP(가게)과 FOOD(음식) 두 엔티티로 정리합니다.

📌 표기법에 대해 이 글의 그림은 IE(Information Engineering, 까마귀 발) 표기법입니다. 도구나 조직마다 IDEF1X, Chen 표기법 등을 쓰기도 해서 기호 모양은 다를 수 있습니다. ERD 를 읽을 때는 먼저 어떤 표기법인지 확인하세요.


1. 선 끝의 기호 읽는 법

기호 의미
| (수직 막대) 하나(1)
< (까마귀 발) 여러 개(N)
○ (동그라미) 0, 즉 없을 수도 있다(선택)

기호는 이렇게 조합합니다.

조합 의미
| 하나
|< 하나 이상 (1..N)
○| 없거나 하나 (0..1)
○< 없거나 여러 개 (0..N)

읽는 방향이 중요합니다. 선 끝의 기호는 그 기호가 붙은 쪽 엔티티가, 반대쪽 엔티티 하나당 몇 개 대응되는지를 뜻합니다.

SHOP ──|< FOOD 라면, 오른쪽 FOOD 쪽 기호가 |< 이므로 “가게 하나에는 음식이 하나 이상 있다” 로 읽습니다. 반대쪽 SHOP 끝의 기호는 |(하나)이므로 “음식 하나는 반드시 하나의 가게에 속한다” 입니다.


2. 식별 관계와 비식별 관계 (실선 / 점선)

부모의 PK(기본키)가 자식 테이블에서 어떻게 쓰이는지로 나뉩니다.

구분 선 부모 PK 가 자식에서…
식별 관계 실선 자식의 PK 의 일부가 된다 (PK 이면서 FK)
비식별 관계 점선 자식의 일반 컬럼(FK) 이 된다

식별 관계 (실선)

자식은 부모 없이는 존재할 수 없고, 부모의 키가 자식의 식별자(PK)에 포함됩니다.

CREATE TABLE shop (
    shop_id BIGINT       PRIMARY KEY,
    name    VARCHAR(50)  NOT NULL
);

-- 식별 관계: food 의 PK = (shop_id, food_no)
CREATE TABLE food (
    shop_id BIGINT       NOT NULL,
    food_no INT          NOT NULL,
    name    VARCHAR(50)  NOT NULL,
    PRIMARY KEY (shop_id, food_no),
    FOREIGN KEY (shop_id) REFERENCES shop (shop_id)
);

비식별 관계 (점선)

자식은 자기만의 PK 를 갖고, 부모의 키는 일반 컬럼(FK) 으로만 참조합니다.

-- 비식별 관계: food 의 PK = food_id (부모 키는 일반 FK)
CREATE TABLE food (
    food_id BIGINT       PRIMARY KEY,
    shop_id BIGINT       NOT NULL,       -- 필수 관계
    name    VARCHAR(50)  NOT NULL,
    FOREIGN KEY (shop_id) REFERENCES shop (shop_id)
);

비식별 관계는 FK 가 NOT NULL 이면 필수, NULL 을 허용하면 선택적인 관계가 됩니다. 도구에 따라 선택 관계를 점선과 다이아몬드로 따로 표시하기도 합니다.

실무에서는 어느 쪽을?

  식별 관계 비식별 관계
장점 자식 PK 에 부모 키가 있어 부모 기준 조회가 단순, 중복 방지가 자연스럽다 구조가 단순하고 변경에 유연하다
단점 자식 → 손자로 내려갈수록 PK 컬럼이 누적되고, 부모 키 변경의 영향이 크다 부모 기준으로 묶어서 유일성을 보장하려면 별도 UNIQUE 제약이 필요
JPA @IdClass / @EmbeddedId 등 복합키 매핑이 필요 대리키(@GeneratedValue)로 단순하게 매핑

그래서 실무에서는 비식별 관계와 대리키(auto increment 등)를 기본으로 쓰고, 식별 관계는 꼭 필요한 곳(예: 연결 테이블)에만 쓰는 경우가 많습니다. 반드시 이래야 하는 것은 아니고, 팀의 규칙과 데이터의 성격에 따라 정하면 됩니다.

JPA 에서의 복합키는 JPA 연관관계 매핑 - 복합키 매핑 글에서 정리했습니다.


3. 관계의 종류 (카디널리티)

(1 : 1) 관계 — 부모는 하나의 자식이 있다

ERD-1

  • 읽기: 가게 하나에 음식 하나, 음식 하나에 가게 하나
  • 구현: 한쪽에 FK 를 두고 UNIQUE 를 걸거나, 자식의 PK 를 부모의 PK 와 같게 둡니다. (식별 관계)
-- 자식 PK = 부모 PK (식별 1:1)
CREATE TABLE shop_detail (
    shop_id     BIGINT PRIMARY KEY,
    description TEXT,
    FOREIGN KEY (shop_id) REFERENCES shop (shop_id)
);

(1 : N) 관계 — 부모는 하나 이상의 자식이 있다

ERD-2

  • 읽기: 가게 하나에 음식이 하나 이상, 음식 하나는 반드시 한 가게에 속함
  • 구현: N 쪽(자식)에 FK 를 둡니다. 가장 흔한 관계입니다. (위 food 테이블)

(N : N) 관계 — 하나 이상의 부모와 하나 이상의 자식이 있다

ERD-3

  • 읽기: 가게 하나에 음식이 여러 개, 음식 하나가 여러 가게에 있을 수 있음
  • 구현: 관계형 DB 는 N:N 을 직접 표현할 수 없습니다. 연결(교차) 테이블을 두어 1:N 두 개로 풀어서 구현합니다.
-- 가게와 음식이 N:N 인 경우: 연결 테이블로 해소
CREATE TABLE food (
    food_id BIGINT      PRIMARY KEY,
    name    VARCHAR(50) NOT NULL
);

CREATE TABLE shop_food (
    shop_id BIGINT NOT NULL,
    food_id BIGINT NOT NULL,
    PRIMARY KEY (shop_id, food_id),     -- 두 FK 를 합친 복합 PK (식별 관계)
    FOREIGN KEY (shop_id) REFERENCES shop (shop_id),
    FOREIGN KEY (food_id) REFERENCES food (food_id)
);

ERD 에서는 SHOP ─ SHOP_FOOD ─ FOOD 로, 양쪽이 모두 (1 : N) 이 됩니다. 연결 테이블에 “가격”, “등록일” 같은 속성이 필요해지는 경우가 많아서, JPA 에서도 @ManyToMany 보다 연결 엔티티를 직접 만드는 방식을 권장하는 편입니다. (JPA 연관관계 매핑 - 조인 테이블)

(1 : 1(o)) 관계 — 부모는 하나의 자식이 있을 수도 있다 (없을 수도 있다)

ERD-4

  • 읽기: 가게에 음식이 없거나 하나
  • 구현: 1:1 과 같고, 자식 쪽 레코드가 없을 수 있다는 뜻일 뿐 컬럼에 별도의 제약이 생기지는 않습니다.

(1 : N(o)) 관계 — 부모는 여러 개의 자식이 있을 수도 있다 (없을 수도 있다)

ERD-5

  • 읽기: 가게에 음식이 없거나 여러 개
  • 구현: (1 : N) 과 같습니다. 가게를 먼저 등록하고 음식을 나중에 추가하는 구조에서 흔히 씁니다.

4. 가장 많이 헷갈리는 부분: ○ 는 어느 쪽에 붙는가

○(선택) 의 위치에 따라 의미가 완전히 달라집니다.

모양 의미 DB 에서
SHOP ─| ─○< FOOD 가게는 음식이 없을 수 있다. 음식은 반드시 가게에 속한다 food.shop_id 는 NOT NULL
SHOP ─○| ─< FOOD 음식은 가게 없이 존재할 수 있다 food.shop_id 는 NULL 허용
  • 자식 쪽 끝의 ○ → “부모에게 자식이 없을 수 있다.” 별도의 DB 제약은 없습니다.
  • 부모 쪽 끝의 ○ → “자식이 부모 없이 존재할 수 있다.” FK 가 NULL 허용이 됩니다.

위 그림 4, 5번은 자식 쪽 끝의 ○ 입니다.


5. 한눈에 정리

구분 모양 의미 구현
식별 관계 실선 부모 PK 가 자식 PK 의 일부 복합 PK (PK 이면서 FK)
비식별 관계 점선 부모 PK 가 자식의 일반 컬럼 일반 FK (NOT NULL 이면 필수, NULL 허용이면 선택)
1 : 1 | ─ | 서로 하나씩 FK + UNIQUE 또는 FK = PK
1 : N | ─ |< 부모 하나에 자식 여러 개 N 쪽에 FK
N : N |< ─ |< 양쪽 모두 여러 개 연결 테이블로 1:N 두 개로 분해
1 : 1(o) | ─ ○| 자식이 없거나 하나 1:1 과 동일
1 : N(o) | ─ ○< 자식이 없거나 여러 개 1:N 과 동일

6. ERD 를 그릴 때 팁

  • 엔티티 이름은 단수형, 관계는 동사로 읽어 보세요. “가게는 음식을 가진다” 처럼 문장으로 읽히면 관계선이 맞게 그려진 것입니다.
  • 양쪽 끝을 모두 읽으세요. 한쪽만 보면 1:N 과 N:1 을 혼동하기 쉽습니다.
  • N:N 이 보이면 연결 테이블이 빠진 것이 아닌지 먼저 의심하세요.
  • 이 글의 그림은 draw.io 스타일입니다. ERDCloud, dbdiagram.io, MySQL Workbench 같은 도구도 많이 쓰이고, 도구마다 기본 표기법이 다를 수 있으니 설정을 확인하세요.