데이터베이스 설계 시나리오

mskimdev·2026년 4월 7일

MySQL

목록 보기
3/20

데이터베이스 설계 — 테이블은 왜 나누는가

테이블 하나에 다 넣으면 안 되나? 처음 데이터베이스를 접하면 이 질문이 자연스럽게 든다. 어차피 같은 DB 안에 있는 데이터인데, 굳이 여러 테이블로 쪼갤 이유가 있냐는 것이다.

있다. 직접 보면 바로 납득이 된다.


하나의 테이블에 다 넣으면

쇼핑몰을 만든다고 가정하자. 주문이 들어오면 이런 정보가 필요하다.

  • 누가 주문했는지 (회원 이름, 이메일)
  • 뭘 주문했는지 (상품명, 가격)
  • 언제, 얼마나 주문했는지 (주문일, 수량)

처음엔 이걸 테이블 하나로 만들어버리고 싶다.

CREATE TABLE orders (
    order_id    INT,
    order_date  DATE,
    quantity    INT,
    member_name VARCHAR(50),
    email       VARCHAR(100),
    product_name VARCHAR(100),
    price       INT
);

데이터를 넣으면 이런 모양이 된다.

order_idorder_datequantitymember_nameemailproduct_nameprice
12024-03-012김민수kim@email.com무선 마우스25000
22024-03-021이지현lee@email.com기계식 키보드89000
32024-03-051김민수kim@email.com기계식 키보드89000
42024-03-073김민수kim@email.com무선 마우스25000

겉보기엔 문제없어 보인다. 그런데 조금 더 들여다보면 이상한 점이 보이기 시작한다.


뭐가 문제인가

중복 데이터가 쌓인다

김민수가 주문을 할 때마다 kim@email.com이 그대로 반복해서 들어간다. 무선 마우스를 살 때마다 25000이라는 가격도 계속 중복된다.

지금은 4행짜리 예시니까 별 느낌이 없지만, 주문이 수천 건이 쌓이면 같은 데이터가 수천 번 복사된다. 저장 공간 낭비이기도 하고, 더 큰 문제는 따로 있다.

수정할 때 한 곳만 고치면 데이터가 틀어진다

김민수가 이메일을 바꿨다. kim@email.comminsu@email.com으로.

그러면 이 테이블에서 김민수가 포함된 행을 전부 찾아서 하나씩 바꿔야 한다. 만약 하나라도 빠뜨리면 어떤 행엔 kim@email.com, 어떤 행엔 minsu@email.com이 섞여 들어간다. 같은 사람인데 이메일이 두 가지가 되는 것이다.

-- 이걸 빠짐없이 다 찾아서 바꿔야 한다
UPDATE orders SET email = 'minsu@email.com' WHERE member_name = '김민수';

실수 한 번으로 데이터가 오염된다.

삭제하면 같이 사라지면 안 되는 정보도 날아간다

이지현이 탈퇴했다. order_id = 2 행을 지웠더니, 기계식 키보드 상품 정보(89000)도 같이 사라진다. 상품 자체는 여전히 판매 중인데, 그 정보가 없어진 것이다.

물론 다른 회원이 기계식 키보드를 주문한 행이 남아있으면 괜찮겠지만, 만약 이지현만 그 상품을 주문했다면? 상품 가격 정보가 테이블에서 통째로 사라진다.


테이블을 나눈다

문제의 원인은 서로 다른 종류의 정보가 한 테이블에 뒤섞여 있기 때문이다. 회원 정보, 상품 정보, 주문 정보 — 이 세 가지는 성격이 다르다. 각각 따로 관리하면 된다.

회원 테이블

CREATE TABLE members (
    member_id   INT PRIMARY KEY,
    member_name VARCHAR(50),
    email       VARCHAR(100)
);
member_idmember_nameemail
1김민수kim@email.com
2이지현lee@email.com

상품 테이블

CREATE TABLE products (
    product_id   INT PRIMARY KEY,
    product_name VARCHAR(100),
    price        INT
);
product_idproduct_nameprice
1무선 마우스25000
2기계식 키보드89000

주문 테이블

CREATE TABLE orders (
    order_id   INT PRIMARY KEY,
    order_date DATE,
    quantity   INT,
    member_id  INT,
    product_id INT
);
order_idorder_datequantitymember_idproduct_id
12024-03-01211
22024-03-02122
32024-03-05112
42024-03-07311

주문 테이블에는 이름이나 상품명 대신 member_id, product_id만 들어간다. 회원 정보가 필요하면 members 테이블을, 상품 정보가 필요하면 products 테이블을 참조하는 방식이다.


분리하면 뭐가 달라지나

이제 아까의 문제들이 어떻게 해결되는지 보자.

이메일 변경members 테이블에서 딱 한 행만 수정하면 끝이다. 주문이 몇 건이든 상관없다.

UPDATE members SET email = 'minsu@email.com' WHERE member_id = 1;

회원 탈퇴members에서 이지현을 지워도 products 테이블의 기계식 키보드 정보는 그대로 남는다. 회원 정보와 상품 정보가 완전히 분리돼 있으니까.

중복 제거 — 무선 마우스의 가격은 products 테이블에 딱 한 번만 저장된다. 아무리 주문이 쌓여도 product_id = 1이라는 숫자만 반복될 뿐이다.


테이블을 연결하는 방법 — 외래 키

주문 테이블의 member_idmembers 테이블의 member_id를 가리킨다. 이런 관계를 명시적으로 설정해두는 것이 외래 키(Foreign Key)다.

CREATE TABLE orders (
    order_id   INT PRIMARY KEY,
    order_date DATE,
    quantity   INT,
    member_id  INT,
    product_id INT,
    FOREIGN KEY (member_id)  REFERENCES members(member_id),
    FOREIGN KEY (product_id) REFERENCES products(product_id)
);

FOREIGN KEY ... REFERENCES는 "이 컬럼의 값은 저 테이블의 저 컬럼에 존재하는 값이어야 한다"는 제약이다. members에 없는 member_id로 주문을 넣으려 하면 DB가 거절한다. 없는 회원의 주문이 생기는 상황 자체를 막아버리는 것이다.


정리

문제원인해결
같은 정보가 반복 저장됨한 테이블에 모든 정보 혼재테이블 분리 후 ID로 참조
수정 시 여러 행을 바꿔야 함데이터가 여러 행에 중복원본 테이블에서 한 번만 수정
삭제 시 다른 정보도 사라짐서로 다른 정보가 같은 행에 묶임테이블이 독립적으로 존재

테이블 설계의 기본은 결국 하나다. 같은 성격의 데이터끼리 모으고, 다른 성격의 데이터는 분리한다. 그리고 필요할 때 ID로 연결해서 가져온다.


profile
<- 개발 공부하는 나

0개의 댓글