검색결과 리스트
스프링에 해당되는 글 19건
- 2010/10/30 2장 테스트(3) - 스프링 테스트와 학습 테스트
- 2010/10/30 2장 테스트(2) - UserDaoTest 개선과 JUnit 프레임워크
- 2010/10/30 2장 테스트(1) - UserDaoTest 다시 보기
- 2010/09/28 1장 오브젝트와 의존관계(7) - 데코레이터 패턴 그리고 XML 설정
- 2010/09/27 1장 오브젝트와 의존관계(6) - 싱글톤 레지스트리 그리고 의존관계 주입 (1)
- 2010/09/24 1장 오브젝트와 의존관계 (5) - 스프링의 IoC
- 2010/09/20 1장 오브젝트와 의존관계 (4) - 명확한 용어 정의와 제어의 역전
- 2010/09/17 1장 오브젝트와 의존관계 (3) - 원칙과 패턴
- 2010/09/15 1장 오브젝트와 의존관계 (2) - 관심사의 분리(Separation of Concerns) (2)
- 2010/09/14 1장 오브젝트와 의존관계 (1) - 용기 있는 1장의 출현 배경과 토비의 OOD론 (1)
- 2010/09/13 토비의 스프링 3 읽고 토론하기 17주 프로그램 소개 (16)
- 2010/03/16 들을 만한 스프링 교육 (5)
- 2009/08/20 [Spring 기본 다지기 1] Spring과 AOP
- 2009/05/16 2009년의 한국 스프링 사용자 모임(KSUG)
- 2009/03/20 오랜만에 서점에서 본 개발 관련 서적(일부 첨언) (7)
- 2007/12/14 스프링을 통해 진화하기 (2)
- 2007/12/07 6번째 스프링 사용자 모임 공지 (2)
- 2007/04/27 다음 스프링 세미나 주제는 Spring Web MVC (4)
- 2007/04/24 스프링 공개 세미나 에피소드 "투" (5)
글
2장 테스트(3) - 스프링 테스트와 학습 테스트
사진 출처: 이프릴(Epril) 스프링 세미나 풍경
그간 스프링의 테스트 지원 기능은 Java 5 프로그래밍 요소에 맞춰 우아하게 변모하여 Spring TestContext Framework로 발전했다.
이와 관련한 책 읽기 모임 의견을 들어보자. 찬욱군은 TestContext를 학습하면서 JUnit 3.8과 JUnit 4.x 호환성을 지키는 부분에 놀랐다고 한다. 나는 주입을 위해 굳이 생성자나 수정자가 필요하지도 않게 배려한 부분에서 감동했다. :)
테스트 코드에 의한 DI
책을 따라 실습해보면 무리 없이 스프링 테스트 컨택스트를 배울 수 있다. 다만, @DirtiesContext 내용이 정확히 와 닿지 않았다. 이런 경우라면 다음 절에 소개하는 학습 테스트를 만들어 명확히 할 수 있다. 여러 개의 테스트 클래스를 만들고 한 쪽에 정적 변수로 ApplicationContext 개체를 참조할 수 있게 한다.
@ContextConfiguration(locations="/testcontext/applicationContext.xml")
public class AaaTest {
static ApplicationContext firstContext;
그리고 테스트 클래스에서 정적 변수를 한 번은 초기화하게 한다.
public void setUp(){
if(AaaTest.firstContext == null) AaaTest.firstContext = applicationContext;
}
마지막으로 정적 변수와 멤버 변수인 applicationContext가 가리키는 개체가 같은지 비교하는 테스트를 여러 개 만든다. @DirtiesContext를 클래스에 붙였다가 메소드에 붙여본다.
public void test1(){
assertEquals(AaaTest.firstContext, applicationContext);
}
@DirtiesContext
@Test
public void test2(){
assertEquals(AaaTest.firstContext, applicationContext);
}
@DirtiesContext를 클래스에 붙이면 해당 클래스가 끝날 때 애플리케이션 컨텍스트가 새로 만들어진다. 메소드에 붙이면 해당 메소드가 끝나면 새로 만들어진다.
저자의 꼼꼼함을 들여다볼 수 있긴 했으나, 찬욱군은 현장에서 @DirtiesContext가 필요한 경우에 대해 아직 감이 없다고 한다.
컨테이너 없는 DI 테스트
2장까지 내용을 충분히 이해했다면 쉽게 읽고 넘어갈 내용이지만, 사실 관심사 분리(SoC) 훈련이 없다면 이해하지 못할 내용이 아닐까 싶다. 혹시 발췌한 내용이 이해가 가지 않거나 갑자기 왜 이런 설명을 하는지 이해가 안 간다면 안타깝지만 1장을 다시 읽어야 한다. :)
DI를 이용한 테스트 방법 선택
다양한 방법을 소개하고 마지막에 선택 기준을 제시한다. 1번은 역시 스프링 컨테이너조차 없는 테스트다. 앞서 설명한 고립성과 시간 절약은 스프링 컨테이너에도 그대로 해당한다. 스프링 컨테이너를 이용하는 기준은 무엇인가? 여러 개체와 복잡한 의존관계를 갖는 개체를 테스트할 경우다. 이 경우는 테스트 설정을 따로 만드는 방법이 좋다. 세 번째는 예외적인 의존관계를 강제로 구성할 경우다. 이때는 앞서 학습한 @DirtiesContext가 유용하다.
§ 2.5 학습 테스트로 배우는 스프링
작년인가 월간 마소에 JUnit을 이용한 코드 개선 과정 녹화라는 글을 기고한 일이 있다. 개발 후 운영자도 내막을 잘 모르는 레거시 코드를 학습하는 과정과 이를 공유하는 수단으로 테스트를 사용한 경험담이다. 저자가 열거한 학습 테스트 다섯 가지 장점을 그 경험에 대입해보니 그대로 들어맞는다. 학습 테스트는 과정에서 배우는 바도 매우 크지만, 결과를 보존하면 문서로는 전달하기 어려운 생생한 재현을 보장한다. 특히나 프레임워크나 제품의 주요 기능 혹은 API 쓰임새를 포괄하는 테스트를 만들어 둔다면 마치 TCK(Technology Compatibility Kit)처럼 훌륭한 호환성 검증 도구 역할을 할 수 있다.
글
2장 테스트(2) - UserDaoTest 개선과 JUnit 프레임워크
157쪽에서 수정 후에는 성공 메시지가 "조회 테스트 성공"으로 바꾸어야 하는데 출판사 정오표에는 빠진 오류인 듯하다. 159쪽 하단에 JUnit 필수 조건에도 void 가 빠져 있다. 170쪽에 내용이 나오는 내용인지라 저자가 실수로 빠뜨린 듯하다. 저자는 스프링 3.0에서 처음 등장한 설정 방법부터 소개한 것처럼 assertEquals() 메소드보다 assertThat() 메소드부터 소개한다. assertThat은 예전에 만든 교육 자료가 있어 일부를 공개한다.
Joe Walnes의 글은 Flexible JUnit assertions with assertThat()이다. assertThat 자체는 JUnit에 들어갔지만, 책에서 사용하는 Matcher는 hamrest 라이브러리에 있다. 책 읽기 모임에서 나온 의견을 덧붙여 보자. JUnit을 충분히 써본 찬욱군은 굳이 assertThat을 사용하는 이유를 모르겠다고 한다. 이에 대해 용권씨는 Scala 학습 전에는 자신도 몰랐으나 이제는 DSL로 대변하는 가독성 있는 스타일에 대해 이해가 가며, assertThat도 같은 맥락으로 이해한다고 했다. 내 생각엔 assertThat 자체는 영어문화권이 아닌 우리에게 큰 의미는 없다. 다만, Matcher는 (클래스 수준 이하) 단위 테스트를 돕는 훌륭한 개념이기 때문에 은근 슬쩍 스프링 학습과정에서 배웠으면 하는 저자의 노파심이 아닐까 싶다. 찬욱군 의견처럼 161쪽 리스트 2-5는 assertEqual이 차라리 낫다. :)
JUnit에 hamcrest가 포함되어 있긴 하지만, 테스트 주도 개발 TDD 실천법과 도구에 따르면 최신 버전(1.2)은 직접 내려받아야 한다. hamcrest에 대한 자세한 내용은 테스트 주도 개발 TDD 실천법과 도구에서 배울 수 있다. 134쪽부터 약 15쪽 정도 분량으로 hamcrest 기초부터 확장 방법까지 설명하고 있다.
테스트 주도 개발 - 
채수원 지음/한빛미디어
205~206쪽을 보면 종전 사용법까지 포함한 여러 가지 확인 코드 작성 방식을 보여준다. 저자는 더 나아가 자신의 블로그를 통해서 JUnit assert 매쉬업이라는 최신 기법까지 소개하고 있다.
개발자를 위한 테스팅 프레임워크 JUnit
저자는 다시 한번 테스트를 강조한다.
역시 지나치다 싶을 정도로 초강수를 둔다. 하지만, 단위 테스트가 주는 이점(품질 향상, 빠른 개선 주기 지원)을 공감하지 못하는 개발자에게 이 정도 위협(?)이 먹힌다면 의미는 있다. 필자는 다른 회사가 개발을 맡는 2번의 프로젝트에서 DAO 단위 테스트만 의무화했던 경험이 있는데 모두 예상치를 웃도는 효과를 얻었다. '우리도 한번 해보자!'라고 하시는 분은 저렴한 방법으로는 테스트 주도 개발 TDD 실천법과 도구 학습이 있고, 비용이 들어가는 방법으로는 필자에게 컨설팅 요구를 하실 수 있다. :)
동일한 결과를 보장하는 테스트
혼동하기 쉬운 내용을 잘 지적하는 내용이다. 외부 요인이나 실행 순서가 테스트에 영향을 미치지 않도록 실험실 꾸미듯 단위 테스트를 만들어야 한다.
토스 177쪽을 보면, 스프링의 창시자인 로드 존슨이 '항상 네거티브 테스트를 먼저 만들라'라고 조언했다고 하는데 정말 그럴까? Expert One-on-One J2EE Development without EJB 430쪽에 Negative Tests라는 내용이 나온다. '항상 먼저 만들라'라고 한 내용은 찾을 수 없지만, 바람직한 작동을 위한 테스트만큼이나 비정상적일 때에 대한 테스트도 잊지 말 것을 강조하고 있다. 영어라 접근에 제약은 있지만, Expert One-on-One J2EE Development without EJB 14장은 J2EE/Java EE 영역에 있어서만큼은 가장 얇으면서 풍부한 내용을 담은 주옥같은 글이니 꼭 읽어보길 권한다. 사실 많은 내용이 토스에 녹아 있긴 하다.
책 읽기 모임에서 용권씨가 막장(?) 사례를 말해줬다. 이를 테면 assertTrue(true)와 같은 코드로 단위 테스트를 한 경우도 있단다. ㅡㅡ;
반면에 찬욱군은 외부 솔루션이나 고객 사이트 환경을 모르고 대답해주는 이가 없어서 대충 테스트 했던 과거를 회계했다.
테스트 코드 개선
테스트 순서나 외부 요인에 영향을 받지 않는 고립 테스트의 중요성은 여러 차례 이야기했다. JUnit은 이를 위해 테스트마다 별도 개체를 생성한다. 토스 2장에서는 실습과 함께 체득하기 때문에 효과적으로 익힐수 있다.
픽스처
테스트 픽스처(Test fixture)에 대한 위키피디아 정의를 옮겨본다.
Test fixture refers to the fixed state used as a baseline for running tests in software testing. The purpose of a test fixture is to ensure that there is a well known and fixed environment in which tests are run so that results are repeatable. Some people call this the test context.
글
2장 테스트(1) - UserDaoTest 다시 보기
아래 발췌한 도입부 내용은 테스트에 대한 강조가 지나쳐 마치 스프링을 볼모로 독자를 위협하는 듯한 인상을 받는다.
스프링 프레임워크 자체는 테스트를 강제하지 않는다. 그럼에도 저자가 2장 전반에 걸쳐 무리다 싶을 정도로 강조하는 이유는 무엇일까? 추측건대 테스트를 거의 하지 않는 개발 풍토 탓이 아닐까? 2005년부터 현재까지 참여한 9개 프로젝트 가운데 단위 테스트 작성에 성공(?)한 경우는 5회이고, 실패한 경우는 4회다. 다른 이유를 배제하면 단위 테스트에 성공한 다섯 번은 모두 납기 내에 시스템을 오픈했다. 단위 테스트 작성을 도입하지 못한 4번 중 3개의 프로젝트는 필자가 조기 철수하는 프로젝트여서 결말은 모르지만 무리한 야근이 있었다는 점은 확인할 수 있었다. 그리고 필자의 참여 비중(주 1회)이 낮아 어찌할 수 없이 실패를 지켜봤던 1번은 6개월가량 오픈이 늦어졌다. 자동화 테스트와 회귀 테스트를 충족하는 단위 테스트의 효과는 분명한데 실전에 도입하기란 만만치 않다. 필자가 성공한 5번의 프로젝트 중에 3번은 우리 팀만으로 개발한 경우다. 우리 팀에서도 단위 테스트를 한 번도 작성하지 않았던 개발자가 있었지만, 짝 프로그래밍 형태로 일주일만 가르쳐주면 무리 없이 테스트를 작성했다. 문제는 소속이 다른 여러 조직에서 개발하는 경우다. 필자는 항상 단위 테스트를 주장하지만, 개발이 끝날 때까지 참여하는 경우만 힘을 쓸 수 있었다. 필자를 대신하여 테스트를 유도하고, 개발자가 막힐 때 방법을 알려줄 사람이 없기 때문이다. 성공한 두 차례중 한 번은 외국에서 훈련 받은 최고수준의 프로젝트 관리 진이 포진한 경우였다. 그렇지 않은 한 차례는 필자가 속한 팀이 프로젝트 관리 조직을 장기간 계몽(?)했다. 사실 투쟁의 역사이기도 했다. 그리고 실무적으로도 1,000회 정도의 코드 인스펙션을 수행했다. 우리 팀 개발자는 '차라리 내가 짜는 편이 빠르겠다'는 불평을 수없이 내뱉었다. 이런 사회적 배경을 고려하면 테스트는 아무리 강조해도 지나치지 않다.
토론 모임에서는 '스프링을 통해 처음으로 자동화 테스트를 경험했다'는 사람이 많았다. 소수지만 모인 사람만 놓고 보면 압도적인 비중이었다. 한편으로는 스프링이 현실에서 테스트를 적합하게 해낸 사례기도 하다.
작은 단위의 테스트
직접 관계는 없지만, JSP 모델1 구조에서 화면 단위로 테스트하던 모델2 MVC 구현일텐데. 그 부분이 아니라 아이들이 학교와 와야 의미가 있겠죠.
토스 151쪽 내용은 단위 테스트 경험자라면 누구나 고민해봤거나 고민했어야 할 내용을 잘 짚어낸 좋은 예다. 단위 테스트의 고립(isolated) 테스트 특성을 잘 설명한 내용이다. 필자는 2006년 단위 테스트의 "단위"라는 글을 쓸 즈음에 단위 테스트 개념을 이해하려고 여러 가지 시도를 한 바 있다. Mock을 이용한 테스트가 단위 테스트를 이해하는 데 큰 도움이 되었다. 국내 블로그 등에서 "단위"에 대한 고민을 찾을 수 없다는 점은 얼마나 단위 테스트를 안 하는지를 반증한다. 예전에 단위 테스트에 대해 고민했던 흔적을 남겨둔다.
- 단위 테스트의 "단위"
- easymock을 이용한 Spring MVC Form 컨트롤러 요청 처리 테스트 1
- easymock을 이용한 Spring MVC Form 컨트롤러 요청 처리 테스트의 개선
- 단위 테스트의 경계: 어디까지가 단위 테스트인가?
- 개발자들이 테스트 작성시 어려워하는 점
- JUnit 기본 사용법
- 단위 테스트에 관한 흥미로운 글
- 단위/통합 테스트의 경계 선정을 돕는 그림들...
- EasyMock2을 활용한 협업 테스트 1
- cohesion, TDD 그리고 SRP(Single Responsibility Principle)
저자는 작은 단위 테스트의 효과를 문제가 발생했을 때 찾을 수 있다고 설명한다. 프로젝트 전체를 놓고 생각하니 V 모델이 입자 크기와 겹쳐져서 떠올랐다. 프로젝트 초반에는 시스템을 규정하는 입자가 크고, V 모델 하부 구현단계에 들어서면 입자가 가장 작아졌다가 점차 테스트 입자가 커지는 그림이 머릿속에 그려졌다.
출처: 위키피디아
검증과 확인을 제공하는 V 모델의 효과를 극대화하는 방법은 무엇이 있을까? 수학적으로 증명할 수는 없지만, 빠른 피드백을 받고자 한다면 가장 작은 V 인스턴스(?)를 만드는 방법이다. 다시 말해서 작은 단위 테스트를 활용하는 방법이다. 필자가 켄트벡의 TDDBE를 읽고 가장 인상 깊었던 부분이 바로 작은 테스트를 통해 찾아가는 리듬인데, 앞서 사용한 표현에 따라 가장 적절한 V 인스턴스 크기라고 말할 수 있다. 린 소프트웨어 개발의 적용에서도 작은 테스트를 지지하는 경구를 제공한다.
하지만, 적절한 V 인스턴스 크기를 찾는 일은 매우 높은 밀도로 상당 기간 경험을 쌓았을 때 주어지는 선물이다. 볼링 게임으로 처음 TDD를 배우던 때를 회상하면 밥 삼촌이 카타에서 보여준 놀라운 칼질은 내공 차이를 명확히 보여준다.
저자는 단위 테스트에 대해서 개발자 테스트라는 다른 표현을 제시한다. 책에서 다루는 단위 테스트 작성자가 개발자임을 분명히 한다. 단위 테스트 수행자가 누구냐에 따라 테스트 목적이 달라지고, 프로젝트 갈등 구도도 달라진다. 하지만, 설사 제삼자 테스트 형태로 단위 테스트를 수행하는 이상적인 조직이 있다고 해도 개발자 스스로 단위 테스트를 해야 한다. 그렇지 않은 코드는 부실 코드(anemic code)라 불러 마땅하다.
자동수행 테스트 코드
저자는 수치까지 예를 들며 자동화 테스트의 중요성을 설명한다. 사실 자동화 테스트 작성의 생소함 탓에 놓치기 쉬운 그러나 실로 엄청난 자동화 테스트의 위력이다. 프로젝트 전체를 놓고 보면 잘 만든 자동화 테스트가 모여 만들어낸 회귀 테스트 자산의 힘은 말로 설명하기 어렵다. 앞에 언급한 필자의 경험을 놓고 보면 프로젝트 성공의 핵심 열쇠 중 하나다.
작은 시간이라도 아끼라는 자동수행 테스트 저번에 깔린 교훈은 필자가 학교에서 C++을 배울 때 가장 먼저 마음에 새긴 원칙인 Principle of least privilege을 떠오르게 한다. 이른바 POLA 원칙은 변수의 가시성(scope) 맥락에서 배웠지만, 자원 사용에 대한 정책이나 보안에도 응용된다. 그런데 지금 생각해보니 프로젝트에 주어진 시간 자원에 적용해도 의미가 살아난다.
지속적인 개선과 점진적인 개발을 위한 테스트
다시 한번 V 모델을 떠올린다. 작은 단위 테스트가 쌓여 회귀 테스트 기반을 이루어 시스템 전반을 검증할 수 있는 토대를 만드는 양상은 실용적인 V 모델 적용의 전형적인 예다. 아쉽게도 많은 프로젝트에서는 V 모델의 맥락을 충분히 이해하지 못하고 높은 성숙도를 요하는 이론을 그대로 적용하려고 옥신각신하는 모습을 볼 수 있다. 진정 V 모델을 실현하고자 한다면 긴 호흡으로 계획하여 단장은 필수적인 단위 테스트부터 팀/조직에 보급하고 성숙도를 높아지면 더 큰 그림을 그리는 방법이 어떨까?
UserDaoTest의 문제점
옥에 티 수준이지만, 두 번째 문제점 제목은 실행 작업의 번거로움보다는 체계적인 테스트 실행의 어려움이 나을 듯하다. UserDaoTest를 수정한다고 실행 작업을 벗어나는 것은 아니다. 155쪽 내용에도 체계적인 테스트 실행과 결과 확인에 대해 이야기하고 있다.
글
1장 오브젝트와 의존관계(7) - 데코레이터 패턴 그리고 XML 설정
부가기능 추가에 제격인 GoF 설계 패턴은 데코레이터(Decorator)다. 토스가 패턴 책은 아니니까 굳이 거론하지는 않지만, 124~125쪽 예가 바로 데코레이터 패턴으로 기능을 추가하는 내용이다. GoF 책 175~184쪽에 해당하며, 2006년에 간단히 요약한 일이 있다.
§ 1.8 XML을 이용한 설정
앞서 말한 바대로 토스 전개는 물 흐르듯 스프링을 소개하고 있다. 사용자 코드에 설정을 위한 최소한의 코드만 추가한다. 이 과정에서 자연스레 3.0의 새로운 설정방식부터 소개한다. 전통적인 설정방식은 오히려 나중에 소개하는 시간의 역순 흐름이 세련된 구성을 돋보이게 해준다.
XML 설정
131~132쪽에서 강조한 내용 역시 비대칭성을 내포한 XML 설정 특성을 이야기한다. 실수를 유발할 수 있는 비대칭성이 바로 DI를 통해 제공하는 마법이라는 점을 이해해야 한다. 마법은 이미 오래전 GoF에서도 거론하는 Dynamic Binding이다. 134쪽에서 지적한 주의사항도 비슷한 맥락에서 이해할 수 있다.
아래와 같이 <property>태그의 두 속성값이 같다 해도 쓰임새는 전혀 다르다. <bean> 태그의 name 속성과 ref 속성값은 둘 다 실행시점에 의미가 있다. 다시 말해 Dynamic Binding 대상으로 코드를 바꾸지 않고 수정할 수 있다.
<property name="connectionMaker" ref="connectionMaker" />
반면에 <property> 태그의 name 속성은 특정 빈의 수정자 메소드 이름과 연계된다. 즉, 코드 내용과 변화 주기가 같다.
XML을 이용하는 애플리케이션 컨택스트
3.0에서 새로 추가한 GenericXmlApplicationContext(이하 GXAC)를 소개한다. GenericXmlApplicationContext는 사실상 ClassPathXmlApplicationContext(이하 CPXAC)나 FileSystemXmlApplicationContext를 대신하기 때문에 독자는 자연스럽게 권장하는 사용법을 배우는 셈이다. 토스는 꼼꼼하게도 그나마 ClassPathXmlApplicationContext가 필요한 경우까지 설명한다. 특정 클래스 위치를 기준으로 설정 파일을 찾을 경우다. 저자의 꼼꼼한 노력은 스프링의 빠른 개선 속도 탓에 아쉽게도 조만간 낡은 내용이 된다. 자바콘픽 개발자인 Chris Beams가 스스로 이슈(SPR-7530)를 올리고 수정한 내용을 반영(#3660)했다.
같은 기능을 하던 CPXAC 생성자는 기준 클래스가 뒤에 나왔지만, GXAC는 varargs를 쓰기 때문에 앞쪽에 나온다. 문자열이나 문자열 배열로 써야 했지만, varargs 채용으로 여러 개의 문자열도 가능해졌다. 곧 출시할 3.0.5 버전에 포함될 예정이다.
value 값의 자동 변환
value에 지정한 값을 자동 변환해주는 내용은 편의성과 신뢰성을 높이는 데 상당한 역할을 하지만 내공이 부족해서인지 충분히 감흥을 얻지 못하고 설명할 방법도 모르겠다.
더 읽어 보기
1장과 관련해서 더 읽어볼 만한 글 링크 모음
글
1장 오브젝트와 의존관계(6) - 싱글톤 레지스트리 그리고 의존관계 주입
서버 프로그래밍에서 중요한 개념인 싱글톤과 스프링이 제공하는 싱글톤 레지스트리를 설명한다. 싱글톤 이해를 위해 필요한 오브젝트의 동일성과 동등성 설명이 나온다. 동등성이란 표현도 나쁘지 않지만, 동치(同値)라는 표현이 더 마음에 든다.
수학과 논리학에서 동치(同値)란 두 문장이 논리적으로 같다는 것을 의미한다. 이것은 한 문장이 참이면 다른 한 문장도 참이고, 한 문장이 거짓이면 다른 문장도 거짓이 된다는 것을 뜻한다.
싱글톤 코드를 살펴보고 단점을 짚어본 후에 싱글톤 레지스트리(혹은 애플리케이션 레지스트리)로 바꾸는 흐름은 Expert One-On-One J2Ee Design and Development 139~141쪽과 같다. 싱글톤뿐 아니라 로드 존슨의 첫 번째 스프링 책의 4장 Design Techniques and Coding Standards for J2EE Projects는 주옥같은 내용을 닮고 있는데, 토스
1장에는 여기서 영감을 얻었음을 추측한 만한 내용이 많다. 영문을 읽을 여력이 있는 분은 토스 책을 읽은 후에 Expert One-On-One J2Ee Design and Development 4장도 일독하시길 권한다.
§ 1.7 의존관계 주입(DI)
토스 115쪽 위쪽에 '사용에 대한 의존관계'란 어색한 표현이 있다. '사용 관계'라고 했으면 명확할 뻔했다. UML 창시자가 직접 쓴 UML 사용자 지침 88쪽을 보면, 의존관계를 쉽게 정의했다.
115~119쪽으로 이어지는 내용은 설명하기 까다롭지만, 무척 중요한 내용이다 보니 UML을 동원해서 설명하고 있다. 내용을 이해하는 데에는 문제가 없지만 어색한 표현이 눈에 띈다. 집필 당시 일민 형이 UML에 대해 조언을 구했었는데, 당시는 도와줄 여력이 없었다. 돌아보니 조금 아쉽고 미안하네.
116쪽에 다시 '런타임 의존관계'란 표현이 나오는데 앞에서도 말했다시피 UML 문맥에서는 오류다. 개발/설계시점에서 정의한 관계에 의해 실행시점(runtime)에 링크가 만들어지기 때문에 의존관계란 표현을 쓰기 때문이다. 119는 표현 자체는 나쁘지 않지만, UML 도해라면 잘못된 표현이다. 어떻게 그러야 UML 도해 한 장으로 이를 표현할 수 있을지는 모르겠다. 코드 작성시점에 개체 사이에 존재하는 관계를 그린 그림은 다음과 같다. 토스에서는 '모델링 시점'이라고 했지만 '코드를 작성하는 시점'으로 이해해도 무방하다.
UserDao 클래스와 DConnectionMaker 클래스 사이에는 직접 관계가 없다는 점이 핵심이다. 관계가 없다는 의미는 DConnectionMaker 코드를 고려하지 않고, UserDao 코드를 작성할 수 있다는 의미기도 하다. 작성할 때는 그렇고, 실행시점에는 다음과 같은 개체도(Object diagram)로 나타낼 수 있다. 먼저 UserDao 객체 입장에서 그리면, ConnectionMaker 타입으로 인식하는 개체기 때문에 다음과 같이 그릴 수 있다.
반면에 실제 구체 클래스를 드러내도록 그리면 다음 그림과 같다. 자바가 제공하는 Dynamic Binding에 의해 같은 개체가 하나 여러 유형으로 표현될 수 있다. 이런 성질을 다형성이라고 한다.
의존관계 검색과 주입
1장 토론 모임에서 찬욱군이 '왜 의존관계 검색이 IoC인지 이해가 안되 강의 때 설명하면서도 어려움이 있었는데 토스를 읽고 수긍이 갔다'고 했다. 공감했다. 또, 토스의 의존관계 검색과 주입에 대한 설명 중에 가장 인상적인 내용은 아래 문장이다.
의존관계 검색 방식의 쓰임새에 대한 힌트를 주는 부분이다. 스프링 컨테이너의 통제 범위 밖에서 즉, 스프링 관리 대상이 아닌 개체가 관리 대상인 개체를 찾을 때는 의존관계 검색이 유용하다. 다만, 의존관계 검색이라는 표현이 어색하다. 검색 대상이 개체인데 관계를 검색하는 듯한 어감이다.
의존관계 주입의 응용
123쪽에서 기능 구현의 교환 예를 들기 위해 수정이 필요한 상황을 언급한다. 앞서 인용한 내용이 다시 떠올랐다.
123에서 제시하는 대처법은 변화의 성격에 따라(concerns) 분리하여 다루기 위한 SoC 적용 과정이기도 하다. SoC 원칙을 실천하는 방안은 여러 가지가 있겠지만 우선 중복을 제거하는 '평면적' 방법과 인터페이스와 구현체를 분리하는 '계층적' 방법을 토스에서 배운다.
글
1장 오브젝트와 의존관계 (5) - 스프링의 IoC
명확하게 하기 위해서 Professional Java Development With The Spring Framework에서 빈 팩토리와 애플리케이션 컨텍스트 차이를 설명한 내용을 찾았다. 49쪽을 보면 애플리케이션 컨텍스트에만 있는 내용을 다음 네 가지 항목으로 정리했다.
- General framework-oriented usage style
- MessageSource support
- Support for application and framework events
- ResourceLoader support
J2EE Development without EJB (1) - Why "J2EE Without EJB"?
J2EE Development without EJB (2) - Goal
J2EE Development without EJB (3) - Architecture
J2EE Development without EJB (4) - The Simplicity Dividened
J2EE Development without EJB (5) - EJB, Five Years On
J2EE Development without EJB (6) - Lightweight Container & IoC
토스 97쪽 하단에서 '애플리케이션 컨텍스트는 직접 이런 정보를 담고 있진 않다.'고 설명한다. 이 설명은 애플리케이션 컨택스트를 표현하는 스프링의 ApplicationContext 인터페이스가 상속하는 ResourceLoader 역할을 표현한 내용이다. 그렇다면 실제로 정보는 담는 개체는 누굴까? 관련 글을 2007년 2월에 썼다. 대략의 내용은 유효하지만,
Resource 구현개체가 3.0 에서 두 개가 늘었다. 하나는 AbstractFileResolvingResource 이고, 다른 하나는 VfsResource 이다. javadoc을 보다가 since 표기가 날짜 기준과 버전 기준을 혼용하는 부분이 바뀌었으면 좋겠다는 생각을 해서 이슈로 올렸다. 작년에도 javadoc에 있던 오류를 지적했더니 고쳐준 바 있다. 오픈소스 커뮤니티를 중시하는 회사인지라 피드백이 빠르다. 98쪽부터 3.0 에서 추가된 javaconfig 을 설명한다. 2002년 2월 써둔 글을 보니 클래스 이름도 조금 바뀌었다. 토스 출간 전에 원고형태로 이 내용을 봤을 때는 전율이 흘렀다. 일민 형이 사전에 자랑했음에도 불구하고, 정말 물 흐르는 전개로 스프링 3.0 새로운 기능을 소개하는 방식은 감쪽같고 세련되어 감탄하지 않을 수가 없었다.
99~00쪽 다음 내용을 읽다 보면 반드시 이름이 있어야 한다고 오해할 수 있다.
스프링 3.0에서는 BeanFactory 인터페이스에 <T> T getBean(Class<T> requiredType) 메소드를 추가해서, 클래스가 하나 뿐인 경우에 빈 이름을 생략할 수 있다. 편리하긴 하지만, 둘 이상의 빈이 필요해질 가능성이 있다면 애초부터 이름을 붙여주는 편이 좋을 지도 모르겠다. 토스 102쪽에서도 타입만으로 빈을 찾는 메소드가 있음을 소개한다. 1.5 절 마무리하며 다시 한번 용어/개념을 정확히 짚고 넘어간다.
대개 개발자가 '스프링'을 언급할 때, 정확하게 스프링이 제공하는 자원 중에 무엇인지 혹은 어느 영역인지 정확히 인지하지 못하고 말하는 경우가 있다. 스프링에 대해서만 그렇지도 않지만, 무언가 배울 때는 내가 다루는 내용이 무엇인고, 무엇은 아닌지 이해하려고 노력해야 한다. (말이 좀 꼬이네.. 그만 쉬어야 할 때다.)
예전에 그린 그림이 떠올랐다.
출처: 어제 했던 말들을 반추하며
글
1장 오브젝트와 의존관계 (4) - 명확한 용어 정의와 제어의 역전
§ 1.4 제어의 역전(IoC)
역시 주옥같은 내용이다. 첫 번째로 소개하는 개념은 팩토리(Factories)다. 스프링을 사용하면 반드시 듣는 용어이지만 그리 간단하지는 않은 개념이다. 토스를 보면 팩토리가 GoF의 추상 팩토리 패턴이나 팩토리 메소드 패턴과 다르니 혼동하지 말라고 경고한다. 사실 팩토리 자체 개념을 놓고 보면 다른 내용이 아니다. 굳이 구분하자고 하는 이유는 설계 패턴에서 다루는 두 가지 패턴의 내용과 팩토리 패턴이 다루는 문제의 범주가 달라서 뭉뚱그려서 생각하면 모르는 편이 나을 수도 있기 때문이다. :)
팩토리 개념을 잘 정의한 책이 있다. 에릭 에반스(Eric Evans)의 DDD(Domain-Driven Design) 책이다. 책 136쪽을 보면 자동차 제조 공장 사진이 있고 바로 아래 다음과 같이 정의한다.
이야기가 길어질 수 있으니 합성체(AGGREGATE)를 논외로 하면, 개체 생성 과정이 복잡해지거나 내부 구조나 지나치게 많이 드러나면 팩토리('개체 공장'이라고 쓸 용이가 나지 않네.)로 감쌀 수 있다. DDD 책 137쪽을 보면 굵은 글씨로 핵심을 잘 설명하는데 그중에서도 핵심 문장만 골라 번역하면 이렇다.
적절치 않은 책임을 개체에 지우면 자연스레 응집도 하락과 결합도 상승을 가져온다. DDD 책은 이후에 팩토리 설계 전략을 설명한다. 설명하는 내용은 이미 9년 전 GoF가 정리한 설계 패턴 중에서 생성 패턴(Creatational Patterns)과 겹친다. 길게 설명했는데 토스에서 '팩토리가 GoF의 추상 팩토리 패턴이나 팩토리 메소드 패턴과 다르다'라고 한 말을 명확히 하려는 의도다. 정리하면 팩토리는 복잡한 개체 생성 과정 자체를 책임으로 갖는 개체고, 추상 팩토리 패턴이나 팩토리 메소드 패턴은 이러한 팩토리를 만드는 여러 가지 방법 중에서 빈번하게 나타나는 설계 패턴을 지칭한다.
92쪽 소제목인 설계도로서의 팩토리는 조금 어색하다. 의도를 알 듯도 하지만 '설계도'란 표현은 영 와 닿지 않는다. 그렇다고 대안은 선뜻 떠오르지 않는다. 95쪽에서 프레임워크를 제어의 역전을 구현한 기술로 소개하며, '프레임워크가 단지 미리 만들어둔 반제품이나 확장해서 사용하는 추상 라이브러리 집합'은 아니라고 한다. 또한, 툴킷, 엔진, 라이브러리와 프레임워크는 다르다고 지적한다. 모호한 개념 정의가 가져오는 폐단을 잘 알기 때문에 필자의 의도는 충분히 공감한다. 개념 오용이나 남발에 대해 이미 여러 차례 생각을 정리한 바 있다.
- SoC는 Separation of Components가 아니다
- 지나가다님의 SOA와 CBD 활용 행태에 대한 견해
- 실용주의자 in 형식주의 공화국(?)
- CBD 남용 풍조와 실용화 추이
- (소프트웨어) 유지보수란 표현의 오용
- 프로젝트에서 효과를 발휘하는 개발 방법론 적용 기법(상)
- 유스케이스는 과연 유용한가?
아래 그림은 제3회 아키텍트 대회 발표 자료에 넣었던 프레임워크에 대한 현장 인식 상황을 도식화 한 그림이다. 프레임워크에 대한 요구사항을 말할 때는 전문가가 아니므로 자연스럽게 자기 필요에 의해 규정한 의미를 사용한다. 하지만, 개발자가 프레임워크를 쓰거나 만들기 위해서 프레임워크를 말하는 경우라면 더 엄밀해야 한다. 토스 1.4.3절에서 말하는 프레임워크는 특히 IoC 제공자 역할을 강조하는 문맥이다. 프레임워크가 있기에 사용자 코드는 제어 부담을 줄일 수 있다. 그런 면에서 단순 반제품과 라이브러리와는 다르다.
위키피디아 용어 해석을 찾아보고 넘어가야겠다.
In computer programming, a software framework is an abstraction in which common code providing generic functionality can be selectively overridden or specialized by user code providing specific functionality. Frameworks are a special case of software libraries in that they are reusable abstractions of code wrapped in a well-defined Application programming interface (API), yet they contain some key distinguishing features that separate them from normal libraries.
Software frameworks have these distinguishing features that separate them from libraries or normal user applications:
- inversion of control - In a framework, unlike in libraries or normal user applications, the overall program's flow of control is not dictated by the caller, but by the framework.[1]
- default behavior - A framework has a default behavior. This default behavior must actually be some useful behavior and not a series of no-ops.
- extensibility - A framework can be extended by the user usually by selective overriding or specialized by user code providing specific functionality.
- non-modifiable framework code - The framework code, in general, is not allowed to be modified. Users can extend the framework, but not modify its code.
위키피디아 정의에 따르면 프레임워크는 특수한 라이브러리로서 이를 구분 짓는 특성을 네 가지로 정리한다. 제어의 역전, 기본 행위 제공, 확장성, 수정 불가 코드 등이다. 제어의 역전은 토스에서 설명하는 바이고, 수정 불가 코드는 역시 OCP로 다뤘다. 3, 4번만으로는 프레임워크를 일반 라이브러리와 구분짓기 어렵다. 2번인 기본 행위 제공은 제어의 역전이 있기에 가능하다. 프레임워크가 제어권을 갖고 사용자 코드를 호출할 시점에 사용자가 지정한 내용이 없으면 미리 준비한 기본 행동을 제공할 수 있기 때문이다. 그런 점에서 프레임워크를 일반 라이브러리와 구별 짓는 가장 큰 특징은 바로 제어의 역전이다.
토스에서는 이미 코드 변경을 통해 체득한 제어의 역전 개념을 잘 정리했다. 글 전개 측면에서 한 가지 아쉬운 점이 있는데, 말미(96쪽)에 이런 내용이 나온다.
무리한 내용은 아니지만 토스 1장이 실습을 하고 체득 후 개념 정리를 했는데, 아직 'IoC를 애플리케이션 전반에 걸쳐 본격적으로 적용'하기 위해 무엇이 필요한지 이야기가 나오기도 전에 역시 아직 소개되지 않은 스프링의 다른 기능이 필요하다고 표현했다. 사실 이런 내용은 모두 뒤이어 나온다. 그래서 96쪽에서 미리 스프링을 쓰라고 권장하지 말고, 독자가 스스로 판단하게 했으면 어떨까 하는 생각이다.
마무리하려고 보니 다시 툴킷, 엔진과 프레임워크 구분에 대해 찜찜함이 남아 위키피디아를 찾는다. 툴킷(SDK)는 개발 도구 집합이며, 프레임워크 사용을 지원하는 역할을 한다. 엔진(소프트웨어 엔진)은 프로그램 코어를 의미한다. 제어의 중심이라는 의미보다는 기능을 주도하는 코드를 말한다.
사실 용어 정의가 어려운 이유는 개념과 실제 현상이 1:1 대응이 아니기 때문이다. 그래서 용어나 개념이 규정하고자 하는 바(Concern)를 구분해서 봐야 한다. SoC와 같은 사고법은 소프트웨어 설계뿐 아니라 정확한 개념 이해나 용어 정의에도 유익하다.
글
1장 오브젝트와 의존관계 (3) - 원칙과 패턴
새로운 절을 시작하는 글에서 다시 지침으로 쓸 만한 의견을 제시한다.
분리할 관심사를 선정할 기준으로 생각할 수 있다. 74쪽부터 이어지는 클래스로 분리하는 과정은 GoF 책 18쪽부터 이어지는 상속(inheritance) 대 합성(composition)을 몸(?)으로 익히는 흐름으로 투자 대비 효과(ROI)가 탁월하다. 개념을 다지는 방편으로 1.3.1 학습 이후에 GoF 책 18~21쪽을 읽어볼 수 있다.
![]() |
Design Patterns: Elements of Reusable
Object-Oriented Software (Addison-Wesley Professional Computing Series)
(Hardcover) - ![]() Gamma, Erich/ Helm, Richard/ Johnson, Ralph/ Vliss/Addison-Wesley Professional |
참고로 75쪽에 메소드 이름에 오타가 있는데 출판사 홈페이지에 정오표가 있다. 1.3.2 인터페이스 도입은 역시 GoF 책 17~18쪽에서 개념 정리를 위한 보충 설명을 찾을 수 있다. 로드 존슨(Rod Johnson)이 쓴 J2EE 설계와 개발에 대한 첫 번째 빨간 책을 본 사람은 토비의 스프링 3 1장 내용과 빨간 책 4장 내용이 비슷한 내용을 다루고 있음을 알 수 있다. 사실 둘을 비교하는 일은 무의미하지만, 토비의 스프링 3에서만 찾을 수 있는 내용은 잘 그린 UML 도해다. 언젠가 일민 형이 메신저로 자꾸 UML 문법을 물어본 일이 있다. 링크(Link)나 관계(Relationship), 의존 관계(Dependency) 등에 대해 꼬치꼬치 물었다. 1장의 UML 도해는 당시 그린 그림이다. 호주산 EA도 시도했는데, 결국 가장 예쁜 그림을 위해 오피스에서 도형으로 직접 그렸다. 사실 컨설팅 과정에서 UML이 필요한 경우도 오피스에서 그린다.
![]() |
Expert One-On-One J2Ee Design and Development
(Paperback) - ![]() Johnson, Rod/John Wiley & Sons Inc |
당시 일민형은 기본적인 UML 표기법을 묻는 것이 아니라 의존 관계와 관계의 인스턴스 성격인 링크에 대해 물었다. 관계가 클래스라면, 링크는 인스턴스이다. UML 관계에 대해 정확히 기술하려면 명세를 봐야 하는 처지라 생략하겠다. 하고 싶은 이야기는 UML 자체가 아니라 그림 1-5를 봤을 때 놀라움이다. 불필요한 의존 관계를 제거하여 결합도를 줄여야 하는 필요성 그리고 과정에서 인터페이스를 사용해야 하는 이유를 UML 하나로 설명했다. 이 그림을 처음 봤을 때 너무 짜릿했다. 보이지 않는 내용을 눈으로 보게 해주는(visualization) UML 이점을 제대로 활용하는 모습을 목격했기 때문이다. 나름 UML 전문가라 떠들며 CBD 컨설팅을 할 때 왜 굳이 서비스와 DAO 계층에 인터페이스를 두어 파일을 두 배로 만드느냐고 묻는 개발자에게 구구절절하게 설명하던 기억이 떠올라 머쓱했다. 쩝.
이 그림은 잘 그린 명작은 아니지만, UML을 제대로 활용한 대표적 사례다. 그래서 일민 형 허락을 받아 책 출간 전에 모 회사에서 강의할 때 사용했다. 인터페이스 필요성을 설명할 때 이만한 그림이 없다. 웬만한 UML 전문가라는 이보다 UML 활용을 훨씬 잘했지만 미세한 오류는 있다. 81쪽에 나오는 '오브젝트 사이에 다이내믹한 관계'와 같은 표현이나 82쪽에 나오는 '오브젝트 사이의 관계가 만들어진 상태' 등의 표현은 UML 맥락에서는 오류다. 오브젝트를 다이내믹한 클래스라고 부르지 않는 것처럼 링크를 다이내믹한 관계라 부르지는 않기 때문이다. 굳이 따지자면 그렇지만, 내용 이해에는 문제가 없다.
1장 읽고 토론하는 자리에서 P님이 일반 업무시스템에서 계층마다 기계적이다 싶을 정도로 적용한 인터페이스에 대한 경험담을 공유했다. 인터페이스나 구현체만 따로 바꿀 일이 거의 없는 서비스와 DAO에도 모두 일괄적으로 인터페이스를 만드는 일이 과연 가치 있나 고민했다고 한다. 공감할 수 있는 일이다. 그런데 나중에 전체 업무를 파악하는 데에는 유익했다고 설명할 때, '코드의 ERD'란 표현이 떠올랐다. 종종 현행업무를 분석하는 ERD도 없는 사이트를 보곤 하는데 마찬가지로 현행업무에 제대로 이름을 붙인 인터페이스가 있다면 코드 구조나 주요 기능을 파악할 때 큰 도움이 될 것이 분명하다.
개방 폐쇄 원칙
사례를 통해 체득한 내용을 정리하는 내용이다. 이론 중심으로 이해하면 실전 적용에선 막히는 일이 많다. 그런 면에서 실습으로 체득하고 개념을 잡기 위해 정리하는 책의 기술 방식은 매우 효과적이다. SOLID에 대한 내용은 지난 마소 기사를 인터넷에서 볼 수 있으니 필요한 만큼 참조할 수 있다.
zdnet - 객체지향 SW 설계의 원칙 ① 개방-폐쇄 원칙
zdnet - 객체지향 SW 설계의 원칙 ② 사례연구, 단일 책임 원칙
zdnet - 객체지향 SW 설계의 원칙 ③ 인터페이스 분리의 원칙
zdnet - 객체지향 SW 설계의 원칙 ④ 리스코프 치환 원칙
내 블로그의 관련 글도 옮겨둔다.
cohesion, TDD 그리고 SRP(Single Responsibility Principle)
높은 응집도와 낮은 결합도
응집도와 결합도는 구분해서 생각할 수 없다. 개체의 응집도와 결합도는 같은 현상에 대해 바라보는 다른 시각을 정의한 개념이다. 개체 경계는 설계자 인식에서 출발한 인위적인 내용이다. 아래는 이런 생각을 설명하기 위해 머릿속으로 떠올린 그림이다. 그림과 같은 겹치기도 하고 관계도 명확하지 않은 경계를 정리해서 온전한 개체를 만드는 일 자체가 설계이기도 하다. 설계에 대해 이처럼 인식하다 보니 Object에 대한 우리 말로 객체보다는 개체(個體)가 적합하게 느껴진다.
적당한 설계를 구분하는 지표가 무얼까 고민하면 "Atomic"이란 단어가 떠오른다. 더 쪼갤 수 없을 만큼 단단하게 느껴지는 개체, 거기서 더 쪼개면 본래 특성이 사라지는 수준. 다른 말로 표현하는 응집도가 최고조에 달한 상태다. 반면에 응집도가 약해졌다는 의미는 특성이 빠져 있거나 관계가 빈약한 특성을 함께 포함한다는 의미다. 전자는 다른 개체에 그 특성이 있다면 의존해야 하기 때문에 결합도가 높아진다. 후자는 서로 다른 목적으로 접근하는 개체가 늘어나는 이유로 결합도가 높아진다. 아래 발췌한 토비의 스프링 3 87쪽 내용을 보면 부작용에 대해 구체적인 예를 든다.
"Atomic" 개체를 만드는 일이란 말처럼 쉽지 않지만, 그래서 처음부터 완벽하게 설계하는 진화형 모델이 주류로 부상하는 듯하다. 몇 년 전에는 Unified Process 등이 표방하는 반복/진화였다면 최근에는 애자일에서는 JIT(Just-in-time)를 거론한다. 다른 분야에서 복잡한 설계를 할 때 시뮬레이션을 하는데, TDD에서 활용하는 단위 테스트에서 시뮬레이션과 유사한 효과를 얻는다고 느꼈다. 또한, 단위 테스트를 하면 자연스럽게 병행하는 리팩토링은 '티끌 모아 Atomic 객체'를 만드는 생산적인 활동이다.
88쪽에 '낮은 결합도는 높은 응집도보다 더 민감한 원칙'이라고 소개했지만, 응집도를 높이면 결합도는 낮아진다. 아마 개발자가 체감하는 정도에서 결합도가 더 민감하다는 표현을 이렇게 쓴 듯하다. 하지만, 누군가 결합도가 뭐냐고 묻는다면 저자의 정의를 인용해도 좋을 듯하다.
글
1장 오브젝트와 의존관계 (2) - 관심사의 분리(Separation of Concerns)
초난감 DAO를 예로 선정한 점은 일민 형의 내공과 통찰을 보여주는 증표다. 일민 형이 워낙 좋아하면서 수줍어해서 내가 나서 말을 걸었던 롭 해롭(Rob harrop)에게 물었다. 스프링 구성요소 중에서 가장 좋아하는 기술은 무엇이냐고. 롭은 개인 의견을 내세우는 대신 고객을 빌렸다. 스프링소스의 최대 고객인 JP 모건에서는 스프링 기술 중에서 하나만 사용한다는 일화로 대답을 대신했다. 그것이 바로 JDBCTemplete 다. 가만 생각해보면, J2EE/Java EE 기술 중에 팥소는 JDBC다. EE 영역에서는 여전히 데이터베이스 중심으로 처리한다. 데이터베이스의 본질인 데이터 관리뿐 아니라 동적인 측면인 거래 처리까지 데이터베이스에 의존한다. DB 연결 누수로 서비스를 주기적으로 내렸다 올려야 하거나 시스템 오픈을 못하는 일을 2006년까지 목격했다. 하지만, JDBCTemplete를 이용하면 쉬운 문제다.
토비의 스프링 3 61쪽에 밑줄 친 내용이 있다.
스프링 스타일이라는 표현은 모호하지만, 무슨 의미인지 뒤이어 나오는 내용을 통해 추측할 수 있다.
스프링은 본말이 전도되는 일을 치밀하게 막고자 한다. 한때, 스프링이 지나치게 복잡하다고 주장하는 이가 있었다. 스프링이 추구하는 본질을 몰랐기 때문이다. 디자인 패턴도 쓰임새와 필요성을 모르면 지나친 설계 왜곡으로 보일 수 있다. 또, 스프링을 비롯한 프레임워크때문에 개발자 수명이 줄어든다는 의견 제기도 있었다. 얼핏 맞는 의견 같지만, 스프링 대신 객체지향설계나 디자인 패턴을 가르쳐 주는 방법이 무엇이 있을까? 나는 스프링 소스코드를 보기 전까지 많은 디자인패턴 책을 봤지만, 코드에 적용할 엄두를 내지 못했다. 단위 테스트(자동화)는 어떤가? 역시 스프링 테스트 코드를 보기 전까지는 DB를 쓰고, 컨테이너가 필수인 J2EE/Java EE 환경에서 테스트를 시도했던가? 프레임워크를 쓰기 때문에 애플리케이션 내부 작동방식이나 구성원리를 모르고 API만 아는 개발자로 전락한다는 발상은 아주 틀린 이야기는 아니다. 하지만, 오픈소스 형태의 프레임워크는 오히려 반대다. 마음만 먹으면 책이나 테스트를 통한 학습(라이브러를 쓰면서 이것저것 해보기)외에 소스코드를 직접 볼 수 있고, 심지어 SVN 저장소를 통해 발전 과정에서의 코드 변경 이력까지 볼 수 있다.
§ 1.2 DAO의 분리
변화를 대비하는 자세는 기본이다. 지금 날씨가 맑아도 비가 올 가능성이 있다면 우산을 준비한다. 일민 형이 그 부분을 정말 잘 설명했다. 사실 관심사의 분리(Separation of concerns)는 쉬운 주제가 아니다. 꼼꼼쟁이 일민 형이 이 내용을 쓸 때 다른 사람 의견을 찾느라 SoC 관련 포스팅을 찾아다닌 것으로 안다. 그러다가 SoC에 대해 오해를 유발할 수 있는 글에 대해 일민 형이 댓글을 달았으나 필자가 감정적으로 대응했다. 채팅으로 답답함을 호소했는데 마침 술 마시고 귀가한 날 약간 자극적인 글을 썼다. 상대를 알아보고 썼어야 했는데 실수였다. 어떤 마음에서 썼는지 솔직히 잘 모르겠다. 하지만, 노OOO님처럼 막말에 가까운 비판이나 비방은 아니었다. 딴에는 스스로 자꾸 거만해지는 모습을 우려해서 종종 자아비판도 하는 터라 비판의 수위는 높다고 생각하지 않았는데, 결과는 최악으로 흘렀다. 다행히 봉합은 했지만, 못내 아쉬웠다. 최근에도 패턴 전문가로 활동하시는 분이기에 SoC에 대해 이해가 더 성숙해질 수 있는 계기였는데, 감정싸움으로만 귀결되었다. 이미 일 년 반 전의 글인데 내가 쓴 글에서 크게 충격을 받았다고 해서 지워 버렸다. 당시 정황을 공유할 방법은 없지만, 공감하는 글을 다시 찾을 수 있어서 공유한다.
Separation of Concerns (SoC)
마지막 문장은 당시 굳이 시간을 내서 비판했던 이유이기도 하다.
어쨌든 SoC에 대한 설명은 토비의 스프링 3에서 놀랍게도 명쾌하게 설명했다. 왜냐하면, 단어만으로 전달하는 대신 실습(practice)으로 몸에 익히는 방식을 취했기 때문이다. 초난감 DAO가 포함하는 여러 가지 관심사를 순서대로 나누는 접근은 탁월하다. 책의 효과를 더 높이려면 독자는 코드를 작성해보길 권한다. 타자하는 과정에서 몸이 기억하는 효과도 얻지만, 무엇보다 책으로 휙 넘겼을 때보다 사고하고 소화할 시간을 충분히 벌 수 있기 때문이다. SoC랄 표현을 가장 먼저 썼다고 알려진 사람은 컴퓨팅 분야의 거성인 에드가 다익스트라다. 1974년 논문 'On the role of scientific thought'에서 처음 쓰인 이후로 설계 원칙으로 널리 회자 되었다. 위키피디아에서를 보면 TCP/IP 프로토콜의 계층(layer) 구분과 AOP 등을 예로 들고 있다. 전형적인 사례인데 조금 사고를 확장하면 새로운 사례를 찾을 수 있다.
켄트 벡(Kent Beck)의 책에서 TDDBE에 서 가장 감명을 받은 내용은 적절한 작업 분량을 떼어 내면서 리듬을 찾는 방법이다. 엉클 밥(Uncle Bob)의 볼링 카타에서는 구체적인 사례로 보여주기도 한다. 이러한 분할 역시 SoC라고 할 수 있다. 작업 시간을 짧게 나눈 후에 관심사를 명확하게 나누어 테스트를 작성하는 방법도 SoC 응용이다. 켄트 벡(Kent Beck)은 저서인 구현패턴(Implementation Patterns)을 통해 극한의 SoC 활용 사례를 보여준다. 프로그램 작성 진도를 늦추면서, 자신의 사고 과정 자체를 추적하여 미세한 관심사를 패턴으로 정리하는 일 말이다. 머리로는 이해가 가지만, 과연 실천할 수 있을지 싶은 놀라운 능력과 인내다.
위키피디아 설명을 보면 관심사 분리 방법으로 모듈 작성이나 캡슐화(encapsulation)를 들고 있다. 토비의 스프링 3에서는 모듈화나 캡슐화 실현 방법으로 리팩토링을 소개한다. 리팩토링은 수학에서 배운 인수분해가 떠오르게 한다. 리팩토링에 해당하는 우리 말은 뭘까? 재구성(Re+Factor+ing)?
앞서 발췌한 내용처럼 객체지향 설계의 3요소에 리팩토링과 단위 테스트를 포함한 점은 매우 적절하다. 단위 테스트가 모여 만든 회귀 테스트는 리팩토링에 대한 막강한 후원자가 된다.
이후에 전개하는 내용은 유연성 측면에서는 상속보다 위임이 좋다는 사실에 기초한다. 하지만, 항상 그렇지는 않다. 소규모 집단이 많은 개발자 코드 사이에서 일관성을 유지하려는 경우는 상속이 좋다. 상속을 통한 템플릿 메소드 패턴(template method pattern)이 대표적이다. 69쪽 이후의 내용은 다음 이 시간에 GoF 책을 인용해서 정리하려고 한다.
책 읽고 토론하기 모임에서 P군이 프레임워크 유지 보수와 지원 담당자 시절 경험을 공유했다. 처음에는 상속을 사용하여 개발팀의 코드를 일관성 있게 통제하는 점이 상당한 이점이었지만, 시간이 흐르면서 기존 구조에서는 충족하기 어려운 요구 사항이 생기면서 상속의 문제가 드러났다는 경험담이었다.
성급한 일반화인지 모르지만, 통제권 안에 있는 코드 즉, 지역적으로나 소속이 같은 팀에서 작성한 코드는 상속을 써서 강한 통제를 하고 관련 코드를 유착시켜서 얻는 이점이 있다. 물론, 시스템 오픈 이후에도 수정할 일이 많은 경우라면 예외라 할 수 있다. 반면에 멀리 떨어진 조직이나 소속이 다른 팀에서는 상속은 장애물로 작용할 수 있다. 이런 경우는 JDBC 드라이버(혹은 데이터소스 관리 라이브러리)에서 널리 쓰인 인터페이스와 구현체 분리가 굉장한 효과를 발휘한다.
마침 얼마 전 만난 Method Chain 개발자가 직접 말씀해주신 내용이 생각났다. 자바 스크립트 상속으로 구현한 코드 베이스를 '필요할 때 new로 생성하는 방식'으로 고치는데 상당한 시간이 걸린다고 했다. 상속이 스크립트 API 편의성 측면에서 장점이 많지만, 모바일 버전 개발할 때는 문제라고 한다. 자바스크립트는 잘 몰라서 '필요할 때 new로 생성하는 방식'이 위임인지는 모르겠으나 비슷하지 않을까 싶어 흥미로웠다.
글
1장 오브젝트와 의존관계 (1) - 용기 있는 1장의 출현 배경과 토비의 OOD론
어차피 이 책을 지금처럼 꼼꼼하게 다시 읽어볼 기회는 없을 것이다. 그래서, 한 글자도 빠뜨리지 않고 꼼꼼하게 읽고 정리할 셈이다. 내 소감과 토론을 덧붙여 쓰다 보면 초점이 사라질 우려가 있어서 토비의 스프링 3 읽고 토론하기 17주 프로그램 소개에서 밝힌 목적을 상기시켜보자.
- 책 내용 알리기
- 교재 초안 작성
- 토론 촉발
§ 1장 전체와 도입부를 읽고 느낀 점
아직 책을 다 읽지도 않았지만, 1장은 이 책 최고의 작품이다. 앞서도 소개한 바 있는 코드 진화를 축으로 하는 책의 전개 방식은 이 책을 다른 책과 구분을 지어주는 핵심 특성이다. 그리고 아마도 많은 독자에게 그간 고민해보지 않았던 문제에 대해서 초심으로 돌아가 생각할 기회를 줄 것이라 믿기에 단언할 수 있다. 훌륭한 내용은 노력의 산물이고, 때로는 고통의 산물이다. 일민 형이 블로그에 쓴 후기를 오해하는 분이 많아 배경을 소개하는 글을 남겨둔다. 최근에 프로젝트를 함께 하는 K과장님은 아래 글을 읽고 얼마나 '심하길래' 하고 책을 봤다가 '괜찮은데 왜 그랬지'라는 의문을 품었다고 한다.
2장을 쓰는 중에 영회가 자꾸 책 진도를 물어왔다. 그래서 1장을 마쳤으니 한번 읽어보라고 1장 원고를 넘겨줬다. 2장은 완성되면 줘야지 하고 아직 넘기지 않았다. 진득하게 기술을 공부하고 연구하는 것보다는 사람들과 어울려서 수다떠는 것을 더 좋아하는 영회인지라 원고가 넘어가고도 한참이 지나서야 겨우 읽은 듯 했다. 다 읽었다고 하길래 어땠냐고 물어봤다.
그 질문을 한 것이 일생일대의 실수였다.
돌아온 영회의 피드백은 충격적이었다. 사실 기대한 것은 스프링에 대해서 이렇게 설명하는 것보다는 이렇게 하는 것이 좀 더 이해하기 쉽지 않겠냐라든가 스프링의 정의에 이런 요소를 넣었으면 좋겠다와 같은 실제 1장의 의도에 맞는 분석이나 제안이었다. 하지만 영회는 원래 그런 것에 별 관심이 없다. 평소에 문과 출신이고 IT계에서 흔치 않게 인문학적 소양이 높다는 점을 자랑했듯이 돌아온 피드백도 스프링의 기술과 본문의 내용과는 상관없는 단순 인상비평이었다.<중략>
위기가 왔다.
속도 상하고 화도 많이 났다. 책을 쓴다고 5개월 가까이 투자해 왔는데 건질게 없는가 해서 좌절감이 몰려왔다. 나는 책을 쓸 자질이 없다는 생각이 들었다.<중략>
그렇게 다시 며칠을 마음을 비웠다. 그리고 그 때까지 쓴 1,2장 원고를 모두 버렸다.
출처: http://toby.epril.com/?p=1098
보통 블로그에 투고한 긴 글은 꼼꼼하게 읽지 않는 사람이 많다. K과장님도 내용은 기억하지 못하고 1장에 대해 내가 지적했다는 단편적인 기억만 간직했다. 또한, 일민 형도 오랜 기억인지라 사실은 부정확하고 감정만 생생하게 남았다. 글에는 소개가 없었지만, 여느 책처럼 추상적인 내용으로 시작하지 않기를 바랐다. 아래 일민 형 글에 나오지만, 본인도 따분한 1장은 쓰기 싫다고 했다. 하지만, 코드로 바로 들어가는 것은 거부했다. 당시 내 비판적인 피드백의 배경에는 문과 출신(엄밀히 말하면 상대 출신의 이학석사다.)이 갖는 문학적 소양보다는 상투적인 출발을 극복할 수 있는 용기에 대한 기대감이 있었다. 말처럼 쉬운 일은 아니지만, 일민 형이라면 할 수 있을꺼라고 봤다. 지금 보니 채팅으로 나눴던 대화에서 의도는 100% 잘못 전달된 모양이다.
결과적으로는 일민 형은 해냈다. 조금 미화하면 용기있는 초보 저자로 탄생하는 출발점은 내가 제공했다. 여러분이 보고 있는 아름다운 1장에 2%는 나의 노력임을 기억해주길 바란다. (농담) 가끔 스스로 대견하다 싶은 놀라운 생각을 할 때가 있다. 처음에는 자아도취 기회로 삼았다. 그러나 시간은 많은 것을 가르쳐 준다. 어느 날인가 고객인 J차장님과 대화하던 중, 이런 생각은 공공재라는 말을 했다. 내 생각과 노력만으로는 뛰어난 결과를 만들기 어렵다. 역사를 거친 수많은 사람의 노력이 나를 통해 실현되었을 뿐이라는 생각은 살면서 시나브로 주입되었다는 점은 여간 다행스러운 일이 아니다.
날려버린 1장을 처음 쓸 때 사실 힘들었다. 그 1장에는 코드 한줄 나오지 않는다. 대신 3만피트 상공으로 올라가서 스프링 세계를 내려다보며 스프링이 이렇게 생겼네라고 구름 위에서 얘기하듯이 설명하는 내용이다. 그래서 신경쓸 것은 단어, 표현 등이었다. 함축적인 단어를 어떻게든 잘 골라서 이런 저런 스프링의 특징을 깔끔하게 묘사해야 할텐데라는 고민으로 대부분의 시간을 보냈다.
나는 그런 식의 얘기가 편하지 않다. 내가 가장 편한 시간은 코드를 앞에 놓고 코드에 대해서 이야기 할 때다. 열 줄 정도의 코드만 있어도 재미나게 한 시간쯤은 수다를 떨 수 있다. 지난 27년간 거의 매일 만들고 다듬고 뜯어보고 감상해왔던 것이 코드다. 그래서 누군가에게 기술을 설명해줄 때도 코드를 놓고 이야기해야 편하다. 특히 어설픈 코드를 만들어 놓고 그것을 다듬고 발전시켜서 아름다운 코드로 만들어내는 과정을 즐기는 것이 좋다.
처음 무언가를 시도하면 본 뜰 대상을 찾는다. 레퍼런스라는 우아한 표현으로 위장하지만 결국은 따라하기를 의미한다. 앞서 용기란 표현을 쓴 이유는 일민 형이 쓰는 책은 기존 서적의 틀에 갇히지 않기를 바랐기 때문이다. 위 글에서도 확인하는 바대로 불편한 이야기지만, 책에 대한 고정관념을 벗기는 힘들었을 것이다. 나에 대해 복수의 칼을 간 결과가 이런 도약이라면 악당 역할도 나쁘지 않다.
글이 늘어지는데, YUST에 헌신한 일민 형의 경험도 큰 공헌을 했음을 확인할 수 있다.
나는 이미 이전에 간단한 DAO 코드를 가지고 스프링의 DI를 설명해본 경험이 있다.
<중략>
그래서 향화에게 어떻게 스프링을 가르쳐 줄까 고민하다가 생각한 것이 그나마 향화가 가장 익숙하고 많이 만들어본 DAO였다. 초보 개발자들이 교육센터 등에서 만드는 DAO 수준은 뭐 뻔하다. try/catch/finally라도 적용했으면 다행이고, 그렇지 않은 경우도 많았다. JDBC API를 사용해서 돌아만 가는 CRUD만 만들 수 있어도 잘하는 것이었으니까. 물론 향화는 내가 교육하면서 try/catch/finally나 안전한 DAO를 만드는 방법에 대해서 확실하게 교육했으니 잘 알고 있었지만.
그래서 향화가 그나마 잘 아는 DAO 코드를 하나 만들어줬다. 그리고 그 코드의 문제점이 무엇인지 찾아보고 그 코드를 매일 매일 조금씩 개선하면서 OO적인 코드로 다듬는 것을 알려줬다. 그렇게 짬짬이 원격 교육을 하면서 서서히 DAO코드를 다듬어서 DataSource에 대한 DI도 적용하고 템플릿/콜백도 만들어가는 식으로 설명을 해줬다. 그냥 XML 설정파일 만들고 DAO와 DataSoruce 빈을 등록하고, CRUD는 JdbcTemplate가져다 쓰고, web.xml에 컨텍스트로더리스너 등록해서 돌리라고 가르쳤으면 일주일이면 충분했을 것을 몇 달에 걸쳐서 설명을 해줬다. 하지만 그렇게 스프링을 이해하고 배우는 것이 나중에 내가 더 이상 스프링을 가르쳐 주지 못하고 혼자서 공부할 때 분명 도움이 될 것이라는 확신이 있었다.어쩌다 보니 책과는 무관한 경험담만 소개했다. 사실 도입부에서 느낀 점은 두 가지다. 다른 책에서 흔히 보여주는 지루한 1장은 깨끗이 사라지고, 일민 형 색깔이 묻어나는 훌륭한 1장이라는 점이 하나다. 일민 형이 장고한 후기를 쓰지 않았다면 저자로서 자아를 바꾸는 과정이 얼마나 힘든 일인지 짐작조차 못 했을 것이다. 두 번째는 책에 나타난 내용에 대한 소감이다.
한 분야에서 열심히 고민하는 사람이라면 간단하지 않은 개념을 설명할 때 핵심 요소나 특징을 꺼내면서 자연스럽게 균형감 있게 정리하려고 노력한다. 그래서 책을 읽으면서 굵게 표기한 세 단어에 동그라미를 쳤다. 저자가 생각하는 객체지향 설계의 주요 항목이다. 훌륭한 저자라면 이런 생각은 책 전체에 투영하기 마련이니, 행간의 배경으로 쓰인다. 내 경우는 행간의 이해 목적보다 나중에 객체지향 설계에 대해서 정리하거나 토론할 일이 생기면 참조할 목적이었다.
- 포스팅 대신 사용 [본문으로]
글
토비의 스프링 3 읽고 토론하기 17주 프로그램 소개
맥스님이 독중감이라는 생소한 표현을 써서 센스 넘치는 글을 썼다. 아이러니하게 독중감이라는 표현 탓에 독후감으로 쓰려던 생각이 바뀌었다. 토비의 스프링 3 은 술술 읽히는 책도 아닌지라 몸소 코딩도 함께해야 한다. 다시 말해서 상당한 시간을 투자하고 생산하는 내용이니만큼 조금 더 욕심을 내야겠다는 생각이 들었다. 더구나 가벼운 마음으로 시작했던 팀 내 토의가 상당히 유익했다. 네 명이 함 1장을 읽고 20분 정도 소감이나 나누자던 자리는 정확히 1시간 반만에 끝이 났다. 그래서, 독후감보다는 저자의 노력으로 만들어진 값진 책에 십시일반 생각과 경험을 더한 기록을 남겨 다만 몇 사람에게라도 생각을 풍부하게 돕는 촉매제가 되길 기대하며 17주의 장정을 시작한다.
토비의 스프링 3 - 
글을 쓰는 목적
첫째, 토비의 스프링 3 홍보다. 책이 많이 팔리면 나에게 돌아오는 금전적 보상은 전혀 없다. 그럼에도 책을 홍보하는 이유는 단지 일민 형과의 친분 관계 때문이 아니다. 토비의 스프링 3 은 한글 책으로는 드물게 명서 반열에 올리고 싶은 기술서적이다. 자바 아니 어쩌면 엔터프라이즈 프로그래밍 영어에서 이 정도 비법과와 고민이 담긴 책이 있었을까 싶고, 일민 형이 고생한 시간을 따져보면 앞으로도 이런 책이 나올까 싶다. 물론, 내가 모르는 좋은 책이 있었을 수도 있고, 기억력이 믿을만하지 못한 관계로 지나친 극찬일지 모르지만, 매우 훌륭한 책임에는 분명하다. 좋은 책은 널리 읽혀야 한다. 그래서 넓게 보면 모두 동료인 이 시대의 개발자들의 수준이 향상되기를 기대하는 마음이다. 물론 기대하기 어려운 바램이지만, 일민형이 책이 많이 팔려서 또 유사한 책을 쓰고 싶은 욕구가 생기기도 기대해본다.
둘째, 토비의 스프링 3 에서 사용하는 자연스러운 코드 진화 흐름을 빌린 교재를 만들기 위함이다. 2005년 즈음에 Foundations Of JSP Design Patterns 라는 책에서 처음 봤던 전개 방식이다. 이 책은 빈 조차 쓰지 않는 JSP 코드에서 빈을 뽑아내고, 패턴을 적용해서 궁극에는 프레임워크를 만들어내는 전개 방식을 담고 있었는데, 이런 류의 접근방식을 처음 보았던 터라 신선한 충격이었다. 당시에 자바 개발자 사이의 분위기는 '유행하니까' 스트러츠를 쓰거나 하이버네이트를 쓴다는 식이어서 한국에는 왜 이런 책(원리를 몸소 이해하게 유도하는)이 없는지 아쉽기만 했다.
![]() |
Foundations Of JSP Design Patterns (Paperback)
- ![]() Patzer, Andrew/Springer-Verlag New York Inc |
사실 이런 방식은 KSUG 세미나의 전신인 이프릴세미나 때, 일민형이 기획하고 내가 발표한 스프링 테스트 전략에서도 써먹었던 방법이고, 그 이후 다양한 강의에서 활용했다. 특히 토비의 스프링 3 1장에 펼쳐진 코드 진화 과정은 장고의 시간을 거쳐 진화시킨 내용이라고 할 수 있다. 책 한 권에서 쓰이고 말기엔 아까운 내용이라 교재로 만들기로 했고, 초안은 블로그를 통해 공유하기로 했고, 일민 형도 허락했다.
셋째, 토론에 대한 기대다. 블로그를 보는 즐거움 측면에서는 2006년 맹목적으로 스프링을 증오하던 댓글러(?)가 활약하던 시절이 즐거웠다. 엠파스가 사라져 흔적이 없어졌지만, 내 블로그에서 일민형과 와스추종자가 주고받던 댓글 전쟁을 그야말로 흥미진진했다. KSUG 그룹스에서 일부 토론이 이어지지만, 블로그 공간에서는 찾아보기 어려운데 17주 동안만이라도 글 타래가 이어지길 기대한다. 혹시라도 토론이 벌어진다면 가장 마음에 드는 글을 골라 '2010년 영회인포 베스트마우스상'을 이벤트를 방금 생각해냈다. 도전 하시라! (물론 공정성 따윈 없이 내 맘대로 시상한다.)
시작도 안 했는데 글이 꽤 길다. 원피스에서 잘 써먹는 방법대로 볼만할 때 다음 시간을 기약해야겠다.
소프트웨어에 미치지 못하는 하드웨어(?)
목적만 딸랑 이야기하고 마치기 아쉬우니 본론을 꺼내기 전에 맥스님의 독중감에 의견 보태는 글로 마무리해야겠다. 말을 꺼내기 전에 일민 형 마음을 상하게 할 수도 있는 내용임에도 연거푸 책의 겉모습에 대한 불만을 토로하는 이유는 분명히 하려고 한다. 나는 이 책의 내용에 대해 더 할 수 없는 극찬을 하고 싶은 사람이다. 아마 영문으로 출간했으면 아마존에서 상당한 판매량을 올렸으리라고 확신한다. 그래서 내용과 비교하면 고민이 부족한 외형이 불만스럽다. 심지어 해당 출판사에 계신 분도 모두 지인이고, 노력하는 모습을 멀리서나마 치켜봤음에도 눈 감아 줄 만한 내용은 아니다. 미래를 위해 쓴소리를 마다할 순 없다. 전에 외형에 대해 이야기할 때 출판사 부사장님은 종이질에 대한 투자를 이야기하셨고, 출판 경험에서 나온 독자의 평균적인 요구사항에 대한 확신을 말씀하셨다. 하지만, 내 생각은 다르다. 물론, 출판 문외한이니 대단한 의견이랄 순 없다. 1장을 지하철에서 읽기 위해 긴 고민 없이 바로 칼로 1장을 뜯는 모습은 일반적이라고 할 순 없다. 그런 면에서 맥스님의 생생한 글을 보니 낯선 땅에서 동지를 찾은 듯해 기뻤다. 생생한 표현력을 느끼시라고 발췌해본다.
출처: 토비의 스프링3 :: 독중감(1) - 느낌
최근 내가 만난 토비의 스프링 3 독자 사례를 더 들어 본다.
- SI 회사에서 프레임워크 관련 일을 하는 K모 과장님을 만났다. 토비의 스프링 3 샀냐고 물었더니, 책을 집으로 배송했더니 회사로 가져올 엄두가 나지 않아 아직 읽지는 못했다고 답했다.
- 우리 팀 직원 C군. 1장 읽고 토론하자고 했는데, 집에 책이 있어서 빈손으로 왔다. 차마 책을 안 가져왔느냐고 나무랄 수가 없었다.
- 함께 토론했던 P씨. 토론하자고 만난 자리인데 역시 빈손으로 왔다. 모두 공감하리라는 표정으로 들고 올 엄두가 나지 않았다고 말했다.
- 우리 팀 직원 P씨. 한 손에 노트북을, 한 손에 토비의 스프링 3을 들고 나가는데 비가 왔다. 토론 장소로 이동하는 거리가 꽤 멀었다. 하마터면 버릴 뻔했다고 농담을 했다.
- 구글 채팅으로 J님과 대화를 했다. 금요일 퇴근이라 토비의 스프링 3을 집에 들고 오는데 비 때문에 책이 다 젖었다고 한다. 보통 책은 가방에 넣지만, 배낭을 매는 일이 드문 회사원은 토비의 스프링 3을 가방에 넣기 어렵다.
출판사의 판단과 달리 분량 자체에 불만을 느끼는 사람은 아직 찾지 못했다. 토비의 스프링 3은 기존 서적과 독자층이 다르다. 물론, 판매만 놓고 보면 다른 유형의 독자 혹은 구매자까지 폭넓게 고려해야 하지만, 적어도 토비의 스프링 3 독자를 제대로 이해했다면, 기존 틀을 벗어나려는 시도를 해봤으리라 생각하기에 겉모습에 진한 아쉬움이 남는다.
1장을 뜯어서 봤더니 낱장으로 분리된다. 남은 내용은 제본가게에 맡기라는 충고를 들었는데, 좋은 방법인 듯하다.
2010.9.20 추가
글
들을 만한 스프링 교육
시장수요에 따라 국내 교육기관이 개설한 스프링 강좌는 있다.
하지만, EJB의 기술적 제약 극복을 위한 노하우를 쌓아온 교육 기관이 아니라면
하루아침에 높은 수준의 스프링 교육을 만들 수 없을 것이다.
레퍼런스를 통해 익힌 사용법 정도만 익혀도 교육을 만들 수는 있지만
그 정도라면 시중에 나와 있는 책이나 인터넷에서 찾을 수 있는 내용을 참조하여
실습을 하면서 고민과 시행착오를 겪는 일로 대신할 수 있다.
생업이 있어 스프링만 연구할 수는 없고 우리나라에도 쓸만한 스프링 교육이 있었으면 하는 마음에
작년 JCO 컨퍼런스에 맞춰 SpringSource 컨설턴트를 초청해 스프링 공식 교육을 시도했었다.
당시 환율 상황도 안 좋아서 4일에 300만 원(?) 정도였던 교육은 최소 수강인원(6명) 미달로 열리지 못했다.
이제는 개인적으로나 기술 수요측면에서나 때가 되었다는 생각에 스프링 교육을 다시 시도하려고 한다.
단순히 스프링 사용법이 아니라 응용력에 초점을 맞춘 첫 번째 시도를 슬슬 기획하면서
소통을 하고 싶어 글을 올렸더니 의미 있는 댓글이 달려 생각을 더 풀어놓는다.
개발 보다 운영의 일정부분은 책임을 져야 한다는 책임 의식
충분히 공감하지만 당장은 스프링에 대한 응용력 교육이 선행되어야 한다는 생각이다.
4월 첫 번째 스프링 교육을 기획하는 지금 처음 이프릴 세미나를 준비할 때가 떠오른다.
90분 라이브 코딩을 위해 연습할 때 가졌던 긴장감이 필요한 시점이다.
글
[Spring 기본 다지기 1] Spring과 AOP
스프링과 AOP(Aspect-Oriented Programming) 관계는 다음 그림이 잘 설명해준다.

AOP는 기괴하다 싶을 용어와 함께 하기로 유명하다. 그래서, 비유적으로 이야기를 끌어가 보자. 위 삼각형을 도원 탁자라고 해보자. 탁자 위에는 사발과 술병이 올려 있을 법하다. 물론 탁자를 앞에 두고 유비, 관우, 장비가 앉아 있다. 스프링의 중추인 IoC는 유비에 비유할만하다. 하지만, 스프링이 EJB를 잠재우는 데에는 관우격인 Portable Service Abstractions의 공이 크다. 이제 하나 남은 AOP는 장비라 하자.
AOP는 장비만큼이나 다루기 어렵다. 보통은 으뜸가는 장수로 일당백을 한다. 하지만, 감정에 휘말려 자칫 실수를 범한다. 비유가 기막히게 들어맞는다. 보통 스프링을 처음 쓸 때는 AOP를 쓰는지도 모르고 사용한다. 레퍼런스를 따라 하다 보면, 필수 기능인 트랜잭션 처리 과정에서 자연스레 쓰이기 때문이다.
이제 비유는 접어두고 스프링 삼각형의 한 축을 이루는 AOP의 역할을 한마디로 정의하면 다음과 같다.
하지만, 스프링은 반드시 AOP를 쓰도록 강제하진 않았다. IoC 컨테이너와 AOP 기능은 소위 말하는 "loosely-coupled" 연결을 맺고 있다. AspectJ와 통합하면서 점차 강력해지긴 했지만, 초창기 Spring은 AOP에 대한 별다른 지식이 없이도 AOP를 활용할 수 있게 했다. 스프링은 AOP 적용에 있어서도 늘 그렇듯 다양한 선택을 준비했다. 그래서, 새로운 기술을 무리하게 도입하기보다는 점진적으로 활용할 수 있는 토대를 제공한다.
![]() |
Professional Java Development With The Spring Framework (Paperback) - ![]() Johnson, Rod/John Wiley & Sons Inc |
어느 조직이나 회사건 모든 업무에 걸쳐 발생하는 일이 있다. 기획, 영업, 구매, 회계, 총무, 경영지원 등 기능과는 다른 영역이 있다. 예를 들어 청소나 기반 제품 납품과 유지보수 같은 일은 어떤가? 최근에는 본질적 기능 외에는 전문 업체에 외주(Out-sourcing)를 줘서 전체 비용(TCO)을 줄인다.
AOP는 이러한 지혜를 순수 기술 차원에 포팅했다. 그 이름도 유명한 제록스(Xerox)가 해냈다. 지금은 다른 엔지니어와 조직에서 계승했다.
하지만, 태생적으로 본질 업무(OOP)와 다른 면이 있어서 오브젝트(object)가 아닌 애스펙트(aspect) 혹은 어드바이스(Advice)로 구분한다.
너무 비유로 흘렀는데 Professional Java Development With The Spring Framework 에 따르면 다음 사항이 AOP 적용을 통해 이익을 볼 수 있는 전형적인 사례다.
- 특정 인터페이스를 구현하는 모든 메소드(혹은 Operation)가 각기 다른 트랜잭션 안에서 수행해야 할 때
- 결과 반환에 자원 소모가 많은 경우에 빠른 응답을 위해 일정 기간 캐시(cache)를 써야 할 때
- 공유하는 DB 필드(field) 값인지라 한 쓰레드에서 변경이 발생하면, DB Lock을 걸고 바로 반영하여 I/O를 발생하기보다는 메모리에서 처리하고 필요할 때 혹은 노는 시간(idle time)에 반영하기
- 한 달간 진행하는 판촉행사를 위한 코드를 현행 코드 여기저기에 끼워 넣고 나중에 빼버리는 실수하기 위한 작업이 아니라 명확하게 구분하여 관리할 수 있게 하기
글
2009년의 한국 스프링 사용자 모임(KSUG)
다시 측면에서 보면 아직 KSUG는 정체성을 갖고 있지 않다. KSUG를 함께 설립한 토비님이 쓴 글, KSUG는 커뮤니티인가에 나타난 고민은 여전히 유효하다. 정체성은 약한데, 존재감은 커진다. 프로그램으로 비유하면 코드는 늘어나고 기능은 커지는데, 아직 응집력 있는 클래스로 명확하게 구분하지 못해 내부적으로는 가칭의 클래스로 진화하는 꼴이다.
한 때, 나는 잘못 생각하여 존재감을 더 키워 무기로 삼고자 했다. 그 중 하나가 포럼 가입자 수에 대한 집착이었다. 후원을 받아 무언가 일을 하려면, 어느 정도의 회원수를 요구했다. 그런데 회원 수가 늘어날수록 오히려 의구심이 들었다. 비전 설정이나 현실 인식 모두가 적절하지 못했다.
이유는 달랐지만 비슷한 시점에 토비님과 나는 포럼을 버리기로 마음 먹었다. 2009년 4월 17일부로 포럼은 읽기 전용으로 묶고 메일링 리스트로 이전했다. 1400 여명의 가입자를 뒤로 하고 물갈이(?)한 결과 딱 한 달이 지난 지금 76명을 찍고 있다.
KSUG를 만들고, 첫 세미나가 2007년 6월이니 아직 채 2년도 지나지 않았다는 사실에 새삼 놀랐다. 꽤 긴 시간동안 정체성 확립조차 하지 못했다고 채근했는데, 생업에 쓰고 남은 자투리 시간을 이용했다는 점을 고려해보면 2년 동안 그래도 한 일이 적지 않았다. 좀체 보기 힘들었던 양질의 세미나를 했고, 활성화라고는 할 수 없지만 포럼도 운영했다. 기술 웹진 실험도 했고, 밀도 있는 스터디도 만들어냈다.
그리고, 새로 시작하는 느낌을 갖는 지금은 좀 더 밀도 있는 논의를 할 수 있는 토대를 쌓고 있다. 근자에 읽은 나는 빠리의 택시운전사에서 마음에 드는 표현을 찾았다. '택시운전사들 사이의 집단 연대감'. 토비님과 KSUG를 만들 때부터 우린 'User Group' 혹은 '사용자 모임'을 표방했다. 스프링 사용자는 영구적인 직업이 아니기 때문에, 스프링 사용자로서의 삶만으로는 연대감을 만들긴 힘들다.
그치만 스프링은 그저 하나의 프로그램에 지나지 않는 것은 아니다. 매년 2차례의 국제적인 컨퍼런스를 열고, 주류로 부상한 프레임워크이기도 하지만, 새로운 프로그래밍 모델, 배포 모델, 운영 모델을 논하는 이들의 위상은 과거 SUN이 J2EE 커뮤니티를 통해 하고자 했던 역할 모델을 실현한 모습이다. 하지만 스프링의 산업에서의 위상은 나에게 그리 큰 의미를 주지는 않는다. 스프링의 성공이 나의 성공은 아니니까. :)
나에게 있어 스프링은
- 한 방을 노리기 보다 끈질기고 치밀한 노력을 통해 만들어낸 결과를 보여주는 스승이고
- 일관성을 지키면서도, 지속적으로 향상하는 것이 가능함을 알려주는 표상이며
- 지금 있는 자리에서 너도 스스로의 솔루션을 찾으라는 지엄한 꾸짖음이며
- 심지어 언제라도 돌아갈 수 있는 편안한 안식처
KSUG에 모인 사람들은 모두 각자의 다른 삶을 살고 있고, 스프링에 대한 이해와 관심도가 모두 다르다. 우리사회의 관성을 반영하여 굳이 이를 획일화 할 필요는 없다. 오히려 차츰 서로 생각을 나누고, 각자의 '스프링'을 둘러싼 삶의 단편을 공유하다 보면 연대를 만들 수 있을 것이다.
이야기를 하다보니 감상적이 되었는데, 거창한 뜻을 가지고 메일링을 만든 것은 아니다. 그저 일상이 모여 내려진 자연스런 판단을 따랐을 뿐이다.
연대를 꿈꾸는 스프링 사용자들은 메일링을 함께 하길 바란다:
http://groups.google.com/group/ksug
아마 다음 달에 처음으로 KSUG 이름으로 스프링 교육을 할 예정이다. 계획 안은 2, 3가지가 있지만 현재 그 중 하나가 실현 단계에 있다. 유명 교육 기관에서 수행하는 스프링 교육이 만족스럽지 못하다는 이야기를 많이 들어 양질의 교육을 내놓고 싶은 욕심이 있었다. 하지만, 강사료가 적어서 고민했는데 박찬욱군이 나서서 결국은 개설하기로 했다. 강사료가 적어도 스프링 교육에선 국내 최고가 아닐까 싶다. 교육 과정은 찬욱군과 함께 내가 직접 만들었다. 노동부 지원을 통해 중소기업 재직자 대상으로 무료로 교육할 예정인데, 주말 시간에 진행할 듯하다.
6월 20일 개설하는 이번 교육을 필두로 KSUG는 여력이 되는 한 부끄럽지 않은 스프링 교육을 내놓을 예정이다. 교육을 하려는 마음은 직작부터 있었는데, 생업 탓에 여력이 없어 덮어 두었는데 '스프링 유행에 편승하여 만들어진 엉터리 스프링 교육에 피해를 본 여친'과 '내 이름과 KSUG 이름을 팔아먹는 교육이 있다는 첩보'가 결정적인 계기가 되었다.
참! 그리고 조만간 번개가 있을 예정입니다.
글
오랜만에 서점에서 본 개발 관련 서적(일부 첨언)
하나는 ray님 추천도서 목록에서 봤던 이클립스 프로젝트 필수 유틸리티 : subversion, Ant, JUnit, Trac 이다. 필요할 때 딱 맞춰서 나온 좋은 책이다. 말 그대로 필수 유틸리티를 잘 정리했다. 책을 훑어보니 초심자가 반드시 알아야 할 내용을 적절한 수준으로 정리했다.
![]() |
이클립스 프로젝트 필수 유틸리티 : subversion, Ant, JUnit, Trac - ![]() 민진우 외 지음/한빛미디어 |
책에 대한 아쉬움은 아니지만, 좀 더 깊이 있는 내용을 원하거나 실무에서 문제 해결을 위해 참조하려는 독자를 위한 내용으로는 다른 책이 필요할 듯하다. 과연 그런 책이 나온다고 해도 얼마나 팔릴 수 있을지 의문이지만...
(아래 책은 저작권 침해 논란에 휘말린 책임을 알려 드립니다.)
두 번째 눈에 띈 책은 SPRING 2.5 실무 프로그래밍이다. 스프링 2.5 책이라곤 하나밖에 없는 줄 알았는데 처음 보는 책이다. 전체적으로 초보자가 접근하기 좋은 흐름으로 구성했다. 저자 약력을 보니 강의 경험이 많은 베테랑인 듯하다. 예제도 어렵지 않아 처음 따라 해보기엔 좋을 듯하다. 내가 못 찾았는지 모르지만, 2.5 고유한 기능에 대한 설명은 없고, 설정은 모두 xml을 이용했다. 출판 시점에 맞춰서 판매 촉진을 위한 2.5를 붙여둔 듯하다.
![]() |
SPRING 2.5 실무 프로그래밍 - ![]() 성윤정 지음/삼양미디어 |
서점을 나서면서 막연히 생각해봤다. 이런 책을 통해 천천히 예제를 따라 해보는 방법이 효과적인지. 배우는 이의 성향 문제가 중요하겠지만, 영어 읽기가 가능하다면 스프링 배포 파일에 들어 있는 예제를 돌려보면서 분석하는 방법을 권하고 싶다. 아마 그 정도를 해보면 위 책의 내용과 비슷한 수준의 지식을 얻을 수 있다. 물론, 영어 읽기, 스프링 레퍼런스 찾아보기, 왜 이렇게 만들었을까 고민해보는 인내의 시간을 감당해야 한다.
지인의 블로그를 보니 내가 위 책을 폄하하는 듯이 느낄 수도 있을 듯 하여 사족을 단다. 나는 이 책을 스프링을 공부하는 가까운 지인에게 추천한 바 있다. 하나의 시스템이 여러 개의 인터페이스를 갔듯 사람마다 다른 책을 원할 수 있다. 나는 스프링을 학습하는 방법으로 책과는 다른 방식을 조언했다. 위 책에서 불편하게 느껴지는 부분은 단 하나다. 스프링 2.5 고유의 내용을 살펴보기 힘든데, 2.5 라고 붙어 있어서 잠재적인 독자/스프링 사용자의 오해를 조금이나마 막고 싶었다.
글
스프링을 통해 진화하기
| 스프링을 통해 진화하기 |
|
|
스프링 소스코드가 아름다운 이유 |
|
스프링의 아버지인 로드 존슨(Rod Johnson)은 최근 올린 글 Our approach to the JCP에서 Spring Source(Interface21의 새로운 회사 이름)가 자바 표준을 만드는 단체인 JCP에 임하는 자세를 기록했습니다. 굵은 글자로 쓰인 Honesty가 유독 눈에 띄었습니다. 예전에 스프링 웹 프레임워크(Spring Web MVC)를 살펴보다가 이해가 안되어서 소스코드를 찾아본 일이 있습니다. 그때 느낀 것이 정직하게 진심을 다해 코드를 작성하면 스프링과 같아지겠구나 싶었습니다. |
|
그림 1. Strategy 패턴을 적용한 스프링 소스코드 일부 | |||||
|
| |||||
스프링을 대규모 사이트에 적용하며 | |||||
|
한창 스프링의 매력에 빠져 있을 때 실전에서 사용할 수 있는 기회가 왔습니다. 수백 억대 시스템 구축 프로젝트에서 스프링 도입을 허락한 것입니다. 프로젝트 수행업체는 그때 필자가 소속해있던 컨설팅 회사를 전적으로 신뢰했습니다. 그래서, 필자는 많은 부분을 직접 결정할 수 있었습니다. 스프링의 매력에 더하여 고객의 신뢰는 필자에게 엄청난 힘을 주었습니다. 누군가에게 전폭적인 신뢰를 받는다는 것이 어떤 것인지 독자 분들도 잘 아시리라 믿습니다. 그런 신뢰를 받지 못했다면 감히 스프링 적용을 시도하지 못했을지 모릅니다. 물론, 제가 단지 스프링을 좋아해서 결정한 것은 아니었습니다. 기술적인 면에서 보자면, 스프링 채택은 EJB 프로그래밍 모델을 대치하기 위한 것이었습니다. 대규모 사이트에서는 대부분 CBD 방법론을 적용하여 설계를 합니다. 분석까지는 객체 지향 기반으로 잘 끌고 와도 EJB 프로그래밍 모델에 적용시키려고 하면 설계 모델이 너무나도 복잡해지는 것이었습니다. EJB 컴포넌트는 다수의 클래스나 인터페이스로 구성되기 때문이죠. 그 무렵 필자는 TSS(TheServerSide.com)라는 J2EE 커뮤니티에 배포된 ‘The J2EE Architect’s Handbook’에서 소개한 방법을 채용하여 EJB 배포 모델과 애플리케이션 사이 종속성을 제거하는 기법을 사용하여 설계하도록 설계자들을 가이드 했습니다. EJB는 필수라고 여겼던 필자가 스프링에 관심을 가진 것은 스프링 1.2 버전이 준비될 즈음이었습니다.
그림 3. 스프링 배경 철학이 닮긴 로드 존슨의 서적들 |
글
6번째 스프링 사용자 모임 공지
글
다음 스프링 세미나 주제는 Spring Web MVC
엠파스 블로그를 사용하던 시절에 Spring MVC컨트롤러 탐험기 안내 라는 이름으로 정리를 했었다. 벌써 1년도 훨씬 지났다. 스스로 다시 한번 정리를 할겸 세미나 주제로 정했다. 게다가 지난 세미나에서 가장 많은 분들(57명)이 다음에 다뤄졌으면 하는 내용으로 꼽았다.
아직 발표를 구상할 단계는 아니지만 주로 다음과 같은 내용이 다뤄질 것이다.
- 스프링 웹 MVC가 제공하는 컨트롤러 클래스 각각의 특징
- PropertyEditor의 활용
- Validation
- referenceData() 활용
- DispatcherServlet 작동 및 다른 웹 MVC와의 연동 원리
토비님이 발표할 내용은 아직 확정되지 않았지만, 아마도 irene이라는 이름의 프로젝트 스타트킷이 될 것이다. appfuse보다 간결하고, 이클립스에 최적환 된 녀석으로 고안되었다. 오픈시드에서 처음으로 내놓는 오픈소스 프로젝트가 될 것이다. 토비님 블로그에 가보면 irene의 기반으로 사용되는 Maven에 대한 공부가 한창인 것을 확인할 수 있다.
어제 기묘 대표님이 얼핏 사용이 가능한 다른 세미나 장소를 얘기한 것 같은데, 다음에는 화면이 좀 큰 곳에서 할 수 있으면 좋겠다.
글
스프링 공개 세미나 에피소드 "투"
세미나를 준비한 입장에서는 참석하신 분들이 어떻게 느끼셨는지 궁금하기 마련입니다. 제가 쓴 후기보다 먼저 혹은 비슷한 시점에 올라온 글들은 역시 자원봉사에 참여했던 '주최측' AJN 친구들이었습니다. 가장 먼저 확인한 글은 후기라기 보다 갤러리였죠. 다음날도 갤러리가 또 올라왔습니다.
예전에 저처럼 엄청난 포스팅을 자랑하는 기선이가 쓴 글에선 테스트를 위한 클래스들의 긴 작명의 의미를 이해하는 기회가 되었다니 흐뭇했습니다. 역시 멀티 포스팅을 보여주는 찬욱이 글을 보곤 화면이 작았다는 아쉬움을 다시 돌아볼 수 있었다. 가장 앞에 앉아서 봤는데 화면이 작았다니...
이프릴 사이트에서 incoming link로 제일 먼저 확인한 글은 pell님의 글이었다. 사진을 상당히 잘 찍으신다는 것을 대번에 알 수 있었고, 어느 위치에 앉아서 보셨겠구나 하는 추측을 하게 된다. 다른 사람의 시선으로 내 모습을 본다는 것이 새삼 신선했다. 
(위치나 카메라로 봐서 동국님 뒤에 있는 분이 pell님이 아닐까? ㅡㅡ*)
그리고 보니, 맨 앞자리에서 캠으로 촬영하던 분이 있었는데... 어디에 활용하시려고 찍은 것인지 무척 궁금하다.
민재님도 포스트를 올려주셨다. 짧막하게 요점이 글쓴이의 관점을 잘 대변한 것이 티가 난다. 열심히 들었다는 반증. :) 미물님의 후기는 왠지 로드 존슨의 서적을 연상(?)케 할 정도로 긴 글로 일목요연하게 세미나 내용이 정리되어 있다.
Max님의 후기에선 토비형 블로그의 글을 보고 미리 예습을 하고 왔다니 놀라웠다. 사실 두 번째 세션은 어느 정도 준비가 없었다면 따라가기 힘든 내용이었는데... 참 그리고 대전에서 올라와서 바쁜 하루를 보낸 물개선생님의 후기는 120%의 호평으로 이루어져 있었다. :)
또 다른 글이 없을까 찾아보다가 대박을 찾아냈다. ^^
세미나 안내를 전날 밤에 onjo님께서 okjsp에 올린 모양이다. 늦은 공지에 대해 익살어린 불평이 미소를 짓게 했다.
- 이런, 오늘이잖아요 (ㅡ_ㅡ)++++ 강혜원 2007-04-21 23:47:11
- 저는 참가신청까지 했습니다,, 좀전에 ㅠㅠ aspt 2007-04-23 09:00:05
- 아짜증나 왜 지나고 난후에 알게되는건지1!! 널차리버릴꺼야 2007-04-23 09:54:1
세미나 끝나고 나서 참가 신청 하신 분도 있는 모양이다. :)
다음번에는 okjsp에 직접 공지를 하거나 kenu님의 협조를 받는 것을 고려해봐야겠다.









