1) 데이터의 중복을 방지, 효율적인 데이터 저장
-> 논리적으로 작은 단위의 테이블로 분리되어진다.
2) 1차, 2차, 3차, 4차, 5차 정규화까지 있지만,
일반적으로 3차까지만 정규화를 해서 사용한다. 이게 현실적이므로.
- 데이터의 중복을 방지, 효율적인 데이터 저장
-> 논리적으로 작은 단위의 테이블로 분리되어진다.
제 1 정규화
- 반복되는 속성이나 그룹 속성을 제거하고 새로운 실체를 추가한뒤 기존의
실제와 1:N의 관계를 형성한다.
제2 정규화
- 복합키로 구성된 경우 해당 테이블 안의 모든 컬럼들은 복합키 전체에
의존적이어야한다.
만일 복합키 일부에 의존적인 컬럼이 존재한다면 제거해야한다.
복합키가 아닌 경우 제 2 정규화의 대상이 되지 않는다.
N:M 관계
학생 | - 동아리등록 |- 동아리
-학번 | ~ 동아리코드(FK), 학번(FK) | - 동아리 코드
이름, | 등록일자 | 동아리명
주민번호,| 등록사유 | 설립취지
전화번호,| | 설립일자
.....
제3 정규화
- 한테이블 안의 모든 키가 아닌 컬럼들은 기본키(Primary Key)에 의존해야한다.
만일 키가 아닌 컬럼에 종속되는 속성이 존재한다면 이를 제거해야한다.
* 정규화는 순서적으로 하는것이 절대 아니다
1차 정규화에 위배할 경우 정규화함
2차 정규화를 위배하지 않을 경우 할 필요가 없다.
보이스/코드
정규화
3차 정규화도 여러가지 이상이 존재합니다. 그렇다면 이상이 발생하지
않는 정규화 과정은 어떤거냐고 의문을 가지는 분도 있을 겁니다. 이상이 발생하지 않는 정규화는 키/도메인 정규화입니다. 이것은 증명은 되었으나, 키/도메인 정규화 테이블을 만드는 구체적인 방법을 발견하지 못했기
때문에 실무에서 직관적으로 사용되는 방법이기도 합니다. 그러나 보통 실무에서는 3차 정규화과정이나
다음에 할 보이스/코드 정규화까지 합니다. 그 이유는 일반적으로 4차 정규화나 5차 정규화 과정을 거쳐야 하는 상황은 거의 발생하지
않기 때문입니다. 이 책에서는 보이스/코드 정규화 과정까지만
언급하겠습니다. 만약 보이스/코드 정규화 과정을 거쳤으나
사용자가 원하는 작업을 수행할 때 이상이 발생한다면 4차 정규화 과정을 거쳐야 할 것입니다. 4차, 5차 정규화는 다른 책을 참고하셔야 할 것입니다.
이제 위의 3차
정규화를 거친 테이블에 대한 이상현상이 발생하는 원인을 분석하고 보이스/코드 정규화에 대해서 언급하도록
하겠습니다.
3차 정규화 과정을 거치 테이블에서 이상현상을 발생시키는 원인은 후보키들이 중첩되어 있다는 것 때문입니다. 후보키는 기본키가 될 수 있는 자격이 있는 속성 또는 속성들입니다. 즉, 하나의 릴레이션에 여러 개의 후보키가 존재하는데 하나 또는 여러 개의 속성이 중첩되어서 후보키될 때 이상현상이
발생할 수 있다는 것입니다. 보이스/코드 정규화 과정은 바로
이러한 문제점을 해결하는 것입니다. 이러한 의미에서 볼 때 보이스/코드
보이스/코드
<박스>
-. 하나의 과목을 여러 교수가 담당할 수 있다.
-. 각 교수는 하나의 과목만을 담당한다.
-. 각각의 학생은 같은 과목명을 가진 다른 과목을 수강하지 못한다.
</박스>
<그림 4_84.jpg>
앞서서 언급한 3차
정규화의 문제점인 후보키의 일부가 되는 속성인 “학번”이
중첩되어 있는 것이 보입니다. 즉, 수강_교수 릴레이션의 후보키는 “학번 +
과목명” , “학번 + 담당교수” 입니다. 이 후보키중 “학번 + 과목명”을 기본키라고 가정하겠습니다. 함수 종속 다이어그램에서 보는 바와 같이 “학번 + 과목명”은 “담당교수”를 결정하고, “담당교수”는
“과목명”을 결정합니다. 이런
구조를 가지고 있는 릴레이션의 문제점을 파악해 보도록 하겠습니다.
<박스>
삽입이상:
만약
삭제이상:
학번이 “9655032” 인
학생이 자료구조의 수강 취소를 한다면 오용선 교수가 자료구조를 담당하고 있다는 사실도 함께 삭제됩니다. 이
뿐만 아니라 다른 과목들도 마찬가지로 수강하는 학생이 수강을 취소한다면 과목에 대한 담당교수도 같이 삭제되므로 이상현상이 일어납니다. 만약 다른 수강 신청자가 있다면 이와 같은 사실은 같이 삭제되지 않으나 현재 상황으로 볼 때 어떤 교수가 어떤
과목을 담당하고 있는지를 나타내는 것이 한 개의 투플(행)뿐이기
때문에 이러한 문제를 해결되어야 합니다.
갱신이상:
만약
</박스>
이러한 문제점은 보이스/코드
정규화 과정을 거치면 해결되는 문제입니다. 즉, “모든 결정자가
후보키” 가 되게 하면 되는 것입니다. 다음은 보이스/코드 정규화의 결과입니다.
<그림 4_85.jpg>
이제 여러분은 1차
정규화에서 3차 정규화 까지를 종합적으로 살펴볼 필요가 있습니다. 즉, 이러한 원리만 알고 있다면 바로 3차 정규화 또는 보이스/코드 정규화까지 직접 도출이 가능합니다. 직접 도출하는 예를 들어 보겠습니다. 다음과
같은 스키마가 존재하다고 가정하겠습니다.
대출 (대출번호, 고객명, 지점명, 지점위치, 자산, 대출합계)
이 스카마는 어떤 은행은 대출에 관련된 스키마입니다. 이 스키마를 가지고 함수적 종속만 파악한다면 나머지 보이스/코드
<함수적 종속>
지점명 à 자산
지정명 à 지점위치
대출번호 à 대출합계
대출번호 à 지점명
<그림 4_86.jpg>
도출한 R1, R2,
R3, R4, R5는 모두 보이스/코드
결과적으로 R1(지점명, 자산),
R2(지점명, 지점위치), R3(대출번호, 대출합계), R4(대출번호, 지점명), R5(대출번호, 고객명)으로 일단은 테이블을 최대한 분해하였습니다. 그러나 R1과 R2는 기본키가 같으므로 통합할 수 있습니다. 그러므로 R1_2 (지점명, 자산, 지점위치) 로 통합되고, R3와 R4, R5가 기본키가 같으나 R3, R4와 R5는 은행(R3, R4)과 고객(R5)으로
서로 다른 것을 나타내므로 R3와 R4는 통합되고, R5는 독립적으로 존재하게 됩니다. 즉, (R3, R4)와 R5는 표현하려는 정보가 틀리기 때문에 통합이
불가능합니다. 마지막에 나온 R5는 원래 정규화되기 전의
원래 테이블의 기본키가 됩니다. 결과적으로 다음과 같이 보이스/코드
정규화가 이루어졌습니다.
R1_2 (지점명, 자산, 지점위치)
R3_4 (대출번호, 지점명, 대출합계)
R5 (대출번호, 고객명)
[출처] 보이스/코드 정규화|작성자 톡
출처 : http://myhome.naver.com/yasicom2/normalization2.htm
정규화
우 리는 이제까지 데이터베이스의 설계를 위한 여러가지를 살펴보았습니다. 위에서 다룬 것은 현실을 어떻게하면 가장 근접하게 표현하는가에 대한 고려사항들이였습니다. 이것들은현실을 직관적으로 바라보고, 논리적으로 어떻게 하면 현실을 제대로 데이터베이스에 반영할 것인가에 대한 것이였습니다.
데 이터베이스의 설계에서 가장 중요한 것은 현실을 제대로 반영하는 것이며, 이를 어떻게 논리적으로 구성하는가를 결정하는 것입니다. 특히 관계형 데이터 모델에서는 데이터 값들이 2차원의 평면 테遣?형태로 표현하므로 어떤 릴레이션들이 필요하고, 어떤 애트리뷰트가 필요한가를 결정하는 것이 중요합니다.
이 젠 앞서서 직관적으로 바라보았던 것들을 '정규화'라는 원리를 도입할 것입니다. 정규화는 관계형 데이터 모델에서 아주 중요한 역할을 하고 있습니다. 학자마다 정규화는 튜닝의 도구 또는 설계 검증의 도구이다라고 의견이 약간씩은 다르지만 결국은 같은 의미를 가지고 있습니다. 현실을 제대로 반영하는 것은 튜닝과 검증이라는 것을 모두 포함하고 있기 때문입니다.
데 이터베이스 설계를 할 때 우리는 단계적인 사고방식을 가져야한다고 했습니다. 단계적인 사고 방식에서 윗 단계를 생각해 봅시다. 대부분은 설계의 초기단계에서 복잡한 생각을 하지 않는다고 나중에 누락되지는 않을까 하고 생각하는 분들이 많습니다. 그러나 이러한 것들은 정규화 과정이나 앞의 단계를 거치면서 데이터 모델링은 멋있게 틀을 잡아갑니다. 이렇게 틀을 잡아가는 것중 정규화는 그야말로 아주 큰 역할을 하는 것입니다. 앞에서 행했던 설계를 검증하고, 데이터의 중복을 없앤다 것 자체가 정보의 질을 높이고, 설계의 튜닝을 하는 것이니까요.
정 규화란 속성이 제위치에 제대로 찾아가게끔 하는 것입니다. 정규화의 목적은 당연히 데이터의 중복의 최소화와 여러가지 이상(Anomaly)들을 제거함에 있습니다. 데이터가 중복되어 있으면 여러 문제를 일으킬 수 있습니다. 삽입, 삭제, 변경에서 나타는 이상들이 개발자를 괴롭히는 것입니다. 이것은 결국 속성이 제자리에 있지 않기 때문에 발생하는 중복의 문제점 때문이라고 할 수 있습니다.
정 규화 과정은 속성간에 관계성, 데이터 종속성, 성능, 데이터베이스의일관성 유지등을 고려해야합니다. 정규화를 검증도구라고 하는 것도 설계가 잘못되면 일어날 수 있는 여러가지 문제점을 예방하는 차원이기 때문입니다. 또한 데이터의 중복을 없앤다는 자체가 엄청난 튜닝의 효과를 가지는 것입니다. 일단 데이터의 중복이 많은 설계는 먼가가 문제가 있는 설계입니다. 데이터베이스의 정의에서도 언급했듯이 데이터베이스는 중복의 최소화로 기존의 파일처리방식이나 수작업 방식에서 오는 정보의 질을 떨어뜨리는 문제점을 없애는 것입니다. 이러한 문제점을 좋은 정보의 질을 유지하기 위한 하나의 정형화된 도구 즉, 정규화를 통해 해결을 하게 되는 것입니다.
정 규화는 데이터의 중복으로 인한 문제를 해결하기 위해서 속성들간에 종속성(Dependency)을 분석해서 기본적으로 하나의 릴레이션(테이블)에 표현하도록 분해를 하는 것입니다. 어떻게 보면 테이블을 무작정 쪼개는 것으로 보일 수도 있습니다. 그러나 테이블을 쪼개는 기준은 "함수적 종속"이란 개념으로 쪼개는 것입니다. 즉, 함수적 종속성을 파악한 다음 그 함수적 종속을 기본으로 해서 속성들을 하나의 테이블로 그룹짓는 것입니다.
함수적 종속
그럼 "함수적 종속" 이란 것이 무엇인가 살펴보도록 하겠습니다. 일단 함수라 하면 다음의 그림과 같이 나타낼 수 있습니다.
이것을 테이블로 표현한다면 다음과 같겠지요.
감이 약간 오시나요?? 일단 함수적 종속이란 말에서 함수라는 것에 대해서 살펴보도록 하겠습니다. 함수가 무엇인가요? 다름의 그림을 보고서 설명을 하도록 하겠습니다.
그 림처럼 왼쪽은 2라는 원소가 두개가 들어 있습니다. 2를 어떤 함수에 집어 넣어야지 4가 될까요? 일반적으로 생각해 보면 2의 제곱을 구하는 함수에 값을 집어 넣는다면 4가 되겠지요. 그러나 역으로 4를 집어 넣는다면 16이 되버리는 것입니다. 즉, 2와 2는 4가 되기 위해서 함수적으로 종속되어 있는 것입니다. 결국 4는 2와 2가 4가 되기 위한 함수에 종속적이기 때문에 2의 제곱이라는 함수에 종속적이게 만드는 4는 "결정자"라고 부릅니다. 또한 2와 2를 "종속자"라고 합니다.
사 실 이렇게 수학적으로 함수적 종속을 설명하였으나 정규화는 시스템을 구축하고자하는 조직내의 의미에 함수적 종속을 설명해야 합니다. 즉, 정규화는 관계형 모델에서 표현하고자 하는 주제가 동일한 속성들끼리 뭉쳐져 있는 것입니다. 그러므로 설계의 초기부터 나타내고 자하는 정보를 의미론적으로 묶는다면 정규화라는 과정의 설계의 검증도구가 되는 것입니다.
위의 예에서 2를 Y로 하고 4를 X라 한다면 함수적 종속의 표현은 "X Y" 로 표기합니다. 이러한 표현을 실제의 예를 들어서 살펴보겠습니다.
학생 릴레이션에서 ...
학번 이름 학번 학과 학번 학년
위 에서 보는 바와 같이 학번은 이름, 학과, 학년을 결정하고 있습니다. 즉, 학생 릴레이션에서 각각의 학생을 유일하게 구분지을 수 있는 속성은 학번으로 학번은 기본키의 역할을 하는 속성입니다. 즉, 이름만 가지고는 각각의 학생을 알 수 없다는 것입니다. 제가 옛날에 휴학을 하려고 했는데 시간이 없어서 조교님께 휴학 신청을 대신해달라고 한 적이 있었습니다. 그런데 저와 같은 이름을 가진 다른 사람이 있었는데 그 사람으로 휴학을 한적이 있어서 상당히 난감했던 적이 있습니다. 즉, 저의 이름인 "이재학" 만 가지고는 정확성이 있는 정보가 될 수 없던 것입니다. 만약 교수님께서 "이재학"을 불러오라 라고 한다면 이미 과에 "이재학"이 란 이름을 가진 사람이 2명이라는 것을 아는 사람은 학번을 교수님께 되물을 것입니다. 이렇듯 이름은 학번에 종속되어 있다는 것입니다. 이름이 이재학이고, 학과가 정보통신공학과이고, 4학년인 학생은 저 말고도 한명이 더 있습니다. 즉, 이것들은 학번에 종속적이라는 것입니다.
테이블로 표현한 것을 가지고 좀더 살펴보도록 하겠습니다.
9555023, 이재학, 4학년, 정보통신공학과 라는 것은 한명의 학생에 대햔 데이터입니다. 학번, 이름, 학년, 학과중에 대표성을 띄고 있는 것은 학번이고, [9555023, 이재학], [9555023, 4학년], [9555023, 정보통신] 이라고 해야지만 정확한 정보를 표현할 수가 있는 것이죠. 앞에서 언급했듯이 [이재학, 4학년, 정보통신]이라고 해서 정확한 정보가 되는 것일까요? 당연히 학번이 9555023인 학생과 학번이 9839011인 학생을 구별하지 못하는데 문제가 있습니다.
이렇듯 학번은 이름, 학년, 학과를 결정하고, 이름, 학년, 학과는 학번에 종속적입니다. 이렇게 데이터에 대한 의미를 표현한 것을 함수적 종속이라고 합니다.
<참고> 함수 종속에 대한 증명된 추론 규칙 (R 릴레이션) (데이터베이스시스템, 이석호, 정익사)
R1: (반사규칙) A B 이면 A B 이다. R2: (첨가규칙) A B 이면 AC BC 이고 AC B 이다. R3: (이행규칙) A B 이고 B C 이면 A C 이다. R4: (분해규칙) A BC 이면 A B 이다. R5: (결합규칙) A B 이고 A C 이면 A BC 이다.
정규화는 이러한 "함수적 종속"을 기본 원칙으로 하나의 의미를 가지는 집합으로 나누는 작업입니다. 정규화는 1차 정규화, 2차 정규화, 3차 정규화, 보이스/코드 정규화, 4차 정규화, 5차 정규화, 도메인/키 정규화가 있습니다. 이 순서가 높아지는 단계의 정규화일수록 무결성은 강화되나 과도하게 테이블이 쪼개지므로 쓸 때 없는 부하가 걸릴 수 있습니다. 그러므로 현실을 감안해서 어느 정도 수준의 정규화까지 행해야 하는가를 결정해야 합니다. 보통 실무에서는 3차 정규화와 보이스/코드 정규화까지 합니다. 기본으로 3차 정규화까지는 해야 하며, 3차 정규화 과정을 마치고도 사용자의 요구사항에 의해서 여러가지 이상들이 발생할 요지가 있다면 더 높은 차원의 정규화를 해야 합니다. 이제 각 단계별 정규화에 대해서 설명하도록 하겠습니다.
1차 정규화
하 나의 릴레이션은 어떤 도메인의 집합입니다. 각각의 속성은 해당 도메인에 속하는 단지 하나의 값을 가져야 합니다. 이것이 1차 정규화 이며, 실제로 1차 정규화도 거치지 않은 테이블이 많이 존재합니다. 예를 들면 다중값 속성들이 그대로 표현될 때 정규화된 테이블이 아닌 즉, 비정규화 테이블인 것입니다. 사원테이블에 사번, 이름, 보유기술, 월급의 속성이 있는데 보유기술은 여러 개를 가질 수 있다는 현실을 생각해 보도록 하겠습니다. 일반적으로 문서를 만들면 다음과 같은 문서가 나올 수 있습니다. 보유기술에서 하나의 속성값에 여러 개의 값이 들어간 것을 볼 수 있습니다. 이러한 표현은 비정규화 된 테이블입니다. 여기서 기본키는 사원번호입니다.
그 렇다고 다음과 같이 보유기술을 옆으로 펼친다고 해서 달라지는 것은 없습니다. 이도 역시 1차 정규화된 테이블이 아니라고 볼 수 있습니다. 의미상으로 보유기술1, 보유기술2, 보유기술3는 그냥 보유기술의 종류일 뿐입니다. 그러니 하나의 속성에 여러 개의 값을 다른 표현으로 한 것 뿐입니다.
어떤 독자분은 보유기술 속성에 속성값을 넣는데 콤마로 구분하면 어떻겠냐? 라는 생각을 가질 수도 있습니다. 만약 사원번호 1111 인 사원의 보유기술을 하나더 추가하려면 기본키가 "사원번호" 이므로 "사원번호"가 1111 인 사원이 추가되지 못하는 것을 알 수 있습니다. 즉, 다음과 같은 그림이 되어 삽입을 할 수 없는 형태가 되는 것입니다.
이 제 본격적인 정규화에 대해서 알아보겠습니다. 아래의 테이블은 각각의 학생에 대해서 각각의 속성마다 단일값을 가지고 있으므로 1차 정규화된 테이블이 입니다. 여기서 독자분들은 함수적 종속관계를 찾아보아야 할 것입니다. 여러분은 찾아낸 함수적 종속성을 바탕으로 데이터가 많이 중복되어 있고, 그 데이터의 중복으로 인한 여러가지 문제점(이상)들을 찾아내어야 합니다.
이 테이블의 함수적 종속 다이어그램의 다음과 같습니다.
함 수적 종속 다이어그램에서 보는 바와 같이 학번은 학생명과 학년을 결정하고, 학번은 학과를 결정합니다. 또한 수강코드는 담당교수와 과목명을 결정합니다. 각각의 학생은 자신이 수강신청한 과목의 성적등급을 알기 위해서 학번과 수강코드가 필요합니다. 담당교수는 학과를 결정합니다. 여기서 자칫 잘못하면 학과가 담당교수를 결정할 수 있다고 볼 수 있는데 하나의 학과에 소속된 교수는 여러명인 것이 보입니다. 즉, 지도교수가 학과를 결정하는 것이지 학과가 교수를 결정하는 것이 아닙니다.
이제 1차정규화된 테이블을 가지고 나타나는 문제점을 살펴보도록 하겠습니다. 이러한 문제점은 함수적 종속과 관련하여 찾아보아야 합니다.
이 테이블은 학번만 가지고는 어떤 과목의 성적의 등급이 얼마인지를 모릅니다. 그러므로 이 테이블의 기본키는 학번 + 수강코드입니다. 여기서 주의할 것은 수강코드라는 속성의 이름이 수강을 해야만 하는 코드가 아니라는 사실입니다. 즉, 수강할때 그 과목을 나타내는 과목의 고유번호응 나타내는 것입니다.
2차 정규화
앞 서서 삽입, 삭제, 갱신 이상들이 일어 날 수 있다는 것을 보았습니다. 1차 정규화된 테이블에서 이러한 문제점이 일어나는 원인이 무엇일까요? 원인은 바로 기본키가 아닌 각각의 속성들이 기본키에 종속적이지 않고, 부분적으로 함수 종속이 되기 때문입니다. 즉, 기본키를 제외한 모든 속성이 기본키에 함수적 종속이 아니기 때문입니다. 이러한 문제를 해결하기 위해서는 기본키에 함수 종속을 시킨 것 끼리 따로 테이블을 만들어야 합니다. 2차 정규화된 테이블은 다음과 같습니다. ( 테이블 밑은 점(...)은 생각치 않도록 하겠습니다. )
2 차 정규화의 결과로 위와 같은 3개의 테이블이 나왔습니다. 학생과 수강과목은 다:다의 관계를 맺고 있기 때문에 학생의 학번과 수강과목의 수강코드가 합쳐진 것을 기본키로 하여 학생 테이블과 수강과목 테이블을 연관지어 주고 있습니다. 사실 데이터 모델링의 초기단계부터 차근 차근 진행해 오면서 엔티티만 제대로 도출해 냈다면 이와 같은 2차 정규화 작업은 필요가 없습니다. 그러나 이와 같은 검증된 원리를 알고 있다면 애매모호 함이 없어지고, 좀더 정확한 정보를 산출하는 정보시스템이 만들어 질 수 있는 것입니다.
학생 테이블과 수강과목 테이블에 학과라는 속성이 중복되어 존재하는 것이 보입니다. 이것은 어떤 다른 엔티티 집합이 더 존재한다는 것을 의미합니다. 즉, "학과" 엔티티가 "학생"과 "수강과목"과 관계를 맺고 있다는 것입니다. 위의 테이블을 볼 때 학과와 관련된 엔티티와 학생, 수강과목은 1:다의 관계를 맺고 있음을 알 수 있습니다. 즉,
학과 : 학생 1 : 다 학과 : 수강과목 1 : 다
의 관계입니다. (사실 더많은 객관적인 업무규칙이 파악되어야 정확히 알수 있습니다.) 그러므로 속성의 이름은 학과보다는 "학과명"이라고 하는 것이 더 명확하겠지요. 그러나 이 단원에서는 다른 엔티티 집합은 생각치 않고, 이에 대한 고려는 다음 단원에서 하겠습니다. 단지 이것은 정규화를 위한 예제라는 것을 염두해 두시기 바랍니다.
이제는 어느정도 속성들이 자신이 있어야 할 곳에 배치된 것으로 보입니다. 그러나 이러한 2차 정규화 테이블에도 이상들이 존재합니다. 이러한이상들을 살펴보도록 하겠습니다.
2 차 정규화된 테이블에서 이상이 일어나는 이유는 기본키가 아닌 다른 속성들 간에 함수적 종속이 일어나기 때문입니다. 이렇게기본키가 아닌 속성들끼리의 종속성을 가지는 것은 이행 종속(Transitive Function Dependency) 라고 합니다. 이러한 개념으로 위의 테이블에서 일어날 수 있는 문제점을 찾아보록 하겠습니다. 먼저 문제의 이행 종속이 일어나고 있는 테이블을 추려내야 합니다. 앞서서 그려본 함수적 종속 다이어그램에서와 같이 이행 종속이 일어나고 있는 테이블은 수강과목 테이블입니다.
삽입이상: 각 과목을 담당하는 교수가 특정 학과에 속한다는 사실을 삽입하려 할 때 과목이 존재하지 않는다면 이 사실을 삽입할 수 없습니다. 즉, 각각의 행을 구분할 수 있는 대표성을 지닌 속성(기본키)가 존재하지 않으므로 삽입이 불가능하다는 것입니다. 기본키는 수강과목 테이블에서 반드시 들어가야만 하는 것인데 이를 무시한채 다른 속성값을 삽입하려 한 것이 문제입니다.
삭제이상: 만약 해당 학과의 커리큘럼이 바뀌어 오상훈 교수가 담당하고 있는 과목인 "자료구조"라 는 과목이 없어진다면 오상훈 교수가 정보통신공학과에 소속된다는 사실도 없어지게 됩니다. 오상훈 교수가 정보통신공학과에 소속된다는 사실은 이행종속이 일어나고 있다는 것이며, 역시 2차 정규화된 테이블에서 일어나는 삭제이상도 이행 종속때문이라는 것을 알 수 있습니다.
갱신이상: 만약 박덕규 교수의 소속 학과가 정보통신에서 다른 학과로 변경된다면 박덕규 교수에 해당되는 학과에 대한 속성값을 모두 변경시켜 주어야 합니다. 역시 이행종속이 일어나서 일어나는 이상현상입니다.
3차 정규화
2 차 정규화된 테이블에서 이행 종속에 의해서 여러 가지 이상현상이 발생되는 것을 보았습니다. 이러한 여러 이상현상을 제거하려면 어떻게 해야 할까요? 당연히 이상현상의 원인이 되었던 이행종속을 없애면 됩니다. 어떻게 없애야 할까요? 당연히 이행종속을 일으키는 속성들을 묶어서 그룹지어 주면 문제는 해결됩니다.
이 렇게 이행 종속성을 제거한 테이블은 3차 정규화된 테이블입니다. 만약 독자분들 중에 여기까지 대충 읽어 보신분들은 아마도 정규화란 것이 테이블을 쪼개는 것이구나 라고 생각하시는 분들도 계실겁니다. 그러나 테이블을 쪼갠다는 개념을 갖지 말고, 좀더 세부적으로 관련성이 많은 것끼리 새로운 그룹을 만드는 개념으로 정규화를 생각하셔야 합니다.
<쉬어가기>
자존심... 여 러분은 느껴보셨는지요? 공대인이 마음이 닫혀있다는 것을... 얼마전 웹상에서 알게된 친구가 저에게 메신저로 호출을 하더군요. 그래서 왜 그러느냐고 했더니 지금 큰일났다고 하더군요. 다시 왜 그러냐고 물었더니 지금 자기가 하고 있는 프로젝트가 원래 D사 의 프로젝트인데 하청으로 받아서 하고 있는데, D사 사람이 와서 DB설계 개판(?)으로 했다고 하면서 엄청 깨졌다고 하더군요. 그러더니이거 DB 설계 다시해서 그쪽 사람과 협상해야 한다고 하소연을 했습니다. 그래서 한번 보자고 했습니다. ㅡㅡ;;
저 는 그 DB설계 해논 것을 보고 이게 도대체 머냐? 그럴만 하다 라고 했습니다. 그랬더니 자기자신도 모르는 상태에서 했기 때문에 그럴만 하다라는 것을 인정하면서도 너무나도 화가 난다고 하는 것이 였습니다. 왜 화가 나는 것일까요? 자신이 해논 것에 대한 쓸 때 없는 자존심 때문일까요?
이 상스럽게 이쪽 분야에서 일하는 사람이나 공부하는 사람들은 지는 것을 싫어합니다. 사실 게임도 아닌데 많은 사람들이 자신이 제시한 솔루션이 가장 옳다라고 우겨서(?) 이기고자하는 경향이 있습니다.(물론 필자도 그런 경향이 매우 짙게 나타납니다. 모르는 것도 전에 알던 지식을 이용해서 논리적으로 엮어서 아는 척하는 합니다. ㅡㅡ;;) 정보기술분야는 너무나도 빨리 발전하고 있습니다. 거의 대부분의 사람이 따라가기 바쁘지요. 물론 필자도 따라가기가 너무 힘듭니다. 그래서 매일 꾀죄죄한 모습으로 학교에서 중국음식에 길들여지면서 고생하는 이유일지도 모르겠습니다. 다음 그림을
여러분은 마음을 열고 다른 사람의 것을 받아들일 수 있어야합니다. 너무나도 빨리 발전하고 있는 기술을 따라가는데 가장 빠른 지름길은 사람과 사람이 나누는 Communication 일것입니다.
보이스/코드 정규화
3 차 정규화도 여러가지 이상이 존재합니다. 그렇다면 이상이 발생하지 않는 정규화 과정은 어떤거냐고 의문을 가지는 분도 있을 겁니다. 이상이 발생하지 않는 정규화는 키/도메인 정규화입니다. 이것은 증명은 되었으나, 키/도메인 정규화 테이블을 만드는 구체적인 방법을 발견하지 못했기 때문에 실무에서 직관적으로 사용되는 방법이기도 합니다. 그러나 보통 실무에서는 3차 정규화과정이나 다음에 할 보이스/코드 정규화까지 합니다. 그 이유는 일반적으로 4차 정규화나 5차 정규화 과정을 거쳐야 하는 상황은 거의 발생하지 않기 때문입니다. 이 책에서는 보이스/코드 정규화 과정까지만 언급하겠습니다. 만약 보이스/코드 정규화 과정을 거쳤으나 사용자가 원하는 작업을 수행할 때 이상이 발생한다면 4차 정규화 과정을 거쳐야 할 것입니다. 4차, 5차 정규화는 다른 책을 참고하셔야 할 것입니다.
이제 위의 3차 정규화를 거친 테이블에 대한 이상현상이 발생하는 원인을 분석하고 보이스/코드 정규화에 대해서 언급하도록 하겠습니다.
3 차 정규화 과정을 거치 테이블에서 이상현상을 발생시키는 원인은 후보키들이 중첩되어 있다는 것 때문입니다. 후보키는 기본키가 될 수 있는 자격이 있는 속성 또는 속성들입니다. 즉, 하나의 릴레이션에 여러 개의 후보키가 존재하는데 하나 또는 여러 개의 속성이 중첩되어서 후보키될 때 이상현상이 발생할 수 있다는 것입니다. 보이스/코드 정규화 과정은 바로 이러한 문제점을 해결하는 것입니다. 이러한 의미에서 볼 때 보이스/코드 정규형은 엄격한 3차 정규형이라고도 합니다.
보 이스/코드 정규형은 릴레이션의 모든 결정자가 후보키이면 보이스/코드 정규형이라고 보는 것입니다. 결정자라는 개념은 어떤 속성을 함수적으로 완전히 종속시키는 속성을 의미합니다. 만약 다음의 업무 규칙이 존재하는 테이블이 있다고 가정 한다면
-. 하나의 과목을 여러 교수가 담당할 수 있다. -. 각 교수는 하나의 과목만을 담당한다. -. 각각의 학생은 같은 과목명을 가진 다른 과목을 수강하지 못한다.
앞서서 언급한 3차 정규화의 문제점인 후보키의 일부가 되는 속성인 "학번"이 중첩되어 있는 것이 보입니다. 즉, 수강_교수 릴레이션의 후보키는 "학번 + 과목명" , "학번 + 담당교수" 입니다. 이 후보키중 "학번 + 과목명"을 기본키라고 가정하겠습니다. 함수 종속 다이어그램에서 보는 바와 같이 "학번 + 과목명"은 "담당교수"를 결정하고, "담당교수"는 "과목명"을 결정합니다. 이런 구조를 가지고 있는 릴레이션의 문제점을 파악해 보도록 하겠습니다.
삽입이상: 만약 이현태 교수도 자료구조를 담당하게 되었다면 수강신청을 한 학생이 있어야만 이와 같은 사실을 입력할 수 있습니다. 만약 "담당교수"의 의마가 해당 과목을 담당하고, 또한 그 학생에 대한 생활지도 등의 "지도"를 할 수 있다면(여기서는 담당과목을 수강하지 않은 학생도 지도할 수 있다는 가정), 과목을 수강하지 않은 학생은 지도교수가 누구인지 결정을 할 수 없게 됩니다.
삭제이상: 학번이 "9655032" 인 학생이 자료구조의 수강 취소를 한다면 오용선 교수가 자료구조를 담당하고 있다는 사실도 함께 삭제됩니다. 이 뿐만 아니라 다른 과목들도 마찬가지로 수강하는 학생이 수강을 취소한다면 과목에 대한 담당교수도 같이 삭제되므로 이상현상이 일어납니다. 만약 다른 수강 신청자가 있다면 이와 같은 사실은 같이 삭제되지 않으나 현재 상황으로 볼 때 어떤 교수가 어떤 과목을 담당하고 있는지를 나타내는 것이 한 개의 투플(행)뿐이기 때문에 이러한 문제를 해결되어야 합니다.
갱신이상: 만약 이현태 교수가 "DB" 에서 "네트웍 프로그래밍"으로 담당과목이 바뀌었다면 3개의 투플(행)을 모두 변경해주어야 합니다.
이러한 문제점은 보이스/코드 정규화 과정을 거치면 해결되는 문제입니다. 즉, "모든 결정자가 후보키" 가 되게 하면 되는 것입니다. 다음은 보이스/코드 정규화의 결과입니다.
이 제 여러분은 1차 정규화에서 3차 정규화 까지를 종합적으로 살펴볼 필요가 있습니다. 즉, 이러한 원리만 알고 있다면 바로 3차 정규화 또는 보이스/코드 정규화까지 직접 도출이 가능합니다. 직접 도출하는 예를 들어 보겠습니다. 다음과 같은 스키마가 존재하다고 가정하겠습니다.
대출 (대출번호, 고객명, 지점명, 지점위치, 자산, 대출합계)
이 스카마는 어떤 은행은 대출에 관련된 스키마입니다. 이 스키마를 가지고 함수적 종속만 파악한다면 나머지 보이스/코드 정규형을 도출하는 과정은 간단합니다. 다음은 이 스키마에 대한 함수적 종속을 나타내는 것입니다.
<함수적 종속> 지점명 자산 지정명 지점위치 대출번호 대출합계 대출번호 지점명
도 출한 R1, R2, R3, R4, R5는 모두 보이스/코드 정규형을 만족합니다. 각각의릴레이션의 모든 결정자가 후보키입니다. 그러나 이렇게 너무 불필요한 정규화는 결과적으로 성능을 떨어뜨릴 수 있습니다. 그러므로 다음과 같은 통합작업을 거쳐야 합니다.
결 과적으로 R1(지점명, 자산), R2(지점명, 지점위치), R3(대출번호, 대출합계), R4(대출번호, 지점명), R5(대출번호, 고객명)으로 일단은 테이블을 최대한 분해하였습니다. 그러나 R1과 R2는 기본키가 같으므로 통합할 수 있습니다. 그러므로 R1_2 (지점명, 자산, 지점위치) 로 통합되고, R3와 R4, R5가 기본키가 같으나 R3, R4와 R5는 은행(R3, R4)과 고객(R5)으로 서로 다른 것을 나타내므로 R3와 R4는 통합되고, R5는 독립적으로 존재하게 됩니다. 즉, (R3, R4)와 R5는 표현하려는 정보가 틀리기 때문에 통합이 불가능합니다. 마지막에 나온 R5는 원래 정규화되기 전의 원래 테이블의 기본키가 됩니다. 결과적으로 다음과 같이 보이스/코드 정규화가 이루어졌습니다.
R1_2 (지점명, 자산, 지점위치) R3_4 (대출번호, 지점명, 대출합계) R5 (대출번호, 고객명)
결 과적으로 정규화라는 과정은 함수적 종속이라는 하나의 원칙으로 관련성으로 속성들을 묶어서 데이터의 중복을 없애고, 데이터의 중복에 의한 여러가지 이상현상을 없애는 유용한 도구입니다. 데이터의 중복이 최소화되는 자체는 시스템이 가장 가벼운 데이터를 가지고 처리하기 때문에 전체적인 시스템의 성능이 높아지기도 하는 것입니다.
키/도메인 정규화
' 정규화란것은 '함수적 종속'관계를 파악하는 것입니다. 이 종속관계를 파악하여 속성이 원래 갈 자리에 가게 하는 것입니다. 즉, 주제에 맞는 한 객체가 관련된 업무에 관한 속성들이 있어야 할 곳에 있게 하는 것입니다. 우리는 1차 정규화에서 보이스/코드 정규화까지 알아보았습니다. 보통 실무에서는 3차 정규화나 보이스/코드 정규화 때에 따라서는 아주 가끔씩 4차정규화를 행합니다.
그 러나 검증은 되었으나 그 방법이 찾아지지 않은 키/도메인 정규화를 이 글에서 이야기하고자 합니다. 키(key)라는 것은 객체를 유일하게 구별할 수 있는 속성중에 가장 관련된 대표적인 것을 이야기 합니다. 이 키에 함수적으로 모두 종속되고, 속성의 도메인이 맞다면 즉, 모든 제약이 키와 도메인의 정의에 따른 논리적인 결과인 것은 모두 키/도메인 정규화인 것입니다. 이 것은 완벽한 정규화입니다. 3차 정규형은 기본키에 모두 함수적 종속적인 것들로 테이블을 분리하고, 기본키가 아닌 속성들끼리의 종속성 즉, 이행종속을 일으키는 속성들을 다른 테이블로 옮기고 그 테이블에 기본키를 정의할 수 있으면 됩니다. 이와 같이 분리된 테이블은 기본키를 가지게 됩니다. 이러한 개념으로 테이블을 봤을때 데이타가 중복되어 나타나는 것들 잘 살펴보면, 왜 중복이 일어났는지 알수 있을 것입니다.
정 규화의 해법들이 키/도메인 정규화 빼고는 모두 나와있습니다. 그러나 직관적으로 바라본다면 해법이 나와 있지는 않지만 키/도메인 정규화가 더 쉽습니다. 또한 초기에 엔티티를 선정할때 우리가 시스템화 하고자하는 관련된 것들끼리 모인 즉, 엔티티를 잘 선정한다면 직관적인 관점에서 3차정규화는 충분히 할 수 있으리라 생각합니다. 그 렇다고 정규화 과정을 무시해서는 안됩니다. 이렇게 직관적으로 설계를 하면서 나갈때는 정규화는 검증도구가 되는 것입니다. 학자에 따라서 정규화는 검증도구다 또는 튜닝도구다라고 하는 의견들이 분분합니다. 그러나 정규화는 반드시 필요한 것이 틀림이 없습니다.
도 메인/키 정규화에서 중요한 단어는 제약, 키, 도메인입니다. 한가지 주의할 것은 제약에 시간의 개념을 뺏다는 것입니다. 엑기스만 뽑는다면 키와 도메인에 대한 제약을 준수시켰을때 모든 제약이 준수되는 릴레이션은 키/도메인 정규형입니다.
다 시 핵심단어 키, 도메인, 제약 이 세가지의 관점에서 살펴보겠습니다. 키라는 것은 객체들을 유일하게 구분지어 주는 속성입니다. 즉, 속성들중 대표하는 것을 말합니다. 이 속성들이 가질수 있는 값들의 범위를 정의한 것이 바로 도메인입니다. 독자들중에 아시는 분이 별로 없으시겠지만 푸리에변환 같은 것을 보면 시간 도메인에서 주파수도메인으로 주파수 도메인에서 시간 도메인으로 변환을 할 수 있습니다. 시간 도메인에서 본다면 이 값들은 절대로 변환과정을 거치지 않고는 시간이라는 단위밖에 가지지 못하는 것입니다. 실제로 주민번호를 본다면 생년월일 담에 오는 1이란 숫자는 남자밖에 가지지 못하는 숫자입니다. 이 도메인을 벗어난다면 현실에 맞지 않게 되는 것입니다. 누누히 얘기하지만 데이타베이스는 현실을 최대한 반영하는 것입니다.
정리하자면 키라는 것은 "unique + not null + 대표성" 입니다. 도메인은 앞에서 얘기한 것처럼 속성이 가질수 있는 값의 범위이고 가질수 있는 꼭 그것을 가져야만 하는 의미입니다. 이것은 현실의 제약이라고 볼수 있으며, 이러한 제약이 지켜진다면 이것은 완벽한 이상이 없는 정규형입니다. 정규화의 정리
이 제 앞에서 살펴보았던 정규화에 대해서 의미로만 따져도록 하겠습니다. 필자의 경우는 정규화 과정은 검증도구로 사용하는 편입니다. 사실 함수적 종속이란 것이 조직의 범위내에서 통용되는 의미에 따라 틀려집니다. 그러므로 모델링을 하기전 단계에서부터 정보시스템을 구축하려는 조직에서 사용되는 정보의 의미를 파악하는 것이 더 중요하다고 합니다.
3 차 정규화된 테이블을 보면 테이블마다 어떤 정보들을 나타내기 위해서 데이터 들이 뭉쳐있습니다. 즉, 각각의 속성들이 뭉쳐서 어떠한 하나의 정보(의미)를 만들어 내기 때문에 그 의미만 잘 파악한다면 앞에서 행했던 것처럼 바로 보이스/코드 정규화까지 직접 도출이 가능한 것입니다. 그냥 어떤 "의미"를 나타내기 위해서 그룹짓는 과정이라고 하기엔 너무 애매모호 합니다. 그래서 함수적 종속이란 개념을 도입하여 누구나 고개를 끄덕이게 만든 것이 정규화입니다.
독 자가 파악해야 할 것은 사용자의 정보가 무엇인지 정확하게 판단하여야 할 것입니다. 만약 사용자의 요구사항이 정확하게 파악되면, 그 요구사항을 정확히 반영하기 위해서 엔티티를 도출하고, 각각의 속성들을 배치해야 합니다. 엔티티는 속성의 집합이기도 합니다. 하나의 엔티티가 다른 엔티티와 관계를 맺고, 어떠한 정보를 만들어 낼 수 있습니다.
일반적으로 데이터 모델링은 하향식(Top-Down)의 방식으로 설계를 하고, 정규화를 통한 하향식(Bottom-up) 방식으로 검증을 하는 방법론을 사용합니다. 이제 속성을 가지고 다음 그림을 살펴보도록 하겠습니다.
제일 먼저 파악해야 할 것은 "관련성" 입니다. 릴레이션이란 것이 속성들이 어떠한 관련성에 묶여서 있는 모습입니다. 그러니 관련성이라는 의미는 매우 중요한 것입니다. 이것은 기본키와의 관련성입니다. 하나의 개체( 학생으로 하였을 경우 학번이 9555023인 학생 하나는 인스턴스입니다.)를 대표하는 것이 기본키이기 때문입니다.
두 번째는 파악해야 할 것은 속성의 도메인입니다. 각각의 속성은 가질 수 있는 값의 범위 즉, 도메인을 가지고 있습니다. 이 도메인에서 표현할 수 있는 속성값들을 대표할 수 있는 것들을 찾는 것입니다. 이 도메인도 관련된 엔티티의 범위를 가지기 때문에 관련성이라는 것은 매우 중요합니다.
의 미상으로 볼 때 학번과 학생명이 같은 객체의 다른 표현인 것을 알 수 있습니다. 그러나 한 학년에 속하는 학생이 여러명인 것을 알 수 있지만, 학년자체는 독립적으로 존재할 수 있는 즉, 엔티티가 아니라 속성이라는 것입니다. 결과적으로 이 릴레이션은 "학생" 엔티티 집합이 포함된 것입니다.
이 러한 방식으로 속성값을 살펴보면 위의 그림이 나올 수 있습니다. 그림에서 학과명과 관련된 것을 살펴보면, 일단 학번이 이름과 학년을 결정하는 것은 앞에서 체크었으므로 이 두 속성은 제외하고 학번으로만 생각해보도록 하겠습니다. 학번이 학과명을 결정하나요? 이 부분은 상당한 혼돈의 여지가 있습니다. 그러나 좀더 원천적으로 생각하면 데이터베이스 시스템을 개발하려는 도메인이 무엇인가요? 바로 "학교"입니다. 즉, 학교에는 기본적으로 "학생"과 "학과"가 존재해야 "학교"가 존재할 수 있는 것입니다. 즉, 학과와 학생은 기본엔티티 집합인 것입니다. 이렇게 "닭이 먼저냐? 달걀이 먼저냐?" 라고 따지는 상황이 온다면 이것은 기본엔티티 집합입니다. 그러므로 학과명은 "학과" 엔티티 집합의 속성입니다. 그러므로 이것은 외부키인 것입니다. 그렇다면다른 속성은 어떨까요? 당연히 다른 속성들도 따져볼 것이 못되는 것입니다. 만약 관련이 있다면 그것은 외부키로 의 기능을 하는 속성입니다.
결과적으로 이 테이블에서 도출할 수 있는 엔티티 집합은 "학생", "수강(또는 과목)", "학과", "교수" 입니다. "학생" 과 "수강" 은 다:다의 관계를 맺고 있으므로 "수강코드, 학번, 등급" 은 이 다:다의 관계를 해소한 것이 되는 것입니다.
이렇게 엔티티와 속성과 관계를 도?하는 것은 데이터 모델리의 핵심입니다. 이와 같은 기본적인 것만 확실히 파악이 된다면 정규화는 데이터 모델링의 검증의 도구와 튜닝의 도구로 써 훌륭한 역할을 할 것입니다. |
<표 1> 정규화에 대한 정리
1차 정규화 사례 1
<그림 2> 1차 정규화의 응용 1
이 사례의 특징은 주문의 PK(Primary Key)인 주문번호가 중복 속성 값을 가지기 때문에 PK를 가진 데이터베이스 테이블 생성이 불가능하다는 특징이 있다.
1차 정규화 사례 2
<그림 3> 1차 정규화의 응용 2
<그림 3>의 모델을 보면 왼쪽 모델의 일재고 엔티티 타입에는 3개월 분에 대한 장기재고 수량, 주문수량, 금액, 주문금액이 차례대로 기술되어 있다. 이렇게 되면 장기재고 관리가 4개월 이상으로 늘어날 때 모델을 변경해야 하는 치명적이 결함이 있다. 따라서 오른쪽과 같이 1차 정규화를 통해 모델을 분리함으로써 업무 변형에 따른 데이터 모델의 확장성을 확보하도록 해야 한다.
2차 정규화(주식별자에 종속적이지 않은 속성의 분리) 1차 정규화를 진행했지만 속성 중에 주식별자에 종속적이지 않고 주식별자를 구성하는 속성의 일부에 종속적인 속성인, 부분종속 속성(PARTIAL DEPENDENCY ATTRIBUTE) 을 분리하는 것이 2차 정규화(SECOND NORMALIZATION)이다. 2차 정규화는 반드시 자신의 테이블을 주식별자를 구성하는 속성이 복합 식별자일 경우에만 대상이 되고 단일 식별자일 경우에는 2차 정규화 대상이 아니다.
2차 정규화 사례
<그림 4> 2차 정규화 응용
<그림 4>의 모델은 고객번호에 종속적이지 않은 속성들을 분리하여 고객점포라는 새로운 엔티티 타입을 생성하였다. 실전 프로젝트에서는 코드 유형의 엔티티 타입들이 2차 정규화가 되지 않고 하나의 엔티티 타입으로 표현되는 경우가 많이 발견된다. 이 모델에서 함수종속 관계 표기법으로 표기하자면 고객번호 -> (고객명)으로 표시하여 별도의 엔티티 타입으로 분리할 수 있다.
3차 정규화(속성에 종속적인 속성 분리) 3차 정규화(third normalization)는 속성에 종속적인 속성을 분리하는 것이다. 즉 1차 정규화나 2차 정규화를 통해 분리된 테이블에서 속성 중 주식별자에 의해 종속적인 속성 중에서 다시 속성 간에 종속 관계가 발생되는 경우에 3차 정규화를 진행한다.
3차 정규화 실전 적용
<그림 5> 3차 정규화 응용
<그림 5>의 모델은 고객 엔티티 타입에 등록카드에 대한 정보가 포함되어 있는 모습이다. 등록카드번호가 결정자 역할을 하고 있고 등록카드사명과 등록카드유효일자가 의존자 역할을 하는 속성 간의 종속적인 속성이 발견되었으므로 3차 정규화의 대상이 되는 모델이다. 따라서 등록카드에 대한 내용에 대해 별도의 엔티티 타입을 도출한 오른쪽 모델로 만듦으로서 3차 정규화를 완성하였다. 실전 프로젝트에서는 1:1관계의 엔티티 타입이 하나로 통합이 되었거나 업무분석 과정에서 하나의 엔티티 타입에 많은 속성이 포함되어 있을 때 3차 정규화의 대상이 되는 경우가 많이 나타난다. 이 모델에서 함수종속 관계 표기법으로 표기하자면 등록카드번호 -> (등록카드사명, 등록카드유효일자)으로 표시하여 별도의 엔티티 타입으로 분리할 수 있다.
제공 : DB포탈사이트 DBguide.net [출처] 정규화(1,2,3정규화 사례)|작성자 뚜루우 |
객체지향을 왜 배워야 하는가? | |
주정섭 [jjsverylong] | 5015 읽음 2004-10-27 15:15 |
객체지향을 왜 배워야 하는가? "간혹 객체지향을 왜 배워야 하는가요? 배우지 않아도 개발하는데 문제가 없는데요"라고 질문하는 사람들이 있다. 사실 어찌보면 맞는 말이다. 객체지향이 대세이기 때문에 배워야 한다는 생각도 좋지 않다. 모든 개발론은 의무감 보다는 실리적인 이유를 따져서 채택해야만 한다. 그렇다면, 객체지향을 왜 배워야 하는지 따져볼 필요가 있다. 가장 중요한 이유는 개발 속도 때문이다. 객체지향이 개발 속도를 향상시킨다는 것은 이미 여러번 증명된 바 있다. 객체지향적으로 개발들면 왜 개발 속도가 빨라질까? 그 이유들을 알아보자. 첫번째로 전면부 코드가 간략화 진다. 객체지향으로 개발하면 상당수의 코드는 뒤로 사라지고, 전면부 코드는 매우 단순해 진다. 뒤로 사라진 코드는 라이브러리리 코드인데, 델파이로 비유하자면, 콤포넌트들과 같다. 델 개발자들이 콤보박스를 사용하기 위해서, TComboBox Class의 모든 소스를 이해해야할 필요가 있는가? 당연히 없다. 델 개발자들은 TComboBox의 사용방법만 알면 되지, 그 모든 소스를 암기하거나 매번 볼 필요가 없다. 그렇다면 내가 만든 코드에도 TComboBox처럼 한번 만들면, 다시 볼일이 없는 라이브러리 성격의 코드가 있기 마련이고, 이런 코드들을 덜어내서 다음에 봐야할 코드량을 줄여야 한다. 사실 어플 코드와 라이브러리 코드의 분리는 매우 중요한 개념이고 이를 어떻게 분리해야하는지 자세한 내용은 이번 세미나로 미루자. 그런데, 중요한 사실은 화면 배경 처리 코드와 거래처의 금액 합계 처리 코드가 한 곳에 있으면 안된다는 것이다. 이는 후일 유지보수를 엄청나게 힘들게 할 수 있다. 두번째 객체지향의 장점은, 설계 방식이 유동적이 된다는 것이다. 처음 설계대로 만들어지는 프로그램은 없다. 왜냐하면 사용자는 프로그램을 모르기 때문에 자신의 요구사항이 어떤 것인지 프로그래머에게 설명을 잘 못하고, 프로그래머는 업무를 모르기 때문에 사용자의 요구사항을 이해하지 못한다. 이러한 관점 차이를 극복하는 방법은, 빠른 시간내에 대략 동작하는 프로그램을 만든 다음, 사용자에게 이런 기능을 원하냐고 확인해 보는 것이다. 빨리 개발하여 확인하고 기능을 수정하고 추가하는 것이, 객체지향이 잘된 프로그램이 비교적 쉬운 이유는, 객체지향 방식에서는 부품 조립 방식으로 프로그램을 만들기 때문이다. 특정 부품이 안맞으면 다른 부품으로 갈아치우듯이 개발한다는 것이다. 세번째 객체지향의 좋은 점은 유지보수가 편해진다는 것이다. 과거 절차지향적 방식에서는 전역변수가 난무하고, 이 전역변수를 사용하는 전역함수간의 관계와 원칙을 개발자들이 일일이 암기해서 해야 했다. 그러나 객체지향에서는 전역 변수를 완전히 없애 버릴 수 있고, 전역변수와 그 변수를 사용하는 전역함수간에 어떤 관계가 있는지 확연히 문법적으로 표시할 수 있다. 다시 말해서, 개발론 중에서 코드 자체가 도큐멘트가 되도록 하란 말이 있는데, 객체지향에서는 클래스란 개념때문에 이것이 훨씬 쉽다는 것이다. 네번째로, 절차지향 방식에 비해서 객체지향 방식은 팀작업에서 훨씬 유리하다. 절차지향 방식에서의 팀작업은 만들 함수를 팀원들이 분담하는 방식인데 비해서, 객체지향에서는 만들 클래스를 팀원들이 보통 분담하게 된다. 이 때문에 진행 방식에서 두 방식은 차이점이 발생하는데, 절차지향에서는 처리 단계를 중시하지만, 객체지향에서는 필요한 프로그램 부품이 뭔가가 중심이 되므로, 월등히 분업이 쉽다. 다섯번째로 객체지향에서는 쪼잔한 버그들로 부터 벗어날 수 있기 때문에, 좀더 중요한 부분의 코딩에 몰두할 수 있게 된다는 것이다. 의외로, 많은 개발자들이 쪼잔한 버그들을 가볍게 본다. 가랑비에 옷 젖는다란 속담이 있듯이, 쪼잔한 버그들이 떼거리로 나타나게 되면 자칫 프라젝트 전체를 포기해야할 지경에 까지 이를 수 있다. 엄청나게 중대한 버그는 차라리 고치기 쉬울 수도 있다. 왜냐면 이런 중대한 버그들은 어떤 경우 그 버그가 재현되는지, 어디를 고쳐야 하는지를 잘 알 수 있기 때문이다. 그런데 쪼잔한 버그들이 떼거리로 발생하면, 그 버그가 언제 발생하는지 판단이 어렵게 된다. 최악의 경우는 쪼잔한 버그들이 뭉쳐서 새로운 버그를 만드는, 즉 버그들이 합성되어 새로운 희안한 버그를 만드는 경우다. 이런 경우, 정말 고치기 힘든 버그가 된다. 고치고서도 해결되었는지 안되었는지 긴가민가한 버그가 된다. 이 쪼잔한 버그들 때문에, 상당수의 개발자들이 날밤 새우는 경우가 허다하다. [맺음말] 최근 몇몇 다른 개발자들의 소스를 받아서본 결과, 이상한 방식으로 코딩을 해놓고 이를 객체지향이라고 우기는 경우가 있었다. 객체지향에는 여러 방식이 있긴 하지만, 제대로 객체지향을 적용했다면, 코딩 체계가 더욱 단순화되어야 하며, 전면부 코드가 매우 간결해 져야 한다. 이전 코드 방식에 비해서 어떤 면에서도 간결화되지 못했다면 뭔가 잘못된 것이다. 만일 이전 코드에 비해서 코딩 절차가 더 복잡해 졌거나, 전면부 코딩량이 엄청 늘어 났다면 이는 최악의 객체지향적 재난이다. 사실 객체지향을 이해하기는 쉽지 않다. 더우기 델파이에 관한 책중에서 이에 대한 체계적인 책은 정말 찾기 힘들다. 많은 델 개발자들이 델파이 팁이나, 델파이 문법 혹은 콤포넌트 사용법에 대해서 지나치게 치중하는 면이 없잖아 있다. 이런 지식도 중요하긴 하지만, 더욱 중요한 것은 올바른 코딩 습관을 몸에 터득하는 것이다. 올바른 코딩 습관을 터득해야만, 개발 속도가 빨라지고, 따라서 납기일내에 프로그램 개발이라는 중요한 약속을 어기지 않게 되고, 그래야만, 사용자는 기꺼이 돈을 지불할 것이기 때문이다. 객체지향과 올바른 코딩 습관을 익히는 가장 좋은 방법은 많은 책을 보고 연구하면서 응용해보는 것이다. 그러나, 단순히 책만보고 이론만 연구해서는 별로 소득이 없을 수도 있다. 객체지향에 익숙한 다른 개발자들의 소스를 뒤져보면서 실전에서 응용해보는 습관을 길러야 한다. 코드로 구체화되지 못하는 개발론은 말짱 헛소리기 때문이다. 이번 세미나가 객체지향의 실전 응용 방법을 여러분들에게 전달하는데 많은 도움이 되기를 바라면서, 마지막 결론을 다음과 같이 내리고 싶다. 객체지향은 델파이 뿐만 현존하는 모든 언어에서도 통용되는 개념이다. 다시 말해서 이 지식은 일회성이 아닌 장기적 이용가치가 있는 실질적인 기술이다. http://cafe.daum.net/delphinegong 주정섭의 델파이 강좌. |
|
두번째 폼이나 다이알로그 박스 초기화를 위해서나 마지막 값을 얻기 위해 프로퍼티나 메소드를 사용할 수 있습니다. 초기화라는 것은 위에서 언급했듯이 생성자를 사용해서 수행할 수 있습니다.
|
|
|
procedure TFromInherit.SetTetx(Const Value: String);
begin
inherited SetText (Value);
if Value = .. then
Button1.Enabled := False;
end;
|
NOTE: Version 2.0 does not have XSD or XML associated files due to structural problems with the UML metamodel.
The current version is found at http://www.omg.org/spec/UML/Current
|
||
2.3 | May 2010 | http://www.omg.org/spec/UML/2.3 |
2.2 | February 2009 | |
2.1.2 |
November 2007 |
|
2.1.1 |
August 2007 |
|
Please note that version 2.1 was never released as a formal specification |
||
2.0 |
July 2005 |
|
1.5 |
March 2003 | |
1.4.2 |
July 2004 |
see ISO/IEC 19501 |
1.4 |
September 2001 | |
1.3 |
March 2000 |
ISO Number | Release date | UML Version | Format | URL |
ISO/IEC 19501 | January 2005 | 1.4.2 | http://www.omg.org/spec/UML/ISO/19501/PDF | |
PostScript | http://www.omg.org/spec/UML/ISO/19501/PS |
두 용어는 비슷하게 생겨서 꽤나 헷갈린다.
사전적 의미를 알아보면..
Override: ~보다 우위에 서다. ~을 넘어서까지 퍼지다. ~을 무효로 하다.
Overload: ~에 짐을 너무 많이 싣다. 부담을 너무 많이 지우다.
사전의 의미만 봐도 대충 감이 온다. override를 하면 이전에 정의한 함수를 무효로 하고 새로 정의한 내용으로 쓰겠다는 의미일거고, overload는 중복해서 정의해서 사용을 하겠다는 의미가 될 것이다.
이제 저 두 용어가 C++에서는 어떤 개념으로 사용되는지 알아보자. (참조: Teach Your Self C++ in 21Days)
Override와 Overload는 [chapter 12. 상속]에 나온다.
아래의 12.4의 예제코드를 보면.. 파랑색으로 되어 있는 부분이 있다.
Dog이라는 클래스는 Mammal이라는 클래스를 상속했다.
그러면서 Dog클래스의 생성자를 overload해서 여러 개 선언을 했다. 별도로 설명은 하지 않겠다.
1: //Listing 12.4 Overloading constructors in derived classes
2:
3: #include <iostream.h>
4: enum BREED { YORKIE, CAIRN, DANDIE, SHETLAND, DOBERMAN, LAB };
5:
6: class Mammal
7: {
8: public:
9: // constructors
10: Mammal();
11: Mammal(int age);
12: ~Mammal();
13:
14: //accessors
15: int GetAge() const { return itsAge; }
16: void SetAge(int age) { itsAge = age; }
17: int GetWeight() const { return itsWeight; }
18: void SetWeight(int weight) { itsWeight = weight; }
19:
20: //Other methods
21: void Speak() const { cout << "Mammal sound!\n"; }
22: void Sleep() const { cout << "shhh. I'm sleeping.\n"; }
23:
24:
25: protected:
26: int itsAge;
27: int itsWeight;
28: };
29:
30: class Dog : public Mammal
31: {
32: public:
33:
34: // Constructors
35: Dog();
36: Dog(int age);
37: Dog(int age, int weight);
38: Dog(int age, BREED breed);
39: Dog(int age, int weight, BREED breed);
40: ~Dog();
41:
42: // Accessors
43: BREED GetBreed() const { return itsBreed; }
44: void SetBreed(BREED breed) { itsBreed = breed; }
45:
46: // Other methods
47: void WagTail() { cout << "Tail wagging...\n"; }
48: void BegForFood() { cout << "Begging for food...\n"; }
49:
50: private:
51: BREED itsBreed;
52: };
아래의 12.5의 예제 코드는 override를 보여준다.
Dog클래스는 Mammal이라는 클래스를 상속받았다. 그러면서 Mammal의 Speak라는 함수를 override해서 사용하는 것이다. (예제코드는 컴파일이 되도록 수정을 했다. VS 2005기준)
#include <iostream>
enum BREED { YORKIE, CAIRN, DANDIE, SHETLAND, DOBERMAN, LAB };
class Mammal
{
public:
// constructors
Mammal() { std::cout << "Mammal constructor...\n"; }
~Mammal() { std::cout << "Mammal destructor...\n"; }
//Other methods
void Speak()const { std::cout << "Mammal sound!\n"; }
void Sleep()const { std::cout << "shhh. I'm sleeping.\n"; }
protected:
int itsAge;
int itsWeight;
};
class Dog : public Mammal
{
public:
// Constructors
Dog(){ std::cout << "Dog constructor...\n"; }
~Dog(){ std::cout << "Dog destructor...\n"; }
// Other methods
void WagTail() { std::cout << "Tail wagging...\n"; }
void BegForFood() { std::cout << "Begging for food...\n"; }
void Speak()const { std::cout << "Woof!\n"; }
private:
BREED itsBreed;
};
// 코드 옆에 주석 부분이 그 줄을 실행했을 때 나온 결과이다.
int _tmain(int argc, _TCHAR* argv[])
{
Mammal bigAnimal; //Mammal constructor...
Dog fido; //Mammal constructor...
//Dog constructor...
bigAnimal.Speak(); //Mammal sound!
fido.Speak(); //Woof!
return 0; //Dog destructor...
//Mammal destructor...
//Mammal destructor...
}
결과를 보면..bigAnimal은 Mammal클래스이므로 Speak를 호출했을 때 "Mammal sound!"를 출력한다. 그러나 fido는 Dog클래스이고, Dog클래스는 Speak함수를 override하였으므로 "Mammal sound!"대신에 "Wood!"를 출력한다. 즉, Mammal의 Speak함수가 무시된 것이다.
출처: http://blog.naver.com/phrack?Redirect=Log&logNo=80040464488
출처: e-campus 쉽게 따라 배우는 UML
UML 2.0의 다이어그램
이탤릭은 실존하지 않는 분류
빨간색은 새로 추가된 다이어그램
- Composite Structure Diagram
- Package Diagram
- Interaction Overview Diagram
- Timing Diagram
파란색은 이전 1.3의 다이어그램에서 이름이 바뀐 것
- Collaboration Diagram > Communication Diagram
- Statechart Diagram > State Machine Diagram
UML 2.2 has 14 types of diagrams divided into two categories.[11] Seven diagram types represent structural information, and the other seven represent general types of behavior, including four that represent different aspects of interactions. These diagrams can be categorized hierarchically as shown in the following class diagram:
3.stack과 heap의 차이점 (heap도 자료주고의 heap정렬로 생각했는데 잘..흠)
가장 큰 차이는 stack은 LIFO의 형태이다. Heap은 그냥 메모리 공간이다. stack은 주로 작업할때 데이터를 임시 저장하는 용도로 사용한다. 함수내부의 local변수들은 stack을 이용한다. 함수가 호출되면 stack에 함수 반환시 돌아올 주소영역을 저장하고, 함수에서 쓸 local변수들 크기만큼 할당을 받는다. 다시말해서 local 변수들은 stack을 이용하는 것이다. 함수가 반환되면 이 stack영역은 자동으로 삭제가 된다.
heap은 주로 프로그램 시작시 할당할 크기를 결정할 수 없고 동적으로 할당해야 할 필요가 있을 때를 위한 메모리 영역으로써 사용자가 직접 할당하고 해제해 주어야 하는 메모리 영역이다.
stack에 저장된 data 항목들 중에 먼저 삽입된 것은 나중에 삭제되고, 나중에 삽입된 것이 먼저 삭제된다. 그래서 stack을 후입 선출 리스트(Last- In-First-Out List)라고 부른다.
새로운 함수가 호출되면, return 될 때 어디로 돌아가야 할지를 알아야 하고, 넘어온 parameter에 대해서도 저장해 놓아야 하며, 함수 안에서 선언된 변수들도 저장해야 한다.
함 수 호출시 이러한 정보를 묶어서 stack에 집어넣는다. 함수 수행도중 또 다른 함수가 불리면, 해당 함수의 정보도 stack에 넣는다. 만일 함수내부수행이 끝나서 return이 되면, 해당 함수에 관련된 자료는 필요가 없게 되어 stack에서 꺼낸다.
stack의 구조상 다음 꺼낼 차례는 방금 return 된 함수를 호출한 함수이다. 그러므로 호출한 함수의 정보를 읽어 함수내부의 그 다음 줄을 계속 수행할 수 있다.
이런 식으로 stack에 넣고(push) 빼는(pop)일련의 작업들을 하면서 프로그램이 돌아가게 된다.
책 에서 보면 stack영역에 저장되는 변수의 내용은 local변수 혹은 지역변수라고 하는 스코프를 벗어나면, 사라진다고 하는데 위에서 설명한 것처럼 return 된 함수의 내용을 stack에서 꺼내 버리기 때문에 없어지는 것이다. 하지만, 필요에 의해서 malloc 또는 new를 이용하거나, static으로 선언한 경우에는 이러한 호출stack에 data를 저장하지 않는다. 따로 그 변수만을 위한 메모리의 공간을 할당하여, 함수들이 호출이 되든 return이 되든 data가 유지될 수 있도록 한다. 이러한 할당 공간을 heap이라고 부른다.
<stack의 구조>
Heap 은 여러개의 노드들 가운데서 가장 큰 키 값을 가지는 노드나 가장 작은 키 값을 가지는 노드를 빠른 시간내에 찾아내도록 만들어진 자료 구조이다. heap은 완전 이진 트리의 하나로서 각각의 노드는 유일한 키 값을 가진다. Heap은 다른 말로 Priority Queue라고 한다.
Priority Queue는 값들의 콜렉션으로부터 가장 큰 값을 신속하게 찾거나 제거할 필요가 빈번하게 발생하는 상황에서 유용하게 사용할 수 있다. 즉, 중요도에 따라 수행할 작업들을 정리하고, 가장 급박한 것을 골라 수행한다.
http://www.mydiyworld.net/?p=440