크리에이티브 커먼즈 라이선스
Creative Commons License

경제학에는 수확 체감의 법칙과 한계효융의 체감 법칙이 있다.


수확 체감(diminishing returns)이란 일정한 면적에 노동력을 추가 투입했을때 수확량(혹은 생산성)의 증가가 노동력의 증가를 따라가지 못하는 현상을 말한다. 즉, 노동력의 투입이 결코 생산성과 연결될 수는 없으며, 과다 투입된 노동력에 대해서는 단위 면적을 넓히던가 아니면 더 생산적인 수단 방식을 사용해서 효율을 높여야 함을 의미한다.


한계효용(marginal utility)은 재화나 용역이 증가 혹은 감소함에 따라 주관적으로 매겨지는 가치의 관계에 대한 개념이다. 예를 들어, 갈증이 심할 때 먹는 50원의 물의 가치와 그러한 갈증이 해결된 후에 먹는 50원의 물의 가치는 절대적인 수치는 동일할지라도 이를 접하는 이의 주관적인 가치는 차이가 발생하게 된다.


Fields of Gold
Fields of Gold by Werner Kunz 저작자 표시비영리동일조건 변경허락


우리가 시스템을 개발할 때에도 이러한 법칙은 간혹 나타나기도 한다. 초반 시스템의 형상이 어떻게 만들어질지 모르는 상황에서 개발 인력이 투입되어 시스템을 만들 때와 많은 기능들이 구현되어서 서로 복잡하게 얽혀있는 상황에서 개발 인력이 투입되어서 시스템을 만들 때에는 그 생산성이란 큰 차이를 보인다. 초반의 시스템은 구현 마지막의 시스템보다도 훨씬 복잡도가 없으며, 하나의 기능을 구현하는 속도나 시간적인 측면에서 복잡한 시스템을 이해하고 구현하려는 속도나 시간보다도 상대적으로 훨씬 짧게 걸릴 것이다. 이는 시스템 개발 후반부에 생산성이 나지 않는 경우에서 흔히 목격할 수 있다.


또한, 초반의 시스템은 구성 요소가 단순한 것도 있고, 비즈니스 로직 자체도 상대적으로 복잡하지 않아서 여기에 나타나는 버그나 기능 확장 등의 작업을 하기가 수월할 뿐만 아니라, 그 효과 역시 이를 접하는 사람에게 크게 다가온다. 즉, 아무것도 없는 상태에서 만들어낸 시스템의 가치는 후반부의 복잡하게 얽혀있는 시스템의 버그를 수정하거나 기능을 확장하는 가치보다도 훨씬 크다. 즉, 한계효용에 따른 가치가 작용된 것이다.


프로젝트는 많은 사람들과의 관계를 통해서 문제를 해결하는 과정이라고 볼 수 있다. 그 대상이 컴퓨터라고 하더라도 그 안에는 다양한 문제와 위험들이 존재하게 되며, 이는 후반부로 갈수록 더 많이 나타나게 된다. 초반의 문제 해결 능력은 아직은 많지 않은 문제들을 접하고 해결하는데 아주 큰 가치를 주지만, 후반부의 문제 해결 능력은 산적한 문제와 해결될 수 없는 위험들로 인해서 그 능력을 의심받기 시작한다.


또한, 아무리 일을 해도 계속 쏟아지는 일들로 인해서 점점 더 많은 스트레스와 함께 더 이상 생산성을 낸다는 것의 의미를 무력하게 만들기도 한다. 이러한 상황이 계속 지속되다보면 문제를 해결하는 능력에 대한 의심과 같이 부정적인 견해와 불평 불만의 이야기들이 쏟아져 나온다. 심지어 업무 간의 커뮤니케이션 역시 서로의 책임을 이야기하고 있으며, 한발짝 양보하려는 현상은 전혀 보이지를 않는다.


일을 떠나서 개인적으로 만나 이야기를 해보면 좋은 이야기를 하고, 긍정적인 말들을 하지만, 일을 접하는 순간부터 부정적인 견해와 비관적인 미래를 말하는 경우도 있다. 프로젝트는 원래의 특성상 성공이라는 단어를 함부로 꺼내가 힘든 일 중에 하나이다. 더군다나 수많은 사람들이 모여서 특정 목표를 향해 노력한다는게 얼마나 어려운지는 모두 알고 있을 것이다. 프로젝트 후반부에는 조그마한 실수 역시도 수많은 지탄의 대상이 되기도 한다. 혹은 남들보다 일찍 퇴근하는 것 역시 곱지 않은 눈으로도 보여질 수도 있다.


프로젝트를 수행하는데 있어서 중반부를 넘어가는 시점에서는 다시 한번 목표를 설정하고 공유할 필요는 있다. 그 목표가 애초에 생각했던 목표와 일치하는지 혹은 방향성 차원에서 다른 목표를 찾아야 하는지에 대해서 공유할 필요가 있다. 또한, 특정 업무가 시간만 잡아먹고 해결될 기미가 보이지 않는 내용에 대해서는 특단의 조치도 필요하다. 하지만, 무엇보다도 아무런 말과 견해를 보이지 않는 사람이라고 하더라도 분위기에 묻혀서 부정적인 생각을 가질 수 있기 때문에 지속적인 커뮤니케이션은 반드시 필요하다.


프로젝트를 성공으로 만드는 것은 이세상에 존재하지 않는다. 프로젝트에서 실패한 것들의 범위를 줄이는 것만이 있을 뿐이다.

저작자 표시 비영리 동일 조건 변경 허락
신고
크리에이티브 커먼즈 라이선스
Creative Commons License

철학의 한 분야인 인식론(epistemology)에서는 지식 습득에 대한 다양한 정의를 하고 있다. 즉, 인식론에서는 '앎(knowledge)이란 무엇인가?', '지식(knowledge)은 어떻게 얻는가?', '주어진 주제나 대상에 대해서 어느 정도까지 알 수 있는가?' 등의 질문에 대한 답을 구하는 과정을 이론화시킨다.


인식론은 앎의 성질을 분석하는데 초점을 두고, 진실(truth), 믿음(belief), 근거(justification)와 같은 개념과 어떤 관계가 있는지를 논한다. 이러한 인식론에 반해서 아무것도 알지 못한다고 하는 관점이 회의론(skepticism)이다. 인식론을 지식론(theory of knowledge)라고 한다.


인식론에 대한 내용은 소프트웨어 개발을 이해하는 방법에 마찬가지로 적용된다. 이는 개발 방법론 뿐만 아니라, 개념을 인식하는 과정에서도 동일하게 적용되기도 한다. 개발 방법론의 경우, 기존 전통적인 폭포수 개발 방법론에서 점증/반복 개발 방법론으로 전환이나 애자일과 같은 경량 프로세스를 이해하려는 인식의 전환에 있어서 이러한 인식의 활동들이 일어나게 된다. 또한, 프로그래밍 방식의 경우, 절차적인 개발 방식에서 객체지향 개발 방식, 그리고 컴포넌트/서비스 개발 방식으로의 전환이나, 관계형 데이터 모델에서 객체지향 관점의 데이터 모델로의 전환 역시 이러한 인식의 활동을 통해 개인의 지식(knowledge)이 발전되어 나아간다.



vastu/prativastu
vastu/prativastu by romana klee 저작자 표시동일조건 변경허락


IT 관점에서 인식의 전환을 필요로 하는 것들은 단순히 기술(technology)라고 부르기에는 한계가 있다. 왜냐하면 기술이라는 관점에서 이를 지식화시키는 과정은 매뉴얼이나 지침서를 만들어서 익히기만 하면 된다는 생각이 지배적이기 때문에 위에서 말한 지식들은 어찌보면 단순히 쓰여진 글이나 들어서 알아가는 과정 못지 않게 체득화시키는 과정이 강력히 필요하기 때문이다.


최근 NoSQL의 등장으로 인해서 대용량 데이터에 대한 분산 기술에 초점을 맞춘 내용들이 봇물을 이루듯이 나오고 있다. 하지만, 이러한 NoSQL의 관점을 기존 엔티티 간의 관계로만 데이터를 기술하려는 RDB의 관점을 개념과 개념의 집합(aggregate) 관계로 인식을 전환해야 함을 강조하는 글들이 찾아보기 힘들다. 분명 NoSQL이라고 부르는 DB들은 분산 관점의 처리에 대해 기존 RDB보다는 상당히 강점이 있다. 하지만, 분산에 대한 데이터 덩어리를 어떻게 구성하고 어떤 설계 형태가 될지에 대해서는 기존 RDB 관점의 접근 방식과는 다른 면이 있다.


데이터를 여러 테이블에 산재한 row들의 집합으로 표현하는 RDB의 관점은 NoSQL로 전환되면, 그러한 데이터 덩어리들이 하나의 집합된 형태로 표현된다. (XML이나 JSON과 같은 형태) 즉, 데이터의 구성이 관련있는, 그리고 애플리케이션 관점에서 필요한 형태의 구조를 갖게 된다.


이 두가지 인식의 차이는 얼핏 그냥 보기에 유사한 것처럼 보이지만, 아주 큰 차이를 보여준다. 데이터를 구성하는 구조에 대한 사실이 DB 자체에 저장되느냐 그렇지 못하냐는 애플리케이션 코드를 작성하는 개발자에게 그대로 영향을 미치게 되며, 데이터 저장에 있어서 마찬가지로 큰 인식 전환을 필요로 하게 된다.


예를 들어, 어느 사용자가 작성한 블로그(혹은 게시글) 정보를 기존 RDB에 저장하여 조회하는 경우, 관련 테이블의 join을 통해서 나온 결과를 다시 화면이나 애플리케이션 코드에 적합 형태로의 변환을 수행하는 로직을 생각해 볼 수 있다. 이러한 지식은 RDB에서 어느 비즈니스에 관련된 데이터의 집합이라는 관점을 시스템 상에 저장할 수 없기 때문에 이를 다루는 사람은 테이블간의 관계를 통해 매핑에 대한 사고를 한번 더 수행해야 함을 의미한다.


만일, 이를 NoSQL을 사용해서 저장한다면, 사용자에 관련된 블로그나 게시글에 대한 정보는 모두 한덩어리의 형태로 XML이나 JSON의 형태로 저장이 가능하다. 특정 사용자가 작성한 블로그나 게시글을 조회하려면 그 사용자의 ID를 조건으로 모든 데이터를 조회할 수 있다. 즉, 데이터 저장소에 저장된 데이터 구조와 화면이나 애플리케이션 코드에서 사용하려는 데이터 구조로의 매핑이 전혀 필요없게 된다.


하지만, 여기에도 단점은 존재한다. 데이터 덩어리를 어떠한 관점에서 볼 것인가에 따라서 저장된 데이터 구조가 달리 설계될 수 있다. 위의 예에서 NoSQL이 들어간 블로그를 검색하려면 사용자 기준으로 저장된 블로그나 게시글들을 모두 탐색하여 조회를 해야 한다. 즉, 데이터 덩어리를 사용자 중심으로 구조를 형성할 것인가, 혹은 블로그나 게시슬을 중심으로 형성할 것인가가 설계의 이슈로 나타나게 된다.


결국 이러한 다양한 관점의 데이터 구조를 NoSQL이 해결해주기는 아직까지 힘들기 때문에 기존 RDB의 강점과 NoSQL의 강점을 같이 혼합한 hybrid 방식의 데이터 관리를 생각해볼 수 있다. NoSQL의 등장은 기존 RDB의 반대 급부의 현상이라기 보다는 기존 데이터를 저장하는 방식에 대한 인식을 좀 더 다양한 형태로 저장할 수 있는 선택의 폭을 넓혔다고 볼 수 있다.


결론적으로, NoSQL의 등장이 단순히 기술적인 관점에서의 접근 방식이 아닌, 인식의 전환으로 바라봐야 하는 이유가 데이터를 저장하는 구조에 대한 변환을 가져오기 때문에 이러한 인식의 전환은 지식의 습득 과정과 체화의 과정을 거쳐야 하며, 이는 진실과 믿음이라는 개념을 필요로 하기도 한다. 즉, 기존에 알고 있던 정보공학 방식의 데이터 구조의 설계 방식에 대한 진실이나 믿음과는 반하는 진실이나 믿음이 존재할 수 있다는 것을 인식하는 과정이 필요한 것이다. 이러한 인식의 전환은 외부에 의한 자극보다는 내부의 자각으로 인해서 바뀌는 경향이 강하기 때문에 선택의 폭을 아무리 넓힌다고 하더라도 이를 받아들이는 입장의 인식이 변하지 않는 한 단지 새로운 또 다른 기술로 인식할 수 있을 것이다.

저작자 표시 비영리 동일 조건 변경 허락
신고
크리에이티브 커먼즈 라이선스
Creative Commons License

빌드의 통합은 형상관리도구, 워크스페이스의 소스코드 관리 도구, 배포 바이너리 버전 관리 도구 등을 통해서 상당 부분 자동화를 시킬 수 있다. 빌드는 단순히 형상관리에 있는 소스 코드들을 모두 가지고 와서 실행 파일로 컴파일을 만들어주는 의미만 포함되는 것은 아니다. 물론, 이러한 자동화 역시 전체 소스 코드의 깨짐 현상을 방지할 수 있고, 이를 지속적으로 반복적으로 수행한다면 소스 코드 깨짐 현상에 대한 위험은 줄일 수 있을 것이다.


문제는 전체 소스 코드의 크기가 적고, 어느 정도 인내할 수 있는 시간 동안 빌드를 한다면 괜찮겠지만, 소스 크기가 상당하고 많은 사람들이 만들어내는 소스 코드 (심지어 서로 다른 지역에 있는 사람들이 만들어내는 소스 코드와 같이 빌드하는 경우) 라면 상황이 달라진다.


실제 약 20 ~ 30만 라인을 소스 체크아웃에서부터 약 3분 정도 소요되고(물론, 물리적인 환경에 따라 다르기는 하겠지만, 여기서는 동일 환경에서 빌드한 수치들로 상대적인 수치로 받아들이면 된다), 약 70 ~ 80 만 라인은 약 15분 정도가 소요되고, 120 ~ 130 만 라인 소스 빌드 시간은 약 30분 가량이 든다. 이와 같은 수치로 본다면, 소스 코드의 증가는 빌드 시간의 단순한 증가를 의미하는 것도 있겠지만, 그 수치로 봐서도 기하급수적인 수치로 늘어날 것으로 예상해볼 수 있다. 실제 약 50만 라인 정도를 빌드하는 시간이 4분 정도 소요되었는데, 7 ~ 80 만으로 늘어나는 경우에는 그 수치가 2배를 훨씬 넘어서는 기간이 걸렸다. (빌드 시간은 내부 코드의 복잡도도 영향을 미치기 때문에 서로 다른 성격의 애플리케이션이나 컴포넌트를 비교하는 경우에는 수치적으로는 다소 차이가 발생할 수도 있다.)



위의 그림에서 LOC의 증가 정도(기울기)와 그에 따른 빌드 시간의 증가 정도(기울기)의 차이가 점점 늘어나는 것으로 볼 수 있다. 즉, 한번에 빌드하는 LOC가 증가할수록 그에 따른 빌드 시간의 증가는 더 급격히 늘어난다고 볼 수 있다.


통합 빌드의 시간이 길어졌을 때 통합하는 시간이 걸리는 것은 당연하며, 특히 빌드 중에 빌드 에러가 나서 다시 빌드를 해야하는 경우의 수가 많아질수록 그 시간이 더 늘어난다는 것이다. 예를 들어, 30분에 걸쳐서 빌드하는 애플리케이션의 경우, 거의 빌드 막바지인 25분 경과 시점에 빌드 에러가 발생한다면, 이를 조치하고 다시 처음부터 빌드를 해야하기 때문에 그 시간은 거의 2배인 1시간 가량을 소비해야 한다. 이러한 시간 소비는 그 시간 동안 형상관리에 다시 새로운 코드를 커밋하는 과정에서 재반복이 될 우려가 있으며, 심지어는 몇시간 동안 빌드를 못하는 경우도 있다.


이러한 문제들에 대한 해결책은 빠른 빌드를 위해서 필요하며, 단순히 빌드 자동화만 도입한다고 해결되는 부분은 아니다. 빌드 자동화의 장점과 더불어서 원칙이 있는 각 모듈(컴포넌트)간의 관계를 형성하여 빌드 단위를 최소한을 나누어서 애플리케이션을 구성하도록 해야 한다.


빌드 단위의 정의


빌드 단위를 정의하려면, 최소한 아키텍처에서 배포 단위를 결정해야 한다. 통상 배포 단위는 하나의 컴포넌트 단위로 매핑하며, 이는 컴파일된 바이너리 파일들의 묶음이기도 하다. 이 배포 단위는 서로 의존관계를 형성하고, 그 의존관계들로 인해서 배포 단위는 빌드의 순서를 결정하게 된다. 즉, 컴포넌트는 해당 비즈니스 로직의 성격으로 분류되어야 하며, 이러한 컴포넌트 유형 간의 의존관계 원칙이 최소한 정의되어야 한다.


빌드 단위를 컴포넌트로 정하는 경우, 컴포넌트 유형별로 관리를 할 필요가 있으며, 각 유형을 묶어서 관리할 수 있는 체계가 필요하다. Maven을 사용하는 경우, 컴포넌트 유형을 관리하는 단위를 하나의 POM으로 묶어서 그 하위에 해당 컴포넌트들을 위치시켜 상위에서 빌드가 되면 동일한 유형의 컴포넌트들이 동시에 빌드할 수 있는 형태로 관리가 가능하다. 컴포넌트 유형은 크게 분류해보면 Business Data Type을 모아두는 형태, Utility 형태, Entity 형태, Process 형태 등으로 나눌 수 있다. 분류체계를 더 세분화시킬 수도 있지만, 기본적인 비즈니스 로직의 근간을 이루는 컴포넌트를 이와 같이 분류를 해볼 수 있다. 이 컴포넌트들은 한꺼번에 배포를 해도 되지만, 컴포넌트 유형 간의 의존관계 규칙을 강화시키거나 규정하면 해당 의존관계를 이루는 컴포넌트의 순서에 맞추어서 자동 빌드에 대한 프로세스를 나누어 볼 수 있다. 예를 들어, Process가 Entity나 Utility로의 의존관계만 형성되어 있다면, Entity나 Utility를 먼저 빌드/배포하고, Process를 그 후에 배포하도록 순서를 결정할 수 있다.


마찬가지로, 외부 시스템과 연결되는 부분을 모아두는 유형을 별도로 모아둘 수 있으며, UI와 연계되는 로직을 구성하는 UI 관련 컴포넌트를 별도의 유형으로 분류할 수도 있다. 이 경우에도 다른 컴포넌트 유형과의 의존관계를 고려해서 빌드 순서를 조정할 수도 있다.


빌드 프로세스 세팅


통상 빌드 자동화 도구(CI, Continuous Integration)를 사용하는 하나의 빌드 작업과 다른 빌드 작업을 연결시킬 수가 있으며, 이 빌드 작업은 여러개의 빌드 작업으로 분화(fork) 가능하다.


즉, 컴포넌트 유형의 빌드 순서가 A -> B -> (C | D | E) 라고 한다면, A의 빌드 작업이 종료함과 동시에 B의 빌드 작업을 연결해서 기동시킬 수 있으며, B의 빌드작업이 종료됨과 동시에 C, D, E의 빌드 작업이 동시에 수행하는 것이 가능하다.


이와 같이 하나의 애플리케이션을 구성하는 컴포넌트를 빌드하는데 빌드 프로세스 형태로 구성했을 때의 장점은 무엇보다 적은 코드의 빌드 작업이 수행되기 때문에 전체 코드를 빌드하는 것보다도 시간이 더 적게 걸릴 수 있으며, 중간에 빌드 에러가 발생되면, 멈춘 작업에서 에러를 수정하여 다시 이전에 수행된 작업을 다시 기동하지 않고 그 이후부터 다시 빌드를 시작할 수 있는 장점을 가진다.



위의 그림에서 위의 알파벳으로 표현된 부분은 제일 하단에 있는 하나의 애플리케이션을 구성하는 컴포넌트 유형을 분리하여 빌드 프로세스로 구성한 것이며, 그 순서는 오른쪽에 나타나 있다. 이들 각각의 빌드 작업들의 걸리는 시간의 총합은 총 10분 30초 정도가 되며, 전체를 하나의 빌드 작업으로 구성하는 경우에 약 14분 정도가 소요되었다. 즉, 약 1.5배의 시간이 더 걸리는 셈이다.


빌드를 이와 같이 애플리케이션 전체를 통합하여 하나의 작업을 만드는 것보다 가능하면 나누어서 빌드를 하도록 구성하는 편이 시간적인 비용 측면에서 크게 이익이 된다.


고려 사항(한계)


빌드를 자그마한 단위로 나누어서 작업을 만드는 경우, 도구의 지원에 따라서 분화(fork) 프로세스는 가능하지만, 병합(join) 프로세스를 지원을 하지 않는 경우가 있다. 위의 경우에도 H, J, L, N으로 나누어진 빌드 프로세스가 모두 O 작업으로 병합되지만, 실제로는 O가 4번 실행되는 형태로 빌드 작업으로 구성되어 있다. 하지만, 이렇다 하더라도 빌드 중간에 에러나는 부분에 있어서는 다시 A부터 실행하지 않아도 되기 때문에 큰 이익이 있으며, O가 4번 빌드된다고 하더라도 전체적으로 통합/빌드/배포 작업에 있어서 아무런 영향은 미치지는 않는다. 다만, 불필요한 작업이 발생할 뿐이다. CI 도구가 이러한 부분을 잘 지원해주거나, 혹은 내부적으로 플러그인이나 스크립트를 사용해서 이러한 불필요한 작업에 대해서는 여력이 된다면 보정을 해줄 수도 있을 것이다.


빌드 프로세스에 맞게 컴포넌트 유형 간의 의존관계가 형성되어 있어야 한다. 예를 들어, C 작업 후 D를 수행해야 하는데, C 유형의 컴포넌들이 D 작업 이후의 유형에 대해 의존관계를 형성한다면, 위의 빌드 프로세스는 조정을 해야 하거나 해당 의존관계를 다른 형태로 구성해야 한다. 이는 아키텍처 관점에서 컴포넌트 유형의 의존관계를 빌드를 통해서 규제하거나 강제하는 효과를 낳는다.


빌드 작업에 대한 인스턴스가 하나만 수행하도록 하는 경우에는 전체적인 시간에 대한 차이가 그리 크지는 않는다. 예를 들어, 위의 빌드 프로세스에서 H, J, L, N으로 나뉘어서 동시적으로 빌드 프로세스가 수행되지 않고, 하나의 빌드 작업만을 차례로 수행하게 한다면, 전체 빌드 시간은 차이가 얼마 나지 않을 수도 있다. 하지만, 이전에 언급했듯이 처음부터 다시 빌드하는 수고는 덜 수 있는 충분한 장점을 가진다.



빌드는 자동화시키려는 노력은 필요하며, 나름대로 원칙을 세워서 작은 단위로 빌드하려는 작업들이 필요하다. 또한, 빌드를 하는 시간을 빠르게 하면 할수록 개발자가 자신이 만든 코드에 대한 피드백을 빨리 받을 수 있는 장점을 가지게 된다. (실제로 에러 수정시 수정된 내용이 제대로 되었는지를 파악하는데 통합/빌드/배포의 긴 시간으로 아무런 진전을 못하는 경우도 많다)





저작자 표시 비영리 변경 금지
신고

'Homo Faber > Techniques' 카테고리의 다른 글

빌드 시간을 더 빠르게 하라  (0) 2012.05.12
신중하게 행동하라  (0) 2010.06.16
Spring의 AOP로 구현한 테스트 스파이(Spy)  (0) 2009.12.04
비즈니스 컴포넌트와 데이터 ownership  (4) 2009.10.05
m2eclipse 설치  (0) 2009.09.22
m2eclipse 소개  (0) 2009.09.22

+ Recent posts

티스토리 툴바