DB/관계형 DB

도메인 설계 전략

쿠와와 2021. 1. 19. 14:32

DB 설계에서 가장 어려운 것이 도메인 설계이다. 

 

응용프로그램에서 어떤 릴레이션이 필요하고 각 릴레이션은 어떤 속성을 가져야 하며 각 속성의 데이터형은 무엇인가와 같은 것들은 사람이 생각해서 판단하지 않으면 안 되는 분야이다. 

 

이 장에서는 2가지를 살펴볼 것이다. 

  1. 이름 
  2. 도메인 : 데이터 형

 

1. 도메인이란?? 

관계형 모델에서 데이터형에 불과하다. 즉 도메인은 속성이 취할 수 있는 값의 집합이다. 관계형 모델에서 컴퓨터가 ㅜ치급하는 데이터는 유한하게 한정되므로 도메인도 필연적으로 유한집합이 된다. 

도메인의 요소에 어떤 구조를 가진 데이터를 할당할 것인지는 관계형 모델상의 제한은 없다. 컴퓨터가 표현할 수 있는 것이면 상관없다.

 

집합의 요소

구조는 상관없지만 집합의 요소로 정의할 필요가 있으므로 명확한 값을 가진 것이여야 한다. NULL, 포인터는 불가능

 

 

2. 도메인 셜계 전략의 요소

모든 것은 자의적인 선택 

도메인은 속성이 취할 수 있는 값의 집합이다. 이 때 어떤 한 개의 도메인을 나타내는 방법은 한 가지뿐이 아니다. 무수히 많은 방법 중에 하나를 선택하는 것이다. -> 어째서 그러한 설계를 했는가? 이것은 설계자의 주관에 따라 이뤄짐

상식에 맞게 그리고 지금까지의 경험에 맞게 또는 기세로 결정할 수도 있다. 도메인 설계는 이와 같이 주관에 따라서 결정하는 것 외에는 방법이 없다. 

 

 

응용프로그램의 필요성으로 생겨난다.

속성이 어떤 값을 얻을 수 있는지 결정하는 것은 응용프로그램이다. 그래서 처음 필요한 것은 응용프로그램에 어떤 데이터가 필요한지 인식하는 것이다. 

 

DB쪽 설계를 수행하기에 앞서 응용프로그램의 설계, 즉 응용프로그램이 무엇을 수행하고 어떤 데이터가 입출력되며 이를 위해서 어떤 데이터를 영속화해야 하는지 찾아내야한다. 

 

적절한 DB설계를 위해 필요한 것 

1. 실제 응용프로그램에 대한 이해 

2. 구현된 로직을 깊이있게 이해

 

도메인 주도 설계

뛰어난 응용프로그램을 설계하려면 적어도 어떤 것이든지 응용프로그램의 설계 방법을 익혀야한다. 저자가 추천하는 설계 방법은 도메인 주도 설계(DDD)이다. 이때 도메인은 관계형 모델의 도메인과는 관계없다. 

응용프로그램에 어떤 데이터나 로직이 필요한가를 알아내는 것은 DB에 어떤 릴레이션이나 속성이 필요하냐는 주제와 직결된다. 도메인 주도 설계는 여러 번 리팩터링 하면서 이와 같은 응용프로그램의 본질을 파악하게 된다.

 

DB의 리팩터링

응용프로그램의 구조적인 변화가 있을 대는 DB 설계도 그와 맞게 바꿔어야 한다. 이것은 나중에 다시 다루겠다.

 

데이터의 본질을 파악한다. 

숫자 값에 문자열 칼럼을 할덩하는 실수에 관한 예

ID값이 숫자 값인데도 실제로 문자열의 칼럼을 할당하는 경우가 있다. 숫자 값이라면 RDB에서 숫자형 칼럼으로 표현하면 좋겠지만, 불행하게도 실제로 문자열을 사용한 설계가 많이 사용되고 있다. 

 

그렇다면 왜 좋지 않을까?

 

DB는 본질적인 데이터를 처리하게 된다.

단순히 우리 인간은 편리하게 사용하기 위해 잘 못된 방법으로 할당을 한다. 이 경우 본질적인 의미가 있는 데이터가 의미를 잃을 수 있다는 것이다. MVC처럼 응용 프로그램을 기능별로 나눈 디자인 패턴이 나오고 나서 꽤 시간이 흘렀다. MVC를 이해하고 있는 사람이라면 본질적인 데이터와 표시를 나눠서 설계해야 한다는 것도 알고 있을 것이다 

 

도메인을 설계할 때는 자릿수와 같은 표시상의 문제나 사용자의 편리성 등 본질적인 데이터를 확실하게 구별하자. DB가 다루는 것은 본질적인 데이터 뿐이다. 다른 것은 응용프로그램에게 맡기는 것이 현명하다. 

 

속성의 이름 

가장 중요한 점은 속성이 나타내는 데이터의 본질을 표현하는 이름을 사용하는 것이다. 

[ 이름은 본문을 나타내는] 속성명이여야 한다. 

이와 같은 데이터의 본질을 표현하는 이름을 붙여야하는 것은 관계형 DB 뿐만 아니라 프로그래밍에서도 마찬가지다.

 

3. ID를 설계한다는 개념 

ID란 무엇인지부터 확인해보자

현실 세계의 물체나 개념을 나타내는 수단

DB에 저장된 ID는 현실 세계의 물체나 개념을 나타낸다. 이와 같은 물체나 개념을 집합으로 표현한 것이 관계형 모델의 기본적인 개념이다. 

즉 현실 세계의 물건과 속성이 1:1로 일치해야 한다는 것이다. (전단사 함수) 

 

이때 주의해야하는 것은 ID를 설계하는 경우에 그것이 개체에 대한 것인지 집단에 대한 것인지, 집단이라면 어떤 크기로 집합을 식별화할지 등을 고려해야한다. (ID는 유일성을 가져야한다.) 

 

자연키와 대체키

RDB에서 어떤 ID를 설계할 때 그 ID를 자연키로 해야 하는지, 대체키로 해야하는지 논의하는 경우가 있다. 어느 쪽도 RDB에서 필요하며 상황에 따라 구분해야 한다. 

 

자연키 : 현실 세상에 존재하는 어떤 단어나 꼬리표를 키로 사용하는 것 

대체키 : 현실 세계에 존재하지 않는 DB 또는 DB를 사용하는 응용프로그램 내부에서만 통용되는 ID 

 

어느쪽을 선택??

일반적으로는 자연키가 바람직하지만 중복될 가능성이 있다고 알려져 있다. (ex. 사람의 이름) 작은 마을이라면 이름은 사람을 특정 짓기에 충분할지도 모른다. 그런데 마을의 규모가 커지고 사람의 수가 늘어나면 같은 이름을 가진 사람이 나올 수 있다. 이때 이름은 더이상 특정 사람을 지칭하는 것이 아니므로 ID로써 기능을 잃게된다. 

 

이대 모든 릴레이션에 대체키를 도입해야한다고 말하는 것은 난폭한 주장이다.  ID로써 사용할 수 있다는 것, 즉 현실 세계의 물건이나 개념과 1:1로 대응하는 집합이라면 자연키를 사용해도 문제가 없다. 그렇게 돼 있는지를 판단하는 것이 중요하다. 

 

자연키의 사용 대상과 문제점

DB 설계쌍 자연키를 사용하는 것은 아무런 문제가 되지 않는다. 문제는 사용값이 ID로써 기능을 할 수 있는가? 의 여부이다. 이미 누군가가 운영하고 무언가로 식별할 수 있고, 오랜 기간을 거친 값에 변경이 없고 신뢰할 수 있다고 생각되는 것은 자연키로 사용해도 문제없을 것이다. 예를 들어 사회보장보험번호, 기초연금번호 등이 있다. 

하지만 이처럼 권위가 있어 보이는 ID도 실제로는 운영이 잘못돼 중복이 발생할 대도 있다. 주의해서 사용하자

 

또한 ID가 무엇을 특정하는 것이냐는 관점도 중요하다. 자주 범하는 실수 중 하나로는 이메일 주소를 사람을 식별하는 ID로 사용하는 경우이다. 문론 이메일은 고유하지만 이메일 주소는 어디까지나 이메일 주소를 식별하는 것이며 사람을 특정하는 것은 아니다. 바꿔 말하면 사람과 1:1로 일치하지 않는다. (다른사람이 이메일을 사용할 수도 있는 것)

 

∴ 값이 무엇을 특정하는 것인지 생각하자.

 

대체키의 사용 대상과 문제점 

이떄의 문제는 이미 자연키가 있는데 대체키를 새로 생성할 때 문제가 발생한다. 이런 대체키는 낭비이다. 

새롭게 대체키를 작성해도 본래의 자연키에 유니크키 제약이 필요할 것이다. 이 때 오버헤드가 발생한다. 

이미 적절한 자연키가 존재할 때는 본질적으로 대체키는 불필요하다. 

 

다른 경우는 복합 기본키(여러 개의 칼럼을 가진 기본 키)가 싫어서 대체키를 추가하는 경우이다. 

관계형 모델에서는 후보키가 여러 개의 속성으로 구성되는 것은 지극히 자연스러운 것이다. 

불필요한 대체키는 DB설계를 불필요하게 복잡하게 만들 것이고 DB의 규모가 커지면 커질수록 그 폐해는 커질 것이다. 

 

의미가 있는 ID

ID에 의미를 부여하는 설계를 자주 볼 수 있다. 그런데 DB에서 하나의 속성으로 다루기에는 문제가 있다. 

특히나 문제가 되는 것은 이와 같은 ID 일부분에 의존한 처리가 생길 때이다.

 

예를 들어 청소기의 아이디가 [CLN-CYC-01234-BL] 이라는 코드를 할당했다고 하자. 그때 아래와 같은 쿼리를 작성해야한다.

SELECT * FROM product_list WHERE product_id LIKE 'CLN%' AND product_id LIKE '%BL'

이러한 쿼리가 되어버리는 것은 이 ID가 1NF의 요건을 만족하지 않기 때문이다. 속성의 값을 여러 부분으로 나눌 수 있는 설계는 1NF라고 할 수 없다. 각 부분을 개별 속성으로 정의해야 한다.

 

길이 색, 무게 등의 성질을 나타내는 속성 

중복이 없다면 이것을 성질이라는 개념을 구별하는 ID로 사용할 수 있다. 사용가능하다.

 

∴ ID 일부에 의미를 부여한 설계는 피하자. 

 

ID 결함이 미치는 영향

어떤 키가가 다른 릴레이션에도 있느 것은 자연스러운 일이다. 하지만 ID의 영향력이 너무 커져 온갖 릴레이션에 영향을 미칠 수 있다. 

 

4. SQL로 도메인 표현

적절한 데이터 형 선택 

수치형 ID를 문자형 컬럼으로 정의하지 말자. 테이블의 사이즈가 커지고 문자가 들어갈 수도 있으며 숫자로 연산할 수 없다. 

도메인과 SQL의 각종 데이터 형은 1:1 대응하지 않지만 적어도 도메인이 가지는 값을 모두 포함할 수 있는 데이터형을 골라야한다. 

 

술어를 제약으로 표현할 때

도메인과 그 칼람의 데이터형이 1:1 관계로 전단사되어 있는 것이 바람직하다. 그렇기에 전사에 CHECK 제약을 들어 단사에 가깝게 할 수 있다. 

 

하지만 무분별한 CHECK 사용은 손이 많이가고 오버헤드고 커지게 된다. 너무 지나치게 사용하지는 말자.