어떻게 중복을 없애는 정리, 정규화
주문이 들어올 때마다 한 표에 손님의 이름과 전화번호까지 함께 적는다고 하자. 같은 손님이 열 번 주문하면 같은 이름과 번호가 열 줄에 그대로 되풀이된다. 그 손님이 전화번호를 바꾸면 열 줄을 모두 고쳐야 하고, 한 줄이라도 놓치면 그 줄에는 옛 번호가 남아요. 탈은 같은 정보를 여러 번 적은 데서 시작된다. 되풀이되는 정보를 떼어 내 한 곳에만 두도록 표를 나누는 일, 이것이 정규화예요.
같은 정보를 여러 번 적으면
앞 레슨에서는 두 표를 공통 열로 이어 물었다. 이번에는 거꾸로, 표를 왜 그렇게 나누어 두는지 보자. 주문을 받을 때마다 표 하나에 한 줄씩 적으면서 손님 이름과 전화번호도 함께 적는다고 해 보자.
같은 손님이 여러 번 주문하면 그 손님의 이름과 번호가 줄마다 똑같이 다시 적힌다. 아래 표에서도 민수는 주문 세 건에 세 번 나와요.
손님 이름을 눌러 보자. 그 손님의 정보가 몇 줄에 똑같이 적혀 있는지 한눈에 드러나요.
같은 정보가 줄마다 박혀 있다. 자리를 괜히 차지하는 것도 문제지만, 더 큰 탈은 고칠 때 생긴다. 민수가 전화번호를 바꾸면 민수가 적힌 줄을 모두 찾아 고쳐야 하고, 하나라도 놓치면 같은 사람에게 번호가 둘 생긴다. 어느 쪽이 맞는지는 표만 보고 알 수 없어요.
탈은 이것만이 아니다. 아직 주문하지 않은 새 손님은 적을 줄이 없어서 이름조차 올려 둘 수 없고, 하늘의 하나뿐인 주문을 지우면 하늘의 전화번호까지 함께 사라진다. 고칠 때, 넣을 때, 지울 때 생기는 이런 어긋남을 이상 현상이라고 부른다.
되풀이되는 부분을 떼어 낸다
해결책은 생각보다 단순하다. 되풀이되는 부분을 떼어 따로 표를 만든다. 손님의 이름과 전화번호는 주문마다 적지 않고, 손님만 모은 고객 표에 한 사람당 한 줄로 한 번만 적어요.
그러면 주문 표에서는 손님 정보가 통째로 빠지고, 주문 번호처럼 주문에만 딸린 칸이 남는다. 어떤 정보가 무엇에 딸린 것인지 따져 제자리에 두는 셈이다.
나누기를 눌러 보자. 되풀이되던 손님 정보가 주문 표에서 떨어져 나와 고객 표에 한 줄씩 모여요.
손님 정보가 한 곳에 모였다. 이제 민수가 번호를 바꿔도 고객 표의 한 줄만 고치면 된다. 주문이 백 건이든 천 건이든 고칠 곳은 한 줄이라, 놓칠 일도 번호가 둘로 갈릴 일도 없어요. 새 손님은 주문이 없어도 고객 표에 올릴 수 있고, 주문을 지워도 손님 정보는 남는다.
그런데 걱정이 하나 생긴다. 주문 표에서 손님 정보를 빼 버렸으니 어느 주문이 누구의 것인지는 어떻게 알까?
공통 열로 다시 잇는다
여기서 앞 레슨의 조인이 쓰인다. 나눌 때 그냥 떼어 내기만 하면 안 되고, 두 표에 같은 열을 하나 남겨 둔다. 고객 표에는 고객번호와 이름, 전화번호를 두고, 주문 표에는 이름 대신 고객번호만 적는다.
이 고객번호가 두 표를 잇는 끈이에요. 주문 표의 번호를 보고 고객 표에서 같은 번호를 찾으면 그 주문이 누구의 것인지 바로 알 수 있다.
주문 줄의 고객번호를 눌러 보자. 같은 번호를 가진 고객 표의 줄로 끈이 이어지며 누구의 주문인지 드러나요.
번호 하나로 두 표가 이어졌다. 정보는 한 곳에만 적혀 있어도 끈을 따라가면 언제든 합쳐 볼 수 있다. 되풀이는 사라지고 고칠 곳은 한 군데로 줄었는데, 필요한 정보는 조인으로 그대로 다 모여요.
이것이 정규화의 핵심이다. 실무에서는 이 생각을 정규형이라는 단계별 규칙으로 정리해 두고, 한 칸에 값을 하나만 두는 것부터 시작해 표를 차례로 다듬는다. 그런데 좋은 것도 지나치면 탈이 난다. 표를 너무 잘게 나누면 어떻게 될까?
너무 나누면 일부러 합치기도 해요
되풀이가 싫다고 무작정 잘게 나누면 표가 자꾸 늘어난다. 주소는 주소 표에, 등급은 등급 표에 두는 식으로 자잘한 것마다 표를 따로 만드는 것이다.
그러면 손님 한 명을 제대로 보려고 표 서너 개를 조인으로 이어 붙여야 한다. 조인은 공짜가 아니어서, 이어 붙일 표가 많을수록 답이 늦게 나와요. 되풀이는 줄었지만 읽는 속도가 느려진 셈이다.
잘게 나눔과 일부러 합침을 번갈아 눌러 보자. 나눌수록 이어 붙일 표가 늘고, 합치면 되풀이가 조금 생기는 대신 한 번에 보여요.
나눔과 합침은 서로 주고받는 관계다. 잘게 나누면 되풀이가 없어 깔끔하지만, 볼 때마다 표를 이어 붙이느라 느리다. 그래서 늘 같이 읽는 정보는 일부러 한 표에 합쳐 두기도 하는데, 이것을 비정규화라고 해요.
대가도 있다. 같은 정보가 다시 여러 곳에 생기니, 바뀔 때마다 그 사본들을 함께 맞춰 줄 장치가 필요하다. 쓰기가 잦은 곳은 정규화 쪽으로, 읽기가 훨씬 잦은 곳은 비정규화 쪽으로 기울이며 균형을 잡는다.
정리
정리하면 이렇다. 한 표에 같은 정보를 되풀이해 적으면 자리를 낭비하고, 고치거나 넣거나 지울 때 정보가 어긋난다. 그래서 되풀이되는 부분을 떼어 별도의 표로 나누고, 공통 열로 다시 잇는다.
정보는 한 곳에만 두고 필요할 때 조인으로 합쳐 본다. 너무 잘게 나눠 느려지면 일부러 합치기도 하는데, 그 균형을 잡는 일까지가 정규화예요.
핵심을 차례로 눌러 되짚어 보자. (반복은 낭비·불일치 → 반복을 떼어 나누기 → 공통 열로 잇기 → 너무 나누면 일부러 합치기)
이제 표를 어떻게 나누고 어디서 멈출지 판단하는 기준이 생겼다. 정보를 한 곳에만 두면 고칠 때 어긋날 일이 줄어요.
그런데 한 번에 여러 표를 함께 고쳐야 할 때도 있다. 주문을 기록하면서 재고를 줄이는 일처럼, 둘 중 하나만 되고 멈추면 표끼리 어긋난다. 여러 고침을 한 덩어리로 묶어 전부 되거나 전부 안 되게 하는 방법을 다음 레슨 트랜잭션에서 다룬다.