경영학과에 입학했지만, 컴퓨터에 자신이 없어 배워보려고 들어갔던 컴퓨터 동아리 때문에 인생이 바뀌었다. 대학원에서 정보시스템(IS) 석사 학위를 취득했고, 실무에서는 여러 프로젝트에서 시스템 구축과 데이터베이스 설계 업무를 맡았다. 최근에는 영진출판사에서 ‘솔라리스 서버 바이블’이라는 책을 내기도 했다. 언젠가는 경영학 교수인 아내와 더불어 이론과 실무가 겸비된 정보시스템 개론서를 써보려고 한다.
큰 규모의 개발 프로젝트는 예외 없이 데이터베이스가 핵심적인 부분을 차지하고 있다. 데이터베이스를 설계하고 구축하는 것이 전체 시스템을 구축하는 것과 그다지 차이가 없는 경우도 많다. 그러나 중요성에 비해 데이터베이스 설계를 잘 아는 개발자는 예상 외로 많지 않다. 이 글에서는 데이터베이스 설계에 대한 지식이 없는 독자를 대상으로 데이터베이스 설계의 개념과 전체적인 설계 과정을 설명한다. 이 글을 통해 큰 어려움 없이 이번 호 특집 기사의 내용을 이해하는데 도움이 되기 바란다.
요즘에는 어떤 정보시스템을 만들든지 데이터베이스는 거의 빠지는 법이 없다. 그러나 데이터베이스 설계에 대한 개념이 없이 만들다보니 제대로 된 데이터베이스 시스템을 보기는 생각보다 쉽지 않다. 데이터베이스를 사용한다고 해서 자동으로 데이터 처리의 문제점이 해결되는 것은 아니다. 기존 데이터 처리 방식의 구조를 그대로 데이터베이스에 적용한 경우에는 데이터를 담는 그릇만 바뀌었을 뿐 기존 문제점은 그대로 존재하기 때문이다. 기존 문제점을 데이터베이스로 상당 부분 해결할 수 있지만, 이는 데이터베이스를 적절하게 설계했을 때만 해당되는 얘기이다.
데이터베이스 설계의 기본 철학
기존 데이터 처리 방식의 문제점을 포드 자동차 사례를 통해 알아보자. 1980년대 초 포드의 경영진이 마쯔다 자동차 회사를 방문한 후 엄청난 충격을 받게 된다. 포드에는 북미 지역에만 500명이 넘는 외상매입금 부서의 직원이 있었는데, 마쯔다의 외상매입금 부서에는 단지 5명의 직원만으로 업무를 처리하고 있었기 때문이다. 마쯔다의 효율성에 놀란 포드의 경영진은 자기 회사 외상매입금 부서의 업무처리 전 과정을 면밀히 분석해 보았다. 외상매입금 부서는 주문서 사본, 제품 수령증, 제품 배송장의 세 가지 서류가 일치하면 업무를 진행하는데, 만약 서류 중 일부가 일치하지 않는 경우에는 업무를 중지하고 그 원인을 조사하게 된다. 서류가 일치하지 않는 경우는 그리 많지 않았지만, 원인을 규명하기 위해서 많은 인력이 소요되었다. 사실 포드의 외상매입금 부서의 직원이 많은 것도 이 업무에 상당한 시간을 소비하기 때문이었다. 서류 간의 불일치를 줄이기 위한 최선책은 뭘까? 불일치의 가능성을 사전에 배제하는 것이다. 포드는 데이터베이스를 이용해 데이터간의 불일치를 배제하도록 외상매입금 처리 과정을 개선했고, 그 결과 외상매입금 부서의 생산성을 400% 가까이 향상할 수 있었다.
수작업으로 데이터 처리하기
기존 데이터 처리 방식은 어떤 것이 있을까? 전통적인 방법으로는 수작업으로 데이터를 처리하는 방법을 들 수 있다. 즉, 각 부서마다 장부에 정보를 기록하는 것이다. 부서마다 같은 내용의 문서가 중복해서 존재하기 때문에 자원이 불필요하게 낭비되는 것은 쉽게 알 수 있다. 그러나 그것보다 더 심각한 것은 중복으로 인해 데이터의 일관성이 깨질 수 있다는 것이다. 예를 들어 주문정보가 영업부와 창고 등의 여러 부서에서 보관되고 있는데, 만약 고객이 주문을 변경할 경우 두 부서의 주문 정보를 동시에 변경하지 않는 한 데이터는 일관성을 잃게 된다. 따라서 수작업 방식은 포드의 예처럼 장부 사이에 불일치가 일어날 가능성을 항상 가지고 있게 된다.
컴퓨터를 이용한 파일 처리
또 다른 데이터 처리 방식으로는 컴퓨터를 이용한 파일 처리 방식이 있다. 파일 처리 방식은 데이터가 파일에 저장되었기 때문에 붙여진 이름이다. 예를 들어 영업부에서는 고객 데이터 파일, 주문 데이터 파일에 정보를 저장하는 주문처리 프로그램을 만들어 활용하고, 창고에서는 고객 데이터 파일, 배송 데이터 파일에 정보를 저장하는 배송처리 프로그램을 만들어 활용하는 식이다. 파일 처리 방식은 수작업 방식을 자동화한 것에 불과할 뿐이지 근본적으로 그 구조를 바꾼 것은 아니기 때문에 수작업 방식에서 존재했던 데이터의 중복은 여전히 남아 있다. 예를 들어 영업부에서 사용하는 고객 데이터 파일과 창고에서 사용하는 고객 데이터 파일이 중복되어 있기 때문에 데이터를 중복 입력하느라 인력을 낭비하는 것은 물론, 같은 데이터가 여러 곳에 독립적으로 보관됨으로써 데이터의 불일치 문제가 발생해 더욱 심각한 문제로 대두되었다. 물론 이런 파일 처리 방식의 문제점은 사용자의 노력으로 줄여 나갈 수 있다. 하지만 더 바람직한 방법은 처음부터 이런 문제점이 발생하지 않는 환경을 만드는 것이다. 오류 가능성을 사전에 배제하는 것, 그것이 바로 데이터베이스의 기본 철학이다.
데이터베이스를 데이터베이스답게 설계하기 위한 지침
데이터 중복을 최소화하라
데이트(Date) 같은 학자는 데이터베이스의 특징으로 통합과 공유를 들었다. 풀어서 얘기하면 데이터베이스란 모름지기 서로 관련 있는 데이터를 최소한의 중복으로 통합해서 여러 사용자가 사용할 수 있도록 해야 한다는 뜻이고, 데이터를 덕지덕지 중복해서 만들어 놓은 것은 데이터베이스라고 하기 힘들다는 뜻이기도 하다.
일반적으로는 데이터 항목의 각 값이 데이터베이스에 중복 없이 한번만 기록될 때 데이터의 일관성을 유지되는데, 이처럼 중복 없이 데이터를 한번만 기록하기 위한 데이터베이스의 설계 이론을 정규화(normalization)라고 한다.
경우에 따라서는 처리 속도의 향상을 위해서 특정 데이터 항목의 값을 중복해서 기록할 수 있지만, 예외적인 경우이다. 이런 경우에도 데이터베이스 시스템이 데이터의 중복을 통제하도록 설계해야 한다. 예를 들어 고객의 주소를 부득이하게 두 군데 기록했다면, 그중 하나의 주소가 변경되면 다른 주소도 자동으로 변경되게끔 만들어야 한다는 것이다. 데이터의 중복이 있더라도 미리 계획된 것이고, 일관성을 유지할 수 있는 대책이 마련되어 있다면 이를 ‘통제된 중복’이라고 부른다. 그러나 불가피한 경우를 제외하고는 중복을 만들어 통제하기보다 아예 중복이 없게끔 만드는 것이 데이터베이스 설계의 철학임을 다시 강조한다.
데이터 정의를 표준화하라
파일 처리 방식에 비해 데이터베이스는 데이터가 한 곳에 저장되기 때문에 데이터 항목의 정의, 명칭, 형태 등의 표준화를 하기가 쉽다. 따라서 데이터베이스가 가진 장점을 잘 살리려면 같은 용어를 다른 뜻으로 사용하거나, 다른 용어를 같은 뜻으로 사용하는데서 오는 개발상의 혼란을 사전에 방지하기 위해 용어사전 등을 이용해 데이터 정의를 표준화해야 한다.
예를 들어, 주문일 속성을 어떤 곳에서는 order_date, 다른 곳에서는 order_day, 또 다른 곳에서는 ordered_date, 혹은 OrderDate처럼 여러 이름으로 나타낸다면 주문일 속성을 이용할 때마다 여기서는 어떤 이름을 사용해야 하는지 고민하거나 설계도를 그때마다 참조해야 한다. 더 좋지 않은 경우는 다른 의미를 가진 속성을 동일한 이름으로 지정하는 경우인데, 이 속성이 자주 사용하는 속성인 경우엔 피해가 막심하다. 숱한 버그 발생으로 개발 기간이 엿가락 늘어지듯 늘어나 버린다. 이렇게 데이터베이스를 만드는 경우엔 제대로 데이터베이스를 설계했다고 볼 수 없다.
데이터 무결성을 위한 기능을 최대한 활용하라
파일 처리 방식에서는 사용자마다 다른 파일을 가지고 있기 때문에 한 파일에 부정확한 데이터가 있더라도 그 파일을 이용하는 사용자에게만 국한된 피해로 끝날 수 있지만, 데이터베이스는 모든 사용자가 동일한 데이터를 사용하기 때문에 일단 잘못된 데이터가 저장된다면 심각한 피해가 발생한다. 따라서 입력 데이터에 대한 철저한 오류 검사를 하도록 데이터베이스를 설계해야 한다. 데이터가 오류가 없는 상태를 데이터 무결성이라고 하는데, 데이터베이스에는 데이터 무결성을 위해 여러 제약을 가할 수 있는 기능이 있다.
예전에는 클라이언트 프로그램으로만 입력이 가능했기 때문에 데이터의 오류를 프로그램에서만 검증해도 어느 정도는 데이터의 무결성이 보장되었다. 하지만 이제는 최종 사용자가 엑셀 등을 사용해서 데이터베이스에 임의로 접근하는 것도 가능하게 되었기 때문에 어떤 프로그램을 사용해서 데이터에 접근하든지간에 비정상적인 데이터는 입력이 되지 않게끔 막아야 할 필요성이 생겼다. 따라서 프로그램에서 데이터의 무결성을 지키기보다는 데이터베이스에서 데이터의 무결성을 지키도록 노력해야 한다.
데이터베이스 설계의 핵심 개념
관계형 데이터베이스
데이터베이스에 저장할 개체와 그 관계를 요약한 것을 데이터 모델이라고 하는데, 계층형(구조적, hierarchical) 데이터 모델, 그물형(네트워크, network) 데이터 모델, 관계형 데이터 모델, 객체 데이터 모델 등이 있다. 현재 업계에서 가장 널리 채택되고 있는 것은 관계형 데이터 모델이다. 관계형 데이터 모델을 채택하고 있는 관계형 데이터베이스는 오라클, 인포믹스, 사이베이스, MS SQL 서버 등 여러분이 들어본 대부분의 데이터베이스가 해당된다. 관계형 데이터 모델의 대표적인 특징으로는 각 행(튜플, tuple)을 유일하게 구분할 수 있는 열(속성, attribute)이 있다는 것이다. 이를테면 회원 테이블은 각 회원을 유일하게 구분할 수 있는 ID 속성을 가지는데, 이런 속성을 주 키(primary key)라고 한다. 또 다른 특징으로는 테이블의 각 셀의 값은 반드시 단일 값이어야 한다는 게 있다. 예를 들어, 어떤 책을 ‘홍길동’과 ‘임꺽정’이라는 저자가 공동으로 썼을 경우 한 셀에 ‘홍길동, 임꺽정’처럼 두 개의 값을 저장하면 안 된다는 것이다. 만약 두 개의 값을 저장하고 싶다면 다음에서 설명할 정규화 과정을 통해 단일 값을 갖는 셀로 바꿔줘야 한다.
제약
모든 데이터 모델은 본질적 제약, 내재적 제약, 명시적 제약을 가진다. 본질적 제약은 데이터 모델의 구조적인 특성으로 인한 제약을 말한다. 그러므로 정의에 따라 반드시 주 키가 있어야 하고 테이블의 각 셀이 단일 값을 갖는다는 관계형 데이터 모델의 특징이 바로 본질적 제약이 된다. 관계형 데이터 모델은 다른 데이터 모델에 비해 비교적 적은 본질적 제약을 가진다. 본질적 제약이 적다는 것은 데이터베이스를 자유롭게 설계할 수 있지만, 그 대신 데이터의 무결성을 유지하고 관계성의 의미를 정확히 표현하기 위해 많은 노력을 하지 않으면 데이터베이스가 엉망이 된다는 의미이기도 하다.
내재적 제약은 데이터의 의미를 정확히 표현하고 오류를 방지하기 위해 데이터베이스에 지정하는 제약이다. 관계형 데이터베이스의 주요 제약으로 영역 제약과 참조 무결성 제약이 있다. 영역 제약은 허용되는 데이터 값에 대한 제약이다. 예를 들어, 고객의 마일리지가 규정상 0 이하로 내려갈 수 없다면, 0 이상의 정수만 입력될 수 있도록 영역 제약을 사용하는 것이다. 참조 무결성 제약은 어떤 데이터에 의해 참조되는 데이터는 항상 존재해야 한다는 제약이다. 예를 들어 주문 테이블에 주문을 한 고객번호가 남아 있는데 정작 고객 테이블에는 그 고객 번호에 해당하는 고객이 없는 경우를 참조 무결성이 깨졌다고 하는데, 참조 키(외부 키, foreign key)를 설정해서 참조 무결성을 보장할 수 있다.
개발자의 생산성이나 데이터 입력 오류의 가능성을 고려할 때 데이터 무결성은 내재적 제약으로 지키는 것이 가장 바람직하다. 그러나 어떤 데이터 모델도 현실 세계의 모든 제약을 데이터베이스에 내재하는 것은 불가능하다. 이런 제약은 프로그램에서 처리하거나 사용자의 수작업에 의지할 수밖에 없는데 이런 제약을 명시적 제약이라고 한다. 명시적 제약으로 처리해야하는 복잡한 무결성도 프로시저나 트리거 등 서버에서 처리할 수 있는 방법을 동원하는 것이 좋다. 이렇게 되면 업무 규칙이 바뀐다고 해도 데이터베이스 한군데에서만 바꿔주면 되기 때문에 클라이언트 프로그램 모두를 바꿔주는 것보다 훨씬 간편하다. 물론 그렇게 하면 데이터베이스의 부담이 가중되어 전체적인 성능이 나빠지는 경우가 생길 수 있다. 그런 경우에도 프로그램에서 무결성을 보장하는 것이 아니라 애플리케이션 서버에서 무결성을 보장하는 3티어(tier) 구조로 가는 것이 바른 길이다.
정규화
정규화는 데이터베이스에 저장되는 데이터의 중복을 최소화시키는 방법이다. 정규화는 1차, 2차, 3차, 보이스-코드, 4차, 5차, 영역-키 정규화가 있는데, 실무에서는 보통 3차 정규화 또는 보이스-코드 정규화 정도까지 하기를 권장하고 있다.
1차 정규화
1차 정규화는 테이블의 각 셀은 단일 값을 갖는다는 관계형 데이터모델의 본질적 제약과 관련된 개념이다. <표 1>에서 제품번호, 단가, 수량의 속성값은 한 셀에 여러 값이 들어가 있기 때문에 관계형 데이터의 본질적 제약을 위배한 것이다.
주문번호 | 주문일 | 고객번호 | 고객이름 | 제품번호 | 단가 | 수량 |
0001 | 2003.7.15 | c1 | 홍길동 | p01 P02 |
350 100 |
1 3 |
0002 | 20037.16 | c2 | 임꺽정 | p01 | 350 | 4 |
00003 | 2003.7.17 | c1 | 홍길동 | p03 | 400 | 5 |
<표 1> 정규화되지 않은 테이블
주문번호 밑에 주키를 나타내는 밑줄을 꼭 그어주세요 1차 정규화를 하기 위해서는 <표 2>처럼 한 셀에 하나의 데이터만을 나타내야 한다. 이렇게 1차 정규화가 된 상태에서는 주문번호 속성이 더 이상 유일한 값을 갖지 못하므로 주문번호와 제품번호를 연결한 합성키가 1차 정규화 상태의 새로운 주 키가 된다.
주문번호 | 주문일 | 고객번호 | 고객이름 | 제품번호 | 단가 | 수량 |
0001 | 2003.7.15 | c1 | 홍길동 | p01 | 350 | 1 |
0001 | 2003.7.15 | c1 | 홍길동 | P02 | 100 | 3 |
0002 | 20037.16 | c2 | 임꺽정 | p01 | 350 | 4 |
00003 | 2003.7.17 | c1 | 홍길동 | p03 | 400 | 5 |
<표 2> 1차 정규화가 끝난 테이블
주문번호와 제품번호 밑에 주키를 나타내는 밑줄을 꼭 그어주세요
2차 정규화
2차 정규화 단계부터는 데이터의 중복을 제거하게 된다. <표 2>에서 중복된 데이터를 찾아보자. 제품번호 ‘p01’의 단가가 350이라는 정보가 두 번 중복되어 나타나고 있음을 볼 수 있다. 단가는 제품번호 속성에 종속되어 있기 때문에 제품번호가 정해지면 그 제품의 단가가 정해진다. 따라서, <표 3>처럼 종속관계에 있는 제품번호와 단가 속성을 별도의 [제품] 테이블로 분리하고, 원래의 테이블에는 제품번호 속성만 남겨두면 제품번호 ‘p01’의 단가인 350이라는 정보가 두 번 중복되는 것을 피할 수 있다.
또 다른 중복 정보는 없을까? 주문번호 ‘00001’에 종속되는 주문일, 고객번호, 고객이름이 두 번 중복해서 나타나고 있다. 마찬가지 방법으로 <표 3>처럼 주문번호와 주문일, 고객번호, 고객이름을 별도의 [주문-고객] 테이블로 분리하고, 원래의 테이블에는 주문번호 속성만 남겨두면 특정 주문번호에 대한 주문일, 고객번호, 고객이름 데이터가 두 번씩 중복되는 것을 피할 수 있다.
이 외에도 중복을 제거할 수 있는 부분이 있다. <표 3>의 [주문-고객] 테이블을 보면 고객번호 ‘c1’의 이름이 ‘홍길동’이라는 정보가 두 번 중복해서 나타나고 있다. 그러나 이것은 3차 정규화에서 처리할 부분이다. 2차 정규화는 주 키의 일부분, 즉 주문번호와 제품번호에 종속된 것만을 대상으로 하는데, 고객번호나 고객이름은 주 키를 구성하는 속성이 아니기 때문이다.
주 키의 일부분에만 종속된 상태를 부분 종속이라고 하는데, 부분 종속을 갖는 속성을 별도의 테이블로 분리한 <표 3>의 상태가 2차 정규화이다. 따라서 1차 정규화된 상태의 주 키가 하나의 속성뿐이라면 2차 정규화는 건너뛰고 바로 3차 정규화를 하면 된다. 그러나 <표 2>
처럼 1차 정규화된 상태의 주 키가 둘 이상의 속성을 가지고 있을 경우에는 2차 정규화 작업이 필요하다.
제품
제품번호 | 단가 |
p01 | 350 |
p02 | 100 |
p03 | 400 |
<표 3> 2차 정규화가 끝난 테이블
주문-제품
주문번호 | 제품번호 | 수량 |
00001 | p01 | 1 |
00001 | p02 | 3 |
00002 | p01 | 4 |
00002 | p03 | 5 |
주문-고객
주문번호 | 주문일 | 고객번호 | 고객이름 |
00001 | 2003.7.15 | c1 | 홍길동 |
00002 | 2003.7.16 | c2 | 임꺽정 |
00003 | 2003.7.17 | c1 | 홍길동 |
3차 정규화
2차 정규화가 주 키 속성과 주 키가 아닌 속성간의 종속관계가 있을 경우 이를 별도의 테이블로 분리한 것이라면 3차 정규화는 2차 정규화가 끝난 상태에서 주 키가 아닌 속성끼리 종속관계가 있을 경우 이를 별도의 테이블로 분리한 것이다. <표 3>은 2차 정규화가 끝난 상태이기 때문에 주 키가 아닌 속성끼리 중복되는 정보가 있는지를 살펴보면 된다. 앞에서 얘기한대로 <표 3>의 [주문-고객] 테이블을 보면 고객번호 ‘c1’의 이름이 ‘홍길동’이라는 정보가 두 번 중복해서 나타나고 있다. 2차 정규화와 마찬가지 방법으로 고객번호와 고객이름을 별도의 [고객] 테이블로 분리하고 원래의 [주문-고객] 테이블에는 고객번호 속성만 남겨두면 3차 정규화가 완성된다.<표 4>는 3차 정규화까지 끝난 상태의 최종 테이블이다.
제품번호 | 단가 |
p01 | 350 |
p02 | 100 |
p03 | 400 |
<표 4> 3차 정규화가 끝난 테이블
주문-제품
주문번호 | 제품번호 | 수량 |
00001 | p01 | 1 |
00001 | p02 | 3 |
00002 | p01 | 4 |
00002 | p03 | 5 |
주문-고객
주문번호 | 주문일 | 고객번호 |
00001 | 2003.7.15 | c1 |
00002 | 2003.7.16 | c2 |
고객
고객번호 | 고객이름 |
c1 | 홍길동 |
c2 | 임꺽정 |
보이스-코드 정규화
3차 정규화가 끝난 상태에서도 여러 개의 후보 키(주 키가 될 수 있는 속성)가 존재하는 경우에는 속성간의 종속이 남아있을 수 있다. 이를 제거한 것이 보이스-코드 정규화이다. <표 4>에서는 후보 키가 여러 개 있는 테이블이 없으므로 보이스-코드 정규화를 추가적으로 할 필요가 없다.
데이터베이스 설계 과정
PC를 이용해 한두 명의 사용자가 이용하는 간단한 데이터베이스를 만드는 작업은 구체적인 방법론 없이도 할 수 있다. 그러나 분당 수천, 수만 건의 온라인 거래를 처리하는 데이터베이스의 구축은 간단한 작업이 아니다. 이런 대규모 데이터베이스의 구축은 방법론에서 제시하는 과정을 거쳐야 한다. 데이터베이스 설계 방법론에 따라 세부적인 과정은 조금씩 달라지지만, 어떤 방법론이든 전체적으로는 대략 다음과 같은 과정을 거치게 된다.
데이터베이스 요구사항 파악 및 해당 업무 분석
데이터베이스 설계를 하려면 우선 요구사항을 먼저 파악해야 한다. 요구사항에는 사용자가 필요로 하는 정보와 출력물 외에도 처리속도나 보안의 정도 등도 포함된다. 이 과정에서 해당 업무를 분석해서 데이터베이스와 관련된 사용자를 파악하고, 각 개체와 개체간의 관계도 파악하고, 업무처리 규칙 등도 도출하게 된다. 이와 같은 사항을 파악하기 위해서 될 수 있으면 많은 자료를 수집하는 것이 좋다. 조직도표, 업무기술서, 각종 보고서, 입출력 양식, 시스템 화면 등은 좋은 자료가 된다.
논리적 설계
요구사항 분석이 끝나면 논리 데이터베이스를 설계하게 된다. 논리적 설계는 실제 데이터베이스 관리시스템(DBMS)에 최적화된 설계를 하는 단계가 아니므로 컬럼(필드) 길이나 데이터 타입 같은 상세한 사항까지 설계하지 않아도 무방하다. 데이터베이스의 설계도 격인 개체-관계 다이어그램(E-R 다이어그램)을 손으로 그리는 것도 가능하지만 한정된 시간 안에 충실한 설계를 하기 위해 이 단계에서부터 데이터베이스 설계를 위한 케이스툴(Case Tool)을 사용하는 게 보통이다.
개체 지정
논리적 설계의 첫 번째 단계는 요구사항 분석 단계에서 수집한 자료를 가지고 개체를 정하는 것이다. 업무에서 관리되고, 일정한 자신만의 속성을 여러 개 가진 집합적인 성격의 것을 개체(정확하게 말하면 개체집합)로 고르면 된다. 이 때 개체와 개체의 속성을 혼동하지 말아야 한다. 이를테면 주민등록번호는 회원이라는 개체의 속성이기 때문에 주민등록번호를 개체로 정하면 안 된다. 나중에 물리적 설계 단계에서 개체는 테이블로, 개체의 속성은 칼럼으로 변환한다.
관계 지정
개체 지정이 끝나면 각 개체간에 어떤 관계가 있는 지를 지정한다. 관계를 그림으로 나타내는 방법에는 여러 가지가 있는데, 그 중 정보공학방법론(Information Engineering Methodology)에서 주장하는 방법을 위주로 설명을 하겠다. 관계는 업무기술서나 기타 자료에서 정확하게 표현되지 않는 경우가 많으므로 내용을 보고 관계를 유추해서 작업하는 경우가 대부분이다. 예를 들어 회원과 주문간의 관계를 유추한 내용이 다음과 같다고 하자.
◆ 각 회원은 여러 개의 주문을 신청할 수 있다. 물론, 한번도 주문하지 않은 회원도 있을 수 있고, 한번만 주문한 회원도 있을 수 있다.
◆ 각 주문은 그 주문을 신청한 회원이 반드시 한명 있다.
이 관계를 E-R 다이어그램으로 나타내면 <화면 1>과 같다.
주문과 회원의 관계
회원 한명의 입장에서 볼 때 주문을 한번도 하지 않을 수 있고(?), 한번만 주문할 수도 있고(?), 여러 번 주문할 수도 있다(>)는 것이다. 보통 이런 경우를 1대다 (엄밀하게는 1대 0, 1, 다) 관계라고 말하곤 한다. 반대로 하나의 주문 입장에서 볼 때, 그 주문을 한 회원은 반드시 한명만 있어야 한다(?)는 뜻이다. ?이나 < 표시가 없으므로 주문한 회원이 없어서도 안 되고, 주문한 회원이 둘 이상일 수도 없다. 다른 개체들간의 관계도 그려보면 <화면 2>와 같다. 거의 대부분의 관계는 1대다 관계이다.
다른 개체들간의 관계
개체간의 관계를 가지고 <화면 2>처럼 나타낼 수도 있어야 하지만, 반대로 <화면 2>를 보고 개체간의 관계를 해석할 수도 있어야 한다. 예를 들어, 상품과 장바구니의 관계를 해석하자면 다음과 같다.
◆ 하나의 상품은 여러 장바구니에 담길 수도 있고(∧), 하나의 장바구니에만 담길 수도 있고(?), 장바구니에 전혀 안 담길 수도 있다(?).
◆ 하나의 장바구니는 반드시 하나의 상품만을 담아야 한다(?).
관계를 설정했을 때 1대다 관계가 아닌 것이 생길 수도 있다. 예를 들어 한 학생이 여러 강의를 수강할 수 있고, 한 강의는 여러 수강생을 등록받을 수 있다는 업무규칙을 표현하면 <화면 3>과 같이 다대다 관계가 된다.
다대다 관계의 예
이런 다대다 관계는 두 개체의 주 키를 합친 것을 주 키로 하는 개체를 새로 만들어 1대다 관계로 변환해준다. 예를 들어 <화면 3>은 <화면 4>와 같이 변환해주면 된다.
다대다 관계를 해소한 E-R 다이어그램
어떤 경우에는 1대1 관계가 생길 수도 있다. 1대1 관계가 있을 때는 두 개체를 하나의 개체로 통합할 수 없는지 생각해본다. 두 개체를 하나로 합쳐도 무리가 없다고 판단되면 하나의 개체로 통합을 한다.
주 키 지정
관계를 설정한 다음에는 각 개체의 속성 중에서 주 키를 지정한다. 주 키는 <화면 5>의 장바구니에서처럼 여러 속성이 모여서 이루어질 수도 있다. 주 키가 없는 경우에는 자동증가 컬럼 등을 만들어서 주 키로 지정한다. 주 키가 있더라도 너무 많은 속성이 모여서 이루어진 경우에는 자동증가 컬럼 등을 만들어서 주 키로 지정하고, 원래의 주 키는 후보키로 활용하는 것이 좋다.
주 키를 지정한 E-R 다이어그램
이 단계에서부터는 용어사전을 만들어서 활용해야 한다. 용어사전은 (주 키/후보 키를 포함한) 모든 속성의 이름, 그 속성의 물리 이름(물리적 설계 때 사용할 컬럼 이름), 용어의 뜻을 정리해놓은 것이다. 한사람이 데이터베이스 설계를 한다면 용어사전을 생략할 수도 있겠지만, 여러 명이 데이터베이스 설계를 할 때는 반드시 용어사전을 만들어서 활용해야 한다. 어떤 속성의 이름을 지정할 필요가 있을 때는 먼저 용어사전을 뒤져보고, 그 속성의 뜻에 해당하는 이름이 사전에 있다면 그 이름을 사용한다. 만약 용어사전에 그 뜻에 해당하는 이름이 없다면 용어사전에 그 뜻에 해당하는 속성의 이름 등을 추가해준다.
속성 지정
주 키/후보 키 지정이 끝나면 나머지 속성을 지정한다. 업무에 필요한 속성이 빠진 게 없는지 꼼꼼히 따져봐야 한다. 이 때, 업무에 필요 없는 속성을 마구잡이로 추가하지 않도록 주의한다.
정규화
각 개체에서 정규화할 것은 없는지 확인한다. 정규화에 대해서는 앞에서 설명했으므로 여기에서는 설명을 생략한다.
개체의 통합
하나의 테이블에는 데이터를 추가, 삭제, 조회, 수정하는 4개의 프로그램이 필요하다. 따라서, 개체의 수가 많아지면 많아질수록 개발해야 하는 프로그램의 양도 많아진다. 그리고 많은 테이블을 머리 속에 담고 작업하기에는 인지적인 무리가 따르므로 하나로 통합할 수 있는 개체는 통합해서 개수를 줄이는 것이 좋다. 통합의 고려 대상이 되는 개체는 1대1 관계에 있는 개체와, 서로간에 비슷한 속성을 가진 개체이다. 예를 들어, 비슷비슷한 게시판 개체가 여러 개인 경우, 주제별로 개체를 따로 만들 것이 아니라 게시판이라는 하나의 개체로 모두 통합하는 것이 바람직하다.
여기서 주의할 점은 개체 수를 줄이는 것이 모든 것에 우선하는 가치는 아니라는 점이다. 정규화 과정을 거치게 되면 개체 수가 늘어나게 되는데 개체 수가 늘어나는 게 두려워 정규화를 하지 않는다는 것은 웃기는 일이다. 나눠야 하는 것은 반드시 나누되, 굳이 나눌 필요가 없는 것은 하나로 통합하라는 의미이다.
물리적 설계
논리적 설계가 마무리되면 특정 DBMS에 맞춰 물리적 설계를 진행한다. 따라서 물리적 설계를 진행하기 이전에 DBMS가 결정되어 있어야 한다. 물리적 설계에서 해야 할 일은 테이블과 컬럼의 이름을 지정하고 각 컬럼의 데이터 타입 등을 지정하는 일이다. 이외에도 트랜잭션 분석, 뷰 설계, 인덱스 설계, 용량 설계, 보안 설계와 같은 중요한 과정이 포함된다. 물리적 설계를 어떻게 하느냐에 따라 데이터베이스의 성능에 많은 차이가 발생하므로 논리적 설계 못지않게 중요한 과정이다.
테이블과 컬럼 이름 지정
케이스툴을 사용하면 손쉽게 논리 데이터베이스를 특정 DBMS에 맞게 변환해준다. 다만, 이 과정에서 한글로 된 개체 이름과 속성 이름이 변경 없이 그대로 테이블과 컬럼에 사용되는데, 이를 영문으로 바꿔주는 작업은 직접 해야 한다. 여러 가지 이유 때문에 실제 테이블이나 컬럼 이름에는 영문이나 숫자만 써주는 것이 좋다. 숫자가 제일 앞에 오거나, 공백이 이름 중간에 오는 경우도 문제를 발생시킬 소지가 있으므로 피하는 게 좋다. 테이블이나 컬럼 이름을 지정할 때도 꼭 용어사전을 사용해서 중구난방으로 이름이 붙여지지 않게 주의해야 한다.
각 컬럼의 데이터 타입 및 제약 지정
테이블과 컬럼의 이름을 적절하게 변환했다면 각 컬럼의 데이터 타입과 길이, 초기 값, 데이터 무결성을 위한 제약 등을 지정한다.
트랜잭션 분석
데이터베이스에 무슨 트랜잭션이 어느 정도 발생하는지를 분석하고 그에 따라 트랜잭션 처리 방법을 결정한다.
뷰 설계
다양한 사용자 관점에서 데이터를 보여주기 위해서, 혹은 보안상의 문제를 고려하여 뷰를 설계한다.
인덱스 설정
개발 단계에서는 데이터의 양이 그리 많지 않기 때문에 인덱스가 없어도 속도 문제가 나타나는 경우가 별로 없다. 그러나 실제 서비스에 들어가서 많은 사용자가 시스템을 이용하기 시작하면 필연적으로 속도 문제가 불거지게 되므로 데이터베이스를 만들 때부터 인덱스를 신경써야 한다. 특히 참조키에 인덱스 설정을 하지 않는 경우가 종종 있는데, 참조키에는 무조건 인덱스를 설정하기 바란다. 이 외에도 인덱스를 설정하는 데 참고할만한 많은 가이드라인이 있으므로 꼭 관련 서적을 찾아보기 바란다.
용량 설계
데이터의 입출력 양과 저장해야 할 데이터의 양을 예측하고 이에 맞는 하드웨어를 선택한다. 그리고, 데이터의 입출력 성능을 향상시킬 수 있도록 하드디스크를 적절히 분리해서 설계한다.
대략적으로 물리적 설계에서 진행되는 과정은 이와 같다. 이외에도 각종 튜닝 과정이 추가되는데, 물리적 설계 단계의 몇몇 과정, 즉 뷰, 인덱스, 용량 설계 등과 더불어 튜닝과정은 설계할 때 한번으로 끝나는 작업이 아니라, 개발 중이나 개발 후에도 반복적으로 모니터링하면서 진행해야 하는 작업들이다.
어떻게 공부할 것인가?
시스템 구축이라고 부를만한 큰 규모의 개발 프로젝트에서는 데이터베이스가 핵심적인 부분을 차지하고 있다. 그 중에서도 데이터베이스 설계는 핵심 중의 핵심이다. 그 증거로 데이터베이스 모델러가 전체적인 IT 시스템 컨설팅을 담당하는 사례가 빈번하다는 것만 들어도 충분할 것이다. 데이터베이스 설계가 그만큼 중추적인 역할을 하기 때문에 실제 프로젝트에서는 데이터베이스만이 아니라 전체 프로젝트를 분석하고 이끌어갈 수 있는 데이터베이스 모델러를 요구한다.
초보자가 데이터베이스 모델러가 되고자 한다면 우선 논리적 설계에 대한 이론을 공부해야 한다. 논리적 설계에 대한 이론이 기본이 된 후에 자신의 해당 업무부터 분석하고 설계하는 작업을 수행해보자. 초보자가 흔히 빠지기 쉬운 함정은 업무를 파악하기도 전에 바로 데이터베이스를 설계하는 것인데, 성공적인 설계를 하기 위해서는 해당 업무에 관한 한 현업 담당자보다 더 많은 업무 지식을 가지고 있다고 자신할 정도가 되어야 한다. 이렇게 파악한 업무 지식을 바탕으로 논리적 설계를 충분히 해보기 바란다. 물리적 설계 공부는 논리적 설계 경험을 충분히 쌓아서 자신이 붙었을 때 시작해도 늦지 않다. 물리적 설계는 구체적인 DBMS와 관련이 있기 때문에 실제로 테스트하면서 튜닝해보는 노력이 필요하다.
이것으로 충분한가? 아니다. 한정된 시간 안에서 충분한 설계를 하기 위해서는 설계의 질도 중요하지만 설계의 생산성도 결코 무시할 수 없다. 케이스툴과 오피스 프로그램을 공부해서 각종 설계 산출물을 설계가 끝남과 동시에 자동으로 생성할 수 있도록 해야 한다. 시간이 없어서 문서화를 하지 못한다거나, 수작업으로 문서화를 하려다 충분한 설계를 못한다면 데이터베이스 모델러로서의 자질 미달이다.
데이터베이스 설계는 전체 프로젝트와 밀접한 관련이 있기 때문에 다른 사람의 업무에 관여를 하지 않을 수 없다.
그러다보면 직간접적으로 전체 프로젝트 진행에 대한 지식을 쌓기에도 좋다. 따라서 옵션사항이긴 하지만, 정보공학방법론이나 객체지향방법론 같은 프로젝트 방법론에 대해서도 공부할 수 있다면 금상첨화겠다. 아무쪼록 이번 특집을 접하는 독자들이 열심히 노력해서 데이터베이스 설계와 더불어 전체 프로젝트까지 아우르는 전문가가 되었으면 한다.
참고 자료
◆ Robert Orfali, Dan Harkey, Jeri Edwards :
'Client/Server Survival Guide', 3rd edition, John Wiley & Sons
◆ 서길수 : '데이터베이스 관리', 제 2판, 박영사
◆ 이춘식 : '데이터베이스 설계와 구축', 한빛미디어
'Carpe Programming > oracle' 카테고리의 다른 글
vo 생성용 조회 쿼리 (0) | 2011.07.26 |
---|---|
필드명 테이블 명으로 테이블 조회 (0) | 2009.10.26 |
오라클 row 순서 관리 RANK() , ROW_NUMBER() (0) | 2009.10.20 |
insert와 update를 한꺼번에 처리 (0) | 2009.10.20 |
오라클 lag() lead() 함수 (0) | 2009.10.20 |