데이터베이스 학습 노트 목차

데이터 모델링·ERD — 개념·논리·물리 설계

테이블을 바로 만들기 전에무엇을 저장하고, 무엇이 무엇과 어떻게 연결되는지를 그리는 게 데이터 모델링이다. 잘못된 모델은 나중에 정규화·인덱스·쿼리로도 못 고치는 근본 부채가 된다(엔터티를 잘못 나누면 모든 쿼리가 비틀린다). 모델링은 추상(개념)에서 구체(물리)로 세 단계를 거치며, 그 그림 언어가 **ERD(개체-관계 다이어그램)**다. (출처: Silberschatz DBSC 7e Ch 6 E-R Model / 김연희 데이터베이스 개론.)

세 단계 — 개념 → 논리 → 물리

다이어그램 로딩 중…

세 단계를 "쇼핑몰" 요구사항으로 따라가 보자.

  • 개념적(conceptual)무엇이 있고 어떻게 관계되나DBMS와 무관하게 그린다. "회원이 주문을 하고, 주문에는 여러 상품이 담긴다" → 엔터티 회원·주문·상품, 관계 주문하다·담기다. 이해관계자(기획·도메인 전문가)와 합의하는 단계라 기술 용어를 최소화한다.
  • 논리적(logical) — 개념을 *관계 모델(테이블·키·정규화)*로 변환한다. 회원→member 테이블, 주문→orders, "주문에 상품 담기"(N:M)→order_item 연결 테이블. 어떤 DBMS든 적용 가능한 수준이다.
  • 물리적(physical)특정 DBMS에 맞춰 타입·인덱스·파티션·스토리지를 정한다. created_at을 PostgreSQL이면 timestamptz, MySQL이면 DATETIME으로, PK는 IDENTITY/AUTO_INCREMENT로, 자주 조회하는 member_id엔 인덱스를 건다.

개념은 사람이 이해하고, 논리는 모든 DB에 통하고, 물리는 한 DB에 최적화한다 — 단계를 건너뛰고 바로 테이블부터 만들면 요구사항과 어긋난 구조가 굳는다.

엔터티·속성·관계·식별자

모델링 개념관계형(테이블)
엔터티(entity)테이블회원·주문·상품
속성(attribute)칼럼이름·가격
관계(relationship)외래키회원이 주문을 한다
식별자(identifier)기본키회원ID

엔터티는 *"독립적으로 의미 있는 것"*인지로 판별한다 — 회원·주문은 엔터티지만, 주문의 '상태'는 속성이다(주문 없이 상태만 존재할 이유가 없으므로).

카디널리티 — 관계의 수

관계는 *"한쪽의 한 개체가 다른 쪽 몇 개체와 연결되나"*로 나뉜다. ERD의 까마귀발(crow's foot) 표기에서 ||(정확히 하나)·o{(0개 이상)·|{(1개 이상)가 그 수를 나타낸다.

다이어그램 로딩 중…
  • 1:1 — 회원 ↔ 프로필. 드물지만 쓸 이유가 있다 — 선택적·민감한 정보를 분리(프로필 사진·상세 정보를 별 테이블로 빼 회원 조회를 가볍게), 또는 접근 권한을 분리. 보통 자주 함께 읽으면 한 테이블, 따로 다루면 1:1 분리다.
  • 1:N — 회원 1명이 주문 여러 건(가장 흔함). *N쪽(orders)에 외래키(member_id)*를 둔다.
  • N:M — 주문 ↔ 상품(한 주문에 여러 상품, 한 상품이 여러 주문). → 연결 테이블로 푼다.
-- 1:N — N쪽(orders)에 FK
CREATE TABLE orders (
  id bigint PRIMARY KEY,
  member_id bigint NOT NULL REFERENCES member(id)   -- 1명의 회원 : N건의 주문
);

N:M은 연결 테이블로

관계형 DB는 N:M을 직접 표현 못 한다연결(중간) 테이블두 개의 1:N으로 분해한다.

CREATE TABLE order_item (              -- N:M 연결 테이블 (orders ↔ product)
  order_id   bigint REFERENCES orders(id),
  product_id bigint REFERENCES product(id),
  qty        int NOT NULL,            -- 관계 자체의 속성
  unit_price numeric NOT NULL,        -- 주문 '시점'의 가격(상품 가격이 바뀌어도 보존)
  PRIMARY KEY (order_id, product_id)  -- 복합 PK
);

여기서 연결 테이블이 관계 자체의 속성(수량·주문 시점 가격)을 담는다는 게 핵심이다 — 이런 속성이 생기면 단순 연결을 넘어 의미 있는 엔터티가 된다(주문 항목). 상품의 현재 가격주문 당시 가격을 분리해 저장해야 과거 주문 금액이 보존된다.

식별/비식별 관계·약한 엔터티

  • 식별 관계부모의 키가 자식의 기본키 일부(order_item의 PK가 order_id를 포함). 자식이 부모 없이 존재할 수 없다(주문 없는 주문 항목은 무의미).
  • 비식별 관계 — 외래키지만 자식의 PK는 별도(주문의 member_id는 FK지만 PK는 주문 자기 id). 회원이 사라져도 주문은 자체 정체성이 있다.
  • 약한 엔터티(weak entity)스스로 식별 못 하고 부모에 의존하는 엔터티(주문 항목). 식별 관계로 모델링된다.

모델링 안티패턴

  • EAV(Entity-Attribute-Value)속성을 행으로 빼는 (entity, key, value) 테이블. "어떤 속성이든 담을 수 있어" 유연해 보이지만 — 조인이 속성 수만큼 폭발하고, 타입 안전·제약·인덱스를 다 잃는다(value가 전부 text). 정말 동적·희소한 속성jsonb([08])로 담고, 핵심은 정규 칼럼으로 둔다.
  • 만능 테이블(God table) — 한 테이블에 수십~수백 칼럼, 대부분 NULL. 여러 엔터티가 뭉친 신호 → 엔터티로 분리([03 정규화]).
  • 의미 없는 과한 정규화/반정규화측정 없이 어느 쪽 극단으로도 가지 않는다([03]).

물리 설계로 — 타입·인덱스 결정

논리 모델이 서면 물리 설계에서 *타입(PostgreSQL timestamptz vs MySQL DATETIME)·PK 전략(IDENTITY/AUTO_INCREMENT/UUID, [06])·인덱스([06])·파티션([08])*을 정한다. 이때 예상 데이터량·접근 패턴·읽기/쓰기 비율을 근거로 삼는다 — 같은 논리 모델도 "하루 100건"과 "하루 1억 건"의 물리 설계는 완전히 다르다(후자는 파티셔닝·샤딩까지 고려).

정리 — 그리고 나서 만든다

데이터 모델링의 핵심 — 개념(엔터티·관계, ERD)→논리(테이블·키·정규화)→물리(타입·인덱스, DBMS별) 3단계, 카디널리티(1:1·1:N·N:M)를 정확히(N쪽에 FK, N:M은 연결 테이블), 연결 테이블은 관계 속성을 담는다, EAV·만능 테이블 같은 안티패턴 회피. 테이블을 그리기 전에 관계를 그리는 습관이 나중의 큰 부채를 막는다.

한 줄 요약 — 3단계: 개념(ERD·엔터티/관계, DBMS 무관·이해관계자 합의)→논리(테이블·키·정규화)→물리(타입·인덱스·예상 규모). 카디널리티 1:1(선택/민감 분리)·1:N(N쪽 FK)·N:M(연결 테이블, 관계 속성 포함). 식별/비식별·약한 엔터티. 안티패턴: EAV·만능 테이블.

(출처: Silberschatz DBSC 7e Ch 6 / 김연희 데이터베이스 개론 개체-관계 모델 / PostgreSQL data types.)

정규화 — 이상현상·함수종속·1NF~BCNF·반정규화트랜잭션 — ACID·격리수준·이상현상(PostgreSQL·MySQL)