2006년 5월 29일 월요일

자동화 도구를 이용한 웹 프로그래밍

군대 오기 몇 달 전에 그러니까 작년에 "실용주의 프로그래머"가 처음 번역되어 출판되던 때 예약구매해서 며칠 만에 읽었습니다. 원서(Pragmatic Programmer)의 명성은 익히 알고 있었지만 게으른 탓에 제대로 읽어보지 못하다가 김창준씨의 번역으로 책이 나온다는 소문을 듣고 기대하면서 바로 구입하여 읽었던 기억이 납니다.

지금은 반년이 지나도록 다시 볼 기회가 없어서 내용의 대부분을 잊었지만 요즘 이곳에서 하고 있는 작업에 실용주의 프로그래머를 읽으면서 자연스럽게 채득되었던 지식들이 도움이 되고 있습니다.

제가 이야기할 내용은 실용주의 프로그래머에서 언급된 내용이지만 "실용주의 프로그래머를 위한 프로젝트 자동화"와 더 가까운 내용입니다. 전, 이 글에서 프로젝트를 진행하면서 수 없이 접하게 되는 똑같은 작업들을 어떻게 하면 더 편하게 할 수 있을지 그리고 노동 집약형의 작업들을 어떻게 빠르게 해결할 수 있을지 이야기 하려고 합니다.


웹사이트를 개발하면서 접하게 되는 상황에서 도구를 이용해 해결하는 사례를 보겠습니다. 참고로 제가 군복무 중이고 군대에서 개발하는 상황이라는 점과 현재 개발하는 웹사이트가 어느 정도 큰 규모(18000여개의 파일, 600Mb정도의 용량) 의 사이트라는 점을 염두에 두시고 읽으셨으면 합니다. 이로 인해 일반적인 회사의 상황과 다른 경우가 많을 수도 있습니다.


1. 소스 버전 관리를 이용한 협업


요즘은 Subversion이나 CVS같은 소스 관리 프로그램이 워낙 많이 알려져서 많은 사람들이 실제로 업무에서 사용하고 있고 그에 따른 효과를 이야기 합니다. 하지만 아직도 기존의 방법을 버리고 버전관리 시스템을 이용하는 것에 거부감이나 어려움을 느끼는 경우가 많습니다.

버전관리를 통해서 얻을 수 있는 다양한 이점들은 다른 곳에서도 많이 접할 수 있기 때문에 말을 줄이고 최근 제가 겪은 버전관리를 통해서 얻었던 이점을 간단히 소개해 보려고 합니다.

우리팀에서는 그동안 웹사이트에 사용하는 DB로 MySQL을 쓰고 있었습니다. 초반에 Oracle로 DBMS가 정해 졌었지만 개발속도를 위해 MySQL로 개발을 했었습니다. 차후 Oracle로의 포팅을 위하여 PEAR DB를 이용하여 작업하였습니다. 하지만 실제 포팅할 시기에 생각보다 포팅을 위해 수정해야 할 부분이 많아서 포팅 작업에 일주일 정도의 시간이 소모될거라 예상되었습니다.

조직의 특성상 프로젝트 관리자들은 날마다 눈에 보이는 성과를 요구했습니다. 그래서 내부적인 작업을 하는 동안이라도 실제로 보이는 성과를 제출해야 했습니다. 물론 비합리적이지만 실제로는 얼마든지 부딪힐 수 있는 경우 입니다. 결국 일주일이란 시간 동안 내부적인 작업만을 하기가 힘들었습니다.

이를 해결하기 위해 html작업을 통한 작업진척을 이용하여 시연을 하여 성과를 제출하려는 계획을 세웠습니다. 프로그램은 90%이상 개발 되었기 때문에 MySQL을 이용해서 작동한다는 점을 제외하면 웹페이지 작업을 통해서 성과를 보여주는데 많은 문제가 없었습니다. 다만 Oracle로의 포팅 작업 도중에는 프로그램이 정상적으로 실행되지 않기 때문에 웹페이지 작업을 하는 부분은 기존의 프로그램이 계속 동작해야 했습니다.

이를 해결하기 위해 Subversion의 branch기능을 이용해 /branches/RB-x.x.x-MySQL(이하 RB)과 같은 형식으로 복사했습니다. 그리고 웹페이지 작업은 분리된 RB에서 진행되도록 웹페이지의 작업 소스를 switch기능을 이용해 바꾸었습니다. 그리고 기존에 작업이 이루어지고 있던 /trunk/src(이하 trunk) 에서는 Oracle로의 포팅작업을 진행하였습니다. 그렇게 4일 정도 작업이 이루어진 후 포팅 작업을 완료하고 RB에서 이루어진 웹페이지 작업과 포팅작업의 결과물을 합쳐야 했습니다. 4일 정도의 길지 않은 기간이지만 Subversion Revision이 200이 넘는 차이가 나고 변경된 파일만 수백개에 이르는 많은 양의 작업이 진행된 후였습니다. 그 중에는 trunk에서의 작업과 중복되는 부분도 있어서 일일이 수작업으로 합치는건 불가능했습니다. 여기서 subversion의 merge기능을 유용하게 사용하여 쉽게 소스를 통합할 수 있었습니다.

소스를 통합하기 위해서 제가 사용한 명령은 아래와 같은 한줄의 간단한 문장이었습니다.


svn merge - r 981:HEAD file:///home/svn/framework/branches/RB - 0.7.1


간단한 이 명령을 통해 revision 981(4일전의 작업)에서 분기 되었던 소스의 분기 시점부터 현재까지의 변경분을 메인 소스에 적용시킬 수 있었습니다.


2. 게시판 생성과 같은 단순 반복 작업


프로젝트를 진행하면서 여러 유형은 단순 반복작업을 접할 수 있었습니다. 특히 군 내부 프로젝트라 중간 점검 단계가 군인이다보니 그로 인한 것인지 개인적인 것인지는 알 수 없지만, 단순한 중간 점검을 위해서도 게시판이나 각 프로그램들에 실제와 유사한 데이터가 입력되어 있고 800개에 가까운 게시판 중에 300개 이상이 생성되어 있어야 했습니다. 문제는 개발과정에서 그러한 것을 요구했기 때문에 300개의 게시판을 생성했다가도 변경으로 인해 스키마나 DB를 변경해야 할 문제가 발생하기도 하고 여러 이유로 다시 생성하거나 전반적인 이름을 바꿔야 할 경우가 생기곤 했습니다. 그리고 각 게시판은 사용하는 부분에 따라 스킨을 다르게 쓰거나 게시판 이름을 붙여줘야 하는 경우도 있어서 단순한 게시판 생성 프로그램을 만들었지만 이를 활용하여 초기 게시판 생성을 하기에는 무리가 있었습니다.

이 문제를 해결하기 위해 게시판 정보를 excel로 작업하여 문서로 만들었습니다. 문서에는 800개 가량의 게시판형 프로그램의 정보가 들어 있으며 전 이 문서를 읽어들여 정보를 바탕으로 각각에 맞는 게시판을 생성하는 프로그램을 만들었습니다. 이를 이용해 생성을 하여 중간 중간 대규모의 변경도 쉽게 적용할 수 있게 되었습니다.

이와 비슷한 많은 작업들이 같은 방식으로 해결 할 수 있습니다. 시연을 위한 가상의 데이터를 입력해 줘야 할 경우도 sql문을 만들어 가지고 있는 것보다 스키마 변경이나 로직 변경에 유연한 생성 프로그램을 만들어 이용하면 데이터의 무작위성이나 현실적인 부분에서 많은 이익을 볼 수 있다고 생각합니다.

이런 종류의 프로그램을 만들 때는 아래와 같은 점들을 고려하는 것이 좋습니다.


1) 전반적인 작업이 한번의 실행으로 이루어져야 합니다


예를 들어 기존에 입력되어 있는 db의 테이블, 시퀀스 등을 제거하고 새로운 테이블이나 시퀀스를 생성한 후, config테이블 등의 테이블에 내용을 입력하고 permission세팅과 같은 부분을 해야 하는 작업이 전부 이루어져야 하는 것과 같은 경우, 한번의 실행으로 순차적으로 위의 작업들이 일괄적으로 이루어지도록 프로그램을 만들어야 합니다. 각 부분의 재사용을 위해서는 해당 부분을 모듈화하거나 각각의 함수로 만들어 사용하여 해결하고 각 파트를 따로 실행시킬 수 있는 부분 또한 추가하는 것이 좋습니다.


2) 튼튼하게(?) 만들어야 합니다


다소 웃기는 표현이지만 단순하게 도구로 사용하는 프로그램이라도 튼튼하게 만들어야 합니다. 프로그램이 실행되는 도중에 종료되더라도 쓰레기 데이터나 값들을 남기지 않도록 트랜젝션 처리에 신경을 써야 합니다. 그리고 다시 실행시키더라도 이미 완료된 동작은 스킵하고 지나갈 수 있도록 해야 합니다. 예를 들어 총 500개의 테이블을 생성해야 할 경우에 150번째 생성에서 오류로 종료되었다면 다시 실행시키면 정상적으로 만들어져 있는 경우는 넘어가서 150번째 부터 다시 시도하게 되어야 합니다.

프로젝트에 따라 다르겠지만 프로그램 동작의 기반을 만들어주는 프로그램은 다양한 경우에서 다양한 방법으로 사용될 수 있기 때문에 기반을 만들다기 보다는 쓰레기를 추가 시킬 우려가 없도록 하는 것이 중요합니다. 이를 위해 앞에서 말한바와 같이 미리 입력된 데이터를 점검하여 상태를 파악하여 입력할지 하지 않을지 업데이트를 할지 결정하는 부분이 있어야 합니다.


3) 사용자 입력에 친화적으로 제작해야 합니다


이는 화려한 인터페이스를 통해 사용자가 쉽게 입력할 수 있도록 해야 한다는게 아닙니다. 일반적으로 자동화 프로그램은 표준입력을 받아서 실행되기 보다는 config파일이나 내부적으로 특정 목적에 특화되어 있기 때문에 그냥 실행만 시키면 알아서 동작하도록 하는 것이 좋습니다.

다만 이때 소스로 사용할 데이터는 기획자와 같은 프로그래머가 아닌 사람을 통해서 만들어지는 경우가 많은데 그런 경우를 위해 간단한 형식의 excel문서를 이용할 수 있도록 만드는 것이 좋습니다. 그렇다고 이해하기 힘든 프로그램을 위한 정보만 기입된 문서보다는 프로젝트에서 스펙문서로 사용될 수 있을 정도의 문서를 입력받아 적당한 파싱을 통해 이용하는 것이 좋습니다. 차후에도 사용자가 간단한 변경을 했을 경우 소스만 변경하면 그 변경사항이 적용되도록 하는 것이 중요합니다. 일반적으로 excel을 바로 파싱하는 것은 복잡하기 때문에 excel에서 csv로 저장한 결과를 파싱하도록 작업하는 것이 괜찮습니다.


3. 시간을 잡아 먹는 프로그램 배포 작업


프로젝트를 배포하는 작업은 웹사이트의 경우 목적 서버에 웹사이트 소스를 올리고 사이트가 동작하도록 변수 변경이나 빌드, 테스트 등을 하는 작업입니다. 여기에 몇 가지 사항이 추가되거나 할수도 있지만 일반적으로 목적 서버에 소스를 올리고 동작시키는 작업을 배포라고 할 수 있습니다. 팩키지 프로그램의 경우는 빌드하여 패키지를 생성하여 웹사이트에 배포하거나 목적 장소에 위치시키는 작업이 될 것입니다.

이러한 배포작업을 자동화 시키는 것에 대한 최고의 서적은 "실용주의 프로그래머를 위한 프로젝트 자동화"입니다. 제가 아는 한 이 책은 이 부분에 대한 최고의 책이며 프로젝트 자동화에 대해 다룬 몇 안되는 책입니다. 강추입니다. 번역판도 나와 있으니 꼭 읽어보세요~.

각설하고 CruiseControl과 Subversion을 이용하여 일정 주기로 변경사항을 개발서버에 적용시키고 유닛 테스트를 실행시키는(있다면) 작업을 알아보겠습니다.

CruiseControl은 제가 이전에 쓴 포스트에 간략하게나마 설명되어 있습니다. 지금 제가 개발하고 있는 웹사이트는 PHP로 만들었기 때문에 Ant를 이용한 빌드 과정은 불필요합니다. 경우에 따라서는 초기화 디렉토리를 생성하거나 기동 스크립트를 실행시키는 역할을 ant를 이용해서 할 수도 있습니다. ant를 프로젝트 빌드에만 이용할 필요는 없는 것이죠. 현재 제가 개발하고있는 웹사이트는 파일이 18000여개 정도이고 600메가가 넘는 사이즈이기 때문에 시연을 위해 서버에 개발중인 소스를 복사하고 환경에 맞게 세팅하는 것에만도 많은 시간이 소요됩니다.

이를 해결하기 위해 subversion을 이용해서 소스를 update하는 방법을 이용하고 있습니다. subversion의 업데이트 기능은 변경된 부분만을 받아와서 적용시키기 때문에 주기적으로 update해줄 경우 동기화에 많은 시간이 걸리지 않습니다.

CruiseControl은 램에 상주하면서 주기적으로 subversion 저장소에 소스가 업데이트되었는지 체크하여 버전이 올라갔을 경우 subversion의 update명령을 실행합니다. 그리고 unittest를 위한 testcase를 실행하여 결과를 저장할 수 있습니다. 또한 프로그램을 제대로 실행하기 위해 필요한 디렉토리를 생성한다거나 설정을 변경하는 등의 작업을 추가적으로 실행시킬 수도 있습니다.

CruiseControl의 최대 장점은 한번 실행되면 자동적으로 소스를 동기화 시키고 추가적인 작업들을 진행하여 결과를 통보해 줄 수 있다는데 있습니다. 사람이 주기적으로 혹은 가끔이라도 해야 했던 일들을 완전히 프로그램에 위임하면 결국 우리가 할 일이 하나 더 줄어듭니다. 남는 시간은 프로그래밍을 하면 되겠죠. :-)

댓글 없음:

댓글 쓰기

Man of Month를 마치며

벌써 2020년 1월 14일이다. 19년의 마지막 달에 Man of Month라는 팀의 제도를 시작한다고 했었는데, 12월이 지나고 그 다음 달도 거의 절반이 흐른 것이다. MoM을 시작하면서 하겠다고 계획했던 것들도 실제 한 것들과 비교해보니...