Toby’s 스프링 3.0 10장 IoC 컨테이너와 DI를 읽고서

결론은 다시보고 있다. 다시 보고 싶은 부분이 생겼다. 들어있는 내용이 꽤 많기 때문에 그 중에서 더 자세히 살펴보고 싶은 부분이 분명히 생길것이다. 그래서 결국 나처럼 다시 보게 될 것이다.

이 책을 쓰느라 얼마나 많은 노력과 학습을 하셨는지 이 장에 잘 묻어나온다. 특히 모든 빈 등록 방법 설명, 장단점 비교, 전략 분석. 모든 빈 의존관계 설정 방법 설명, 장단점 비교, 전략 분석은 토비님의 완벽주의 성향을 잘 드러낸다.
스프링 웹 애플리케이션은 거의 대부분 애플리케이션 콘텍스트 상속 구조로 되어있다. 이것을 잘 이해하지 못하면 AOP가 적용되지 않는다느니 트랜잭션이 되지 않느다느니 원인을 찾기도 힘든 문제들을 만들어 낼 수도 있고 그 문제를 해결하지도 못한다. 그것에 대한 아주 명확한 이해와 해결책을 제시하는 내용이 들어있다. 이걸 모르고 스프링 개발을 하고 있다면 무늬만 스프링 개발자라고 하고 싶을 정도로 중요한 내용이기 때문에 반드시 숙지하도록 하자.
프로토타입과 관련된 내용도 주옥같다. 아주 오래전 KSUG 포럼에 프로토타입 스코프 빈을 참조하는 싱글톤 스코프 빈이 있을때 프로토타입 스코프가 제대로 동작하도록하는 여러가지 방법을 논의한적이 있었다. 사실은 Toby님의 일방적인 퀴즈에 불과했지만 그때 메신저를 통해 들었던 정답과 그 이후에 추가된 해결책까지도 설명하고 있다. 레퍼런스나 API 문서를 빠듯하게 뒤져도 안나올만한 방법이 소개되고 있다. 싱글톤 빈만 사용하면 되지 머.. 라고 안일한 생각을 가진 스프링 사용자가 아니라면 꼭 살펴보고 학습해야 한다.
이밖에도 레퍼런스나 API 문서에서 조차 찾기 힘든 내용이 한둘이 아니다. 그런 내용을 이렇게 친절하게 설명해주는.. 그것도 한글로 된 책을 볼 수 있다는 것은 가히 축복이다.
아. 마지막으로 꼬투리 하나만 잡자면 왠지 10장부터는 약간 토비님 블로그를 읽는 느낌이 난다. 그런데 어쩔 수 없다 저 많은 내용을 더 쉬운 말투와 구체적인 설명과 그림으로 다 풀어내려면 200~300p짜리 책한권이 될 것 같다. 내용자체가 쉽지 않기 때문일 수도 있다. 그렇다고 무슨 안드로메다 수학공식도 아니니까 겁먹진 말자.

Toby’s 스프링 8, 9장을 읽고서

8장은 스프링에 관한 이야기이다. 스프링이란 무엇인가? 스프링의 목적? 그 목적을 달성하는 방법을 설명하며 스프링 삼각형이라 불리는 IoC/DI, AOP, PSA를 자세히 설명해준다. 또한 POJO 프로그래밍에 대해 설명한다. 

그 중에서 기억에 남는 부분은 “복잡함을 해결한다.”라는 부분인데 이 이야기는 2008년 Spring One Ameria 컨퍼런스에 참석하여 직접 들은 이야기라 감회가 새로웠다. 여기서는 그 복잡함이란 무엇인지 또 스프링은 그것을 어떻게 제압하겠다는 것인지 잘 설명해주고 있다.
POJO 프로그래밍에 대한 내용역시 유익하다. POJO라는 단어가 난무하는 요즘 POJO에 대해 제대로 집고 넘어갈 필요가 있는데 그런 간지러움을 잘 긁어주고 있다. 특히 평소 JPA를 사용한 도메인 클래스가 POJO인건지 아닌건지 고민이었는데 그런 고민을 해결하는데 실마리를 제공해주는 기준을 제시하고 있다.
이외에 스프링 삼각형에 대해서는 이미 1부에서 찐하게 살펴본 내용을 이론적으로 점검하는 기분이 들었다. 원래는 8장이 제일 처음이었다고 했는데 1부 맨 뒤로 돌리신건 100번 잘하신것 같다. 아무래도 8장부터 읽기 시작했다면 지레겁먹고 책을 덮었을 수도 있겠다.
9장은 본격적인 2부 시작으로 뭔가 코딩을 할 것 같은 기세이다. 프로젝트를 세팅하고 아키텍처를 논한다. 프로젝트는 세팅이야 스프링 책인지라 STS와 Eclipse+Spring IDE 이야기가 주를 이룬다. 가장 흥미롭우며 9장의 주를 이루는 부분은 사실 그 뒤에 있는 아키텍처 이야기다. 이 부분 토비님 세미나에서 다룰 주제이기도 하고 개인적으로 가장 궁금한 부분이기도 했다. 이 부분을 읽으면서 예전에 시도하다 말았던 아키텍처를 다시 한번 시도해보고 싶다는 생각이 들었다.
자.. 이제 드뎌 10장을 달릴 차례다.

Toby’s 스프링 핵심기술 응용을 읽고서..

먼저 이 장의 제목은 별로다. 이 장에 들어있는 내용을 다 나타내고 있지 못하다. 흠.. 읽고나서 다시 제목을 생각해보니 이번 장은 “스프링 스타일 코딩”이 더 좋을지도 모르겠다.

이번 장에서 살펴볼 수 있었던 스프링의 기능은 내가 미처 몰랐던 기능인 내장 DB 지원 기능을 비롯해서 3.0에 새로 추가된 OXM 그리고 필수로 알아야 하는 리소스 지원 등을 다루고 있다. 이 기능들을 유기적으로 연결하여 SqlService라는 것을 개발하는데 그 과정이 정말이지 놀랍다.
왜 놀라운지는 읽어보는 사람들만이 알수 있겠지만, 이 장을 읽으면서 내내 느낀점은 이 책은 스프링 사용자 뿐 아니라 모든 개발자가 읽어야 한다는 것이다. 이번장에서 SOLID라 일컫는 객체 지향 기본 원칙들을 아무런 거부감 없이 자연스럽게 살펴볼 수 있으며 사용하기 좋은 API 설계 방법이나 점진적인 변화, 진화를 통한 개발 방법을 살펴볼 수 있다. 이런것들은 상당히 딱딱하고 탁상공론 적이며 형이상학적인 주제가 될 수 있는데 반해 이 책에서는 그것들을 항상 눈에 보이는 코드와 테스트를 가지고 증명해 보인다. 또한 이 책의 스타일인 ‘차분차분’과 ‘단계적’인 방법을 통해서 살펴보기 때문에 체할 걱정은 없으며 굉장히 실용적이다.
지난주 봄싹 디자인패턴 스터디에서 SOLID 원칙을 학습했지만 탁상공론에 그칠만한 내용밖에 못다뤄 굉장히 아쉬웠다. 물론 이론적인 내용도 필요하다지만 사실 그런 이론은 시험 볼때나 필요한 것이지 코딩에는 별 도움이 안 된다. 코딩에 도움이 되지 않는 이론이 무슨 소용이란 말인가. 순수 이론으로써의 가치를 가지고자 정리된 원칙들이 아닐 것이다. 그러한 원칙들을 고려하여 코딩하는 것이 어떤 것인지… 그로인해 어떤 스타일의 코드가 탄생되는지 보고 싶다면 이 책을 꼭 보시라권하고 싶다.
나 역시 백날 스프링을 쓰면 머하나.. 스프링에 어울릴만한 코드는 한 줄도 작성하지 못하는데.. 라며 자괴감에 빠졌던 적이 있다. 머 그렇다고 지금도 크게 달라진건 없지만 이 챕터가 그러한 자괴감에서 나를 꺼내주는데 한몫 할것 같다. 역시 이 책은 스프링을 발판삼아 더 나은 개발자가 되고 싶은 분들을 위한 책이다. 자 이제 2부를 달려보자.

[스프링 3.0] @Value 이용해서 기본값 설정하기

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public class ValueTest {
    @Autowired Whiteship whiteship;
    @Test
    public void defaultName(){
        assertThat(whiteship.getName(), is(“keesun”));
    }
}
@Component
public class Whiteship {
    @Value(“keesun”)
    private String name;
    public String getName() {
        return name;
    }
    
    public void setName(String name) {
        this.name = name;
    }
}
악.. 저녁 약속이 있어서 길게 정리는 못하겠네요. 
이것도 DI용 애노테이션이라는거..

[스프링 3.0] PropertyEditorRegistry가 이길까 ConversionService가 이길까

public class Whiteship {

    String name;

    public Whiteship(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

public class SpringSprout {

    private Whiteship whiteship;

    private int num;

    public Whiteship getWhiteship() {
        return whiteship;
    }

    public void setWhiteship(Whiteship whiteship) {
        this.whiteship = whiteship;
    }

    public int getNum() {
        return num;
    }

    public void setNum(int num) {
        this.num = num;
    }
}

이렇게 두 개의 클래스가 있을 때 Whiteship을 SpringSprout로 주입하는 빈 설정을 다음과 같이 했다.

    <bean class=”sandbox.convert.SpringSprout”>
        <property name=”whiteship” value=”keesun”/>
        <property name=”num” value=”1″/>
    </bean>

동작할까 안할까?

당연히 안한다. Whiteship 타입이 필요한데 keesun이라는 문자열을 던져주다니 장난 하는게냐 라고 예외를 던질꺼다.

하지만 되게 만들 수 있다. 이전까지는 PropertyEditorSupport 클래스를 확장하여 아주 손쉽게 구현할 수 있었다.

public class WhiteshipPE extends PropertyEditorSupport {

    @Override
    public String getAsText() {
        return ((Whiteship)getValue()).getName();
    }

    @Override
    public void setAsText(String name) throws IllegalArgumentException {
        setValue(new Whiteship(name));
    }
}

이런 코드는 특히 MVC에서 바인딩 할때 매우 유용하다. 이걸 안쓰면 request에서 일일히 꺼내서 노가다를 해야하는데 난 절대로 그러고 싶지 않다.

그런데 PE의 문제는 쓰레드-세이프하지 않다는 것이다. 그래서 PE를 등록할 때 조심해야 한다. 특히 전역 변수를 가지는 PE를 싱글톤으로 바인더에 등록해버리지 않았나 조심해야 한다. 반드시 그때 그때 new를 사용해서 등록해 주도록 하고 PE 생성자에 필요한 레퍼런스를 전달해주는게 안전하다. 아마 이 내용도 사부님 책에 들어갈 것 같으니 자세한 내용은 그 책을 참고하도록 하자.

PE의 대안이자 좀 더 범용적인 변환기 역할로 3.0에 도입된 것이 ConversionService이고 ConversionServiceFactoryBean에 Converter, ConveterFacrtory, Formatter 등을 등록해놓고 변환을 부탁할 수 있게 되었다.

public class WhiteshipConverter implements Converter<String, Whiteship> {
    public Whiteship convert(String source) {
        return new Whiteship(source);
    }
}

그런데;; PE와 역할이 중복되는데;;; 둘 다 빈으로 등록해둘수 있다.

    <bean class=”org.springframework.beans.factory.config.CustomEditorConfigurer”>
        <property name=”propertyEditorRegistrars”>
            <bean class=”sandbox.convert.CustomPERegister”>
            </bean>
        </property>
    </bean>

    <bean id=”conversionService” class=”org.springframework.context.support.ConversionServiceFactoryBean”>
        <property name=”converters”>
            <set>
                <bean class=”sandbox.convert.WhiteshipConverter”/>
            </set>
        </property>
    </bean>

결국 문제는 대체 String을 Whiteship으로 바꿔야 할 때 PE를 쓸 것이냐 CS를 쓸 것이냐이다. 무엇을 쓰게 될지… 그게 궁금했었다. 그런데 마침 오늘 사부님이 퀴즈를 냈고;; 난 스케줄을 팽개치고 매달렸다;;

1차 문제 상황

CS와 PE가 등록되어 있을 때 PE가 이겼다.
하지만 난 CS가 이기는 경우를 예제에서 본적이 있었다. 그래서 도무지 납득이 되지 않았고 어떻게 설정해야 가능한지 궁금했다.

CS만 등록했을 땐 CS로 동작했다.
PE만 등록했을 땐 PE로 동작했다.
둘다 등록했을 땐 PE가 동작헀다.

2차 문제 상황

Whiteship만 가지고 테스트를 했었는데 기본 타입도 추가해봤다. int num이 그것이다. 이제 더 큰 문제가 생겼다.
Whiteship만 PE가 이기고 나머지 기본 타입은 CS가 이겼다.
정말 깜놀이었다. 이사실을 발견하지 않았다면 난 그냥 클래스로더를 공부했을 것이다.

어디선가 기본 PE를 덮어쓰거나 없애버린 거 아닌지 궁금했고 소스 코드를 뒤져보기 시작했다.
시간이 손살같이 지난간다.
우울해지기 시작한다.

3차 결론

소스 코드를 뒤적거리다가 ConvertingPropertyEditorAdapter 클래스를 찾았다.
이 클래스는 ConversionService를 사용해서 PE를 노출시켜주는 어댑터다.
겉으로는 PE를 등록한것 같지만 실제로는 ConvesionService를 사용하는 것이다.ㅋ

스프링에서 내부에서 저걸 사용해서 기본 PE들을 등록하도록 바꿨는지는 확인하지 않았다.
왠지 답이 아닌것 같다. OTL..
내가 졌다.

트릭같은 기법을 써서라도 PE를 누르고 아니 속이고 CS가 동작하게 했으니…그만 놓아줄 수 있을 것 같다.
어서 사부님 책이 나와주길….

ps: 위에 나온 코드는 급조한 코드오니 조심할 부분을 건너뛴 곳도 있습니다. 주의하세요.