#title 직책/직무/직급 [[TableOfContents]] ==== 사례 ==== 분류테이블로 * 직책 (컬럼:직책코드, 직책명) * 직무 (컬럼:직무코드, 직무명) * 직급 (컬럼:직급코드, 직급명) 이 있다. 사원테이블 구성이 문제인데 2가지 타입을 생각하고 있다. * A TYPE : 사원번호, 이름,직책코드,직책명,직무코드,직무명,직급코드,직급명 * B TYPE : 사원번호,이름 직책코드,직무코드,직급코드 B TYPE으로할 경우 ASP화면에 아이디 이름 직책명, 직무명, 직급명으로 나타낼 경우(또 다른 분류테이블이 많아질 경우) SQL문이 복잡하게 되는데 어떤 설계가 유리한 설계인가? ==== 무엇이 문제인가? ==== 잘못된 것부터 고치고 넘어가자. 일단 테이블이라는 것은 물리적인 용어이다. 물론 지금 상황의 경우는 간단하여 바로 물리설계(테이블설계)가 가능하지만 실제 프로젝트에는 이렇게 하면 곤란하다. 일단 분류테이블이라고 하는 것을 “코드엔티티(집합)”으로 명칭을 수정하겠다. (물론 실제로 정규화라는 것은 관계형 데이터 모델의 용어 즉, 논리적인 것인데 현재까지도 관계형으로 대부분의 설계가 이루어지기 때문에 구분을 크게 두지는 않는다.) 그렇다면 직무, 직책, 직급의 의미는 무엇일까? 네이버 국어사전에는 다음과 같이 나온다. * 직무(職務) (직업으로서) 맡아서 하는 일. ...¶손을 안내하는 일이 그의 직무다.... (준말)직(職). * 직책(職責) 직무(職務)상의 책임. * 직급(職級) 공무원의 직계제(職階制)에서, 관직을 직무와 책임에 따라 분류한 최소의 단위 이것은 조직에 따라 틀려질 수 있다. 이것은 업무를 분석해야만 나오는 정답이다. 직급의 경우 ‘직무와 책임에 따라 분류한 최소의 단위’ 라고 정의되어 있으므로(물론 사전적인 의미이다. 해당 조직에서 다른 의미로 쓰인다면 그것이 직급의 정의이다.) 직급은 하나의 직급은 여러 개의 직무와 그에 따르는 책임이 주어질 수 있다. 여기에서는 업무규칙이 정해졌고 그에 따르는 ERD가 다음과 같이 그려졌다고 가정하자. attachment:design_tuning01.jpg 이렇게 ERD를 그렸다면 상당히 상세하게 된다. (물론 관계명은 관계 맺은 테이블들의 관점에서 모두 정의를 했어야 하지만 여기서는 이 정도로 끝내겠다.) 그러나 위의 질문을 보면 직급과 직무, 직책의 관계는 위와 같은 관계로 볼 수 없다. 그저 사원의 속성으로 판단되는 것을 볼 수 있다. 물론 각각의 사원이 하나 이상의 직급을 가질 수도 있고, 여러 개의 직무를 가질 수 있으며, 직무에 대한 책임인 직책도 여러 개를 가질 수 있다. 이렇게 본다면 또한 사원의 직급, 직무, 직책은 다중값 속성이 되어 또한 1정규화(반복그룹이 있다.) 위배이다. 그러나 위의 질문에서는 다중값 속성이 아니라고 판단되고, 반드시 있어야 할 속성으로 판단하여 ERD는 다음과 같이 그려질 수 있다. attachment:design_tuning02.jpg 질문에서는 A타입의 테이블과 B타입의 테이블 중 어떤 것이 좋을까 하고 물었다. 결론부터 말하면 당연히 B타입이다. 그 이유를 살펴보자. 먼저 A타입을 살펴보자. 다음과 같이 속성들간에 종속이 발생했다. 종속성만 판단되면 지금까지 필자가 열심히 떠들었던 것은 필요 없이 다이렉트로 정규화를 할 수 있다. * 사원번호 -> 이름 * 직책코드 -> 직책명 * 직무코드 -> 직무명 * 직급코드 -> 직급명 이렇게 본다면 직급코드, 직무코드, 직책코드라는 설계속성이 필요하지 않다는 것을 느낄 수 있을 것이다. 대부분 코드를 쓴다는 것은 테이블의 크기를 줄이고, 데이터의 무결성을 위한 것이다.(물론 프로그램을 생각해서 그럴 수 있다. 좋은 사고방식이 아니지만…) 코드테이블을 씀으로써 테이블의 크기를 줄인다는 것은 말그대로다. 직책코드가 ‘1’이고, 직급명이 ‘부장’이라고 다면 당연히 테이블에 저장되는 데이터가 ‘부장’보다는 ‘1’이 크기가 작다는 것을 알 수 있다. 데이터의 무결성은 코드테이블과의 관계를 맺어줌으로써 테이블에 들어가지 말아야 할 데이터를 막아주는 것과 같다. (check조건과 의미가 같다.) 결론적으로 A타입의 테이블의 경우 코드라는 자체가 불필요하다. 코드테이블이 존재하는 것은 데이터베이스에서 피해야 할 가장 중요한 문제인 ‘데이터 중복’에 걸리는 것이다. ==== 실제로 처리양을 따져보자 ==== 개발자들이 위와 같이 테이블을 만드는 이유는 아마도 두 개의 테이블을 접근하는 것(조인)보다 하나의 테이블에 접근하는 것이 더 빠르겠지라는 막연한 생각 때문일 것이다. 과연 빠를까? 답은 아니올시다이다. 이유를 살펴보자. A타입으로 테이블을 생성했을 때 다음과 같이 쿼리했다고 가정하자. {{{ SELECT 아이디, 이름, 직무명 FROM 사원 }}} 사원테이블에 1만건이라고 가정하고 아이디의 길이가 8바이드, 이름의 길이가 8바이트, 직무명의 길이가 10바이트라고 가정하면 다음과 같이 I/O양이 계산이 나온다. 10000 * (8 + 8 + 10) = 260000 바이트 그러나 직무코드가 100건이고, 다음과 같이 조인을 하였다면 어떻게 계산될까? {{{ SELECT A.아이디, A.이름, B.직무명 FROM 사원 A INNER JOIN 직무코드 B ON A.직무코드 = B.직무코드 }}} 이 쿼리는 다른 조건들이 없으므로 무조건 직무코드부터 읽혀질 것이다. 물론 Merge Join이라면 동시에 읽어서 정렬 후 비교 할 테지만 말이다. 쉽게 계산하기 위해서 두 테이블을 한번 씩 풀스캔했다고 생각해보자. 위에서와 마찬가지로 직무코드에 대한 계산을 빼고, 결과 집합을 놓고 계산을 하면 직무코드 테이블에서 읽은 것 100*10 = 1000 바이트 사원테이블에서 읽은 것 10000 * (8 + 8) = 160000 바이트 총 161000 바이트다. 두 개의 쿼리문에서의 입/출력 양의 차는 약 100000 바이트나 차이가 난다. 아마도 사원테이블을 시간이 지날수록 비대(퇴사한 사원의 정보를 지우지 않고 있다면..)해 질 것이며, 이해 비해 직무코드 테이블은 별로 커지지 않을 것이다. ==== 결론 ==== 이로써 질문에 대한 답은 B타입으로 결정되었을 것이다. 그러나 이것으로 끝나서는 안된다. 필자는 가끔 이런 경우 코드테이블이 과연 필요할까 생각해본다. 어떤 이유가 있겠지만 그 이유가 나중에 응용 프로그램에서 if(1==m_strCode) m_strName = ‘부장’ else if … 라면 실망스러울 것이다. 또 한가지 생각해야 할 것은 코드 엔티티 집합를 하나로 두느냐 여러 개로 두느냐이다. 필자의 소견으로 이런 코드 엔티티 집합은 하나로 통합해 놓는 것이 유리하다고 본다. 따로 따로 떨어뜨려 놓아도 설계를 잘한다면 문제가 없겠지만 대부분 코드 엔티티 집합 때문에 실제 개발에서 이상한 코드로 변신하는 경우와 비효율적인 SQL을 작성하는 것을 많이 볼 수 있었다. 실제로 위와 같은 경우는 직무코드, 직책코드, 직급코드란 것은 전혀 필요 없는 쓰레기 데이터다. 코드라는 것은 필요한 것에만 코드를 만들어야 한다. 코드라는 것에 감싸져서 그 속을 들여다 볼 수 없게 될 수도 있다는 것과 잘못된 코드 엔티티 집합으로 인한 영향은 정보의 질을 떨어뜨린다는 것을 꼭 명심해야 한다. 아직도 가끔 웹의 게시물을 보면 조인은 느리다라는 생각을 가지고 계시는 분이 있다. 위에서 보는 바와 같이 조인을 하면 느려지는 경우는 거의 없다. 대부분 DBMS의 옵티마이저가 실행계획을 잘못 세운 탓이다. 그러나 이것은 대부분 사용자의 잘못이다. 쿼리문을 인덱스를 사용하지 못하게 하거나 비용기반의 옵티마이저의 경우 통계정보가 부실해서 일 수도 있다. 그러나 이러한 문제들보다 더 중요한 것은 설계자체의 문제이다. 데이터베이스가 파일 시스템을 능가할 수 있었던 원인은 바로 데이터의 중복을 최대한 없애려고 노력한 것에 있다. 데이터의 중복은 곧 입/출력의 양이 많아짐을 의미한다. 이러한 문제를 해결해 줄 수 있는 가장 유명한 툴은 바로 ‘정규화’이다. 정규화는 데이터의 중복을 없앰으로써 최적화된 데이터를 관리할 수 있게 해주고, 또한 여러 가지 이상현상들을 방지해 줌으로써 데이터의 질을 높이고, 이에 따라 좋은 정보도 제공해 줄 수 있게 해준다. 개발자들은 데이터베이스가 단지 ‘데이터의 저장소’ 정도로 인식하지 말고, 수많은 사람들의 노력이 깃들어 있는 정보의 메커니즘으로 생각을 해야 한다.