논리 모델
고친 사람 github-actions[bot]
논리 모델은 무엇을 저장할지 정한 설계를 데이터베이스가 담을 모양으로 옮겨 적습니다. 대개는 표와 열로 옮깁니다. 어느 데이터베이스 제품을 쓸지는 아직 정하지 않습니다. 데이터 설계를 세 단계로 나눌 때 가운데 단계입니다.
쉽고 빠른 이해
무슨 일을 하나 — 「고객이 주문을 하고, 주문에 상품이 담긴다」 같은 설계를 표로 옮깁니다. 고객 표에는 고객번호·이름·이메일 열을 둡니다. 주문 표에는 누가 주문했는지 가리키는 고객번호 열을 둡니다.
왜 따로 두나 — 곧장 제품에 맞춘 테이블 생성문부터 쓰면 설계 판단과 제품 사정(고객번호를 몇 바이트로 담을지 같은 선택)이 한 문서에 섞입니다. 그러면 어느 줄이 업무 규칙이고 어느 줄이 제품 사정인지 나중에 가려낼 수 없습니다. 제품을 바꿀 때 설계까지 다시 따져야 합니다.
어떻게 옮기나
- 다룰 대상마다 표를 하나씩 둡니다
- 표마다 담을 열과, 줄 하나를 가려낼 번호를 정합니다
- 표와 표의 이어짐은 상대 표의 번호를 적는 열로 나타냅니다
- 같은 내용이 두 곳에 적히지 않게 표를 더 나눕니다
대가 — 표가 잘게 나뉘어 화면 하나를 그리려면 여러 표를 이어 붙여 읽어야 합니다. 빨리 읽기 위한 궁리는 이 단계에서 하지 않고 다음 단계로 미룹니다.
언제 따로 적나 — 작은 서비스는 논리 모델을 문서로 남기지 않고 테이블 생성문부터 쓰기도 합니다. 표가 많거나 여러 팀이 같은 데이터를 다루면 문서로 남깁니다.
상세
집을 지을 때는 먼저 「방 셋에 거실 하나, 부엌은 거실 옆」처럼 원하는 것만 적습니다. 그다음 벽마다 길이를 정합니다. 문을 어느 벽에 낼지까지 평면도에 그립니다. 벽을 벽돌로 쌓을지 나무로 세울지는 그 평면도를 들고 시공하는 쪽과 따로 정합니다.
데이터를 무엇으로 나누고 무엇으로 이을지 정하는 일을 데이터 모델링이라고 부릅니다. 이 일도 흔히 세 단계로 나눕니다.
무엇을 다루는지만 적는 첫 단계가 개념 모델입니다. 그것을 표와 열로 옮긴 둘째 단계가 논리 모델입니다. 특정 제품 위에서 어떻게 저장할지까지 정하는 셋째 단계가 물리 모델입니다. 집으로 치면 논리 모델은 평면도에 해당합니다.
이 절은 쇼핑몰의 고객·주문·상품을 예로 들어 개념 모델을 논리 모델로 옮겨 봅니다. 그 과정에서 논리 모델이 무엇을 정하고 무엇을 뒤로 미루는지 봅니다. 끝에서는 이 단계를 따로 두는 까닭과, 따로 두지 않는 경우를 봅니다.
세 단계가 정하는 내용
세 단계는 같은 쇼핑몰을 점점 더 자세히 적습니다. 단계마다 무엇을 정하는지 모았습니다.
| 단계 | 정하는 것 | 쇼핑몰에서 |
|---|---|---|
| 개념 모델 | 다룰 대상과 그 사이의 관계 | 고객이 주문을 한다 · 주문에 상품이 담긴다 |
| 논리 모델 | 표 · 열 · 표 사이의 관계 | 주문 표에 고객번호 열을 두어 고객 표를 가리킨다 |
| 물리 모델 | 쓸 제품 · 값의 크기 · 빨리 찾는 장치 | 고객번호를 8바이트 정수로 담고, 고객번호로 주문을 빨리 찾게 한다 |
가운데 줄이 이 문서의 주제입니다. 논리 모델은 개념 모델보다 자세합니다. 그러면서도 물리 모델과 달리 제품을 모릅니다.
대상을 표로 옮기기
개념 모델에서 정한 대상 하나하나를 엔티티라고 부릅니다. 고객·주문·상품이 엔티티입니다. 논리 모델은 엔티티마다 표를 하나씩 둡니다.
엔티티에 적을 값 하나하나는 속성입니다. 고객이라면 이름과 이메일이 속성입니다. 속성은 표의 열이 됩니다.
고객 한 명은 고객 표의 줄 하나, 곧 행 하나가 됩니다. 고객이 천 명이면 고객 표에는 행이 천 개 쌓입니다.
행이 여럿이면 그중 하나를 콕 집어 가리킬 값이 필요합니다. 이름은 겹칠 수 있어서 이 일을 못 합니다. 그래서 고객마다 겹치지 않는 고객번호를 매깁니다. 이렇게 표 안에서 행 하나를 가려내는 열을 기본 키라고 합니다.
이어짐을 열로 적기
개념 모델에서는 「고객이 주문을 한다」를 선 하나로 그립니다. 엔티티 사이의 이 이어짐을 관계라고 부릅니다. 표에는 선을 담을 수 없습니다. 그래서 논리 모델은 선을 열로 바꿉니다.
고객 한 명은 주문을 여럿 할 수 있습니다. 주문 하나의 주인은 한 명입니다. 이렇게 한쪽은 하나, 다른 쪽은 여럿인 관계를 일대다라고 부릅니다.
일대다는 「여럿」 쪽 표에 「하나」 쪽의 기본 키를 적는 열을 둡니다. 주문 표에 고객번호 열을 두는 식입니다. 다른 표의 기본 키를 적어 두는 이 열을 외래 키라고 부릅니다. 외래 키가 있어서 주문 하나를 보고 누가 주문했는지 찾아갈 수 있습니다.
주문 하나에는 상품이 여럿 담깁니다. 상품 하나도 여러 주문에 들어갑니다. 이런 다대다 관계는 어느 한쪽 표에 열 하나로 적을 수 없습니다. 그래서 둘 사이에 주문항목 표를 새로 둡니다.
주문항목 표에는 주문 표와 상품 표의 기본 키를 모두 적습니다. 이 표는 개념 모델에 없던 표입니다. 상품을 몇 개 샀는지 적는 수량도 이 표가 담습니다. 논리 모델로 옮기면 표 수가 엔티티 수보다 늘어나는 까닭이 이것입니다.
쇼핑몰의 논리 모델을 표 네 개로 모으면 이렇습니다.
| 표 | 기본 키 | 외래 키 | 그 밖의 열 |
|---|---|---|---|
| 고객 | 고객번호 | 이름 · 이메일 | |
| 상품 | 상품번호 | 상품명 · 가격 | |
| 주문 | 주문번호 | 고객번호 | 주문일 |
| 주문항목 | 주문번호 · 상품번호 | 주문번호 · 상품번호 | 수량 |
주문항목 표는 주문번호와 상품번호 두 열을 묶어 기본 키로 씁니다. 같은 주문번호·상품번호 짝을 가진 행이 둘 생기지 않게 막습니다. 한 주문에 같은 상품의 행이 두 번 들어가지 않는다는 뜻입니다. 같은 두 열은 각각 주문 표와 상품 표를 가리키는 외래 키이기도 합니다.
표가 서로 어떻게 이어지는지는 그림으로 보는 편이 빠릅니다. 이런 그림을 ER(Entity-Relationship, 엔티티-관계) 다이어그램이라고 부릅니다.
erDiagram
direction TB
고객 ||--o{ 주문 : "한다"
주문 ||--|{ 주문항목 : "담는다"
상품 ||--o{ 주문항목 : "들어간다"
선 끝의 세 갈래는 「여럿」, 세로 막대는 「하나」, 동그라미는 「없을 수도 있음」입니다. 둘이 겹쳐 있으면 뜻도 합쳐집니다. 막대와 세 갈래가 함께 있으면 「하나 이상」, 동그라미와 세 갈래가 함께 있으면 「없거나 여럿」입니다.
고객 한 명의 주문은 없을 수도 여럿일 수도 있습니다. 주문 하나에는 주문항목이 하나 이상 있습니다. 주문과 상품 사이의 다대다가 주문항목을 거치는 일대다 둘로 풀린 것이 보입니다.
같은 내용을 한 곳에만 적기
표를 나눌 때 따르는 기준이 하나 더 있습니다. 같은 내용이 두 곳에 적히지 않게 하는 것입니다. 이 소절은 주문 표에 이메일을 함께 적었을 때 무엇이 틀어지는지로 이 기준을 봅니다.
주문 표에 고객 이메일 열까지 두었다고 해 봅시다. 고객 한 명이 주문을 10번 했다면 같은 이메일이 10개 행에 적힙니다. 이메일이 바뀌면 그 10개 행을 전부 고쳐야 합니다. 하나라도 빠뜨리면 한 사람의 이메일이 둘이 됩니다.
그래서 이메일은 고객 표에만 둡니다. 주문 표는 고객번호만 들고 있다가, 이메일이 필요하면 고객 표에서 찾아옵니다. 이렇게 되풀이되는 내용을 걷어 내며 표를 나누는 일을 정규화라고 부릅니다. 논리 모델 단계에서 주로 하는 일입니다.
논리 모델이 정하는 범위
논리 모델은 표·열·키 말고도 열에 걸 규칙을 정합니다. 이메일은 비어 있으면 안 된다, 두 고객이 같은 이메일을 쓸 수 없다 같은 규칙입니다. 열에 거는 이런 규칙을 제약조건이라고 부릅니다. 규칙을 어기는 값은 데이터베이스가 받지 않습니다.
제품은 정하지 않아도, 데이터를 어떤 방식으로 담을지는 이 단계에서 정해져 있습니다. 담는 방식은 표로 담을지 문서 한 덩어리씩 담을지 같은 큰 갈래입니다. 제품은 그 방식을 실제로 구현한 특정 데이터베이스입니다.
논리 모델은 대개 데이터를 표로 담는 관계형 모델을 따릅니다. 이 문서의 쇼핑몰도 이 방식으로 옮겼습니다. 문서 한 덩어리씩 담는 방식을 고르면 논리 모델의 모양도 그에 맞춰 달라집니다.
물리 모델로 넘기는 결정
논리 모델은 제품을 모르는 채로 적습니다. 그래서 제품마다 달라지는 결정은 물리 모델로 넘깁니다. 넘기는 결정을 보기 전에 낱말 둘을 먼저 풉니다.
인덱스는 어느 값이 어느 행에 있는지 따로 적어 둔 목록입니다. 책 뒤의 찾아보기처럼 표 전체를 훑지 않고도 원하는 행을 찾게 해 줍니다. 파티셔닝은 큰 표 하나를 여러 조각으로 나눠 담는 일입니다.
| 물리 모델로 넘기는 결정 | 쇼핑몰에서 |
|---|---|
| 값을 몇 바이트로 담나 | 고객번호를 4바이트 정수로 할지 8바이트로 할지 |
| 무엇으로 빨리 찾게 하나 | 주문 표에 고객번호 인덱스를 둘지 |
| 큰 표를 어떻게 쪼개 담나 | 주문 표를 달마다 나눠 담을지 |
| 읽기 속도를 위해 일부러 되풀이해 적나 | 주문 표에 고객 이름을 한 번 더 적어 둘지 |
이 결정들은 모두 어느 제품을 쓰는지, 데이터가 얼마나 쌓이는지에 따라 답이 바뀝니다. 논리 모델 단계에서는 아직 그 답을 모릅니다. 그래서 표와 열까지만 정하고 멈춥니다.
잘게 나눈 대가
표를 잘게 나눈 대가는 읽을 때 치릅니다. 주문 내역 화면 하나를 그리려면 주문·주문항목·상품·고객 네 표를 이어 붙여 읽어야 합니다. 여러 표를 공통 열로 이어 읽는 이 연산을 조인이라고 부릅니다.
조인이 많아 읽기가 느리면 물리 모델에서 일부러 되풀이해 적는 쪽을 고르기도 합니다. 위 표의 마지막 줄이 그 결정입니다. 정규화로 걷어 낸 되풀이를 속도 때문에 다시 들이는 일을 반정규화라고 부릅니다.
이 결정은 논리 모델이 아니라 물리 모델에서 내립니다. 그래서 논리 모델에는 되풀이 없는 원래 모양이 남습니다.
논리 모델을 따로 두는 까닭
데이터베이스에 표를 만드는 명령문을 테이블 생성문이라고 부릅니다. 논리 모델 없이 이 생성문부터 쓰면 설계 판단과 제품 사정이 한 문서에 섞입니다. 「주문 하나의 주인은 한 명」이라는 판단과 「고객번호는 8바이트」라는 선택이 같은 문서 안에 나란히 놓입니다. 나중에 읽는 사람은 어느 줄이 업무 규칙이고 어느 줄이 제품 사정인지 가려낼 수 없습니다.
논리 모델을 따로 두면 제품이 바뀌어도 논리 모델은 남습니다. 같은 논리 모델 하나에서 제품마다 다른 물리 모델을 만들 수 있습니다. 설계를 처음부터 다시 따지지 않고 물리 모델만 새로 쓰면 됩니다.
검토하기도 쉬워집니다. 표와 열의 이름, 표 사이의 관계만 보면 됩니다. 그래서 제품을 모르는 사람도 읽을 수 있습니다. 「주문 하나에 고객이 여럿일 수는 없나」 같은 업무 질문을 이 단계에서 던질 수 있습니다.
논리 모델을 건너뛰는 경우
작은 서비스에서는 세 단계를 문서로 따로 남기지 않는 일이 흔합니다. 테이블 생성문부터 바로 쓰기도 합니다.
ORM(Object-Relational Mapping, 객체-관계 매핑) 코드로 시작하기도 합니다. ORM 은 코드의 객체와 데이터베이스의 표를 짝지어 주는 도구입니다. Django 의 모델 클래스를 먼저 짜는 식입니다.
그래도 표를 어떻게 나누고 무엇으로 이을지는 정합니다. 논리 모델이 문서로 없을 뿐, 그 판단은 생성문과 코드 안에 섞여 들어가 있습니다.
표가 많아지거나 여러 팀이 같은 데이터를 다루면 논리 모델을 문서로 남깁니다. 그래야 코드를 뒤지지 않고도 표 사이의 관계를 한 번에 볼 수 있습니다. 제품을 옮길 계획이 있을 때도 논리 모델이 옮길 설계의 기준이 됩니다.
관련 항목
논리 모델이 속하는 설계 단계
데이터 모델링 · 개념 모델 · 물리 모델 · 스키마 · ANSI-SPARC 아키텍처
논리 모델을 이루는 구성 요소
엔티티 · 속성 · 관계 · 테이블 · 열 · 행 · 기본 키 · 외래 키 · 후보 키 · 대리 키 · 복합 키 · 카디널리티 · 제약조건 · 유니크 제약
논리 모델을 다듬는 정규화와 그 대가
정규화 · 함수 종속 · 제1정규형 · 제2정규형 · 제3정규형 · BCNF · 참조 무결성 · 조인
논리 모델을 그리는 표기법
ER 다이어그램 · 개체 관계 모델 · 까마귀발 표기법 · IDEF1X · UML 클래스 다이어그램
물리 모델 단계로 넘어가는 결정
인덱스 · 파티셔닝 · 샤딩 · 반정규화 · 데이터 타입
논리 모델의 틀을 정하는 데이터 모델
관계형 모델 · 관계형 데이터베이스 · 문서 데이터베이스 · 그래프 데이터베이스 · 차원 모델링
논리 모델을 데이터베이스와 코드로 옮기는 수단
다른 이름: logical model · logical data model · 논리 데이터 모델 · 논리적 데이터 모델 · 논리적 모델