프로젝트 회고 콤퓨타

예전에 쓴 글 근황 & 프로젝트 중간 점검에서 언급한 그 프로젝트가 지난 12월 31일에 끝났다. 해를 넘기지 말자고 했더니 용케도 12월 31일에 끝났네.

국내 어느 프로젝트도 그러하듯이, 이번 프로젝트도 "성공적" 으로 끝났다. (하하하) 굳이 비꼬는 것은 아니고, 별 탈 없이 잘 끝났다. 나로서는 크게 1) 비개발자로서 개발 프로젝트에 참여한 경험 축적, 2) Spring framework 에 대한 경험 축적이 프로젝트 수행을 통해 얻은 성과였다.

이번 프로젝트는 목적이 무척이나 독특하였기 때문에 참으로 신선한 경험이었다. 딱히 상용 서비스를 하지는 않지만, 제대로 돌아가는 프로토타입 시스템을 만드는 것을 목적으로 수행한 프로젝트였다. 따라서 안정적 서비스에 대한 부담은 거의 없었기 때문에, 보수적일 수 밖에 없는 PL 이나 PM 도 신나게 최신 기술을 마구 마구 사용할 수 있었다. WAS 도 신상, DB도 신상, framework 도 신상, 사용한 기술도 신상. 그렇다고 무책임하게 지난달 나온 제품을 쓰는 정도는 아니었다.

다만 이렇게 안정성에 대한 부담은 없었지만 기존에 없던 무언가를 만들어내야 하는 상황이라서, 요구사항을 고객과 함께 고민해야 하는 부담이 있었다. 또한 6개월 간 4차례의 고객사 시연도 꽤나 부담스러운 것이었다. 막장 SI 프로젝트는 아니지만, 그렇다고 천국같은 프로젝트도 아니었다.

Spring framework


Spring framework 를 적용했는데, framework에 대한 문제는 거의 없었다.

2차에 걸쳐 개발자가 투입되었는데, 각 차수마다 대략 1주일 정도의 framework 교육기간을 가졌었다. 이 기간 동안 개발은 전혀 진행하지 않고, 온종일 교육만 수행했다. 나는 1번 차수의 교육을 담당했었다. 짧은 기간 대비 1주일 교육기간을 따로 빼는 것은 그렇게 쉽지는 않은 일이었을 텐데, 상당히 좋은 선택이었다. 교육의 효과인지, spring framework 이 원래 좋아서인지, 개발자들이 이미 어느정도 알고 있었는지는 모르겠지만 개발 진행하면서 framework 이 발목을 잡은 경우는 거의 없었다.

처음엔 기껏해봤자 spring framework의 여러 구성 요소 중 web, orm, dao 정도만 사용하겠지 했는데 왠걸, 나중에 보니 spring 의 전체 stack 중 jmx 정도만 제외하고 다 사용했다고 해도 과언이 아닐 정도였다. spring security, jms, web service, aop 등등 모조리 필요하게 되더라. 거기에 외부 framework인 spring batch까지 들어갔다. 허헛. 좋은 경험이었다. 그리고, 이런 많은 부분을 하나의 framework 단에서 일괄적으로 제공해주니 아주 편했다. 앞으로도 어지간한 환경에서는 주저하지 않고 spring framework 을 선택할 것이다.

Web 쪽은 특별히 struts 등 외부 framework 을 또 얹지는 않고, spring mvc 로 갔다. 다른 부분에서는 annotation 기반의 설정을 사용하지 않았는데 (아니, 사용을 금하였는데) mvc 와 unit test 에서 만큼은 annotation을 적극적으로 사용하였다. 초반엔 mvc에서 조차 annotation을 사용하는 게 맞는지, 행여나 나중에 문제를 유발하지 않을런지 걱정을 하였으나 기우였다. 직접 코딩을 하지는 않아서 개발자들이 어떻게 느꼈는지는 모르겠지만, 몇개의 화면을 작업 해 본 경험으로는 annotation 사용한 것이 훨씬 작업하기 편하였다. 게다가 annotation 을 사용할 경우 복잡할 수도 있는 spring 의 web controller에 대한 계층구조에 대해 전혀 몰라도 되므로 개발자들에게 가이드 하기도 더 쉬웠다. annotation 기반 mvc는 정말 좋았다.

차후 개발에 annotation을 사용한 injection을 얼마나 사용할 것인가에 대해서는 고민이 된다. annotation 이 무척 편하지만, 껄끄러운 점이 꽤 있다. annotation을 통한 injection 대상이 무엇인지 찾아내는 것이 xml 설정만큼 명시적이지 않다. 또한 @Controller 와 같은 annotation 기반 component 를 쓸 경우 모듈 별로 쪼개기가 쉽지가 않았다. @Component 를 쓸 경우 component scan에 설정을 해야 하는데, 어떤 식으로 패키지 구조를 잡느냐에 따라 다르겠지만 layer 밑에 모듈이 존재할 경우 ( com.myapp.web.abcmodule 뭐 이런 식?) 모듈 별로 쪼개려고 할 경우 일일이 component scan 에서 규칙을 잘! 정의해 줘야 한다. 그렇지 않을경우 남의 모듈의 component 가 load 되다가 injection 이 실패하는 등의 문제 때문에 application 이 제대로 실행되지 않을 수가 있다.

Spring의 단위 테스트 지원도 무척 좋았다. 초반에 내가 잡은 표준은 junit 3.8 이었는데 다른 분이 중간에 4.x 대로 변경되었다. 딱히 4.x 가 주는 잇점은 잘 느껴지진 않았다. Testcase 라는 특정 class를 extends 할 필요 없고, method 명명도 자유로운 이점이 있긴 하지만, unit test case 코드에 까지 그렇게 신경을 쓰나? 그래도 더 좋긴 하더라. 하여간 앞으로는 4.x 로 가야겠다. 단위 테스트 지원 기능 중 가장 좋았던 것은 자동으로 rollback이 되므로 매번 delete 등등을 실행하지 않아도 된다는 것이다. 그런데 application 이 커지면서 단위테스트 실행하기 위한 application context loading에 상당한 시간이 소요되는 것은 큰 문제다. 모름지기 단위 테스트는 빨리 빨리 실행되어 개발자들이 잦은 실행에도 부담을 느끼지 않도록 해야 할 텐데, 꽤 많은 component 를 읽어들으니 시간이 상당히 소요되었다. application context 설정을 모듈별로 쪼개어 놓았기 때문에 읽어들이는 양도 그렇게 많지는 않았을 텐데 왜이리 오래걸리나. 흠흠.

SVN


SVN은 처음 써 보았다. SVN 자체는 좋았지만, eclipse plug-in 이 왜이리 삽질을 해 대는지, 초기엔 정말 힘들었다. 서버로는 visual svn server 를 사용하였고, eclipse plug-in으로 subversive 를 사용하였다.

많은 오류 중 가장 빈번하였던 것은 특정 resource에 lock 이 걸렸다는 것이다. 대부분의 경우 clean-up 을 통해 잘 해결이 되었지만 몇몇 악독한 경우 당췌 해결이 되질 않아 아얘 새로 check-out 한 경우도 있었다. 어떤 경우는 update를 했더니 영 이상한 옛날 revision으로 update되어 현재 작업한 내역이 날아간 경우도 있었고, 어떤 경우는 남의 resource가 지워진 경우도 있었다. (근데 몇몇 경우는 개발자가 실수해 놓고 발뺌한 것으로 생각이 된다... 진실은 어떤 지 모르겠지만) 어찌 되었건 eclipse 의 svn plug-in 은 정말 심심찮게 문제를 유발하여 정말 짜증이 났다. 아무리 기능이 좋다고 한들 불안하면 어디 쓰겠는가.

repository의 생성 및 관리도 나의 업무였다. 초기엔 설마 application이 여러개가 되겠냐~ 생각해서 단일 application에 기반한 repository 구조를 선택했다. 아이고, 그런데 application 이 마구 늘어나 나중엔 repository 가 7~8 개에 달하게 되었다. 단일 application 기반 repository 는 말 그대로 하나의 application 일 경우 굳이 중간에 module 명을 붙이지 않아도 되니 구조가 단순하긴 하지만, 이렇게 복수개 application 으로 확장을 할 수 없으니 문제가 되었다. 또다른 장점들로는 정말 불의의 사고로 repository 하나가 날아간다고 해도 다른 application에 영향을 미치지 않는 것이 있을 것이고, revision number가 repository 별로 관리되므로 번호들을 되짚어가면서 변경을 추적할 경우의 편리함이 있다. 그러나 이들은 꽤나 예외적인 케이스이고, 이번같이 7~8 개 repository 관리를 하게 될 경우 backup script 부터 시작해서 관리자 측면에서는 상당히 귀찮은 면이 있었다. 다음부터는 어지간한 경우 하나의 repository에 복수개 application 을 올리는 구조로 가야겠다.

산출물 문서도 SVN으로 관리하였다. 이 경우 장점은 최신 산출물 set 을 구성하기 쉽다는 것이다. 가장 최신 버전으로 export 하면 그것이 최신 산출물 set 이니 일일이 폴더 돌아다니면서 최신 버전들 복사해서 산출물 set 구성할 필요가 없다. 그러나 svn은 파일명을 기반으로 resource를 관리하기 때문에, 문서를 작성할 때 뒤에 버전번호를 붙여선 안된다. 많은 회사들에서는 "개발표준_v1.0.doc" 혹은 "개발표준_20081215.doc" 와 같이 파일명 자체에 버전을 붙여서 문서를 관리하는데, 이와 같은 내용을 적용을 할 수 없으니 작업하는 데 상당히 답답하였다. 예를 들어 누군가와 문서 내용을 병합하려는데 저 사람이 1.1 버전에 내용을 추가한 것인지, 1.2 버전에 내용을 추가한 것인지 파일명을 통해 알 수 있는데 똑같은 파일명이라면 이런 경우 손이 많이 간다. 물론 문서 내부의 번호 부여를 기똥차게 하면야 문제될 것은 없지만, 이거 정말 어렵다. 또한 많은 문서들이 binary format이라서 svn의 diff도 안되고 걍 마구 repository 에 저장하다보니 repository 용량이 마구마구 늘어난다. 실제로 기껏해야 200메가 되는 산출물에 대한 repository 크기가 4기가 정도에 육박했다. (저 repository 는 나 혼자 쓰는 것이었고, revision 번호도 50번 안쪽이었다.) 따라서 앞으로도 특별한 경우를 제외하고는 문서 산출물의 경우 svn이 아닌, windows의 공유폴더를 사용해서 산출물 관리를 하는 것이 훨씬 낫다고 생각한다.

CI


cruisecontrol 을 통해 매일 빌드를 수행했다. 매일 빌드 말고도 여러 옵션이 있지만, CI 서버와 svn 서버가 다른 네트웍에 물려있는 관계로 새벽에 svn 서버에서 cruisecontrol 서버로 소스를 묶어서 날린 후, CI 서버가 이를 받아 처리하는 형태로 실행했다. 실행한 내용은 컴파일 및 단위테스트, 소스코드 검토 도구 실행, WAS에 최신 빌드 올리기 였다.

일전에 소개한 glean 을 통해 다양한 코드 검토 도구를 쉽게 적용할 수 있었다. glean, 정말 강추다.

사실 CI 를 돌리는 것 자체는 문제가 아니지만, 과연 이것이 얼마나 효과적인가는 별개의 문제다. 안정적으로 CI 환경을 돌리는 데는 대략 일주일정도 걸린 것 같다. (ant build, 도구 및 룰 세팅 등등) 초기에 CI를 도입할 때 기대한 내용은 1) 도구 돌려서 코드 개선 필요 사항 확인 --> 개발자 , 2) 전체 unit testcase 수행을 통해 변경 영향성 파악, 3) WAS에 최신 빌드 올림으로 항상 통합된 최신 개발 내역을 확인, 4)상이한 개발환경과 데모환경 사이의 차이를 신속하게 발견 이었다. 이 중 목적을 달성한 것은 오직 3), 4) 번 이었다.

개발자들은 CI 를 돌리던 말던 관심이 없었다. 대략 2회 정도 checkstyle 과 pmd 를 통해 발견된 내역 중 좀 심각하다 싶은 것들에 대해서는 개발자들에게 report를 하고 회신을 달라 하였으나 이 마저도 그다지 잘 되지는 않았다. 많은 글에서 지적하듯이 QA는 개발조직과 독립적으로 돌아가야 하지만, 내 경우는 전혀 그렇지 못했다. QA 이면서, 개발자 지원도 하고, SVN 관리도 하고, 빌드도 하고. 개발자들이 아주 빡센 프로젝트는 아니었지만 그렇다고 널럴한 환경도 아니었기에 괜히 바쁘게 신규 기능 개발하고 있는 개발자들 발목 잡는 것은 아닌가 내 자신도 이러한 내용에 대한 회의감이 있었다. 서두에 밝혔듯이 실 운영될 시스템이 아니었기에 제때 구현되고 아주 제한적인 상황에서만 문제없이 동작하는 것이 최대 관건이기 때문에 더욱 그러했다. 코드에 ip가 하드코딩되고, System.out.println("haha"); 따위 남아있다 손 치더라도 이것이 큰 문제를 야기한다고 보긴 힘들지. (물론 저 상황까지는 아니었지만) 흐음, 하여간 품질을 우선시 하는 환경 자체가 아니었고, 나도 이것에는 동의를 하고 있기 때문에 애시당초 잘 동작할 수가 없는 환경이었다.

단위 test case도 제대로 작성되지 않았으니 2)번 목적도 달성하지 못했다. 아직도 junit 을 처음 접한다는 개발자가 있었으니 TDD는 정말 남의 나라 얘기지. Spring framework 은 정말 unit test 하기 좋은 환경을 제공하기 때문에 작성한 DAO 나 Service 에 대한 테스트가 정말 쉽다. 이를 이용하면 지겹게 서버 띄우고, jsp 들어가서 버튼 눌러보고 하는 시간 낭비를 확 줄일수 있는데 왜 이 좋은 것을 안할까. 단위 테스트를 하면 품질이고 뭐고를 떠나 개발자가 일단 편해진다. 그런데도 단위 테스트 하자고 하면 귀찮게 왜 그런것까지 하느냐는 (직접적이진 않지만) 반응이 아쉬울 따름이다. 우리 회사, 내 팀이라는 결속력이 좀 더 강하였다면 다르겠지만 여러 회사끼리 모인 SI 프로젝트에서 딱히 그들에게 단위 테스트의 장점을 설파할 정도까지의 열정이 없었기에 형식적으로 사후에 작성된 단위테스트만 돌려보고 마는 수준에서 그쳐버리고 말았다.

3) 번은 상당히 효과적이었다. 이는 고객과의 커뮤니케이션 보다는 개발팀 내에서의 커뮤니케이션 용도에 가까왔다. 즉, 고객-개발팀 보다는 PL-개발자 커뮤니케이션 정도. 매번 PL에게 개발내역 보여주느라 현재 작업 중단하고 보여주지 않고 테스트 서버를 통해 확인할 수 있었다. 또한 개발자들이 부분 부분 개발한 내용을 전체 통합하는 과정에서 발견되는 문제들을 빨리 잡아낼 수 있었다. 대부분의 문제는 spring config 와 추가된 library 때문이었다. 작업은 모듈별로 진행되었고 모듈별 별도의 spring config 를 사용하였으므로 그리 많이 발생하지는 않았지만, 조기 발견에 상당한 도움이 되었다.

4) 번은 매우 도움이 되었다. 이번에 사용한 WAS 는 weblogic 이었다. 가장 초기엔 개발:tomcat, 통합:weblogic 형태였다가, 통합 문제가 발생할 지도 모르므로 개발,통합:weblogic 으로 바뀌었었다. 그러나 도저히 weblogic의 무거움을 감당하지 못해 최종적으로는 다시 초기와 같은 환경으로 돌아갔다. 딱히 EJB 를 올리는 것도 아닌 순수한 spring framework 를 사용하였으므로 문제가 없을 것으로 생각했지만 예상과 달리 짜잘한 문제들이 꽤 발생하였다. 이쪽에서 돌아가는 sql이 저쪽에서 안돌아가고, jsp 문제도 간간히 발생하였다. 이런 문제는 매일 통합한 덕을 아주 많이 보았다.

QA

조직도에 명시된 나의 역할은 QA 였다. 그러나 어쩌다보니 개발자 대상 Spring framework 교육, 초기 framework 설정 및 예제 작성, CI 환경 구성, weblogic deploy 관리, 기타 통합팀과 함께 개발 이슈 해결 등을 곁가지로 맡게 되니 정체가 좀 모호했다. 원래는 저런 기술적인 내용은 다 통합팀에게 이관하고, (아니면 애시당초 내가 하질 말았어야 했다) 나는 산출물 및 테스트에 주력을 했었어야 하는데 그러질 못했다. 이것 저것 다 잘 했다면 좋았겠지만, 그 정도의 역량이 되질 못하고 몸속에 흐르는 개발자의 피를 숨기질 못하여 개발에 치중하다보니 자연스레 QA 본연의 역할을 제대로 하질 못했다.

CI 이야기를 하면서 언급했지만, 대규모 상용 서비스를 염두에 두지 않았고 빨리 동작하는 녀석을 눈앞에 보는 것이 중요한 프로젝트였기에 품질은 처음부터 우선순위에서 밀렸다. 다만 품질이 그렇게 중요하지는 않은 프로젝트였지만(정말로) , PM이나 PL급에서 부터 "품질은 별로 중요하지 않은 프로젝트다" 라고 못박아둔 것은 좋지 않았다. 아무래도 PM이 생각하는 최저 품질 의 기준과 개발자가 생각하는 최저 품질의 기준이 다르다보니 결국 개발자는 이정도면 되겠거니 했다가 PM이나 PL, 고객이 수정을 요구하는 건들이 있었다. 개중엔 좀 너무하다 싶은 것들도 있었다. 디자인 표준을 맞추지 않은 것들이나 정말 만들다 만 것 같은 페이지들. 하여간 다음에 이런 프로토타입 성 프로젝트를 하더라도  이렇게 quick & dirty 로 몰고가지는 말아야겠다. 제품 품질에 미치는 영향보다는 프로젝트의 분위기를 해치더라. 또한 누구보다도 QA 였던 나 자신이 위축되었다. 스스로 "과연 이렇게 검토하고 수정 요청을 하는 게 의미가 있는 것인가?" 하는 생각이 든다. 별도 QA 조직이었다면야 자신들의 목표가 "품질 달성"이니 여기서 동기를 부여받겠지만 내 경우엔 개발팀과 한몸이었기 때문에 더 고민이 되는 것이지. 흠흠, 이건 참 어려운 문제다.

QA의 또다른 중요한 역할 중 하나인 산출물 관리의 측면에서는 실패했다. 위에도 얘기했지만, 너무 기술에 눈이 팔려있다보니 PL이나 개발자들이 만든 산출물에 대해 제대로 검토를 못하고 어영부영 넘겨버렸다가 결국 개발자들 철수 후에 남은 PL들과 함께 생고생을 했다. 이건 나의 개인적인 planning 착오였다. 또한 기술 지원 활동을 미리미리 통합팀에 넘기지 못한 것도 컸고. 기술 지원보다는 산출물 관리가 훨씬 큰 이슈였는데 나의 개인적 부족함을 뼈저리게 (아니, 손가락 저리게) 느꼈다. 다음에는 처음부터 어느정도 role 을 확실히 긋고 가야겠다. 산출물 확인하고, 검토 의견 주는 것도 정말 장난이 아니더라.

정리

음, 너무 잘 안된 것 위주로만 너무 쓰다보니 마치 개판으로 진행된 프로젝트인 것으로 보일 수도 있지만 개발자 분들도 열심히 해 주셨고, 분위기 좋고 결과물도 잘 나온 "잘 마무리 된" 프로젝트였다. 다만 나의 역량 + 경험 부족 등으로 인한 개인적인 아쉬움도 적잖이 남았다.

full-time 개발자로 일하다 약 2년의 공백을 가지고 다시 개발 프로젝트였기에 그 자체로도 즐거웠다. 그리고 평소에 관심있던 Spring Framework을 기능 위주로 꽤나 빡시게 다룰 수 있었던 점, CI 환경을 구축하고 운영해 보았다는 점 (그리고, 그냥 돌리기만 해서는 안되겠다는 후회), 개발자가 아닌 QA로서 개발 프로젝트를 바라보는 경험을 했다는 것에서 의미있는 프로젝트였다. 개발자와 PL들과 싸우기도 하느라 짜증나고 힘들기도 했지만, 지나고보면 힘들었던 것들은 다 까먹게 되더라. :)

트랙백

이 글과 관련된 글 쓰기 (트랙백 보내기)
TrackbackURL : http://kingori.egloos.com/tb/4046674 [도움말]

덧글

  • 레인블루 2009/02/03 23:53 # 답글

    와 대단하다. 오리같은 QAer만 있다면 그회사는 진짜 복받은거야. 개발에 교육에 문서관리까지..

    그나저나 Spring이 정말 쉬워? 진짜?

    난 아무래도 Spring이 아니라 JAVA에 알러지가 있나봐.. T_T
  • 오리대마왕 2009/02/04 17:49 #

    초반엔 완전 삽질했는데 얼추 얼개 짜 놓으니 그 위에 얹는 것은 상당히 편했어요. 관리적 입장에서는 script 언어보다는 java 같은 compile 형 언어가 더 좋다고 생각합니다. 그래서 요즘은 더더욱 grooby 나 ruby 보다 java로 생각이 굳어져요.

    그나저나 뭐 하나라도 제대로 해야 복받은 것일 텐데 Y_Y
  • 매운맛나리 2009/02/04 23:45 # 답글

    헐 뭔 소린지 너무 어려워요
  • 오리대마왕 2009/02/05 10:03 #

    님 왜이러셈~
덧글 입력 영역