ER 다이어그램 읽기와 그리기

Chen 표기법과 Crow's Foot 표기법을 비교하고, 엔티티·속성·관계·기수성(Cardinality) 개념을 쇼핑몰 도메인 ERD 예시와 함께 설명합니다.

· 5 min read · PALDYN Team

지난 글에서 비정규화 결정 기준을 살펴봤다. 이번에는 데이터베이스 설계의 출발점인 **ER 다이어그램(Entity-Relationship Diagram)**을 읽고 그리는 방법을 정리한다.


ERD가 필요한 이유

ERD는 비즈니스 도메인을 테이블로 옮기기 전에 개념 수준에서 엔티티와 관계를 그림으로 표현한다. 코드가 아니라 그림이기 때문에 개발자, DBA, 기획자가 같은 언어로 소통할 수 있다.


핵심 구성 요소

엔티티(Entity)

실세계에서 독립적으로 식별 가능한 객체. 테이블에 대응한다.

강한 엔티티(Strong Entity):  독립적으로 존재 — CUSTOMER, PRODUCT
약한 엔티티(Weak Entity):    강한 엔티티 없이 존재 불가 — ORDER_ITEM

속성(Attribute)

엔티티가 갖는 성질. 컬럼에 대응한다.

단순 속성:   name, email (더 이상 분해 안 됨)
복합 속성:   address = {city, street, zipcode} (분해 가능)
다치 속성:   phone_numbers (여러 값 가질 수 있음) → 별도 테이블로
파생 속성:   age (birth_date로 계산) → 일반적으로 저장 안 함

관계(Relationship)

엔티티 간의 연관. FK로 구현된다.

CUSTOMER  --[PLACES]-->  ORDER
ORDER     --[CONTAINS]--> ORDER_ITEM
ORDER_ITEM --[INCLUDES]--> PRODUCT

표기법 비교

ERD 표기법 비교

Chen 표기법은 엔티티를 직사각형, 속성을 타원, 관계를 마름모로 표현한다. 개념 설계 단계에서 관계의 의미를 명확히 드러낼 때 유용하다.

**Crow’s Foot(IE 표기법)**은 엔티티 박스 안에 속성을 직접 나열하고, 연결선 끝에 기수성을 표기한다. 실무 ERD 도구(ERDCloud, dbdiagram.io, Mermaid)의 기본값이다.


기수성(Cardinality)

두 엔티티 간에 몇 대 몇으로 관계를 맺는지를 나타낸다.

관계의미예시
1:1양쪽 모두 정확히 1사원 ↔ 주차번호
1:N하나가 여럿에 대응고객 → 주문
N:M양쪽 모두 여럿학생 ↔ 강의

N:M 관계는 **교차 테이블(Junction Table)**로 분해해야 물리 구현이 가능하다.

-- N:M 예시: 학생-강의
CREATE TABLE student_course (
    student_id  INT REFERENCES students(id),
    course_id   INT REFERENCES courses(id),
    enrolled_at DATE,
    PRIMARY KEY (student_id, course_id)
);

쇼핑몰 도메인 ERD 예시

쇼핑몰 ERD 예시

위 ERD를 SQL DDL로 옮기면 다음과 같다.

CREATE TABLE customers (
    id         BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
    name       VARCHAR(100)  NOT NULL,
    email      VARCHAR(255)  NOT NULL UNIQUE,
    phone      VARCHAR(20),
    created_at TIMESTAMPTZ   NOT NULL DEFAULT now(),
    grade      CHAR(1)       NOT NULL DEFAULT 'B'  -- A/B/C/D
);

CREATE TABLE orders (
    id           BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
    customer_id  BIGINT         NOT NULL REFERENCES customers(id),
    status       VARCHAR(20)    NOT NULL DEFAULT 'pending',
    total_amount NUMERIC(12,2)  NOT NULL DEFAULT 0,
    created_at   TIMESTAMPTZ    NOT NULL DEFAULT now(),
    shipped_at   TIMESTAMPTZ
);

CREATE TABLE products (
    id          BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
    name        VARCHAR(200)  NOT NULL,
    price       NUMERIC(10,2) NOT NULL,
    stock       INT           NOT NULL DEFAULT 0,
    category_id INT           REFERENCES categories(id)
);

CREATE TABLE order_items (
    id          BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
    order_id    BIGINT         NOT NULL REFERENCES orders(id),
    product_id  BIGINT         NOT NULL REFERENCES products(id),
    qty         INT            NOT NULL CHECK (qty > 0),
    unit_price  NUMERIC(10,2)  NOT NULL  -- 주문 당시 가격 스냅샷
);

필수 vs 선택 참여

기수성 외에 **참여 제약(Participation Constraint)**도 표기해야 한다.

전체 참여(Mandatory):  모든 고객은 반드시 주문을 가져야 한다
부분 참여(Optional):   고객이 주문을 가질 수도, 없을 수도 있다

Crow’s Foot에서는 |O≫ 기호로 표기한다: |는 “정확히 1”, O는 “0 가능”, 는 “다수”.

-- 참여 제약 → NOT NULL로 구현
-- 주문은 반드시 고객을 가져야 함: customer_id NOT NULL
-- 주문에 배송 주소는 선택: address_id NULL 허용

ERD 작성 순서

  1. 도메인 분석: 무엇이 엔티티인가 (명사 추출)
  2. 관계 식별: 엔티티 간 동사 도출
  3. 기수성 결정: 1:1, 1:N, N:M 판별
  4. 속성 배치: 기본키, 외래키, 일반 속성
  5. 정규화 검토: 중복·이상 현상 확인
  6. DDL 생성: ERD → SQL CREATE TABLE

지난 글: 비정규화 결정 기준

다음 글: 관계 매핑: ERD를 테이블로 변환하기


읽어주셔서 감사합니다. 😊