데이터이야기

DB 노하우, 데이터직무, 다양한 인터뷰를 만나보세요.

관계형 데이터 무결성 - 참조 무결성

데이터 이야기
작성자
dataonair
작성일
2014-11-18 00:00
조회
7456


관계형 데이터 무결성 - 참조 무결성



참조 무결성 규칙

참조 무결성 규칙의 정의를 다시 한번 상기하여 보면, “관계 실체유형의 모든 외부키 값(Value)은 관련 있는 관계 실체유형에 모두 프라이머리키 값(Value)으로 존재해야 한다.”이다. 그림 참조 무결성 규칙의 “부서” 실체유형과 “사원” 실체유형의 관계에 있어서 사원 실체유형에 “부서번호”를 외부키로 선언을 하려면, 반드시 데이터 모델 내의 다른 실체유형에 즉, “부서” 실체유형에 “부서번호”가 프라이머리키로 선언 되어 있어야 한다.

dbin_331.jpg

참조 무결성 규칙

참조 무결성에 의한 업무 규칙을 설명하기 전에 관계에서의 중요한 개념을 먼저 설명하겠다. 아래의 그림 관계 읽기에 고객이 상품을 주문하는 경우의 데이터 모델이 있다. 통상 우리가 논리 데이터 모델링 교육을 받거나, 데이터 모델링 책을 보면 그림 관계 읽기에 표현된 것처럼 관계를 읽을 때, 그림과 같이 표현하는 경우가 대부분이며 데이터 모델링을 강의하는 많은 강사들 또한 이렇게 가르친다. 업무 표현이 잘 되어 있는 데이터 모델을 가지고 관계가 갖는 업무 규칙을 읽어 낸다면 이러한 표현을 사용하는데 있어서 전혀 문제가 없다. 하지만 이미 만들어 놓은 데이터 모델을 읽어내는 것이 아니라, 두 개의 실체 유형간에 관계를 설정해야 하는 분석 단계라면 이러한 표현은 업무를 정의하는데 있어서 약간의 오해를 불러 일으킬 소지가 있다.

“고객” 실체유형과 “주문” 실체유형과의 관계(Relationship)에서 모든 고객은 여러 번의 주문을 할 수도 있다. 이것을 달리 표현하면, 모든 고객이 반드시 여러 번의 주문을 하는 것은 아니라는 것이다. 즉 “할 수도 있다.”와 “반드시 ~ 하는 것은 아니다.”라는 표현의 의미가 선택적이라는 것이다. 이러한 표현이 고객과 주문의 관계에 있어서 필수(Mandatory) 관계인지 선택(Optional) 관계인지를 결정하는 요소가 된다는 것인데, 관계를 설정하는 단계에 있어서 이러한 표현법으로 관계의 선택, 필수를 찾는 것이 다소 문제를 야기할 수 있다는 것이다.

dbin_332.jpg

관계 읽기

다른 예를 가지고 다시 한번 살펴보자! “부서” 실체유형과 “사원” 실체유형의 관계에 있어서 보통 현업에게 상기의 관계 읽기 식으로 관계를 물어보면 모든 부서는 반드시 여러 명의 사원을 포함한다고 한다. 이런 식의 표현이라면 “부서” 실체유형과 “사원” 실체유형은 양쪽 필수(Mandatory) 관계로 표현 되야 할 것이다. 하지만 그림 참조 무결성 규칙의 예에서는 한쪽 선택, 한쪽 필수 관계로 표현되고 있다. 이렇게 “할 수도 있다.”와 “반드시 ~ 한다.”식으로 현업에게 질문하면서 두 실체유형 간의 필수, 선택 관계를 설정하다 보면 잘못 설정할 수도 있다는 것이다.

또 다른 예를 하나 더 살펴보면 건물과 건물 층의 관계에 있어서 “건물” 실체유형과 “건물 층 내역” 실체유형의 관계를 관계 읽기 방식으로 물어보면 “건물” 실체유형은 반드시 “건물 층 내역”을 갖고, 역으로 “건물 층 내역”이 있으려면 “건물”이 반드시 있어야 한다고 한다. 현실 세계에서 이 표현은 부정할 수 없는 사실이다. 하지만 데이터 모델링 세계에서는 건물의 내역은 알고, 건물 층에 관한 상세 내역을 알 수 없는 경우에 “건물” 실체유형에만 데이터가 입력되고, “건물 층 내역”에는 데이터 값이 존재하지 않을 수도 있다. 이런 경우라면 이것의 관계는 양쪽 필수 관계가 될 수 없는 것이다.

논리 데이터 모델링에서 말하는 관계라는 것을 제대로 학습 받지 못한 일반적인 사람들은 논리 데이터 모델에서 말하는 관계에 대한 명확한 개념이 부족하기 때문에 이런 방식으로 질문을 하면 관계의 선택, 필수를 잘 못 정의할 수도 있다는 것이다.

“고객” 실체유형과 “주문” 실체유형의 관계에서 선택과 필수라는 것에 대한 개념을 다른 방법으로 정리해보겠다. 여기서 선택이라는 말은 “고객” 실체유형의 각각의 행(Row)이 입력될 때, “주문” 실체유형에 행(Row)이 반드시 필요 하느냐라는 것이다. 필요하다면 필수적이고, 필요 없다면 선택적이다. 다시 말해서 “고객” 실체유형에 행(Row) 이 입력될 때, “주문” 실체유형에 어떠한 행(Row)도 필요 없으므로 이 관계는 선택적이다. 그러나 반대로 “주문” 실체유형에 행(Row) 입력될 때는, “고객” 실체유형의 어느 행(Row)에 의한 주문인지를 반드시 알아야 하기 때문에 이 관계는 필수인 것이다.

“부서” 실체유형과 “사원” 실체유형의 관계를 보면 “부서” 실체유형에 행(Row)이 한 건 입력될 때, “사원” 실체유형의 행(Row)은 필요 없기 때문에 “부서” 실체유형과 “사원” 실체유형의 관계는 한쪽 선택, 한쪽 필수가 맞는 것이다. 그러니 앞으로 프로젝트에서 논리 데이터 모델링을 진행할 때, 관계 읽기 형태의 선택, 필수를 결정하는 방법을 되도록이면 사용하지 말고, 관계가 있는 두 개의 실체유형에서 하나의 실체유형에 행(Row)이 입력되는 시점에 상대 실체유형에 행(Row)이 반드시 필요한지 필요 없는지를 기준으로 선택, 필수를 결정하도록 하는 것이 정확할 것이다. 두 개의 실체유형 간에 관계가 선택인지 필수인지가 명확해야만 참조 무결성 규칙을 정확하게 설정할 수 있는 것이다.

- 필수(mandatory): 다른 실체유형에 어떤 행(Row)을 입력하기 전에 상대 실체 유형에 적어도 한 건의 행(Row)이 반드시 존재해야 하는 경우.
- 선택(optional): 다른 실체유형에 어떤 행(Row)을 입력하기 전에 상대 실체 유형에 어떤 행(Row)이 존재할 필요가 없는 경우.

실체유형이 관계를 맺고 있는 경우 외부키가 나타나는 실체유형을 자식 실체유형이라 하고, 이 외부키 속성이 프라이머리키로 선언되어 있는 실체유형을 부모 실체유형이라고 한다. 그림 관계 읽기를 보면 “고객”과 “주문”, “주문”과 “주문내역”, “상품”과 “주문내역” 간에 관계가 표현되어 있다. “고객”과 “주문”의 관계는 “고객”이 부모이고, “주문”이 자식이며, “주문”과 “주문내역”의 관계는 “주문”이 부모이고, “주문내역”이 자식이다.



참조 무결성 규칙- 입력규칙

입력규칙은 자식 실체유형에 행(Row)이 입력될 때, 부모 실체유형에 그 행(Row)이 먼저 존재해야 하는지를 결정하는 업무 규칙인 것이다.

dbin_333.jpg

그림 참조 무결성 ? 입력규칙

“고객”과 “주문”의 한쪽 필수, 한쪽 선택 관계에서 “주문” 실체유형에 즉, 자식 실체유형에 행(Row)을 입력할 때, 업무적인 관점에서 어떤 조건이 필요한가 이러한 관계에서는 “주문” 실체유형에 행(Row)이 입력되기 전에, 반드시 주문한 고객이 부모 실체유형인 “고객” 실체유형에 먼저 등록되어 있어야만 한다.

이번에는 “고객” 실체유형에 즉, 부모 실체유형에 행(Row)을 입력할 때, 업무적인 관점에서 어떤 조건이 필요한가 이러한 관계에서는 “고객” 실체유형에 행(Row)이 입력되면 되는 것이지 다른 업무적인 어떤 요건이 필요 없다.

“주문”과 “주문내역”의 양쪽 필수 관계에서는 “주문내역” 실체유형에 즉, 자식 실체유형에 행(Row)을 입력할 때, 업무적인 관점에서 어떤 조건이 필요한가 이러한 관계에서도 “주문내역” 실체유형에 행(Row)이 입력되기 전에, 반드시 주문이 “주문내역”의 부모 실체유형인 “주문” 실체유형에 먼저 등록되어 있어야만 한다.

이번에는 “주문” 실 업무적인 관점에서 어떤 조건이 필요한가 양쪽 필수 관계에서는 “주문내역”에도 반드시 한 건 이상의 행(Row)이 입력돼야 한다는 것이 “주문”과 “주문내역”의 관계가 보여주고 있는 업무규칙이다. 하지만 참조 무결성의 관점에서 보면 이러한 업무 규칙을 보장할 수 있는 방법이 없다. 양쪽 필수의 업무 규칙을 만족하기 위하여 부모 실체유형에 데이터베이스 관리 시스템의 물리적인 관점에서 제약을 두면 양쪽 필수 관계는 서로 모순에 빠질 것이다.

이러한 이유로 부모 자식 관계가 있는 실체유형 사이에서의 입력규칙은 자식 실체유형에 행(Row)이 입력될 때, 부모 실체유형에 그 행(Row)이 먼저 존재해야 하는지를 결정하는 업무 규칙인 것이다.

혹자는 실체유형 간에 관계가 양쪽 필수인 경우, 부모 실체유형의 행(Row)과 자식 실체유형의 행(Row)이 동시에 생겨야 하기 때문에, 부모 실체유형에 대한 입력규칙을 설정해야 한다고 설명하는 이도 있다. 위에서도 잠깐 이에 대하여 관계형 데이터베이스 관리 시스템의 물리적인 관점에서 참조 무결성의 입력규칙에 대하여 부모 실체유형에 어떤 제약을 둔다면, 자식 실체유형의 입력규칙에 의하여 서로 모순이 발생된다고 하였다. 이러한 이유도 있겠지만 이러한 논지를 주장하는 데이터 모델러는 참조 무결성에 대한 명확한 의미를 잘 이해 못한 것이라고 사려된다.

참조 무결성은 외부키가 생기는 시점과, 외부키가 생기고 난 후, 이 외부키를 생성하게 된 근원이 되는 부모 실체유형의 프라이머리키에 어떤 업무적인 이유에 의해서 프라이머리키의 값이 변경(수정 또 삭제)될 때, 이 값과 관계된 다른 실체유형의 외부키 속성 값을 어떻게 하느냐에 관한 업무 규칙이라는 것이다. 다시 말해서 부모 실체유형에 행(Row)이 입력될 때는 외부키라는 개념은 존재하지도 않고 생각할 필요도 없다는 것이다.

그림 참조 무결성 ? 입력규칙에는 여섯 가지의 이론적인 입력규칙의 종류가 있다. 보통 상용 관계형 데이터베이스 관리 시스템이 제공하는 입력규칙은 종속 (Dependent) 또는 제한(Restrict)으로, 대응되는 부모 실체유형에 행(Row)이 있는 경우에만 자식 실체유형에 행(Row)의 입력을 허용한다. 만약에 양쪽 선택 관계라면 외부키 속성 값을 널(Null)처리를 한다.



참조 무결성 규칙 - 삭제규칙

삭제규칙은 부모 실체유형에 행(Row)이 삭제될 때, 자식 실체유형에 외부키에 이 값이 존재하면, 부모 실체유형의 행(Row)을 삭제할 것인지, 삭제 안 할 것인지를 결정하는 업무 규칙인 것이다.

dbin_334.jpg

그림 참조 무결성- 삭제규칙

“고객”과 “주문”의 한쪽 필수, 한쪽 선택 관계에서 “고객” 실체유형에 즉, 부모 실체유형에 행(Row)을 삭제하거나 프라이머리키의 값을 수정할 때, 업무적인 관점에서 어떤 조건이 필요한가 이러한 관계에서는 “주문” 실체유형의 행(Row)에 삭제하고자 하는 고객이 값이 존재한다면, 부모 실체유형인 “고객” 실체유형의 행(Row)을 삭제하지 못하게 하거나, “고객” 실체유형의 프라이머리키 값을 수정하지 못하게 해야 할 것이며, 아니면 “주문” 실체유형의 행(Row)을 같이 삭제하거나, 외부키 속성 값을 같이 수정해야 할 것이다.

이번에는 “주문” 실체유형에 즉, 자식 실체유형에 행(Row)을 삭제할 때, 업무적인 관점에서 어떤 조건이 필요한가 이러한 관계에서는 “주문” 실체유형에 행(Row)이 삭제되면 되는 것이지 다른 업무적인 어떤 요건이 필요 없다.

“주문”과 “주문내역”의 양쪽 필수 관계에서는 “주문” 실체유형에 즉, 부모 실체유형에 행(Row)을 삭제하거나 프라이머리키의 값을 수정할 때, 업무적인 관점에서 어떤 조건이 필요한가 이러한 관계에서는 “주문내역” 실체유형의 행(Row)에 삭제하고자 하는 주문의 값이 존재한다면, 부모 실체유형인 “주문” 실체유형의 행(Row)을 삭제하지 못하게 하거나, “주문내역” 실체유형의 프라이머리키 값을 수정하지 못하게 해야 할 것이며, 아니면 “주문내역” 실체유형의 행(Row)을 같이 삭제하거나, 외부 키 속성의 값을 같이 수정해야 할 것이다.

이번에는 “주문내역” 실체유형에 즉, 자식 실체유형에 행(Row)을 삭제할 때, 업무적인 관점에서 어떤 조건이 필요한가 이러한 관계에서는 “주문내역” 실체유형에 행(Row)이 여러 건 중에 최종건이 아니면, “주문내역”의 행이 삭제되면 된다. 하지만 “주문내역”의 행이 마지막 건이라면 “주문”의 행(Row)도 같이 삭제 되야 할 것이다. 양쪽 필수 관계에 있어서 자식 실체유형의 마지막 행(Row)이 삭제될 때의 업무 규칙은 연쇄작용(Triggering Operation)에서 좀 더 자세히 살펴볼 것이다.

이러한 이유로 부모 자식 관계가 있는 실체유형(테이블) 사이에서의 삭제규칙은 부모 실체유형(테이블)에 행(Row)이 삭제될 때, 자식 실체유형(테이블)에 외부키(FK)에 이 값이 존재하면, 부모 실체유형(테이블)의 행(Row)을 삭제할 것인지, 삭제 안 할 것인지를 결정하는 업무 규칙인 것이다.

그림 참조 무결성 - 삭제규칙에는 여섯 가지의 이론적인 삭제규칙의 종류가 있다. 보통 상용 관계형 데이터베이스 관리 시스템이 제공하는 삭제규칙은 제한(Restrict)과 연쇄삭제(Cascade)를 지원한다. 제한(Restrict)은 대응되는 자식 실체유형에 행(Row)이 있는 존재하면 부모 실체유형에 행(Row)의 삭제를 못하게 하는 것이고, 연쇄삭제(Cascade)는 대응되는 자식 실체유형의 모든 행(Row)을 부모 실체유형의 행(Row)과 함께 삭제하라는 것이다.

필자가 여기서 강조하고자 하는 것은 논리 데이터 모델에서 관계의 선택, 필수 표기법에 따라 참조 무결성의 입력규칙과 삭제규칙이 다를 수 있으므로, 이러한 참조 무결성을 프로그램으로 구현한다면, 프로그램을 구현하는 방법이 달라야만 데이터의 무결성을 보장할 수 있다는 것이다. 이러한 표기법의 정확한 이해 없이 프로그램을 하다 보니 참조 무결성을 보장하지 못하고, 참조 무결성이 다 깨져서 부모의 행(Row)이 없는데도 자식의 행(Row)이 있는 경우를 너무도 허다하게 보아왔다.

다시 말해 주문과 주문내역에서 주문내역이 없는데도 주문만 있으며, 주문이 없는데도 주문내역이 있는 것이다. 또한 고객이 없는데도 주문에 고객이 있는 경우도 있으니 이런 것이 관계형 데이터베이스의 참조 무결성 규칙을 위한 논리 모델링이 제대로 이루어 지지 못하면서 발생하는 현상이라 하겠다.

실제로 논리 데이터 모델링 한 실체 관계도(ERD: Entity Relationship Diagram)를 프로젝트 현장에서 살펴보면 한쪽 선택적, 한쪽 필수적, 양쪽 필수적, 양쪽 선택적인 표기법을 아무 개념 없이 혼용해서 실체 관계도(ERD)를 만들어 놓은 곳을 필자는 너무도 많이 보아온 것이다.

데이터의 참조 무결성을 유지하기 위하여 관계형 데이터베이스 관리 시스템의 물리적인 측면을 보면 Foreign Key Constraint를 생성해 주게끔 되어 있다. 이렇게 얘기하면 혹자는 그럼 Foreign Key Constraint를 반드시 설정해야 하냐고 묻는 사람들이 많다. 특히 데이터베이스 관리 시스템을 관리하는 DBA(DataBase Administrator)들은 Foreign Key Constraint가 설정되어 있으면 데이터베이스 관리측면에 있어서 불편한 점도 있고, 또한 성능상에 비효율도 발생시키므로 Foreign Key Constraint의 설정을 상당히 꺼려한다.

필자가 강조하고 싶은 사항은 Foreign Key Constraint를 데이터베이스의 물리적인 장치로 설정하느냐, 프로그램으로 이것을 해결하느냐는 별 개의 문제로 업무적인 관점에서 이러한 참조 무결성 규칙을 정확히 분석 파악하여, 논리 데이터 모델에 표현을 할 때 목적에 맞춰서 정확히 표현하고, 설계 단계에 성능과 데이터이스의 물리적으로 설정할지, 프로그램으로 해결할지를 결정하라는 것이다.

또한 현행 데이터를 목표 데이터베이스로 이행할 때, 현행 데이터의 참조 무결성이 깨져 있어서 즉, 주문과 주문내역에서 주문내역이 없는데도 주문만 있으며, 주문이 없는데도 주문내역이 있고, 또한 고객이 없는데도 주문에 고객이 있는 경우가 있어 목표 데이터베이스에 참조 무결성을 설정할 수 없다는 논리를 펼친다.

어떤 프로그램의 SQL(Structured Query Language: 구조적 질의어)이 성능상의 문제가 있어 수행 속도를 빠르게 하기 위하여 SQL문장을 튜닝(Tuning)하더라도, 그 결과값이 틀렸다면 수행 속도가 빠른 것의 장점은 전혀 없을 것이다. 일단은 값이 정확하고, 수행 속도가 빨라야 하는데 실제 프로젝트를 하다 보면 주객이 전도되는 현상을 가끔 본다.

다시 현행 데이터가 참조 무결성이 깨져있다는 것으로 돌아가서, 이러한 현상 때문에 목표 데이터베이스에도 참조 무결성을 설정할 수 없다는 논리를 펼치는데, 거꾸로 현행의 문제가 참조 무결성을 보장하는 관계형 데이터베이스가 아니었거나, 아니면 관계형 데이터베이스 이면서도 그 당시에는 이러한 개념을 제대로 인식을 못해서 참조 무결성이 깨어져 있을 수 있는 것이다.

필자가 제안하는 것은 현행에서 목표로의 데이터 이행 시, 참조 무결성이 깨져 있는 이런 데이터들은 어떤 기본값(Default Value)을 설정하여 참조 무결성이 깨져 있는 것을 해결하고, 목표 데이터베이스에서는 참조 무결성이 깨지는 일이 없도록 관리할 것을 제안하는 바이다.



출처 : 한국데이터베이스진흥원

제공 : DB포탈사이트 DBguide.net