배송 정보를 주문에 둘 것인가, 주문상품에 둘 것인가
배송 정보는 더 애매하다.
보통은 주문 하나가 한 번에 배송된다.
이 경우에는 주문에 택배사와 송장번호를 두어도 큰 문제가 없어 보인다.
하지만 업무 담당자가 이렇게 말한다면 이야기가 달라진다.
“세제와 수건을 같이 주문했는데 세제는 오늘 보내고, 수건은 내일 보내는 경우가 있다.”
이 문장은 중요하다.
배송이 주문 전체 단위가 아닐 수 있다는 뜻이다.
상품별로 나누어 배송될 수 있다는 뜻이다.
이때 주문 테이블에 송장번호 하나만 두면 문제가 생긴다.
송장번호가 두 개 이상이면 어떻게 할 것인가?
어떤 상품이 어떤 송장으로 배송되었는지 어떻게 알 것인가?
일부 상품만 배송 완료된 경우 주문상태는 배송중인가, 배송완료인가?
이 질문에 답하기 어렵다면 배송 구조를 다시 봐야 한다.
배송이 항상 주문 단위라면 주문과 배송은 단순할 수 있다.
하지만 부분 배송이 필요하다면 배송과 주문상품의 관계를 표현해야 한다.

여기서 중요한 것은 정답이 하나가 아니라는 점이다.
업무가 주문 전체 배송만 요구한다면 단순하게 설계할 수 있다.
하지만 업무가 상품별 배송 추적을 요구한다면 더 세밀하게 설계해야 한다.
정규화는 무조건 테이블을 많이 만드는 일이 아니다.
업무가 구분해서 관리해야 하는 사실을 구분해서 저장하는 일이다.
취소와 반품은 어디에 두어야 할까
취소와 반품은 단순해 보인다.
취소되었으면 Y.
취소되지 않았으면 N.
반품되었으면 Y.
반품되지 않았으면 N.
그래서 처음에는 주문 테이블에 취소여부와 반품여부를 두고 싶어진다.

겉으로 보면 문제가 없어 보인다.
주문이 취소되었는지 바로 알 수 있다.
주문이 반품되었는지도 바로 알 수 있다.
하지만 질문을 하나 해보자.
하나의 주문에 상품이 여러 개 들어 있다면 어떻게 할 것인가?
예를 들어 주문번호 1001번에 세제와 수건이 들어 있다고 해보자.
세제는 정상 배송되었다.
수건만 고객이 반품했다.
이때 주문 테이블의 반품여부를 Y로 바꾸면 어떻게 보일까?
주문 전체가 반품된 것처럼 보인다.
하지만 실제로는 수건만 반품되었다.
이 모델은 반품이 발생했다는 사실은 표현할 수 있다.
하지만 무엇이 반품되었는지는 표현하지 못한다.
문제는 반품여부라는 컬럼이 아니다.
반품여부가 놓인 위치가 문제다.
반품이 주문 전체에 대해 발생한다면 주문 테이블에 있어도 된다.
하지만 반품이 주문상품 단위로 발생한다면 주문상품에 있어야 한다.
취소도 마찬가지다.
고객은 주문 전체를 취소할 수도 있다.
하지만 주문에 포함된 일부 상품만 취소할 수도 있다.
세제와 수건을 같이 주문했는데 수건만 취소할 수 있다.
이 경우 주문 테이블의 취소여부만으로는 정확한 표현이 어렵다.
주문 전체가 취소된 것인지, 주문 안의 일부 상품만 취소된 것인지 알 수 없기 때문이다.
그래서 이 예제에서는 취소여부와 반품여부를 주문상품에 둔다.

이렇게 하면 상품별 상태를 표현할 수 있다.
세제는 취소되지 않았다.
수건은 취소되었다.
칫솔은 반품되었다.
이 구조는 주문 안에서 상품별 상태가 달라지는 상황을 표현할 수 있다.
여기서 중요한 것은 취소와 반품을 무조건 별도 엔터티로 만들라는 뜻이 아니다.
정규화는 테이블을 무조건 많이 만드는 일이 아니다.
업무에서 구분해야 하는 사실을 올바른 위치에 두는 일이다.
취소여부가 주문 전체의 상태라면 주문에 둘 수 있다.
취소여부가 주문상품의 상태라면 주문상품에 두어야 한다.
반품여부도 마찬가지다.
컬럼 하나를 어디에 두느냐에 따라 모델의 의미가 달라진다.
주문에 있는 반품여부는 “이 주문이 반품되었는가”를 뜻한다.
주문상품에 있는 반품여부는 “이 주문 안의 이 상품이 반품되었는가”를 뜻한다.
두 의미는 다르다.
의미가 다르면 위치도 달라야 한다.
이것이 정규화에서 중요한 판단이다.
물론 취소와 반품을 항상 상태값으로만 관리할 수 있는 것은 아니다.
업무가 더 복잡해지면 취소와 반품은 별도 엔터티가 될 수 있다.
예를 들어 취소 요청일자, 승인일자, 승인자, 취소사유를 이력으로 남겨야 한다면 취소는 단순 여부가 아니다.
반품도 회수 송장번호, 검수 결과, 환불 상태까지 관리해야 한다면 단순 여부가 아니다.
이 경우에는 취소 엔터티나 반품 엔터티를 별도로 두는 것이 자연스럽다.
하지만 지금 예제의 목적은 정규화의 기본을 설명하는 것이다.
따라서 여기서는 취소와 반품을 별도 엔터티로 확장하지 않는다.
대신 취소여부와 반품여부가 주문이 아니라 주문상품에 있어야 한다는 점에 집중한다.
정규화의 핵심은 거창한 구조를 만드는 것이 아니다.
속성이 어느 엔터티에 속하는지 정확히 판단하는 것이다.
정규화는 이상현상을 줄이기 위한 과정이다
정규화가 필요한 이유는 이상현상 때문이다.
이상현상은 데이터가 이상하다는 뜻이 아니다.
테이블 구조 때문에 입력, 수정, 삭제가 불안정해지는 현상이다.
주문 테이블 하나에 고객, 상품, 배송, 반품 정보를 모두 넣으면 세 가지 문제가 생긴다.
첫째, 입력 이상이다.
아직 주문이 없는 고객을 미리 등록하기 어렵다.
상품을 등록하고 싶어도 주문이 없으면 상품 정보를 넣을 곳이 애매하다.
둘째, 수정 이상이다.
고객 연락처가 바뀌면 여러 주문 행을 모두 수정해야 한다.
상품명이 바뀌면 과거 주문에 입력된 상품명까지 모두 찾아야 한다.
하나라도 빠지면 데이터가 서로 달라진다.
셋째, 삭제 이상이다.
마지막 주문을 삭제했더니 고객 정보까지 사라질 수 있다.
특정 상품의 마지막 주문을 삭제했더니 상품 정보도 함께 사라질 수 있다.
이것이 정규화가 필요한 이유다.
정규화는 이론을 만족시키기 위해 하는 일이 아니다.
데이터를 오래 사용할 수 있게 만들기 위해 하는 일이다.
'Tech > DB Design' 카테고리의 다른 글
| 식별자 설계 - 3 (0) | 2026.08.02 |
|---|---|
| 식별자 설계 - 2 (0) | 2026.07.15 |
| 정규화-2 (0) | 2026.07.08 |
| 정규화-1 (0) | 2026.07.04 |
| Entity 도출 실습-2 (0) | 2026.06.21 |
댓글