데이터 인사이트

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

노찬형의 제로에서 시작하는 데이터 모델링 시즌II (5회) : M:M 논리 모델을 1:M의 모델로 바꾸기

작성자
관리자
작성일
2020-08-28 18:19
조회
78

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


M:M 논리 모델을 1:M의 모델로 바꾸기

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

주경야독하는 이들을 위해

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

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

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

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

지난 4회에 이어 릴레이션십 구성에 대해 계속하여 알아본다. 이번 연재에서는 물리적 세계에서 존재하지 않는 M:M 논리 모델을 1:M의 관계로 설정하는 방법에 대해 알아본다.

 

• M:M 관계의 해소

앞 연재에서 소개했듯이 데이터 모델의 M:M 상태는 현재의 DBMS들에서는 직접 지원하지 않아 논리적으로만 존재한다. 따라서 물리적 구현을 위한 모델링에서는 반드시 물리적 변환이 필요하다.

M:M 관계를 해소하는 방법으로 릴레이션(교차) 엔터티를 이용하는 방법 이외에 식별자(unique identifier)를 이용하는 방법, 속성(attribute)을 이용하는 방법이 있다. 필자는 주로 릴레이션(교차) 엔터티를 이용하는 방법을 사용한다. 각각의 방법에 대해 알아보자.

1) 릴레이션 엔터티를 이용하는 방법

M:M 관계는 중간에 릴레이션 엔터티를 배치해 각각을 1:M 관계로 설정해 해소할 수 있다. 릴레이션 엔터티는 각 부모(상위) 엔터티와 식별관계로 상속받아 생성된다. 이때 릴레이션 엔터티는 속성이 적고 변경이 적어야 유리하다. 따라서 릴레이션 엔터티에 불필요거나 변경될 가능성이 있는 속성을 넣지 않도록 해야 한다.


[그림 1] M:M 관계 해소: 릴레이션(교차) 엔터티 이용 모델
위 모델을 표로 만들어 보면 [그림 2]와 같다.


[그림 2] 릴레이션 엔터티를 이용한 M:M 관계 해소 모델의 데이터 표
[그림 1]과 [그림 2]를 보면 표기하는 방법만 다를 뿐 같은 말을 하고 있다. 이것을 잘 이해하면 M:M 관계 모델을 잘 처리할 할 수 있다.

2) 식별자로 M:M 관계 해소

이 방법은 부모(상위) 엔터티의 식별자(Unique Identifier)를 자식(하위) 엔터티의 식별자로 상속받아 자식 엔터티 식별자를 ‘잘 설정해주는’ 것이다. 잘 설정한다는 것은 식별자의 정의에 맞게 유일하게 구분할 수 있도록 해주는 것을 말한다.


[그림 3] 식별자로 M:M 관계 해소
식별자로 M:M 관계를 해소하기 위해서는 ‘식재료’의 식별자를 유일하게 만들어 줘야 한다. 일반적으로 부모(상위) 엔터티의 키를 식별관계로 상속받아 해결한다. M:M 관계를 식별자를 변경해 1:M 관계로 바꿈으로써 데이터 모델을 단순화할 수 있고 조인의 복잡도를 줄일 수 있다. 하지만 최근 데이터 추출 방법에 대한 고민이 필요하다.

위 모델을 정리해 보면 [그림 4]와 같다.


[그림 4] 식별자로 M:M 관계 해소 모델 데이터 표
3) 속성으로 M:M 관계 해소

이 방법은 비즈니스적으로 명확한 제약사항이 있을 때 사용할 수 있다. 하지만 유연성이 떨어지는 모델이므로 이런 방법도 있다는 정도만 알고 넘어가자.


[그림 5] 속성을 이용한 M:M 해소 모델
위 모델은 사원은 3번까지만 부서 이동이 가능하다는 전체 아래 속성을 이용해 M:M 관계를 해소한 예다. 이 모델은 유연성이 낮고 조회의 어려움이 있어서 필자는 사용을 지양하는 편이다.

M:M 관계를 해소하는 방법 몇 가지를 알아보았다. 논리모델의 마지막 단계나 논리모델 중 M:M이 자식 엔터티를 갖는 경우에 해소하는 것이 바람직하다. 일반적으로 필자는 논리모델을 하면서 M:M이 나오면 바로 해소하는 편이다.

 

• M:M 관계에 대해 생각해 보기

고객과 상품(보험) 모델로 M:M에 관계에 대해 조금 더 알아보자. 고객이라는 주체와 상품이라는 대상이 만나면, 고객가입계약이라는 행위가 발생한다. 즉 고객이 상품(보험)을 구매(계약)한다가 된다. 이런 대부분의 행위 엔터티는 M:M 형태로 일어난다.


[그림 6] 고객:상품의 M:M 관계
 


[그림 7] 고객:상품의 M:M 관계 해소
[그림 6] M:M 관계를 [그림 7]처음 해소할 수 있다. 여기서 주의 깊게 봐야 할 점은 릴레이션 엔터티는 각 부모 엔터티 식별자를 식별관계로 상속받고 있다는 것이다. 다음으로 부서와 사원에 대해 알아보자.


[그림 8] 부서와 사원 모델
위 모델은 사원이 부서에 소속됐음을 의미한다. 사원이 어떤 부서에 소속돼 있는지 명확하다. 위 모델의 데이터는 [그림 9]와 같다.


[그림 9] 사원 데이터
사원이 부서에 배정되면 사원에 데이터 하나가 생성된다. 부서가 바뀌면 다시 데이터가 하나 생성된다. 이렇게 되면 사원이 현재 어느 부서 소속인지를 알 수 없게 된다([그림 9]의 순서를 데이터 생성 순으로 생각하면 안 된다. 데이터를 조회했을 때 나오는 순서와 데이터 생성 순서는 무관하다).

현 소속 부서를 표현하기 위해 사원 쪽에 데이터 생성 순번을 넣어 해결하는 사례도 봤다. 이 방법은 데이터 생성 순서로 현재의 부서를 알 수 있으나 더 많은 정보, 예를 들어 해당 부서 발령시점 등을 알고 싶다면 또 다른 속성을 추가해야 한다. 이는 사원이라는 엔터티의 성격?정의를 애매하게 한다. 순번을 넣든 안 넣든 위 모델은 정규화 위배가 일어나므로 그리 좋은 방법이 아니다.

위 모델의 문제점은 다음과 같이 모델링함으로써 해결할 수 있다.


[그림 10] 부서와 사원 이력을 고려한 모델
사원과 부서는 각 주체다. 주체와 주체가 만나 행위를 탄생시키는 경우로, 이 경우는이 력성 릴레이션(관계) 엔터티가 된다. 위와 같이 모델링함으로써 사원과 부서의 M:M 관계를 만족하고 이력까지 관리할 수 있다. [그림 5-9] 모델이 틀린 모델은 아니지만 [그림 5-10]과 같이 모델링한다면 확장성과 유연성을 가질 수 있어서 좀 더 좋은 모델이라고 할 수 있다.

 

• 상호 배타적 관계

배타 관계는 두 개 이상의 부모(상위) 엔터티와 관계이면서 그 관계가 상호 배타적일 때의 관계(Mutually Exclusive Arc Relationship)를 말한다. 딱 맞는 예는 아니지만, 아들에게 엄마와 아빠가 동시에 심부름을 시킨다고 하자. 이때 아들은 심부름을 동시에 할 수 없으므로 우선 순위를 둬야 한다.


[그림 11] 배타관계 모델
[그림 11] 모델 ‘상품구매내역’의 한 인스턴스(데이터 한 건)는 ‘개인고객’ 또는 ‘법인고객’과 관계를 갖게 된다. ‘상품구매내역’의 한 데이터가 개인고객과 법인고객 둘 다와 관계를 가질 수 없다.

배타관계가 발생한 엔터티에서는 일반적으로 해당 데이터가 어느 부모(상위) 엔터티와 관계를 갖는지를 보여주는 구분자 속성을 둬 관리한다. 위 모델의 구분자는 고객구분 속성이다. 이 구분자를 기준으로 상품을 구매한 고객(부모?상위)이 누구인지 알 수 있다.

이때 구분자는 널(null)이면 안 된다. 부모(상위)가 누구인지 알기 위해 구분자를 썼는데, 이는 SQL 작성과도 연관된다. ‘상품구매내역’을 기준으로 데이터를 추출할 때, 부모가 누구인지를 모르면 부모 정보를 가져올 수 없기 때문이다. 배타관계는 [그림 11]에서 보듯이 서브타입과 관련돼 있다. 구분자인 고객구분이 서브타입이다.

상호 배타적 관계는 동시에 하나의 부모만 갖는 경우에만 사용해야 한다. 두 개 이상의 엔터티가 상호배타 관계의 부모로 계속 등장하면, 이 엔터티들은 원래 하나의 집합이 적합한 것일 수 있으므로 통합을 고려해야 한다. 그렇다고 상호 배타의 부모를 무조건 통합하는 것은 아니다.

다음 회에는 릴레이션십의 응용에 대해 알아본다. (다음 회에 계속)

 

 

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

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