밥 삼촌이 알려준 조금 유치하기는 하지만 재밌는 동영상. 나찌의 패전은 애자일 방법론을 제대로 따르지 않은 히틀러의 부하들 탓에 킬러(!) 애플리케이션을 못만들었기 때문인가보다.

얼마전에 한국을 방문하기도 했던 초특급 스타 블로거인 조엘 스폴스키가 한 포드캐스트에서 TDD와 SOLID(OOD Principles)를 공격하는 발언을 해서 Kent Beck이 발끈하고, Robert Martin(aka Uncle Bob)이 반박에 나서는 일이 벌어졌다. 당사자들 보다는 주변의 반응이 더 뜨거웠는데, 때는 이때다 하고 격렬한 논쟁과 비난, 반박, 변호 등이 이어졌다. 수퍼 인기 블로거지만 꼽게 보는 사람이 많은 조엘의 과격한 발언과 언제나 논쟁의 단골 주제인 TDD, 별로 많은 사람에게 알려져 있지는 않지만 언젠가 한번쯤 뜨거운 주제가 될 것으로 예상했던 SOLID까지, 다들 한마디씩 하고 넘어가지 않고는 못견디게 만드는 이슈들이 모여있는 덕분이다. InfoQ에도 이 논쟁을 중간정리해주는 글이 올라왔을 정도니 그 논쟁의 열기가 얼마나 대단했는지 모르겠다.

논쟁은 최근 후속 포드캐스트에서 Joel이 Uncle Bob에게 인신공격을 했던 점에 대해서 사과를 하고 슬그머니 넘어갔다. Joel과 함께 낄낄거리며 SOLID를 씹어댔던 Jeff도 자신의 주장에 과장된 표현이 있었음을 인정했다.

 

논쟁의 내용을 떠나서 관련된 글을 읽어보는 것은 여러가지 흥미로운 생각할 거리를 주는 것 같다. 시간이 남는 사람이라면 한번쯤 링크를 따라 가면서 쭉 듣고(podcast. transcript도 제동된다) 글을 읽어보면 좋을 것이다.

 

단골 논쟁거리인 TDD는 그렇다치더라도 이 번에 그 동안 많이 주목받지 못했던  SOLID원칙이 크게 알려졌다는 점은 상당히 고무적이다. 당연히 SOLID가 원칙이나 법칙으로 불리고, 모든 상황에 기계적으로 적용할 만큼 절대적이라고는 할 수 없다. 그런데, 과연 그렇게 절대화 할 수 있는 법칙이라는게 소프트웨어 개발에 과연 존재하기는 하는걸까? 나에게 어떤 대단한 원칙과 법칙을 주더라도 나는 예외가 있음을 들어 그 주장이 절대적이지 않다고 반박할 자신이 있다. 어떤 좋은 기술과 원칙이든 불필요하게 과용될 수 있도 적용하기에 적합지 않은 상황이 있다.

개발자들이 다들 바보라서 그런 원칙을 들으면 기계적으로 적용하고 맹목적으로 신봉하지 않을 것이다. 그런데 그런 주장을 공격할 때는 항상 극단적으로 개발자들이 잘못 적용한 경우를 구지 가정해서 비난을 한다는 점이 문제이다. 그건 비난을 위한 비난 밖에 되지 않는다. 정말 말도 안되는 주장이나 기술이라면 모를까, 그렇지 않다면 그 의견의 장점이 무엇인지 먼저 살펴보고, 개선할 점과 문제점을 짚어나가는 것이 맞지, 조엘처럼 인신공격적인 발언과 왜곡된 상황을 가정하고 비난하는 식으로 접근하는 것은 한심한 일이다. 심지어 EJB를 까는데 온 힘을 기술였던 로드 존슨 조차도 EJB의 장점에 대해서 면밀히 분석하고, 무엇을 취할 것이고 무엇을 개선하고 무엇을 버릴 것인지 살펴보고 그리고 그 대안으로 스프링을 제시했지, 무조건 EJB는 현장은 모르고 책상 앞에서만 기술을 연구하는 연구원들의 과대망상에서 나온 쓰레기 기술이라고 비난하지는 않았다.

 

조엘의 TDD공격의 시작은 사실 TDD의 교조적인 신봉자들의 극단적인 주장에 대한 반박이었다고 한다. 자신이 쓴 Joel Test라는 글에 등장하는 조건에 100% Unit Test를 추가하라는 공격적인 메일을 받은 것에 대한 반박이었다고 한다. 대단히 많은 메일을 받았는지 아니면 딱 하나 받고선 이 참에 맘에 안들던 TDD좀 까보자 하고 과잉반응 했던 것인지는 모르겠다. 물론 그의 표현을 보면 Kent Beck이 화가 나서 쓴 글에 나오는 것처럼 조엘이 TDD의 개념에 대해서 제대로 이해하고 있는지 극히 의문스럽다. 100% 단위테스트를 만들었는데, 일부 설계가 변경되어서 테스트의 10%가 깨지면 그것을 어떻게 감당할 것인가라는 식의 주장은 그가 단위테스트와 OOD의 기본적인 개념을 이해하지 못하고 있다는 증거가 분명하다. 조엘이 처음 Uncle Bob이 만든 SOLID를 보면(사실 제대로 보지도 않았지만) 제대로 된 개발은 해본적으도 없는 관료적인 탁상공론이나 늘어놓는 사람이 만든 것이 분명하다고 공격했다. 이에 대한 Bob의 반박에 보면 일부 변경이 일어났다고 테스트의 10%가 깨지는 상황을 만드는 실력이라면 조엘은 아예 직업을 바꾸는 것을 고려해야 할 것이라고 비난했는데 그 점에 대해서 99.9% 동의한다. 프레임워크(결국 프로그래밍 패턴이)가 바뀌면서 애플리케이션 전체 구조가 흔들리는 0.1%의 예외가 있기는 하겠지만. 그것도 스프링의 개발철학처럼 POJO개발과 같은 하위 기술에 비의존적인 코드를 만들어서 피할 방도는 얼마든지 있을 것이다.

 

한가지 놀란점은 Kent Beck의 글에 달린 코멘트들인데, 그를 존경하고 따르는 사람이 많은 만큼 그를 극히 싫어하고 그의 주장과 아이디어에 대해서 경멸하는 인간들도 적지 않은 듯 하다.

 

SOLID에 대해서는 최상훈, 송치형님이 마소에 연재한 글을 보면 도움이 될 것이다. 내용은 좋긴한데.. 사실 설명이 좀 어렵긴하다.

또 SOLID에 대한 내용은 "UML실전에서는 이것만 쓴다"라는 책에도 간략히 나와있다. 그 책은 UML이 타이틀로 달려있긴 하지만 사실상 OOD에 관한 책이다. 가장 SOLID에 대해서 깊이 있게 설명하고 있는 책은 Agile Software Development, Principles, Patterns, and Practices라는 책이다. 번역이 되었는지는 모르겠다. C#으로 설명된 Agile Principles, Patterns, and Practices in C#도 있다.

지금 쓰고 있는 책의 제목을 애자일 스프링이라고 일단 생각하고 있다. 출판사로부터 최종 동의를 얻어야 하겠지만 이 이름이 마음에 든다.

사실 나는 그간 "애자일 프로그래밍을 위한 자바 어쩌고…" 하는 책들을 싫어했다. 애자일의 인기에 낑겨가려는 수작으로 보였다.

 

엉겹결에 스프링에 대한 책을 쓰기로 해놓고선 고민이 많이 됐다. 기존의 스프링 책 중에서 내 마음에 든 책은 단 한권도 없었기 때문이다. 누군가 스프링을 공부하겠다고 하면 적극 추천해 줄 책이 없었다. 다들 장단점이 있긴 했지만 마치 레퍼런스 북이거나 한두가지 스타일의 스프링 개발에 대한 튜토리얼과 같았다. 스프링을 오래 개발하면서 느낀 그 깊은 뭔가를 딱 느끼게 해줄 수 있는 책이 있었으면 좋겠다는 생각을 많이 했다.

 

그래서 그런 책을 쓰려고 했는데, 막상 쓰려고 보니 겁만 났다. 사실 뭔가를 좀 느끼고 알고 있는 것과 그것을 효과적으로 다시 전달하는 것은 정말 큰 차이가 있는 것을 알기 때문이다. 게다가 스프링은 책으로 쓰기엔 넘 방대하다. 방대한 내용을 다루는 책은 가볍기 쉽거나, 아니면 읽어도 무슨 내용인지 그 맥락을 파악하기 힘든 경우가 많다. 스프링은 그 자체로 그런 약점이 있다. 넘 욕심이 많은 프로젝트인지라 방대하기 때문이다.

 

그래도 그것을 관통하는 하나의 맥이 있을 것이고, 지향점이 있을 것이라고 생각했다. 그러던 중 애자일이라는 단어가 떠올랐다. 내가 스프링을 가르치고, 프로젝트를 진행하면서 가장 강조한 것이 무엇인지, 스프링을 통해서 배울 수 있는 것이 무엇인지를 설명하다보면 애자일이라는 단어와 그 이름으로 시작하는 방법론에서 말하는 것과 이상하리만큼 통하는 무엇이 보인다.

 

애자일이라는 이름의 기원에 관해서 마틴 파울러가 한 얘기를 보자면, 애자일은 "변화에 대한 적응과 대응"이라는 관점에서 애자일 운동의 가장 중요한 가치를 잘 담은 단어이기 때문에 선택했다고 한다. 애자일 방법론들이 가지는 공통의 시각을 잘 표현했다는 것이다.

스프링이 프레임워크이고, 프레임워크란 켄트 벡의 말대로 어떤 문제에 대한 생각의 방법이라고 한다면, 스프링이 풀고자 하는 문제, 즉 – 엔터프라이즈 개발의 복잡함에 대한 스프링의 시각은 바로 애자일이라는 단어를 통해서 느낄 수 있는 애자일 방법론의 시각과 유사하지 않을까 생각이 들었다.

단순함(simiplicity)과 테스트편의성(testability)은 스프링의 핵심철학을 가장 잘 표현하는 단어이다. 이것은 단순함을 필수불가결한 요소로 정의하고 있는 애자일선언의 원리 10항과 변화에 순응하고 기민하게 대응할 수 있어야 한다는 선언과 원칙을 위한 구체적인 실천방법의 대표격인 TDD류의 가치와 매우 잘 통한다고 볼 수 있다.

 

어쨌는 그래서 제목은 애자일 스프링으로 했고, 내용도 사실 이 두가지를 잘 살리는 스프링 개발이라는 부분에 집중하고 있다. 스프링을 제대로 잘 사용하자 이건데.. 음음.

 

어쩌면 애자일이라는 단어가 그냥 폼나서 쓴 것일지도 모르겠다. (  ")

Maven은 Maven Way라고 불리는 자신만의 스타일을 강요한다. 순서가 정해진 build lifecycle도 그렇고, 독특한 default directory layout도 Maven으로 만들어진 프로젝트임을 한눈에 알아볼 수 있게 만드는 Maven에서만 주로 찾아볼 수 있는 독특한 폴더구조를 가지고 있다.

Maven이 이렇게 Maven Way를 강제하는 이유는 프로젝트 관리, 빌드의 best practice를 CoC형태로 제공함으로 빌드 스크립트나 설정의 많은 부분을 간략하게 만들어 주고, 한번 그 스타일에 익숙해지면 어떤 Maven을 사용하는 프로젝트를 접해도 일관된 방법으로 접근할 수 있는 common interface를 제공할 수 있기 때문이다.

Artifact 패키징 전에 항상 모든 test를 먼저 수행하게 한다거나(실패하면 빌드 중단), 복잡한 프로젝트를 sub-modules로 분화해서 프로젝트 설정을 상속해서 사용할 수 있게 하는 것 또 라이브러리 파일은 프로젝트와 분리해서 local repository에 저장해두고 여러프로젝트가 공유해서 사용할 수 있게 하고, Maven coordinates(groupid, artifactid, version..)로 ID를 부여해서 인터넷상의 공용 repository에서 필요하면 다운로드 받아서 사용할 수 있게 하는 것등은 Maven을 사용하면서 자연스럽게 적용하게 되는 좋은 best practice임이 분명하다.

하지만 Maven을 처음 접하면서 상당히 당황스럽고 불편한 Maven Way도 있다. 거의 대부분의 Maven 초보자들이 부담스러워 하는 것이 바로 default layout이다.

Maven은 src/main/java에 자바 코드를 src/main/resources에 메인 설정파일들이나 리소스등을 넣게 한다. Test와 관련된 것도 src/test/java와 src/test/resources를 사용하게 한다.

하지만 Maven을 사용하지 않는 대부분의 프로젝트에서는 기존의 자바프로젝트 관례대로 src에 애플리케이션 자바 소스와 리소스를 , test에 테스트 코드와 리소스를 넣는다. Ant를 이용하는 프로젝트의 관례로 거의 비슷한 스타일이고, Eclipse도 기본 구조로 프로젝트 베이스 폴더 아래 src를 사용한다.

그러다가 Maven의 새로운 폴더 레이아웃을 쓰면 두가지 면에서 불편을 느끼게 된다. 첫째는 directory depth가 2단계나 더 깊어진다는 것이다. 이클립스 같은 IDE를 써도 프로젝트 트리를 펼치는 것은 매우 귀찮은 일이다. 커맨드 라인에서 다른 툴을 사용하는 경우도 마찬가지이다. 패키지 depth마저 길게 되면 편집할 파일이나 패키지, 폴더를 찾아가고 이동하는데 시간이 많이 소모된다.

더 짜증스러운 것은 java와 resource의 분리이다. 개념적으로 분리하는 것이 깔끔해보이는 것은 사실이다. 하지만 그로 인해 depth가 늘어나는 것은 물로이고, 많은 경우 패키지나 폴더 생성의 작업이 두배로 늘어나고 코딩시 폴더 이동으로 인해 많은 불편이 뒤따르게 된다.

사실 Java소스와 resource를 구지 폴더 상단에서 구분하는 것은 아무런 장점이 없다. 기본 방식대로 같이 두어도 아무런 문제가 없기 때문이다. 간단히 확장자로 구분하면 그만이다. Eclipse의 자동빌드 기능은 아무런 문제 없이 .java로 끝나는 파일은 컴파일 해주고 그 외의 파일은 target(bin)폴더로 복사해준다.

리소스와 자바파일이 워낙 많아서 혼란을 주니 구분하자고도 생각해볼 수 있지만, 사실 대부분의 애플리케이션에서 사용하는 main resource라고는 설정파일 정도인데 대부분 패키지 루트에 위치한다. 반대로 자바소스는 default package를 안쓰는 것이 바람직하다. 따라서 자바소스와 리소스를 한 폴더 트리아래 둔다고 혼란을 줄 것도 없다.

반대로 테스트 쪽은 코드와 설정파일을 같은 패키지에 두는 것이 유리하다. 대표적으로 Spring의 @ContextConfiguration을 사용하는 경우를 보자. XXX-context.xml 파일은 테스트 자바 소스와 같은 폴더에 위치하는 것이 매우 편하다. 그 외에 fixture로 사용할 xml, xls, dat, txt 파일도 마찬가지이다.

이클립스를 사용하는 경우에 test와 test resource를 폴더를 구분해 버리면 매우 불편하다. 만약 src/test/java/com/mycompany/myproject/module/submodule/component/XXXTest.java 라는 위치에 테스트 코드를 만들었다고 치자. 테스트 코드를 만들고 테스트에서 사용할 스프링 context파일을 만들려고 하니, 그 패키지에 만들면 간단할 텐데 Maven의 layout을 따르기 위해서는 다시 src/test/resources로 가서 com/mycompany/myproject/module/submodule/component라는 패키지를 생성하고 그리고 그 아래 XXXText-context.xml이라는 설정파일을 만들어야 한다. 매 패키지마다 그 작업을 반복해야 하고, Test 소스 파일 위치가 달라지면 resource 패키지도 같이 움직여야 하는데 6-7줄로 길게 늘어진 폴더 두군데를 쫒아다니면서 그 작업을 하자니 여간 불편한게 아니다. 종종 resource쪽 패키지를 만들다 패키지 명이 틀려서 테스트가 오작동 하거나, 패키지를 혼동해서 다른 위치에 설정파일을 만들어서 문제를 일으키는 경우가 발생한다. 정말이지 이 강제하는 Maven의 default directory layout은 Maven을 사용하는데 가장 큰 장애물 중의 하나라고 생각된다.

Sub modules로 세분화 되어있는 프로젝트를 보면 더욱 가관이다. sub module에 갔더니 또 src/main/java/…/…/…/…/에 소스 하나.. 또 src/main/resources에 하나 src/test/java, src/test/resources에 하나.. 등등 찾다보면 눈이 다 어지럽기까지 하다. 어떤 Maven으로 만든 프로젝트를 보면 sub modules마저 세분화 하다보니 이 layout 구조 때문에 소스의 파일 갯수보다 폴더 갯수가 더 많은게 아닌가 하는 생각이들기도 한다.

처음 Maven을 사용하면서 이 불편함 때문에 당장 Maven의 default layout을 변경할 수 없는가 알아보았다. 당시 Maven 사이트의 문서를 찾아보니 "default layout을 (복잡한 방법을 써서) 변경할 수는 있지만, 그러면 그 CoC를 따르는 수많은 플러그인과 기타 툴들과의 충돌이 발생할 수 있고, 그래서 오히려 더 큰 불편이 뒤 따를테니 손 안대는 것이 좋다"라는 경고가 떡하니 나와있었다.

그래서 바로 포기하고 Maven을 쓴다면 당연히 그 폴더 구조를 따라야 한다라고 생각하면서 지금까지 사용해왔다.

그러던 중에 얼마전에 Maven의 default directory layout을 변경하는 것은 매우 간단하다는 것을 알게 되었다. 그리고 얼마동안 여러가지 테스트를 해보면서 그 방법을 적용한 결과 문제를 일으킬만한 소지는 거의 없다라는 결론을 내렸다. 이럴수가!

내가 원하는 directory layout은 Eclipse나 Spring 소스가 사용하는 그대로이다. 모든 소스의 root 패키지는 project base 폴더 바로 아래 둔다는 것이다. 그리고 자바 소스와 리소스, 그리고 혹시 나중에 aspect나 script가 함께 등장해도 구지 구분하지 말고 하나의 소스트리에 둔다는 것이다. 다만 배포될 소스와 테스트는 반드시 구분한다는 점.

/src와 /test가 기본 소스와 리소스 폴더가 되는 것이다.

설정방법은 다음과 같다. Maven의 POM 안에 build 항목에 다음을 넣으면 된다.


	${project.basedir}/src
	${project.basedir}/scripts
	${project.basedir}/test
	
		
			${project.basedir}/src
			
				**/*.java
			
		
	
	
		
			${project.basedir}/test
			
				**/*.java
			
		
	
...

먼저 build 항목의 sourceDirectory, testSourceDirectory를 변경해주고, resource와 testResource도 같은 방법으로 변경한다. Resource 설정을 할 때 주의할 점은 자바소스코드가 같이 있기 때문에 .java 파일은 복사되지 않도록 exclude 해주는 것이다. 이 설정은 Maven의 Super POM에 있는 설정을 override해주는 것이다.

이렇게 작성하고 컴파일, 테스트, 리소스, 패키징등에 적용해봤을 때 아무런 문제가 발생하지 않는다. Sub modules를 이용한 멀티 프로젝트 구조에서도 역시 설정을 상속 받아서 sub modules에 까지 잘 적용된다.

실제로 Maven 소스를 분석해보면 바로 이 build 설정에 나와있는 디렉토리 설정을 compiler나 resource 플러그인에 제공해서 동작하게 한다. 따라서 Maven의 이 메타정보를 가져다가 적용하는 플러그인이라면 새로운 디렉토리 구조에 아무런 문제가 없을 것이다.

최근에 Maven에 대한 호감이 많이 늘었는데 바로 이 directory layout 변경이 가능하다는 것과 매우 안정적이고 뛰어난 기능을 가진 m2eclipse 플러그인 때문인 듯 하다. m2clipse는 언젠가 다시 소개하겠지만, 바로 실전 프로젝트에 적용해도 문제없을 만큼 충분히 잘 만들어진 Eclipse용 Maven 플러그인이다. 특히 Eclipse에서 가장 고민이었던 sub-modules구조의 Multi-module project를 아주 편리하게 사용할 수 있게 해주는 것은 정말 감동적이기까지 하다. Maven 개발에 있어서 IDEA가 더 이상 안부럽다.  모든게 Maven의 핵심 개발자들이 포진하고 있는 Sonatype 덕분인듯 하다. 최근에 private repository도 Artifactory에서 Sonatype의 Nexus로 바꿨는데 이것도 매우 만족스럽다.

이제 남은 것은 프로젝트의 webapp 폴더를 변경하는 것과 이를 wtp와 깔끔하게 접목시키는 것이다. 이 역시 어렵지 않게 되지 않을까 생각된다. 그 외에는 Main이나 Test를 하나 이상으로 가져가는 것인데, Spring 소스처럼 Tiger(jdk1.5+)와 그 이하 소스를 구분하는 경우 등에 유용할 듯 싶다. 문제는 <build> 설정에는 resource와 달리 sourceDirectory는 하나만 지정할 수 있게 되어있다. 하지만 maven-compiler-plugin에서는 여러개의 source directory를 받아서 사용할 수 있다. 이를 직접 이용하면 되지 않을까.

MS의 Visual Studio 팀의 요청으로 만들어진 Kent Beck의 애자일 소프트웨어 개발과 툴에 관한 white paper가 나왔다. 화이트보드나 종이에 쓱쓱 그린 것 같은 그림들이 인상적이다. 애자일과 툴, 개발환경 등에 대해서 관심이 있는 사람이라면 필독. 안그래도 오늘 영회랑 좋은 툴을 만들어보자는 모의를 했는데… 흠.

 

영회야 이 white paper 번역좀 해라. 이 것부터 해야 하나?

update:
Yahoo Groups의 Extremeprogramming에 Kent Beck이 이 paper에 대한 포스트를 올렸다. 배경이랑 부언 설명이 있으니 읽어보면 도움이 되겠다.

© 2017 Toby's Epril Suffusion theme by Sayontan Sinha