데이터베이스 설계 — 개념과 관계형 모델¶
데이터를 어떻게 구조화할 것인가¶
현실 세계에는 수많은 정보가 있습니다.
학생, 수업, 수강 기록, 성적 — 이것들을 컴퓨터에 저장하려면 먼저 구조를 정해야 합니다.
데이터베이스 설계는 세 단계로 진행됩니다.
현실 세계
↓ 추상화
개념적 모델 (Conceptual Model) — "무엇이 있는가?"
↓ 정형화
논리적 모델 (Logical Model) — "어떤 관계인가?"
↓ 구현
물리적 모델 (Physical Model) — "어떤 DB에 어떻게 저장하는가?"
이 장에서는 개념적 모델과 논리적 모델을 집중적으로 다룹니다.
코드보다 개념이 먼저입니다.
개념적 모델 — ER 모델¶
개념적 모델(Conceptual Model)은 현실 세계를 추상화한 첫 번째 단계입니다.
특정 데이터베이스 제품(MySQL, PostgreSQL 등)에 독립적입니다.
가장 널리 쓰이는 개념적 모델링 방법이 ER 모델(Entity-Relationship Model)입니다.
ER 모델은 세 가지 요소로 현실을 표현합니다.
엔터티 (Entity) — 존재하는 것
속성 (Attribute) — 엔터티가 가진 특성
관계 (Relationship) — 엔터티 사이의 연결
엔터티 (Entity)¶
엔터티 = 독립적으로 존재하며 저장할 가치가 있는 사물이나 개념
현실 세계 예시:
학생, 수업, 교수, 도서, 주문, 상품
엔터티의 개별 사례를 인스턴스(Instance)라고 합니다.
엔터티: 학생
인스턴스: 김지민(17세), 이하나(18세), 박준서(17세) ...
엔터티 vs 속성 판단¶
무언가를 엔터티로 모델링해야 할지, 속성으로 두어야 할지 헷갈릴 때:
독립적으로 존재하는가? → 엔터티
다른 엔터티에 종속된 특성인가? → 속성
예)
주소 — 사람 없이 주소만 존재하는가? → 보통은 속성
하지만 배송지를 여러 개 관리한다면? → 엔터티
속성 (Attribute)¶
속성 = 엔터티의 특성을 설명하는 정보
학생 엔터티의 속성:
학번, 이름, 생년월일, 전공, 이메일
속성의 종류¶
| 종류 | 설명 | 예시 |
|---|---|---|
| 단순 속성 | 더 분해할 수 없음 | 나이, 학번 |
| 복합 속성 | 더 작은 단위로 분해 가능 | 주소 → 시/구/동 |
| 단일값 속성 | 값이 하나 | 생년월일 |
| 다중값 속성 | 값이 여러 개 가능 | 전화번호 (집, 휴대폰) |
| 파생 속성 | 다른 속성으로부터 계산 | 나이 ← 생년월일 |
| 키 속성 | 인스턴스를 유일하게 식별 | 학번, 주민등록번호 |
키 속성 (Key Attribute)¶
엔터티의 인스턴스를 유일하게 식별하는 속성입니다.
학생 엔터티:
학번 — 유일함 → 키 속성 가능
이름 — 중복 가능 → 키 속성 불가
주문 엔터티:
주문번호 — 유일함 → 키 속성 가능
키가 될 수 있는 후보를 후보 키(Candidate Key)라 하고,
그 중 실제로 선택된 것을 기본 키(Primary Key)라 합니다.
관계 (Relationship)¶
관계 = 두 엔터티 사이의 의미 있는 연결
학생 ── 수강 ── 수업
사람 ── 소유 ── 자동차
직원 ── 근무 ── 부서
관계의 카디널리티 (Cardinality)¶
카디널리티는 두 엔터티가 얼마나 연결될 수 있는지를 나타냅니다.
1:1 (일 대 일)¶
사람 ── 여권
(한 사람은 여권 하나, 여권 하나는 한 사람 것)
나라 ── 수도
1:N (일 대 다)¶
부서 ──< 직원
(한 부서에 여러 직원, 직원 하나는 한 부서)
작가 ──< 책
고객 ──< 주문
가장 자주 등장하는 관계입니다.
N:M (다 대 다)¶
학생 >──< 수업
(학생 한 명이 여러 수업 수강, 수업 하나에 여러 학생)
상품 >──< 주문
배우 >──< 영화
N:M 관계는 직접 표현할 수 없습니다.
반드시 중간 엔터티(교차 엔터티)로 분해해야 합니다.
학생 >──< 수업
↓ 분해
학생 ──< 수강 >── 수업
(중간 엔터티: 수강)
수강 엔터티의 속성:
학생번호 (FK), 수업번호 (FK), 수강일, 성적
참여 제약 (Participation Constraint)¶
관계에서 엔터티의 참여가 필수인지 선택인지 나타냅니다.
전체 참여 (Total Participation): 모든 인스턴스가 반드시 관계에 참여
부분 참여 (Partial Participation): 참여하지 않는 인스턴스도 존재 가능
예)
직원 ── 근무 ── 부서
직원은 반드시 부서에 속해야 함 → 전체 참여
부서는 직원이 없을 수도 있음 → 부분 참여 (새 부서 생성 직후)
ERD (Entity-Relationship Diagram)¶
ER 모델을 시각화한 다이어그램입니다.
코딩 전에 이 그림을 그려야 전체 데이터 구조가 보입니다.
Todo 서비스 ERD¶
┌─────────────────┐ ┌──────────────────────┐
│ User │ │ Todo │
├─────────────────┤ ├──────────────────────┤
│ *id │ 1 N │ *id │
│ email │─────────│ user_id (FK) │
│ password │ 작성 │ title │
│ created_at │ │ is_done │
└─────────────────┘ │ created_at │
└──────────────────────┘
* = 기본 키 (Primary Key)
블로그 서비스 ERD¶
┌──────────┐ ┌──────────┐ ┌──────────┐
│ User │ │ Post │ │ Comment │
├──────────┤ ├──────────┤ ├──────────┤
│ *id │1 N │ *id │1 N │ *id │
│ email │──────│ user_id │──────│ post_id │
│ name │ 작성 │ title │ 달림 │ user_id │──┐
└──────────┘ │ content │ │ content │ │
▲ └──────────┘ └──────────┘ │
└──────────────────────────────── 작성 ───────┘
논리적 모델 — 관계형 모델¶
개념적 모델(ER 모델)을 관계형 모델(Relational Model)로 변환하는 단계입니다.
관계형 모델은 현대 데이터베이스의 이론적 기반입니다.
핵심 용어¶
| 관계형 모델 용어 | 일상적 표현 | 설명 |
|---|---|---|
| 릴레이션(Relation) | 테이블 | 데이터를 저장하는 2차원 표 |
| 튜플(Tuple) | 행(Row) | 데이터 하나 |
| 속성(Attribute) | 열(Column) | 데이터의 특성 |
| 도메인(Domain) | 타입 | 속성이 가질 수 있는 값의 범위 |
| 차수(Degree) | 열의 수 | 속성의 개수 |
| 카디널리티(Cardinality) | 행의 수 | 튜플의 개수 |
[students 릴레이션]
학번 | 이름 | 나이 | 전공 ← 속성 (Attribute)
------|------|------|------
2001 | 지민 | 17 | 컴퓨터공학 ← 튜플 (Tuple)
2002 | 하나 | 18 | 경영학
2003 | 준서 | 17 | 컴퓨터공학
차수(Degree) = 4 (열이 4개)
카디널리티 = 3 (행이 3개)
릴레이션의 특성¶
- 튜플의 유일성 — 완전히 동일한 튜플은 없음
- 튜플의 순서 없음 — 행의 순서는 의미 없음
- 속성의 원자성 — 각 셀은 하나의 값만 가짐 (리스트 불가)
- 속성 이름의 유일성 — 같은 이름의 열은 없음
키의 종류¶
| 키 종류 | 설명 | 예시 |
|---|---|---|
| 후보 키 | 튜플을 유일하게 식별할 수 있는 속성(들) | 학번, 이메일 |
| 기본 키 (PK) | 후보 키 중 선택된 하나 | 학번 |
| 대리 키 | 의미 없는 임의 숫자 ID | id (AUTO_INCREMENT) |
| 외래 키 (FK) | 다른 릴레이션의 기본 키를 참조 | todos.user_id → users.id |
| 복합 키 | 두 속성을 합쳐 기본 키로 사용 | (학번, 수업번호) |
외래 키와 참조 무결성¶
외래 키는 릴레이션 간 관계를 표현하는 핵심 수단입니다.
users 릴레이션:
id | email
---|------
1 | jimin@ex.com
2 | hana@ex.com
todos 릴레이션:
id | user_id | title
---|---------|------
1 | 1 | 운동하기 ← user_id=1 → users에서 id=1 (지민)
2 | 1 | 책 읽기
3 | 2 | 영어 공부 ← user_id=2 → users에서 id=2 (하나)
참조 무결성(Referential Integrity) = FK가 가리키는 PK가 반드시 존재해야 하는 규칙
user_id = 99인 todo를 추가하려 할 때:
users에 id=99가 없음 → 오류 (참조 무결성 위반)
정규화 (Normalization)¶
정규화 = 데이터 중복을 제거하고 이상(Anomaly)을 방지하는 설계 기법
이상(Anomaly)이란?¶
중복된 데이터 때문에 발생하는 문제입니다.
[나쁜 설계 — 정규화 전]
주문ID | 고객명 | 고객이메일 | 상품명 | 가격
-------|--------|-------------|--------|-----
101 | 지민 | j@ex.com | 텀블러 | 25000
102 | 지민 | j@ex.com | 노트 | 3000
103 | 하나 | h@ex.com | 텀블러 | 25000
| 이상 종류 | 발생 상황 |
|---|---|
| 삽입 이상 | 상품을 등록하려면 주문도 있어야 함 |
| 삭제 이상 | 주문을 삭제하면 고객 정보도 사라짐 |
| 수정 이상 | 지민의 이메일 변경 시 여러 행을 수정해야 하고, 하나라도 빠뜨리면 불일치 |
1NF — 원자성 확보¶
모든 속성 값은 원자적(더 분해할 수 없는 단일 값)이어야 한다.
위반:
주문ID | 상품목록
-------|----------
101 | 텀블러, 노트, 펜 ← 하나의 셀에 여러 값
준수:
주문ID | 상품명
-------|-------
101 | 텀블러
101 | 노트
101 | 펜
2NF — 부분 함수 종속 제거¶
기본 키의 일부에만 종속된 속성을 분리한다.
(복합 기본 키일 때만 해당)
위반 — 기본 키: (학번, 수업번호)
학번 | 수업번호 | 학생이름 | 수강성적
-----|---------|---------|--------
2001 | CS01 | 지민 | A
'학생이름'은 학번만으로 결정됨 (수업번호와 무관) → 부분 종속
분리:
[학생] 학번 | 학생이름
[수강] 학번 | 수업번호 | 수강성적
3NF — 이행 함수 종속 제거¶
기본 키가 아닌 속성이 다른 비키 속성을 결정하면 분리한다.
위반:
직원ID | 부서ID | 부서명
-------|--------|-------
101 | 10 | 개발팀
직원ID → 부서ID → 부서명
(부서명이 부서ID를 통해 간접적으로 결정됨)
분리:
[직원] 직원ID | 부서ID
[부서] 부서ID | 부서명
정규화 원칙 한 문장¶
같은 사실은 한 곳에만 저장한다.
데이터를 복사하지 말고, 참조(FK)로 연결한다.
ER 모델 → 관계형 모델 변환 규칙¶
개념적 설계(ERD)를 논리적 설계(테이블)로 변환하는 규칙입니다.
| ER 모델 | 관계형 모델 |
|---|---|
| 엔터티 | 테이블 |
| 속성 | 컬럼 |
| 키 속성 | 기본 키 (PRIMARY KEY) |
| 1:N 관계 | N쪽 테이블에 FK 추가 |
| N:M 관계 | 중간 테이블 생성, 양쪽 FK |
| 1:1 관계 | 한쪽 테이블에 FK 추가 |
변환 예시 — 수강 시스템¶
[ERD]
학생 >──< 수업 (N:M)
[관계형 모델]
학생(학번 PK, 이름, 전공)
수업(수업번호 PK, 수업명, 담당교수)
수강(학번 FK, 수업번호 FK, 성적) ← 중간 테이블
└─────────────── 복합 기본 키
실습 미션¶
미션 1: 엔터티와 속성 구분¶
아래에서 엔터티와 속성을 구분하고, 각 엔터티의 키 속성을 정하세요.
도서관 시스템에 있는 것들:
책, 제목, 저자, ISBN, 회원, 회원번호, 이름, 대출일, 반납일, 대출기록
미션 2: 카디널리티 파악¶
아래 관계의 카디널리티(1:1, 1:N, N:M)를 판단하고 이유를 설명하세요.
1. 학생 — 학생증
2. 팀 — 팀원
3. 태그 — 게시글
4. 환자 — 담당의사 (병원에서)
5. 배우 — 영화
미션 3: ERD 그리기¶
아래 요구사항을 ERD로 표현하세요.
엔터티, 속성, 관계, 카디널리티를 모두 표시하세요.
- 사용자는 여러 게시글을 작성할 수 있다
- 게시글에는 여러 태그를 붙일 수 있다 (태그도 여러 게시글에 사용 가능)
- 사용자는 게시글에 댓글을 달 수 있다
- 사용자는 게시글에 좋아요를 누를 수 있다 (한 번만)
미션 4: 정규화¶
아래 테이블에서 발생할 수 있는 이상(Anomaly)을 찾고, 정규화하세요.
[주문 테이블]
주문ID | 고객ID | 고객명 | 고객이메일 | 상품ID | 상품명 | 단가 | 수량
-------|--------|--------|-----------|--------|--------|-------|----
1001 | 201 | 지민 | j@ex.com | 501 | 텀블러 | 25000 | 2
1002 | 201 | 지민 | j@ex.com | 502 | 노트 | 3000 | 5
1003 | 202 | 하나 | h@ex.com | 501 | 텀블러 | 25000 | 1
미션 5 (심화): 내 서비스 ERD → 관계형 모델¶
3장(SRS)에서 정의한 서비스의 ERD를 그리고,
변환 규칙에 따라 테이블 목록(이름, 컬럼, PK, FK)을 작성하세요.
핵심 요약¶
| 개념 | 설명 |
|---|---|
| 개념적 모델 | 현실을 추상화, DB 제품에 독립적 |
| ER 모델 | 엔터티, 속성, 관계로 현실을 표현 |
| 엔터티 | 독립적으로 존재하는 사물/개념 |
| 속성 | 엔터티의 특성 |
| 관계 | 엔터티 사이의 연결 |
| 카디널리티 | 1:1, 1:N, N:M |
| 논리적 모델 | 관계형 모델 — 릴레이션, 튜플, 속성 |
| 기본 키 (PK) | 튜플을 유일하게 식별 |
| 외래 키 (FK) | 다른 릴레이션의 PK 참조 |
| 정규화 | 중복 제거 — 같은 사실은 한 곳에만 |
| 1NF / 2NF / 3NF | 원자성 / 부분 종속 제거 / 이행 종속 제거 |