개발 학습 실습실

이 사이트의 실습은 자바스크립트를 켜야 움직입니다. 아래는 같은 내용을 글로 적은 것입니다.

공부 › DB › 관계형 모델과 설계

정규화

테이블을 나누지 않으면 무슨 일이 생기나

주문 테이블에 회원 이름과 주소까지 같이 넣어 둔 설계와, 회원과 주문을 나눈 설계가 있습니다. 같은 작업을 양쪽에서 해 보면 한 테이블에 몰아넣었을 때만 데이터가 어긋나거나 사라집니다.

실행으로 대조 · SQLite에 같은 테이블을 만들어 확인

이 실습에 나오는 개념

정규화와 반정규화
정규화는 같은 데이터가 여러 곳에 중복 저장되지 않도록 테이블을 나누는 설계 과정이다. 중복이 있으면 한 곳만 수정되어 데이터가 서로 어긋나는 문제가 생긴다. 반정규화는 조회 성능을 위해 의도적으로 중복을 허용하거나 테이블을 합치는 것으로, 조인이 줄어드는 대신 중복된 데이터를 함께 갱신해야 하는 부담이 생긴다.
함수 종속
한 컬럼(또는 컬럼 묶음)의 값이 정해지면 다른 컬럼의 값이 하나로 정해지는 관계다. 예를 들어 회원 번호가 정해지면 회원 이름이 정해진다. 정규형은 이 관계를 기준으로 정의된다. 기본 키의 일부에만 종속되는 것을 부분 함수 종속, 키가 아닌 컬럼을 거쳐 종속되는 것을 이행적 함수 종속이라 하며 각각 제2정규형과 제3정규형에서 제거한다.
기본 키, 유니크 키, 외래 키
기본 키(PK)는 테이블의 각 행을 유일하게 식별하는 컬럼으로 값이 중복되거나 비어 있을 수 없고 테이블에 하나만 둔다. 유니크 키는 값의 중복을 막는 제약으로 여러 개 둘 수 있다. 외래 키(FK)는 다른 테이블의 기본 키(또는 유니크 키)를 참조하는 컬럼으로, 참조 대상이 실제로 존재하도록 보장한다.

이렇게 바꿔 보세요

처음 설정으로 실행하면

  1. 처음 상태입니다. 주문 한 건마다 회원 이름과 주소가 같이 적혀 있습니다. 김철수는 주문이 3건이라 주소 "서울"이 3번 저장돼 있습니다. 주문번호가 회원ID를 정하고 회원ID가 이름과 주소를 정하는 구조입니다(이행 함수 종속).
  2. 회원ID가 1인 행을 전부 찾아 주소를 바꿨습니다. 3행을 고쳤습니다. 주문이 늘수록 고쳐야 할 행도 늘어납니다.
  3. 김철수의 주소를 다시 조회하면 모든 행에서 "부산"입니다. 이번에는 빠짐없이 고쳐서 어긋나지 않았습니다.

실행 결과

코드

-- 정규화 전: 주문과 회원 정보를 한 테이블에
CREATE TABLE orders (
  order_id    INT PRIMARY KEY,
  member_id   INT,
  member_name VARCHAR(20),   -- member_id가 정함
  member_addr VARCHAR(50),   -- member_id가 정함
  item        VARCHAR(30),
  amount      INT
);

UPDATE orders SET member_addr = '부산'
 WHERE member_id = 1;

이 모형의 전제

회원 3명과 주문 몇 건으로 줄인 예입니다. 정규화 전 테이블은 주문번호 → 회원ID → 회원이름·주소로 이어지는 이행 함수 종속이 있어 제3정규형을 만족하지 못합니다. 정규화 후에는 외래 키로 회원을 참조합니다. 이상 현상의 정의는 관계형 데이터베이스 이론의 표준 설명을 따랐습니다. 같은 구조의 테이블을 실제 SQL 엔진(SQLite)에 만들어 확인했습니다. 한 행만 고치자 같은 회원의 주소가 두 가지로 조회됐고, 주문 번호 없이 회원만 넣는 INSERT는 거부됐으며, 마지막 주문을 지우자 그 회원의 정보가 남은 행이 0건이 됐습니다. 테이블을 나눈 쪽에서는 세 경우 모두 문제가 없었습니다.

앞 실습: ER 모델링 · 다음 실습: SELECT가 처리되는 순서

이 실습에 나오는 개념

이 실습에서 보는 것

설정

코드


      
    

그림

실행 비교

이렇게 바꿔 보세요