> For the complete documentation index, see [llms.txt](https://leehyokyun.gitbook.io/openbook/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://leehyokyun.gitbook.io/openbook/3-1.-data-db-modeling.md).

# 3-1. Data / DB Modeling

데이터 및 데이터베이스 모델링에 대하여

### 1. 개념적 모델링과 엔티티 분류

모델링의 단계는 개념적 모델링 > 논리적 모델링 > 물리적 모델링으로 이루어지며, 각 단계를 통해 데이터를 엔티티화하여 표현한 ERD, 정규화된 릴레이션 간의 명세(테이블 스키마), 물리적인 테이블을 생성한다.

개념적 모델링의 경우 다음과 같이 분류한다.

* 요구사항을 존재 형태에 따라 유형/무유형(개념/사건) 엔티티로 분류한다.
* 비즈니스 처리 흐름에 따라 기본/중심/행위 엔티티로 분류한다.
* 관계 기반에 따라 강한엔티티/약한엔티티 (식별) 혹은 비식별 관계로 분류한다.

관계가 행위에 종속될 경우 연관 엔티티, 관계의 포함관계에 따라 슈퍼&서브타입 엔티티로 분류한다.

* 관계 기반의 엔티티의 경우 다대다 관계에 있는 두 엔티티의 관계를 해소하기 위한 중요 전략이다.
* 인스턴스의 조합 및 엔티티의 분류는 시스템의 목적, 의도를 분명하게 하는 길잡이이자 힌트이다.
* 엔티티 분류 이후 카디널리티와 참여도(선택/필수)를 기반으로 관계를 세부 정의한다.
* 생성된 다대다 관계는 관계기반의 연관 엔티티를 적극 활용하여 해소한다.
* 엔티티 명명, 소통의 효율화, 일관성 유지를 위해 용어사전 운용은 필수이다.

### 2. 관계에 대해 쉽고 효율적으로 이해하자

정성적이고 직관적인 접근이 아닌, 특정 인스턴스에 대한 정량적인 접근으로 이해해야 한다. 즉, 여러 개의 A는 여러 개의 B의 방향이 아닌, 한 개의 A는 여러 개의 B와 연결된다는 접근으로 처리한다.

* 카디널리티적 접근: 회원과 주문의 관계를 예로 들면 한 명의 회원은 여러 개의 주문을 시도할 수 있다. N:1 관계에서 1개의 주문은 반드시 한 명의 회원에게만 속할 수 있다.
* 참여도적 접근: 한 명의 회원 입장에서 주문은 선택이다. 한 개의 주문 입장에서 회원은 필수이다. 즉, 유령 주문은 존재하지 않는다.
* 개념적 모델링과 PK/FK: 개념적 모델링은 엔티티간의 관계 도출이 우선이며 PK/FK는 데이터베이스 논리이기에 논리적 모델링 대상이다. 실무에서는 동일시하기도 하며 개념적 모델링에서 PK/FK를 같이 정립하기도 한다.

### 3. 논리적 모델링과 PK

논리적 모델링의 가장 중요한 요점은 확실한 기본키 설정을 통해 비즈니스 상황에 종속하지 않도록 하여 유연한 변경을 가능하게 하며, 유연성 및 무결성을 확보하는 것이다.

* 비즈니스 종속성 배제: 비즈니스 상황에 종속적이며, 절대 변하지 않는 것이란 존재하지 않는다. 자연키를 PK로 설정한다면, 이에 대한 변경점이 발생하였을 상황에 대비한 대체키를 구성하고 있어야 한다.
* 대리키(인조키)의 핵심: 자연 속성을 선택하는 것은 유일성과 최소성을 보장하기에 힘들다. 그렇기에 인조적으로 PK속성에 부합하는 키를 만드는 것이 대리키의 핵심이며 이는 비즈니스 로직과 무관하다.

### 4. 실무에서 권장하는 PK/FK 구성방식

* PK와 자연키의 조화: PK는 대리키 기반으로 구성하고, 비즈니스적 유일성 보장은 자연키 기반으로 처리한다. 이를 통해 정합성 보장, 단순성, 불변성, 확장성 모두 보장이 가능하다.
* 패러다임의 변화: 복합키를 사용하는 상황 자체가 복잡도를 증가하고 ORM의 본질을 저해하는 행위이므로 현대의 패러다임은 대리키를 지향한다. 비즈니스의 유일성 보장을 단일 자연키나 복합 자연키로 구성하는지가 중점 사항이 된다.
* 관계의 구성: 테이블의 개념(개념적 모델링) 및 비즈니스 관점에서의 의미를 기반으로 카디널리티와 참여도를 정의하고, 이에 따른 PK 및 외래키 (FK)를 구성하도록 한다.

### 5. 클러스터링 인덱스

클러스터링 인덱스는 InnoDB 기준 PK 기반으로 데이터베이스가 자동으로 생성하는 인덱스이다. 인덱스 키의 정렬 상태와 PK데이터의 정렬 상태가 동일한 특성을 가진다.

* 인덱스 최적화: 클러스터링 인덱스에 최적화된 AUTO INCREMENT, SEQUENCE, 채번 테이블은 데이터 삽입의 순서와 인덱스 키 순서가 서로 동일하다. 하지만 회원이메일 및 회원명 등은 데이터의 삽입 순서와 인덱스 키 순서가 동일하지 않다. 이러한 속성 기반의 PK 설정 시 조회조건의 속성 및 정렬조건과 일치하지 않으므로 이에 대한 인덱스 추가 설계가 필요하다.
* 설계 지향점: 클러스터링 인덱스 구조에 최적화하기 위해 자연키 기반이 아닌, 대리키 구성의 단순한 PK 구성이 필수적이다.
* DB별 사상의 차이: 데이터베이스 별로 설계 사상이 다르기에 인덱스의 존재유무와 구조적 특성도 각기 다르다. MySQL의 InnoDB는 읽기의 locality를 극대화하기 위해 인덱스 자체를 테이블로 보아 데이터를 저장한다. 반면 Postgres나 Oracle 등은 인덱스를 데이터를 가리키는 포인터로 저장하고 테이블은 Heap에 별도로 저장한다. 이 경우 MySQL은 PK 범위에서의 조회 성능 향상이 뚜렷하나, PostgreSQL/Oracle은 인덱스가 단순 포인터 역할을 하며 정렬 영향이 미미하다.

### 6. 자연키 설정으로 인한 페이지 분할 문제

인덱스를 운용하는 구조 및 설계사상은 다르지만, 인덱스 단편화 및 페이지 분할 문제는 모든 DB의 공통 과제이다. 인덱스의 리프에 저장될 때 각 리프는 16KB의 페이지 단위로 다수의 데이터를 저장한다. 이는 한 리프에 최대한 데이터를 담아 디스크 I/O를 줄이기 위함이다.

* 페이지 분할 메커니즘: 문제는 정렬 후 꽉 찬 페이지에 새로운 데이터를 넣어야 하는 경우이다. 정렬 데이터를 해당 리프에 넣기 위해 새로운 페이지를 생성(Page B)하고, 기존 페이지를 절반 분할(Split)하며, 이에 따라 트리구조를 재정렬하는 번거로운 작업이 발생한다.
* 성능 저하 요인: 리프를 재정렬하기 위한 디스크 I/O, 페이지 분할 및 이동, 인덱스 트리 재구성 등이 수반되므로 쓰기 성능이 매우 안 좋아진다.

### 7. 자연키 설정으로 인한 분할 문제, 그리고 이어지는 단편화 문제

페이지 분할이 발생할 경우 단편화 현상이 이어진다.

* 외부 단편화: 새로운 페이지를 생성하는 과정에서 리프 노드에 위치한 데이터들의 물리적 위치가 분산되어 발생한다. 논리적으로는 연속된 데이터이지만 물리적으로는 흩어지게 된다.
* 내부 단편화: 페이지를 분할하는 과정에서 페이지 내부에 빈 공간이 생기며 발생한다.
* 시스템 영향: 단편화로 인해 랜덤 I/O가 증가하고 캐시 효율이 감소하며 디스크 I/O 비용이 증가한다. 결국 부적절한 데이터를 PK로 구성하거나, 자연키 기반의 불안정한 속성을 PK로 채택 시 정렬 비용이 매우 커진다.

### 8. 테이블 통합보다는 테이블 1:1 분리가 성능적으로 유리

기본적으로 테이블을 하나로 통합하여 1row가 저장하는 컬럼의 개수가 많아진다면 페이지 크기가 커진다. 페이지 크기가 커지면 리프 노드에서 저장하는 페이지 크기가 늘어나고, 결국 페이지 분할 및 단편화가 발생하므로 테이블을 1:1 관계로 분리하는 것이 명확하게 유리하다.

* 성능 최적화: 일반정보와 세부정보를 분리함으로써 페이지 크기를 줄이고 이에 따른 디스크 I/O 비용을 감소한다.
* 보안 강화: 일반정보와 보안정보 관계에서 민감한 개인정보를 분리하여 관리함으로써 보안위험도를 감소한다.
* 확장성 확보: 선택적 정보 선택 시 회원과 판매자정보를 분리하여 공간 효율성 등을 증가한다.
* OCP 만족: 개방폐쇄원칙에 따라 테이블 분리에 따른 확장성을 확보하고 수정변경점을 최소화한다.
* 도메인 분리: 가장 큰 이유는 비즈니스 도메인을 명확하게 분리하여 주체 변경에 따른 상태 관리, 데이터 운용의 효율성을 확보하기 위함이다.
* 데이터베이스 강제: 분리한 테이블 관계에서 비즈니스 로직 상 기준(주) 테이블과 보조(부) 테이블을 분리하여 PK/FK를 지정한다. NOT NULL, UNIQUE 제약조건을 통해 카디널리티 및 참여도를 데이터베이스 상에서 강제한다.
* 테이블 분리 예시: 회원-회원상세, 일반정보-보안정보, 회원-판매자 등 테이블을 통합하지 않고 목적에 따라 분리한다.

### 9. 다대다 관계는 관계형 데이터베이스에서 존재 불가능한 개념

관계형 데이터베이스의 1 row는 논리적으로 더이상 분해할 수 없는 원자적인 데이터 표현 단위이다. 따라서 다대다 관계는 존재할 수 없으며, 비즈니스 행위 기반 혹은 두 데이터의 관계에서 수반하는 행위 엔티티(테이블) 기반으로 다대다 관계를 1:N 관계로 해소해야 한다.

* 연관 엔티티의 독립성: 연관 엔티티는 다대다 관계를 해소하기 위한 단순한 도구를 넘어 관계의 속성을 표현하고 정의하는 독립적인 엔티티로 간주하고 설계하는 방향이 필요하다.
* 예시 분석: 주문항목은 주문과 상품의 다대다 관계를 해소하는 도구가 아닌, 주문이라는 사건에 대한 결과 기록을 표시하는 엔티티이다. 따라서 이러한 속성을 충분히 표현하는 설계와 더불어, 연결강조 및 의미있는 명명 등 본질적인 모델링이 필요하다. 의미있는 정보를 추출하여 연관 엔티티에 이를 적용하고 구체화하며 명명까지 의미를 부여하는 것이 적절하다.
* 핵심 유의사항: 연관 엔티티는 다대다 관계를 해소하기 위한 도구가 아닌 비즈니스의 행위/사건을 의미하는 독립적인 엔티티이다. 관계의 속성과 비즈니스 행위를 표현하기 위한 고려가 이루어져야 하며, 비즈니스 의미를 추출하기 위해 엔티티 속성이나 엔티티 명으로 구체화할 필요가 있다.

### 10. 식별 관계와 비식별 관계

식별 관계와 비식별 관계는 두 엔티티(테이블) 간의 관계 결합도가 종속적인가, 독립적인가 판단하는 중요한 기준이다. 개념적 모델링에서 관계의 강도를 정의했다면, 논리적 모델링 단계에서 이를 해소하는 전략을 구체화한다.

* 식별 관계: 대리키를 PK로 사용하지 않고, 다른 테이블의 PK를 그대로 물려받아 복합키로 사용하는 관계이다. 엔티티 간 강한 결합도를 지니므로 관계 종속성을 가지며, 이로 인해 JOIN의 복잡도와 크기가 커지고 변경관리가 유연하지 못하며 ORM 친화적이지 않다.
* 비식별 관계: 대리키를 PK로 사용하고, 다른 테이블의 PK는 FK/UNIQUE 등의 제약조건으로 사용하는 관계이다. 엔티티 간 약한 결합도를 지니므로 관계 종속적이지 않고 독립적이다. 따라서 JOIN의 복잡도와 크기가 작고, 변경관리가 유연하며 ORM 친화적이다.
* 독립 엔티티의 이점: 애초에 엔티티가 강하고 독립적이라면 비즈니스 요구사항 변화에 종속적이지 않기에 유연하고 확장적이다. 또한 JOIN 자체를 하지 않고도 데이터 조회가 가능하며 그만큼 복잡도가 줄어든다. 인덱스 별도 생성 기술이 필요할 수 있으나 시스템 모델링의 성능적/구조적 이점에 비하면 그리 큰 비용이 아니다.

### 11. 정규화와 BCNF

정규화는 데이터의 일관성을 보장하고 데이터베이스 본연의 목적인 데이터 관리 및 유지를 위한 체계적인 절차이자 방법론이다.

* 제1정규형: 원자성(Atomic)을 만족해야 한다. 테이블의 한 릴레이션은 원자적인 데이터의 집합이다. 엔티티(테이블)의 한 속성(컬럼)은 더이상 분해할 수 없는 최소한의 논리로 이루어져야 한다.
* 제2정규형: 복합키로 이루어진 엔티티(테이블)의 튜플(릴레이션)들은 온전한 복합키에 의한 종속성인 완전함수종속을 만족해야 한다.
* 제3정규형: 오로지 복합키에 의한 데이터 결정이 이루어져야 하며, 단계적인 종속인 이행함수종속이 발생해서는 안 된다.
* BCNF 정규형: 행 내부의 결정자는 모두 행 간의 후보키이어야만 한다. 릴레이션 내부의 기본키에 의한 종속뿐만 아니라, 행 간의 유일성을 보장해야 한다.

### 12. 역정규화 전략

역정규화는 모든 정규화를 완료한 후에, 병목현상이 데이터적으로 명확히 발견되었을 때 진행하는 최후의 수단이다.

* 진행 판단 기준: 테이블 분리로 인한 JOIN 비용 및 계산 비용의 병목이 월등하게 높다는 데이터 기반의 판단 하에 의도적으로 역정규화를 진행한다.
* 적용 방법:
  * 의도적으로 데이터 중복을 허용하여 필요한 항목을 추가한다. (예: member\_name + product\_name)
  * 계산 과정이 복잡할 경우 단일 컬럼 기반으로부터 최종 계산 결과에 대한 파생 컬럼을 추가한다. (예: member\_name + product\_name + product\_qty)
* 용어의 정의:
  * 반정규화: 정규화와 반대되는 모든 개념을 총칭하는 개념이자 체계이다.
  * 역정규화: 반정규화에 포함되는 개념이며, 정규화를 진행한 후 의도적으로 정규화의 반대 작업을 진행하는 것이다.
  * 비정규화: 정규화를 만족하지 않는 항목이나 체계 자체를 지칭한다.
* 손익 요건: 조회 성능 향상 비용이 데이터 중복으로 인한 갱신이상 극복 및 데이터 동기화/일관성 확보(배치 등) 비용보다 큰 경우에 수행한다. 아울러 읽기 기능이 쓰기 기능에 비해 월등하게 높은 사용도를 가지는 도메인이라서 쓰기 부하가 미미한 경우에 적합하다.

### 13. 분산 데이터 모델링과 샤딩

샤딩은 데이터를 하나의 저장소가 아닌 분산하여 저장하고, 이를 기반으로 안정성을 확보하는 전략이다.

* 설계 고려사항: 샤드 키를 어떠한 식별자로 사용할 것인가에 대한 요소를 정해야 한다. 또한 샤딩 전략을 Hashing, Range, Geography 등 어떠한 구체적인 방안으로 적용하여 데이터를 분산할 것인지 정의해야 한다. 설계 시 부모 데이터의 Hot Key나 인기성으로 인해 데이터 쏠림(Skew) 현상이 발생 가능하다는 점을 주의해야 한다.
* 본질과 기준: 분산 데이터 모델링의 본질은 데이터의 분산과 쓰기 성능이며, 핵심 척도는 카디널리티이다. 분산 환경이라고 해서 무조건 모든 데이터에 대해 분산 데이터 모델링을 적용하지는 않는다. 단일 데이터베이스로 충분하다면 그대로 운용한다.
* 트래픽 대응 방책: 분산 데이터 모델링은 전제로 하는 설계라기보다는 문제가 생겼을 때의 방책이며, 트래픽에 대응하기 위한 수단이다. 대규모 데이터와 대규모 트래픽은 서로 다른 개념이므로 상황을 명확히 이해하고 구분하여 적용해야 한다.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://leehyokyun.gitbook.io/openbook/3-1.-data-db-modeling.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
