데이터 인사이트

데이터 전문가 칼럼
데이터 전문가가 전하는 데이터 노하우

노찬형의 제로에서 시작하는 데이터 모델링 시즌II (9회) : 식별자로 인스턴스의 유일성 확보

작성자
관리자
작성일
2020-08-28 18:23
조회
1040

노찬형의 제로에서 시작하는 데이터 모델링 시즌II (9회)


식별자로 인스턴스의 유일성 확보

?
필자: 노찬형 대학에서 소프트웨어공학을 전공했으며 개발자로 사회 생활을 시작했다. 사회 생활 10년을 넘기고 시작했던 DB 공부가 프로그래머로서 자신을 분명하게 되돌아볼 수 있는 기회를 주었다. 사회 초년생 또는 대학생에게 도움이 되는 데이터 모델링 글을 쓰고 싶은 게 그의 작은 바람이다.
pemaker@gmail.com
?

주경야독하는 이들을 위해

우연한 일이 계기가 돼 필자는 DB와 데이터 모델링을 글로 정리할 수밖에 없는 상황에 맞닥뜨렸다. 필자는 2012년부터 2013년까지 한 대학에서 DB 강의를 했다. 강의를 요청받았을 때, 어떻게 해야 할지 난감했다. 필자가 맡은 반은 낮에는 일하고 저녁에 공부하는 학생들로 구성돼 있었다. 일반 대학생들처럼 많은 시간을 공부에 쓸 수 없는 학생들에 DB를 알려줘야 했다. 어떻게 하면 그들에게 작으나마 도움이 될까 하고 고민하던중 시중 교재 대신, 필자가 직접 강의 자료를 만들어 보면 좋겠다는 생각을 하기에 이르렀다.

물론 시중의 책이 부족해서 그런 것은 아니다. 필자가 자료를 직접 만들어 쓰면, 일반 책으로 했을 때보다 더 쉽게 소개할 수 있을 것 같아서 그랬다. 누가 보더라도 이해하기 쉽게 전달하겠다는 목표로 강의 자료를 만들기 시작했다. 2년 넘게 강의 자료를 준비하다 보니, DB의 기초와 데이터 모델링의 기초에 대한 내용을 어느 정도 만들어 낼 수 있었다.

학생들이 강의자료를 요청하면 줬다. 하지만 설명이 없는 프레젠테이션 문서라서 아쉬웠다. 설명이 추가되면 학생들이 예습/복습을 할 때도 훨씬 좋을 텐데…. 배웠거나 배울 학생들을 위해 프레젠테이션 문서를 글로 정리하기 시작했다. 말보다 글로 정리하는 게 더 어렵다는 걸 실감하는 순간의 연속이었다.

‘하늘 아래 새로운 건 없다’는 말처럼 필자의 강의 자료 역시 인식하든 못하든 수많은 자료와 가르침을 받았던 결과물들이다. 물론 보고 들었던 이론을 개발 현장에서 적용?확인하는 과정을 거친, 경험의 산물이다. 앞으로 몇 회에 걸쳐 ‘제로에서 시작하는 데이터 모델링’ 연재를 하겠다고 용기를 내보았다. 독자 여러분과 함께 쓴다는 생각으로 수많은 의견이나 접근 방법을 댓글 또는 이메일로 받을 수 있었으면 좋겠다.
?

지난 연재에서 속성에 대해 알아보았다. 이번 회부터는 식별자(identifier)에 대해 알아본다.

? 인스턴스를 구분할 수 있는 속성의 조합

식별자란 여러 개의 데이터(인스턴스)에서 각각의 데이터(인스턴스)를 구분할 수 있는 속성의 조합을 말한다. 식별자는 엔터티 내의 개체들을 식별하는 중요한 역할을 수행한다. 릴레이션십 관점에서는 두 엔터티 간의 연결에 큰 영향을 미친다. 잘못된 식별자는 개체에 대한 접근(access)를 어렵게 하며, 데이터 정합성을 훼손시킬 수 있다. 또한 식별자의 영향은 자신의 엔터티에서만 끝나는 것이 아니다. 자신보다 하위에 있는 모든 자식(하위) 엔터티에 영향을 미치므로 잘 정의해야 한다.

쉬운 말로 식별자를 표현하면 엔터티의 개체(데이터?인스턴스)를 부르는 이름이다. 이 이름에 해당하는 개체는 반드시 1개만 존재해야 한다. 대한민국 국민의 주민등록번호에 대응하는 사람은 1명이므로 주민등록번호가 대한민국 국민을 식별하는 식별자라고 할 수 있다.

주민등록번호가 앞 생년월일 6자리와 뒤 7자리로 구성돼 있듯이, 식별자는 하나 또는 하나 이상의 속성 조합으로 이뤄질 수 있다. 하나이든 하나 이상의 조합이든 조합된 결과는 유일(unique)해야 한다. 이때 식별자는 엔터티 개체(데이터?인스턴스)에 대해 유일(unique) 하지만 유일하다고 해서 꼭 식별자가 되는 것은 아니다.

식별자는 개체(데이터?인스턴스)의 이름이고, 정의할 때는 △나는 누구인가? △나를 무엇이라고 부르는가? 이 두 가지 근본적인 질문에 답할 수 있어야 한다.

식별자는 엔터티 개체의 본질을 정의하며, 서비스 타입과 함께 엔터티를 구체적으로 규명하는 역할을 한다. 따라서 식별자는 엔터티 내에서 다른 개체들과 구별되는 ‘나’를 정의할 수 있는 속성을 선택해야 한다.

독자들의 식별자를 생각해 보자. 한국의 국민이면 위에서 소개한 주민등록번호가 될 것이다. 한국을 넘어 전 세계 속에서 누군가를 식별할 수 있는 식별자는 무엇이 될까? 어떻게 식별자를 정해야 여러 국민들 중의 특정인을 유일하게 구분할 수 있을까? 이에 대한 답은 독자 스스로 찾아보기 바란다.


[그림 1] 고객 엔터티
[그림 1]에서 고객 엔터티의 식별자는 고객번호다. 고객번호가 다름은 데이터 관점에서 다른 고객을 의미한다. 예를 들어 어떤 온라인 쇼핑몰에 내가 두 번 이상 등록돼 2개 이상의 고객번호를 갖고 있다고 하자. 내 입장에서는 고객번호를 여러 개 갖고 있어도 한 사람이지만, 데이터 관점에서는 고객번호가 다르므로 각각을 별도의 고객으로 인식할 수밖에 없다.


[그림 2] 고객 엔터티에서 주민등록번호가 식별자인 경우
이전에는 [그림 2]와 같이 고객의 식별자로 주민등록번호를 사용했다. 이렇게 모델링할 때는 고객의 주민등록번호를 사용하더라도 문제가 없다. 주민등록번호는 유일하며 바뀌지 않는다는 전제가 있었기 때문이다.

하지만 주민등록번호가 중복되는 경우가 나타났으며, 이로 인해 주민등록번호가 변경될 수 있다. 또한 최근에 개인정보보호 관련 법령으로 주민등록번호 등 개인을 구분할 수 있는 정보 사용이 제한되면서 주민등록번호 대신에 [그림 1]과 같이 별도 식별자를 만들어 사용하게 됐다.

이렇게 되면서 실제로는 동일인지만 데이터적으로 한 명 이상인 경우가 발생할 수 있다. 따라서 데이터의 정합성을 위해 데이터 모델링과 프로그램 측면에서 추가 노력을 해야만 한다. 이런 노력의 대표적인 사례가 회원가입 시 휴대폰 번호인증, I-PIN 인증을 통해 기존에 가입된 가입자인지를 확인하는 것이다.

?

? 식별자의 이름

식별자는 당연히 변하지 않는 속성으로 하는 것이 맞다. 또한 자주 사용하거나 부르기 쉬운 것을 선택하는 것이 좋다. 대한민국 국민의 식별자 후보는 여러 가지가 될 수 있다. 주민등록번호, 지문, DNA 등 유일하게 구분할 수 있는 속성이 여러 개 있다. 이중에 지문이나 DNA를 식별자로 쓰면 유일하게 구분할 수 있으므로 식별자가 될 수도 있지만 쉬게 부르기 어렵다. 사람을 유일하게 구분할 수 있는 식별자 후보 중에서 가능하면 자주 사용하거나 쉽게 부를 수 있는 주민등록번호 등의 속성을 선택하는 것이 좋다.

식별자는 SQL 개발시에 JOIN 등의 구문에서 자주 사용하므로 부르기 쉽고 사용하기 쉬운 이름을 사용하는 것이 유리하다.

? 주식별자와 부(보조)식별자

사람의 식별자를 주민등록번호로 하면, 주민등록번호를 주식별자라고 한다. 지문이나 DNA는 부(보조)식별자라고 한다.

주??적으로 구현되면 PK(Primary Key)가 된다. 또한 엔터티를 대표하는 개체이름이 되며, Not Null이 된다.

부(보조)식별자는 주식별자와 마찬가지로 개체를 식별하는 용도로 사용할 수 있다. 주식별자로 커버할 수 없는 영역을 담당하기도 하며, 하나의 엔터티에 하나 이상이 존재할 수 있다. 물리적으로 구현되면 unique Key가 된다.


[그림 3] 주식별자와 부식별자 사용
[그림 3] 모델처럼 사원근태내역은 사원의 주식별자인 사원번호를 상속받았으며, 연금납부내역은 사원의 부식별자인 주민등록번호를 상속받았다. 이와 같이 부식별자는 다른 엔터티와의 관계에서 사용될 수 있으며, 부식별자도 식별자의 모든 역할이 가능하다.

? 본질식별자와 인조식별자

1)본질식별자

식별자는 본질식별자와 인조식별자로 구분하기도 한다. 본질식별자는 개체마다 고유하며 본질적으로 구분할 수 있는 것을 말한다. 사람의 지문 같은 것이다. 우리가 갖고 있는 주민등록번호는 태어난 후에 발급되므로 엄격하게는 본질식별자라기보다는 인조식별자로 봐야 한다. 그런데 한국 국민이면 누구나 주민등록번호를 출생 신고 시에 부여받으므로 본질식별자로 여기고 있을 뿐이다.

엔터티의 식별자를 정의함에 있어서 이 본질식별자를 찾아내고 그것을 식별자로 사용하는 것이 바람직하다. 본질식별자를 찾는 것은 엔터티를 정의하는 과정의 일부이며, 메인엔터티나 액션(action)엔터티인 경우는 더더욱 중요하다. 본질식별자를 찾으려는 노력을 하지 않고 무분별한 인조식별자의 사용은 지양해야 한다.

엔터티의 식별자로서 꼭 본질식별자를 사용하는 것은 아니다. 최종적으로 엔터티의 식별자를 정의할 때에 따라 본질식별자를 사용하는 경우도 있고, 인조식별자를 사용하는 경우도 있다. 어느 것이 더 효율적이냐는 관점에서 결정하게 된다. 따라서 최종 사용된 식별자는 업무적으로 효율적인 식별자이므로 업무식별자로 부르는 것도 타당하다고 볼 수 있다.

최종적으로 본질식별자를 사용하든 인조식별자를 사용하든 중요한 것은 본질식별자를 찾아냄으로써 엔터티의 본질적인 의미를 정의해야 한다는 점이다. 본질식별자는 엔터티의 정체성을 나타내는 것으로 이를 정의하는 것은 엔터티를 정의하는 과정의 일부다.


[그림 4] 본질식별자의 예
[그림 4] 모델의 통화내역 엔터티의 식별자를 보면 서비스계약의 서비스계약번호, 통화종류의 통화종류코드를 상속받고 본인의 통화시작일시(통합종류코드+서비스계약번호+통화시작일시)로 구성돼 있다. 이렇게 정의된 식별자는 엔터티의 정체성을 결정하고, 정의 과정에서 자연스럽게 부모 엔터티와 릴레이션십이 이뤄진다. 또한 하위(자식) 엔터티의 본질식별자는 내가 어디서 왔는가? 즉 부모가 누구인지가 포함되며, 주로 누가?무엇을?언제라는 의미를 가진다.

2) 인조식별자

인조식별자는 가명 또는 별명이라고 할 수 있다. 인조식별자도 식별자이므로 식별자의 기본적인 원칙은 지켜져야 한다. 인조식별자를 쓰는 이유는 부르기 쉽고 관리하기 쉽게 하기 위해서다. 인조식별자는 식별속성 중에 인조 속성이 하나라도 포함된 것을 말하며, 자연(업무)적 의미가 없는 속성이다.

주민등록번호 앞 6자리 생년월일은 사람에 대한 본질적인 속성이라고 한다면, 뒤 숫자 7자리는 자연(업무)적 의미가 없는 속성이므로 인조식별자라고 할 수 있다. 뒤 7자리는 특별한 규칙에 의해 만들어졌으므로 본질적이라고 할 수 있겠지만, 숫자만 나열해 놓고 보면 특별한 본질적 의미를 갖지 않는다.


[그림 5] 본질식별자가 사용된 모델
[그림 5] 모델의 배송접수내역은 고객번호, 접수일시라는 본질식별자로 정의한 모델이다. 위와 같이 모델링하는 경우도 있겠지만, 시스템(애플리케이션)에서 일자로 구분하거나 그룹하는 경우가 많다면 접수일시를 잘라서 사용해야 한다. 이는 성능상의 문제가 발생할 수 있어서 다음처럼 하기도 한다.


[그림 6] 본질식별자와 인조식별자를 함께 사용한 모델
[그림 6] 모델은 고객번호, 접수일자와 접수일련번호라는 인조식별자로 정의해 위에서 소개한 일자별로 구분하거나 관리할 때 발생할 수 있는 성능 이슈를 해결했다. 이 모델에서 식별자 접수일련번호에는 자연(업무)적으로 의미가 없는 인조식별자가 포함됐으므로 배송접수내역의 식별자는 인조식별자라고 할 수 있다.


[그림 7] 인조식별자만 사용한 모델
인조식별자만으로 식별자의 역할을 충분히 할 수 있다. 따라서 [그림 7-6]과 본질식별자와 인조식별자를 합쳐서 식별자를 구성하는 것은 식별자로서 적절하지 않다.


[표 1] 본질식별자와 인조식별자 비교
[그림 7]과 같이 본질식별자인 접수일자와 고객번호는 일반속성으로 하고, 배송접수번호라는 인조속성 하나만으로 인조식별자를 정의하는 것이 더 좋은 접근이다.

인조식별자를 사용해야 할 때는 다음과 같다. △식별자를 정의할 때 본질식별자로 정의했으나 업무적 요건에 의해 인조식별자가 들어갈 때 △상속받은 본질식별자가 많아서 본인의 식별자가 너무 길어서 부르기 쉽고 편하게 관리해야 할 때 등이다.

인조식별자를 사용하는 것이 문제가 되지 않는다. 단 본질식별자를 모르는 상태에서 무조건 인조식별자를 사용하는 것은 지양해야 한다. (다음 회에 계속)

?

?

출처 : 한국데이터산업진흥원

제공 : 데이터 전문가 지식포털 데이터온에어(dataonair.or.kr)