[None-DBUnit ] 거미줄 프로젝트 II

Posted at 2010.07.02 17:38 // in Project Life // by MOOVA 무바㏇
본고는 얽히고 섥힌 프로젝트에서 테스트 데이터 콜랙터라는 솔루션 제작과정을 그렸다.

기능 개발과 협의건 이외에 따로 시간을 내어 만들어 둔 유틸리티성 솔루션이다. 이것은 ROI를 높이기 위해 개인적으로 사용한 방법입니다.

Migration프로젝트에선 테이블이 빈번하게 생성되고 삭제된다. 또한, 컬럼도 수시로 바뀌고 삭제된다. 이런 경우 테스트 데이터의 입수란 여간 어려운 일이 아니다. 그 와중 필자가 제공한 Random-Access 방식의 Test Data Collector 기법을 사용하면 여러모로 수고를 줄일 수가 있다.


[눅 22:23] 그들이 서로 묻되 우리 중에서 이 일을 행할 자가 누구일까 하더라


하고자 하는 것


하고자 하는 목표는 매우 단순합니다. 미리 준비된 사전파일을 랜덤으로 조회하여 테이블 연관에 맞게 마스터 테이블기분으로 연관된 데이터를 10만건 이상 확보하는 것입니다. 중요한것은 자동으로 처리해야 한다는 점입니다.

Master Table을 중심으로 연관된 테이블의 도표를 잠시 살펴보자 ( 단순한 설명을 위해서 DBLink, Synonym과 같은 기능은 제거했다. )

그림 1. 테이블간 연관(relation ship)

어떻게 데이터 정합성에 맞게 테스트 데이터를 자동으로 입력할 수 있을까? 만약에 외래키가 포함된 경우라면 자식의 테이블을 검색하여 최종 자식을 얻어낸 후 그에 맞는 데이터를 적당하게 입력해야 한다.

마스터 테이블에서 참조해야 할 코드성 데이터를 먼저 검색한 후, 적당한 코드를 로우 단위로 마스터 테이블에 적재할 준비를 한다. ( 이때는 프로젝트에서 실제로 사용된 코드를 사용하는 것이 좋다. ). 동시에 병렬작업으로 외래키로 연관된 테이블을 검색한 뒤, 만약에 연관된 테이블이 검색되었다면 특정한 자료구조에 그 테이블의 주소 값을 적재한다. 여러 차례의 재귀 호출을 통해서 외래키로 연관된 테이블을 반복적으로 검색하여 제일 마지막의 자식 노드를 찾는다. 자식 노드로부터 역으로 순환하면 제일 루트의 테이블은 언제나 마스터 테이블이 된다. 위와 같은 방식으로 일련의 규칙을 찾을 수 있다.

필자는 위의 규칙을 두 가지 방법으로 풀어보았다.

하나는 해쉬 자료구조를 이용하는 것과, 또 다른 하나는 DSL언어로 표기해 자동화하는 방법이다.


1. 해시 자료구조를 이용하는 방법

위 테이블의 연관구조를 해시 테이블로 변환할 경우 고려해야 할 사항이 몇 가지 있다.
테이블을 하나의 객체로 보는 관점이 아닌 컬럼을 하나의 객체로 봐야 한다. 그래야만 해시 알고리즘 중 버킷의 개념과 슬롯의 개념을 사용할 수 있다.[각주:1] 또한, 테스트 데이터 입력 시 충돌(Collision)이 될 만한 부분을 버킷 안에 리스트로 적재함으로써 데이터 충돌의 예방도 했다. 이렇게 일련의 해시 테이블이라는 자료구조를 얻을 수 있다.


그림2. 테이블의 외래키를 해시로 펼친 도표 ( 빅-오(O) 표기법: O(n) )

메모리에 올라온 해시 테이블에 딕셔너리파일에 포함된 문장을 랜덤 조회하여 값을 순차적으로 입력한다.
이때 참고해야 하는 랜덤입력값의 순서는 다음과 같다. (해시 테이블의 알고리즘은 보통 O(1) 표기법을 따르지만, 외래키가 포함된 관계로 상수를 제외한 O(n)으로 표현되었다.)
코드컬럼 값 입력 -> 외래컬럼 (반복 외래컬럼 검색 후 값 입력) -> 일반컬럼 값 입력

준비물 : 코드엑셀파일, 딕셔너리파일
메모리 : 해시 테이블
프로그램 설명 :
1.
마스터테이블을 메모리에 올려 해시 테이블을 만든다.
2. 클라이언트 프로그램은 램덤으로 딕셔너리 파일을 조회하여 적당한 문장을 찾는다.
3. 입력할 문장을 뽑아 온 후 순서에 맞게 값을 입력한다. 만약에 해시테이블에서 코드컬럼이 발견될 경우 미리 준비한 코드엑셀파일로부터 코드의 값을 검색해 딕셔너리파일문장대신 값을 입력한다. (코드컬럼 값 입력 -> 외래컬럼 (반복 외래컬럼 검색 후 값 입력) -> 일반컬럼 값 입력)
4. 모든 값이 입력되었다면 DB에 한 Row를 Insert한다.
5. 2로 돌아가 순서를 반복한다.
제약사항 : 입력한 Row의 개수를 파라미터로 정할 수 있다. 본인은 이 프로그램으로 자동생성된 테스트 데이터를 10만건 이상 확보했다.



2. DSL로 해결하는 방법

DSL은 Martin Fowler[각주:2]의 설명을 참고하길 바란다. (http://martinfowler.com/bliki/dsl.html)
그림1을 DSL로 표기하면 다음과 같은 형태를 취하게 된다.( 필자는 DSL 에디터를 제공하는 eclipse의 xtext[각주:3]를 사용하였다. 조만간 블로그에 xtext에 대한 블로깅을 집약적으로 올릴것이다. )

type (
  General Column : gc
  Reference Column : rc
  Code Column : cc
)

Master Table (
   gc : Col1
   rc : Sub Table1 Col2
   rc : Sub Table2 Col2
   cc : Col4
)

Sub Table 1 (
  gc : Col1
  rc : Sub Table3 Col2
  rc : Sub Table4 Col1
)

Sub Table 2 (
  rc : Sub Table4 Col2
  rc : Sub Table5 Col2
)

Sub Table 3 (
  gc : Col1
  gc : Col2
)

Sub Table 4 (
  gc : Col1
  gc : Col2
)

Sub Table 5 (
  gc : Col1
  gc : Col2
)

해시 테이블을 이용하는 방법 대신 DSL 문장 파일을 사용해서 중첩구조를 표현할 수 있다.
또한, 이 파일을 중심으로 데이터를 자동으로 입력 할 수 있게 된다.

준비물 : 코드엑셀파일, 딕셔너리파일
메모리 : DSL 파일로 읽은 중첨된 객체 or 자료구조
프로그램 설명 :
1.
DSL을 메모리에 로드해 중첩구조를 띤 객체를 생성한다.
2. 클라이언트 프로그램은 램덤으로 딕셔너리 파일을 조회하여 적당한 문장을 찾는다.
3. Master Table에 rc가 있는 경우 해당 객체를 참조하여, 최종 자식 객체를 찾는다.
3. 입력할 문장을 뽑아 온 후 순서에 맞게 값을 입력한다. 만약에 cc가 발견된 경우 미리 준비한 코드엑셀파일로부터 코드의 값을 검색해 딕셔너리파일 문장 대신 값을 입력한다. (코드컬럼 값 입력 -> 외래컬럼 (반복 외래컬럼 검색 후 값 입력) -> 일반컬럼 값 입력)
4. 모든 값이 입력이 되었다면 완성된 마스터 테이블과 데이터베이스간에 동기화를 시작한다.
5. 2로 돌아가 순서를 반복한다.
제약사항 : 입력한 Row의 갯수를 파라미터로 정할 수 있다.



 그렇다면 결론은 무엇인가?

필자는 정말 험난한 프로젝트를 여러 번 진행했다.
거미줄 프로젝트는 말로 표현할 것도 없었으며, 쓰러져 가는 프로젝트에 막판 정리자로 투입도 해 봤다.
한 컨설팅 벤더사가 덤탱이 쓸 문제도 스스로 찾아가 그 회사의 입장을 문제 해결로써 대변하기도 하였다.
한 대형 회사가 맡아서 해야 할 아키텍트 관련 업무도 떠 넘겨받아서 처리를 했었고, 매번 공통 팀과 연관되어 프로젝트를 진행했다. 그 와중에 코드 베이스로써의 역할도 진행했고 ( 일반 SI에서 코드베이스 역할은 굉장히 중요하다. 왜냐하면, 대 다수의 개발자들은 코드베이서가 만들어 놓은 중심코드로부터 모든 것을 복사하고 붙여 넣기 때문이다.), 매 프로젝트마다 얹혀가기나 묻어가기는 꿈도 꾸지 못할 정도로 항상 험난한 프로젝트를 진행했다고 생각한다. ( 그래서 필자는 매번 묻어가는 사람과 매우 다른 견해를 밝힌다. )

이런 경험 중에 얻었던 중요한 깨달음은 그래도 발전하고 있다는 사실이다.
한 프로젝트를 끝마치고 나면 일종의 후유증으로 고생해야 했으며, 그나마 나의 존폐를 유지할 수 있었던 것은 하나 하나 발전하고 있다는 사실을 확인 했기 때문이었다. 현 포스팅의 경우 DBUnit을 사용해야 했지만, 위와 같이 거미줄 냄새가 나서 사용할 수 없었던 경우, 어떻게 해결했는지에 대한 정보를 공유하기 위해 일단 글을 시작했다.
Migration프로젝트에서 새로운 시스템을 만들어내고 기존의 데이터까지 병합하는 것은 여간 힘든 작업임이 분명하다. 조직구성도 통합과정에서 가상조직을 만들어서 진행해야 했으며 조직도 3사가 통합을 해 보안규칙이나 인증체계도 여간 복잡했던게 아니다.
떄로는 화면개발자들에게 적합한 데이터를 제공해 주어야 하는데 때에 따라선 그렇지 못할 경우도 비일비재했다. 따라서 데이터 개발자들과 로직 개발자, 화면 개발자들 사이에 교착상태를 줄여주기 위해선 위와 같은 솔루션을 제공해야 바람직하다. ( 해당 업무는 적당한 기간안에 납품을 마친 바 있다. ) 실제로 DBUnit을 사용하기 취약한 환경이라면 엑셀파일로라도 테스트파일을 구비해 진행에 막힘이 없는 솔루션을 제공해야 한다.

하지만, 우리 개발자들은 너무도 힘들다. 말도 안 되는 일정에 힘에 의한 중노동.. 그것도 모자라서 불철주야 야근에 주말 근무까지.
그런 환경에서 조금이나마 일찍 퇴근하기 위해서 한 프로젝트에서 제공했던 것이 바로 이 Random-Access 방식의 Test Data Collector이다.

  1. 해시 알고리즘에 대해 학습을 원한다면 다음의 URL과 책자를 참고하자. 
1. http://it.toolbox.com/blogs/codesharp/hashing-algorithm-25268
2. http://kangcom.com/sub/view.asp?sku=200504280001
3. http://kangcom.com/sub/view.asp?sku=201001150003 [본문으로]
  2. Martin Fowler의 설명에 따르면 DSL은 외부 DSL과 내부 DSL로 나뉜다고 한다. 하지만 필자는 internal DSL과 external DSL을 넓은 의미의 DSL,좁은 의미의 DSL로 의역해야 함이 맞다고 본다.
1. http://martinfowler.com/bliki/dsl.html
2. http://younghoe.info/126 [본문으로]
  3. http://www.eclipse.org/Xtext/ [본문으로]
저작자 표시 비영리 변경 금지
신고
블로그코리아에 블UP하기

댓글을 남겨주세요.

[None-DBUnit ] 거미줄 프로젝트 1

Posted at 2010.07.02 16:47 // in Project Life // by MOOVA 무바㏇
시편 116:10 : 내가 크게 고통을 당하였다고 말할 때에도 나는 믿었도다


Migration 프로젝트에서 항상 주목해야 할 부분은 정확한 연관 데이터[각주:1]의 취득이다. 만약에 새롭게 구축할 데이터베이스 연관(Database RelationShip)이 현재 진행 중이거나 정규화가 제대로 이루어지지 않고 있다면,  기존 DB 연관을 새로운 DB 연관과 매핑하는 작업도 상당한 시간이 걸린다는 것은 그다지 놀랄 일도 아니다.


Migration 프로젝트에서 발생할만한 데이터 관점의 이슈는 다음과 같다.
1. 10년 이상 된 쌓이고 쌓인 Dirty-Data의 연관성을 파악하기 어렵다.
2. 기존 소스의 일관성을 파악하기 힘들다.
3. 테스트 데이터를 쉽게 취득할 수 없다.
4. AS-IS를 분석했던 문서나 사람이 없으면 아예 새롭게 테이블을 설계하는 것이 좋은 방법이다.
5. 1~4를 포함해서 통계와 배치와 관련된 업무를 진행해야 한다면 그 문제는 더욱 심각해진다.

** 위의 열거한 모든 목록과 함께 일정은 2주 뒤에 완공 될 예정(일정)이다. 캑!!!!

이런 경우 대부분의 엔지니어은 나 몰라라 입장을 취할 것이다. 이런 이슈는 회사의 문제지 개인의 문제는 아니다라는 식이다. 마치 그 선택이 현명한 방법인양 전문가라는 타이틀을 던져 버릴 수도 있다. ( 그것이 정말 현명한 방법이라면 우리는 내가 하고 싶은 것, 내가 잘하는 것만 골라서 하게 되는 이른바 반쪽 전문가가 될텐다. )  하지만 제대로 된 전문가라면 그 일정을 맞춰주는 노력을 해야 하며, 계약서상에 명시한 대로 별 탈 없이 진행해야만 남들이 인정할 수 있는 전문가가 될 수 있지 않을까? 일정을 협의하여 연기하거나 불가능한 지표에 대한 데이터를 고객에게 전달하거나 하는 방법을 써서 일정을 더욱 유연하게 얻어내는 것도 융통성 있는 선택이 될 수 있다.
하지만, 그런 노력조차 할 수 없는 상황이라면 여러분들은 어떤 입장을 취할 것인가?

뷰티풀 아키텍처의 닮은 듯 다른 두 소프트웨어 이야기에서는 위와 같은 상황을 무계획 도시라고 말하고 있다.

그림 1. 무계획 도시

그림 2. 거미줄

뷰티풀 아키텍처 발췌

여러 날이 지나도 아무것도 나아지는 게 없고, 이전 개발자들이 만든 코드를 익히는 데 엄청난 시간이 소요되고, 시스템에 접근하는 명백한 경로조차 없다. 또 코드 냄새(마틴 파울러)가 코드 베이스의 이곳저곳에서 풍겨왔고 마치 매립지에서 나는 냄새 같았다. 이것을 개선하기 위해 다시한번 새로운 레이어가 도입되었고 너무나 당연히 문서화 작업도 이루어지지 않았다.
이는 적신호 였으니, 무계획 도시를 한 눈에 볼 수 있는 지도가 필요했고 여기저기 수소문한 끝에 전체적인 그림을 볼 수 있는 구조를 얻어냈다. ( 그림1. 무계획 도시 )
회사의 초창기에 수많은 신제품들을 빨리 출시해야 한다는 압력을 받으며 시작을 한다. 일정의 지연은 용납될 수 없었고, 이는 회사의 존폐가 걸려있는 문제로 인식되었다. 이러한 압력 속에 소프트웨어 엔지니어들은 인간이 할 수 있는 한 빨리 코드를 짜야 했고, 그 결과 미친 듯이 급히 짠 코드의 연속으로 무계획 도시 시스템이 만들어졌던 것이다.

10여년간 이상을 유지보수 해 왔던 대형 사이트의 데이터와 중요한 비즈니스 로직은 초반에 설계한 목적을 쉽게 찾아볼 수 없을 정도로 구조가 깨져 버려 있는 그림을 흔히 접하곤 한다. 중간마다 비 정형화된 테이블의 설계나 때움식 소스코드 입력등, 얼마나 많은 유지보수 인력들이 수년간 비공식적으로 땜빵처리를 해 왔을까?! 난지도의 쓰레기를 보듯 본인의 두 눈앞에서 해결해야만 했던 안타까움은 이루 말할 수가 없었을 것이다.

여기서 피트 굿리프는 필자가 말하고자 하는 것과 같은 견해를 보이고 있다.

해당 프로젝트가 훌륭하거나 즐거운 작업이었기 때문이 아니라 소프트웨어 개발과 관련한 소중한 교훈을 얻었기 때문에 그러하다.

옳거니!. 프로젝트가 훌륭했거나 즐거운 작업이었기 때문이 아니라, 말도 안 되는 그 일정을 맞추기 위해서 해야 했었던 고뇌의 고통과 소중한 교훈을 얻어낼 수 있었다는 기쁨. 고스란히 그 감정이 책을 타고 넘어와 필자와 교감이 되었던 부분이다.

그림3는 Migration 프로젝트에서 흔히 볼 수 있는 데이터베이스간 매핑도이다.


그림3. 데이터베이스 마이그레이션 매핑


프로젝트 내부 규약에 따라 매핑문서를 만들어 두었다. (보통 TO-BE,AS-IS DB 매핑 문서라함) 무계획 도시 안에서 매핑 규약을 만드는 것은 정말 험난한 작업의 연속일 것이다. 전체적인 컴포넌트 다이어그램이나 전체 구조를 파악할 수 있는 그림(그림1)이 없다면 이런 매핑 규약도 유일무이 해지기 뻔하다. 이처럼 비공식적인 다발적 단계의 발생은 또다시 프로젝트를 교착상태[각주:2]에 빠지게 한다. (컬럼 등록을 하고 작업자를 등록한다. 컬럼 승인 확정이 나면 다시 한번 개발자는 테스트 데이터를 마련해야 하고 테스트 시나리오를 검증을 해야한다. 동시에 다발적으로 다른부서의 결정에 의해 이쪽 부서의 설계가 영향을 받 다면 어떻게 될까? 테이블이 생성되고 공지없이 삭제되는 과정에서 테스트데이터의 취득이란 마치 보잉 747기의 파편중 하나가 새로운 외계물질로 변화되는 과정과 같을 정도로 어려울 것이다.)

무계획도시 위에서 해야만 하는 업무는 깨끗한 종이 위에서 할 수 있는 일의 복잡도에 비해 무려 100배나 달하는 복잡지수를 만끽할 수 있을 것이다. 쓸데없는 프로세스를 따라가느라 번외작업을 상당수 거쳐야 하는 노릇이기 때문이다.

더군다나 이런 상황에서 일정이 빡빡한 것은 기본이다 (이런 막연함은 개발자라면 누구나 한 번쯤은 경험했다.)

초장에 설명한 바와 같이 Migration프로젝트의 주요 관심사는 데이터의 정합성이다. 하지만 이런 거미줄과 같은 프로젝트에서는 정합한 데이터를 쉽게 모을 수도 없을뿐더러, 어떤 데이터가 어떤 비즈니스 로직과 연관이 되어 있는지 판단하기도 어렵다. 데이터 설계가 끝나지 않았는데 일정이 내일모레!?까지라면 더욱 가관이다. 일정을 맞추기 위해서 데이터의 정합성을 포기하고 기존에 있지도 않은 모든 방법을 총동원해 일정을 맞추려 할 것이 뻔하기 때문이다.

DBUnit[각주:3]?!를 사용해 볼까?

 당치도 않은 소리다. 필자는 이런 막연한 상황에서 DBUnit과 같은 툴을 이용해 테스트를 해 보려고 시도해 봤으나, 수많은 테이블이 얽히고 섥혀 있었고 현재 진행중인 테이블들은 개발자 공지없이 수 없이 바뀌고 있었다. (물론 DBUnit과 같은 동조의 툴은 워낙많아서 생략하겠다.) 새로운 연관이 매 시간마다 다른 부서에서 생성되고 있었으며, 배치업무와 모든 업무를 통괄해야 하는 통계업무마저 동적인 테이블 설계속에서 살아남아야했다. 이런 경우 DBUnit은 적당한 툴의 선택이 아니다. DBUnit을 사용하려면 정규화된 수 많은 테이블(100개이상)의 연관을 알고 있어야 하며, 코드규약 또한 맞춰 줘야 하기 때문이다.


이와 같은 상황에 필자가 선택한 히든카드는, Random-Access방식의 Test Data Collector이다.
  1. 정확한 연관 데이터란 정규화를 통해 설계된 테이블에서 발생되어진 정합한 데이터를 말한다. [본문으로]
  2. 교착 상태(膠着狀態)란 두 개 이상의 작업이 서로 상대방의 작업이 끝나기 만을 기다리고 있기 때문에 결과적으로 아무것도 완료되지 못하는 상태를 가리킨다. [본문으로]
  3. http://www.dbunit.org/ [본문으로]
저작자 표시 비영리 변경 금지
신고
블로그코리아에 블UP하기
  1. Favicon of http://minimonk.net BlogIcon 구차니

    2010.07.03 00:39 신고 [수정/삭제] [답글]

    DB 공부를 해보고 싶은데 한번 MOOVA님께 가서 사사를 받아야겠어요 ㅎ

댓글을 남겨주세요.

티스토리 툴바