데이터 모델링의 3단계: 개념적·논리적·물리적 설계

src/content/documents/data-analysis/conceptual-logical-physical-data-models.json

데이터베이스를 만든다고 해서 처음부터 CREATE TABLE을 작성하는 것은 아닙니다.

먼저 어떤 데이터를 관리해야 하는지 정리하고, 그 데이터를 어떤 구조로 연결할지 설계한 다음, 마지막으로 PostgreSQL이나 MySQL 같은 실제 DBMS에서 사용할 수 있는 형태로 구현합니다.

이러한 데이터 모델링 과정은 일반적으로 다음 세 단계로 나눌 수 있습니다.

개념적 모델링
Conceptual Modeling



논리적 모델링
Logical Modeling



물리적 모델링
Physical Modeling

게임 데이터베이스를 만든다고 생각하면 이해하기 쉽습니다.

개념적
→ 게임에 플레이어, 길드, 아이템이 필요하겠네?

논리적
→ Player에 player_id가 필요하고
   Guild와는 1:N 관계로 만들자.

물리적
→ player_id는 BIGINT,
   nickname은 VARCHAR(30),
   실제 PostgreSQL 테이블로 만들자.

즉 같은 데이터베이스를 설계하지만 단계가 내려갈수록 점점 더 구체적이고 실제 구현에 가까워집니다.


전체적인 흐름부터 보기

MMORPG 게임을 하나 만든다고 생각해봅시다.

게임에는 다음과 같은 기능이 필요합니다.

  • 플레이어가 캐릭터를 생성할 수 있다.

  • 플레이어는 길드에 가입할 수 있다.

  • 플레이어는 여러 아이템을 소유할 수 있다.

  • 아이템별 보유 수량을 저장해야 한다.

처음부터 다음 SQL을 작성하기는 어렵습니다.

CREATE TABLE player (
    player_id BIGINT GENERATED ALWAYS AS IDENTITY,
    nickname VARCHAR(30) NOT NULL,
    level INTEGER NOT NULL DEFAULT 1,
    guild_id BIGINT,

    CONSTRAINT pk_player
        PRIMARY KEY (player_id)
);

왜냐하면 그 전에 먼저 결정해야 할 것이 많기 때문입니다.

플레이어와 길드는 별도 데이터인가?

플레이어 한 명은 길드를 몇 개 가질 수 있는가?

아이템은 Player 안에 저장해야 하는가?

Player와 Item은 어떤 관계인가?

PK는 무엇으로 사용할 것인가?

그래서 큰 그림부터 시작해서 점점 구체화합니다.


개념적 모델링

**개념적 데이터 모델링(Conceptual Data Modeling)**은 가장 높은 수준의 설계 단계입니다.

이 단계에서는

우리 시스템에서 어떤 데이터를 관리해야 하는가?

를 결정합니다.

아직 PostgreSQL이나 MySQL 같은 DBMS는 생각하지 않습니다.

컬럼의 VARCHAR(30), INTEGER 같은 세부 데이터 타입도 중요하지 않습니다.


게임 요구사항을 먼저 살펴보자

게임 기획자가 다음 요구사항을 전달했다고 생각해봅시다.

플레이어는 닉네임과 레벨을 가진다.

플레이어는 하나의 길드에 가입할 수 있다.

하나의 길드에는 여러 플레이어가 가입할 수 있다.

플레이어는 여러 종류의 아이템을 보유할 수 있다.

같은 종류의 아이템은 여러 플레이어가 가질 수 있다.

이 요구사항을 보고 먼저 중요한 대상을 찾습니다.

Player
Guild
Item

이것들이 Entity 후보가 됩니다.


개념적 모델에서 중요한 것은 Entity와 관계

개념적 모델에서는 세부적인 컬럼보다는 무엇이 존재하고 서로 어떻게 연결되는가가 중요합니다.

게임의 개념적 모델을 단순하게 나타내면 다음과 같습니다.

[Guild]

    │ 1 : N

[Player]

    │ N : M

[Item]

여기서 알 수 있는 것은 다음 정도입니다.

Guild
→ 여러 Player를 가질 수 있다.

Player
→ 하나의 Guild에 가입한다.

Player
→ 여러 Item을 가질 수 있다.

Item
→ 여러 Player가 소유할 수 있다.

아직

guild_id BIGINT
nickname VARCHAR(30)
price NUMERIC(10, 2)

같은 내용은 필요하지 않습니다.


개념적 모델의 실제 데이터 예시

현재 기획 단계에서 게임 데이터를 대충 다음처럼 생각할 수 있습니다.

플레이어

플레이어

레벨

천기사

35

흑마법사

42

궁수왕

28

길드

길드

용기사단

마법협회

아이템

아이템

철검

포션

지팡이

그리고 관계를 생각합니다.

플레이어

가입 길드

천기사

용기사단

흑마법사

마법협회

궁수왕

용기사단

이 단계에서 중요한 것은

플레이어와 길드라는 별도의 개념이 존재하고 둘 사이에 관계가 있다.

는 사실입니다.


개념적 모델링에서 결정하는 것

대표적으로 다음을 결정합니다.

항목

게임 예시

핵심 Entity

Player, Guild, Item

Entity의 의미

플레이어, 길드, 아이템

주요 관계

Player 가입 Guild

관계의 형태

Guild 1:N Player

주요 업무 규칙

한 Player는 최대 하나의 Guild 가입

업무와 현실 세계의 구조를 데이터 관점으로 정리하는 단계입니다.

개념적 모델: 핵심 엔티티와 관계Guild 1 : N PlayerPlayer N : M Item핵심 업무 대상과 관계만 표현컬럼·자료형·인덱스는 아직 결정하지 않음
개념적 모델: 핵심 엔티티와 관계

논리적 모델링

개념적 모델에서

Player
Guild
Item

이라는 주요 Entity와 관계를 찾았습니다.

다음은 **논리적 데이터 모델링(Logical Data Modeling)**입니다.

논리적 모델에서는

이 데이터를 관계형 데이터베이스 구조로 어떻게 표현할 것인가?

를 구체적으로 결정합니다.

이때부터 PK, FK, Attribute, 정규화 같은 개념이 본격적으로 등장합니다.


Player를 구체적으로 만들어보자

개념적 모델에서는 단순히

Player

라고만 했다면 논리적 모델에서는 어떤 속성이 필요한지 결정합니다.

데이터 모델 구조Player————————————————player_idnicknamelevelguild_id
데이터 모델 구조

그리고 각 컬럼의 역할도 결정합니다.

player_id → PK

guild_id → FK

따라서

데이터 모델 구조Player————————————————PK player_id nickname levelFK guild_id
데이터 모델 구조

형태가 됩니다.


Guild도 구체화한다

Guild 역시 속성을 결정합니다.

데이터 모델 구조Guild————————————————PK guild_id guild_name
데이터 모델 구조

이제 Player의

guild_id FK

Guild.guild_id PK

를 참조합니다.

Guild.guild_id


      │ 참조

Player.guild_id

논리적인 관계가 완성됩니다.


N:M 관계도 해결해야 한다

개념적 모델에서는 다음 관계가 있었습니다.

Player N : M Item

게임을 생각하면 자연스러운 관계입니다.

천기사가 여러 아이템을 가지고 있고

데이터 모델 구조천기사 — 철검 — 포션 — 방패
데이터 모델 구조

포션 역시 여러 플레이어가 가지고 있습니다.

데이터 모델 구조포션 — 천기사 — 흑마법사 — 궁수왕
데이터 모델 구조

하지만 관계형 데이터베이스에서는 보통 이 N:M 관계를 그대로 두지 않고 중간 Entity를 생성합니다.

게임에서는 Inventory가 적절합니다.


Inventory 추가

논리적 모델은 다음과 같이 변경됩니다.

데이터 모델 구조Player——————————————PK player_id nickname levelFK guild_idInventory——————————————PK FK player_idPK FK item_id quantityItem——————————————PK item_id item_name price
데이터 모델 구조

관계는

Player 1 : N Inventory

Item 1 : N Inventory

가 됩니다.

원래

Player N : M Item

이었던 관계를 두 개의 1:N으로 바꾼 것입니다.


실제 데이터를 논리 구조에 넣어보자

Player

player_id

nickname

level

guild_id

1

천기사

35

10

2

흑마법사

42

20

3

궁수왕

28

10

Guild

guild_id

guild_name

10

용기사단

20

마법협회

Item

item_id

item_name

price

101

철검

1500

102

포션

100

103

지팡이

2500

Inventory

player_id

item_id

quantity

1

101

1

1

102

5

2

102

10

2

103

1

3

102

3

이 정도가 되면 실제 관계형 데이터베이스의 구조와 상당히 비슷해졌습니다.


논리적 모델링에서는 정규화도 진행한다

논리적 모델을 설계하면서 데이터가 적절하게 분리되어 있는지 확인합니다.

예를 들어 처음에 다음 테이블을 만들었다고 해봅시다.

player_id

nickname

guild_id

guild_name

1

천기사

10

용기사단

2

흑마법사

20

마법협회

3

궁수왕

10

용기사단

여기에는

guild_id → guild_name

이라는 종속 관계가 존재합니다.

guild_name을 Player에 계속 저장할 필요가 없습니다.

그래서

Player

player_id
nickname
guild_id

Guild

guild_id
guild_name

로 분리합니다.

즉 우리가 앞에서 공부한 1NF, 2NF, 3NF 등의 정규화 과정은 주로 논리적 모델링 단계에서 수행됩니다.


논리적 모델링에서 결정하는 것

항목

게임 예시

Entity

Player, Guild, Item, Inventory

Attribute

nickname, level, price

PK

player_id, guild_id

FK

Player.guild_id

관계

Guild 1:N Player

N:M 해소

Inventory 생성

정규화

Player와 Guild 정보 분리

무결성 규칙

Inventory는 Player와 Item을 참조

개념적 모델보다 훨씬 구체적입니다.

하지만 아직도 특정 DBMS에서 실제로 어떻게 저장할지는 결정하지 않았습니다.


물리적 모델링

마지막은 **물리적 데이터 모델링(Physical Data Modeling)**입니다.

물리적 모델은

논리적으로 설계한 구조를 실제 DBMS에서 어떻게 구현할 것인가?

를 결정하는 단계입니다.

여기부터는 PostgreSQL, MySQL, Oracle 같은 실제 DBMS의 특성이 중요해집니다.


논리적 모델과 물리적 모델의 차이

논리적 모델에서 다음과 같이 설계했다고 해봅시다.

데이터 모델 구조Player————————————————player_idnicknamelevelguild_id
데이터 모델 구조

물리적 모델에서는 훨씬 구체적으로 결정해야 합니다.

player_id
→ BIGINT
→ PRIMARY KEY
→ 자동 증가

nickname
→ VARCHAR(30)
→ NOT NULL
→ UNIQUE

level
→ SMALLINT
→ NOT NULL
→ DEFAULT 1

guild_id
→ BIGINT
→ NULL 허용
→ FOREIGN KEY

실제 저장 방법을 결정합니다.


Player의 물리적 모델 예시

PostgreSQL을 사용한다고 가정해보겠습니다.

데이터 모델 구조player——————————————————————————————————player_id BIGINT PKnickname VARCHAR(30) NOT NULLlevel SMALLINT NOT NULLguild_id BIGINT FK
데이터 모델 구조

실제 SQL로 만들면 다음과 비슷합니다.

CREATE TABLE player (
    player_id BIGINT GENERATED ALWAYS AS IDENTITY,
    nickname VARCHAR(30) NOT NULL,
    level SMALLINT NOT NULL DEFAULT 1,
    guild_id BIGINT,

    CONSTRAINT pk_player
        PRIMARY KEY (player_id),

    CONSTRAINT uq_player_nickname
        UNIQUE (nickname),

    CONSTRAINT ck_player_level
        CHECK (level >= 1),

    CONSTRAINT fk_player_guild
        FOREIGN KEY (guild_id)
        REFERENCES guild(guild_id)
);

이제 단순한 데이터 모델이 아니라 실제로 DBMS에서 실행 가능한 구조가 되었습니다.


데이터 타입을 결정한다

물리적 모델링에서는 컬럼마다 실제 데이터 타입을 결정합니다.

예를 들어 다음처럼 설계할 수 있습니다.

컬럼

의미

PostgreSQL 타입

player_id

플레이어 번호

BIGINT

nickname

닉네임

VARCHAR(30)

level

레벨

SMALLINT

gold

골드

BIGINT

created_at

생성일

TIMESTAMP

is_active

활성 상태

BOOLEAN

논리적 모델에서는 단순히

레벨
골드
가입일

정도로 생각했다면,

물리적 모델에서는 DB가 실제로 어떻게 저장할지까지 결정합니다.


제약조건도 구체적으로 결정한다

게임의 Player 데이터에 다음 규칙이 있다고 해봅시다.

닉네임은 반드시 존재해야 한다.

닉네임은 중복되면 안 된다.

레벨은 1 이상이어야 한다.

길드 가입은 선택 사항이다.

이를 물리적 모델에서는 다음처럼 표현할 수 있습니다.

규칙

DB 제약조건

닉네임 필수

NOT NULL

닉네임 중복 금지

UNIQUE

레벨 1 이상

CHECK

길드 선택

guild_id NULL 허용

Player 식별

PRIMARY KEY

Guild 참조

FOREIGN KEY

즉 물리적 모델링에서는 단순히 어떤 데이터가 필요한가가 아니라,

잘못된 데이터가 들어오지 않도록 DB 자체에서 어떻게 제한할 것인가?

까지 생각합니다.


인덱스도 물리적 모델링에 포함된다

플레이어가 100명일 때는 대부분의 검색이 빠릅니다.

하지만 플레이어가 1,000만 명이라면 이야기가 달라집니다.

예를 들어 다음 검색이 자주 실행된다고 해봅시다.

SELECT *
FROM player
WHERE nickname = '천기사';

닉네임 검색이 매우 자주 발생한다면 nickname에 인덱스를 추가할 수 있습니다.

CREATE INDEX idx_player_nickname
ON player(nickname);

또 길드별 플레이어 조회가 자주 발생한다면

CREATE INDEX idx_player_guild_id
ON player(guild_id);

를 고려할 수 있습니다.

이러한 성능을 위한 인덱스 설계는 대표적인 물리적 모델링 작업입니다.


논리적으로 같은 모델도 물리적으로 달라질 수 있다

논리 모델이 다음과 같다고 해봅시다.

Player

player_id
nickname
created_at

PostgreSQL에서는

player_id BIGINT GENERATED ALWAYS AS IDENTITY
created_at TIMESTAMP

처럼 구현할 수 있습니다.

다른 DBMS에서는 자동 증가 컬럼이나 날짜 타입의 구체적인 문법이 달라질 수 있습니다.

논리적 구조
→ DBMS와 크게 독립적

물리적 구조
→ 사용하는 DBMS에 영향을 받음

이라고 볼 수 있습니다.


같은 게임 DB가 단계별로 어떻게 변하는가?

하나의 예제를 처음부터 끝까지 연결해보겠습니다.

1단계 — 요구사항

플레이어가 존재한다.

플레이어는 길드에 가입한다.

플레이어는 여러 아이템을 가진다.

2단계 — 개념적 모델

Guild

Player

Item

관계는

Guild 1 : N Player

Player N : M Item

정도로 표현합니다.


3단계 — 논리적 모델

데이터 모델 구조Guild————————————————PK guild_id guild_namePlayer————————————————PK player_id nickname levelFK guild_idInventory————————————————PK FK player_idPK FK item_id quantityItem————————————————PK item_id item_name price
데이터 모델 구조

N:M 관계를 Inventory로 분리하고 PK와 FK까지 결정했습니다.


4단계 — 물리적 모델

데이터 모델 구조guild————————————————————————————guild_id BIGINT PKguild_name VARCHAR(50) NOT NULLplayer————————————————————————————player_id BIGINT PKnickname VARCHAR(30) NOT NULL UNIQUElevel SMALLINT NOT NULL DEFAULT 1guild_id BIGINT FKitem————————————————————————————item_id BIGINT PKitem_name VARCHAR(100) NOT NULLprice INTEGER NOT NULLinventory————————————————————————————player_id BIGINT PK, FKitem_id BIGINT PK, FKquantity INTEGER NOT NULL
데이터 모델 구조

그리고 필요하다면

INDEX
CHECK
UNIQUE
DEFAULT
NOT NULL
FK 동작

까지 추가합니다.


세 단계를 표로 비교

구분

개념적 모델

논리적 모델

물리적 모델

핵심 질문

무엇을 관리할까?

어떻게 구조화할까?

실제 DB에 어떻게 만들까?

관점

업무·사용자

데이터 구조

DBMS 구현

Entity

O

O

Table로 구현

Attribute

주요 속성 중심

구체적으로 정의

실제 Column

관계

O

O

FK로 구현

PK/FK

거의 생략 가능

결정

실제 제약조건

정규화

거의 하지 않음

중요

결과 반영

데이터 타입

X

추상적으로 표현 가능

VARCHAR, INTEGER 등

인덱스

X

X

O

DBMS 의존

거의 없음

낮음

높음

SQL

X

X

실제 작성

가장 쉽게 기억하면 다음과 같습니다.

개념적
= 무엇?

논리적
= 어떻게 연결?

물리적
= 실제로 어떻게 저장?

게임 건물 설계로 비유하면

데이터 모델링은 게임의 건물을 설계하는 과정과 비슷하게 생각할 수도 있습니다.

개념적

마을에 무엇이 필요하지?

→ 상점
→ 대장간
→ 여관

아직 건물의 정확한 크기나 재료까지는 정하지 않습니다.


논리적

상점에는 판매 공간과 창고가 필요하다.

대장간은 상점 옆에 위치한다.

여관에는 여러 개의 방이 있다.

구조와 관계가 구체적으로 만들어집니다.


물리적

상점 크기 = 20m × 15m

벽 재료 = 돌

문 = 2개

창고 크기 = 5m × 5m

실제로 건설할 수 있을 정도로 구체적인 설계가 됩니다.

데이터베이스도 마찬가지입니다.

개념적
→ 시스템의 큰 구조

논리적
→ 데이터의 구조와 관계

물리적
→ 실제 DBMS 구현

ERD는 어느 단계에서 만드는가?

ERD는 특정 한 단계에서만 사용하는 것은 아닙니다.

모델링 수준에 따라 ERD에 들어가는 정보가 달라집니다.

개념 ERD

[Guild]

   │ 1:N

[Player]

   │ N:M

[Item]

주요 Entity와 관계 중심입니다.

논리 ERD

데이터 모델 구조Player————————————————PK player_id nickname levelFK guild_id
데이터 모델 구조

PK, FK와 속성이 구체적으로 들어갑니다.

물리 ERD

데이터 모델 구조player————————————————————————PK player_id BIGINT nickname VARCHAR(30) level SMALLINTFK guild_id BIGINT
데이터 모델 구조

실제 컬럼명과 데이터 타입까지 표현할 수 있습니다.

즉 같은 ERD라도 어느 수준까지 표현하느냐에 따라 개념 ERD, 논리 ERD, 물리 ERD로 나눌 수 있습니다.

개념적·논리적·물리적 모델의 발전 과정개념적 모델Player — Guild — Item논리적 모델PK · FK · Attribute · Inventory물리적 모델BIGINT · VARCHAR · INDEX · CREATE TABLE
개념적·논리적·물리적 모델의 발전 과정

실무에서는 한 번에 끝나지 않는다

모델링 과정이 항상

개념 → 논리 → 물리 → 끝

처럼 한 방향으로만 진행되는 것은 아닙니다.

예를 들어 물리적 모델을 만드는 도중 다음 문제가 발견될 수 있습니다.

Player 테이블이 너무 크다.

특정 조회가 너무 느리다.

현재 구조로는 새로운 게임 기능을 표현하기 어렵다.

그러면 다시 논리적 모델을 수정할 수 있습니다.

개념

논리

물리


구조 수정

즉 모델링은 실제 요구사항과 성능을 확인하면서 계속 보완할 수 있습니다.


정규화와 ERD는 어디에 들어가는가?

지금까지 공부한 내용들을 연결해보면 전체 흐름이 더 명확해집니다.

게임 요구사항 분석


개념적 모델링
Entity와 관계 찾기


논리적 모델링
Attribute
PK / FK
관계
정규화


ERD 구체화
IE 표기법으로 관계 표현


물리적 모델링
데이터 타입
제약조건
인덱스
DBMS 선택


CREATE TABLE


실제 데이터베이스

즉 우리가 공부했던 관계형 데이터 모델링, 정규화, ERD, IE 표기법, PK/FK는 따로 떨어져 있는 개념이 아니라 하나의 데이터베이스 설계 과정 안에서 연결됩니다.


세 단계에서 같은 Player를 비교해보기

마지막으로 같은 Player 데이터를 단계별로 비교해보겠습니다.

개념적 모델

Player

플레이어를 관리해야 한다.

논리적 모델

속성

역할

player_id

PK

nickname

플레이어 닉네임

level

레벨

guild_id

Guild FK

데이터 모델 구조Player————————————PK player_id nickname levelFK guild_id
데이터 모델 구조

물리적 모델

컬럼

타입

제약조건

player_id

BIGINT

PK, IDENTITY

nickname

VARCHAR(30)

NOT NULL, UNIQUE

level

SMALLINT

NOT NULL, DEFAULT 1

guild_id

BIGINT

FK, NULL 허용

CREATE TABLE player (
    player_id BIGINT GENERATED ALWAYS AS IDENTITY,
    nickname VARCHAR(30) NOT NULL,
    level SMALLINT NOT NULL DEFAULT 1,
    guild_id BIGINT,

    PRIMARY KEY (player_id),
    UNIQUE (nickname),

    FOREIGN KEY (guild_id)
        REFERENCES guild(guild_id)
);

처음에는 단순히

Player가 필요하다.

였던 생각이 마지막에는 실제 DBMS가 실행할 수 있는 SQL로 변한 것입니다.


정리

데이터 모델링은 일반적으로 개념적 → 논리적 → 물리적 모델링의 세 단계로 구체화됩니다.

단계

한 문장으로

개념적 모델링

어떤 데이터가 필요한지 찾는다.

논리적 모델링

데이터를 어떤 구조와 관계로 저장할지 설계한다.

물리적 모델링

실제 DBMS에서 사용할 테이블과 컬럼으로 구현한다.

게임 데이터베이스를 예로 들면 다음과 같습니다.

개념적

플레이어
길드
아이템이 필요하다.



논리적

Player
Guild
Item
Inventory

PK / FK 결정
1:N 관계 결정
정규화 진행



물리적

player_id BIGINT
nickname VARCHAR(30)
level SMALLINT

PRIMARY KEY
FOREIGN KEY
UNIQUE
INDEX

따라서 가장 간단하게 기억하면 다음과 같습니다.

개념적 모델링은 "무엇을 저장할까?" 논리적 모델링은 "어떻게 구조화할까?" 물리적 모델링은 "실제 DB에 어떻게 만들까?"

이 세 단계가 끝나면 비로소 설계된 ERD를 기반으로 CREATE TABLE을 작성하고 실제 데이터베이스를 구축할 수 있습니다.

댓글 0

댓글을 불러오는 중…