토비의 스프링 3/3.1
Publish date: 2010-07-19Tags: java spring framework
감상
Java의 기초를 테스트코드로 설명한 Agile Java를 보고, 프레임웍도 그렇게 설명했으면 좋겠다고 생각했었는데,Toby님의 책이 그러한듯하다. testability, 좋은 설계 같은 핵심은 시간이 지나도 빛이 바래지 않을 것이고, 최신버전은 오히려 부차적 것일지도
감상2
(2012/11/25 추가) 아래는 일민형의 부탁으로 토비의 스프링 3.1에 들어간 추천사
토비님의 블로그를 통해 이 책의 집필 소식을 알게 되었고, 출판을 오랫동안 기다렸었다. 마지막까지 인쇄 사고로 배송이 지연되는애 태우는 일정 끝에 책을 받아들고는 비싼 전자기기를 산 기분보다 더 뿌듯했었다. 책을 받은 다음날부터 무거운 책을 출퇴근길에 들고 다니면서 완독을 했었다. 고뇌해서 풀어쓰고 다듬었음이 분명한, 맨들맨들한 문장과 친절한 설명에서 저자의 헌신이 느껴졌다. 이 책은 저자의 열정을 잘 표현했다.
기대한만큼 이 책의 열풍은 대단했다. 회사에서, 파견나간 곳에서, 곳곳의 책상에 이 책이 올라가 있었고, 스프링과 이 책이 포탈업계와 SI업계의 개발자를 이어주는 주제가 되지 않나하는 생각까지도 들었다. TDD 교육과정의 사내 강사를 하면서도 이 책을 항상 추천했었다.
스프링의 아버지 로드존슨은 ‘객체지향 설계는 특정 구현 기술보다, 심지어 자바보다도 더 중요하다.‘고 말했었다. 이 책은 그 가치를 잘 담고 있다.테스트하기 쉬운 코드, 구성요소의 역할과 책임을 섬세하게 나누는 설계 같이 이 책에 강조하는 기법은 프로그래밍을 하는 사람이면 누구나 새겨볼만하다. 거기에 비해 어쩌면 최신 기술의 소개라는 측면은 부차적일지도 모른다.
그럼에도 최신 스프링 3.1에 맞춰서 개정판이 나온 다는 소식을 들었다. 이제 이 책이 단순히 흘러가는 트렌드는 잡는 책이 아니라 ‘수학의 정석'처럼 꾸준히 개편되는 스테디셀러로 자리 잡기를 기원한다.
인상 깊은 부분
1권 53쪽
자바 엔터프라이즈 기술의 혼란 속에서 잃어버렸던 객체지향 기술의 진정한 가치를 회복시키고, 그로부터 객체지향 프로그래밍이 제공하는 폭넓은 혜택을 누릴수 있도록 기본으로 돌아가자는 것이 바로 스프링의 핵심철학이다.
1권 60쪽
그래서 개발자가 객체를 설계할 때 가장 염두에 둬야 할 사항은 바로 미래의 변화를 어떻게 대비할 것인가이다.
1권 61쪽
모든 것을 뭉뚱그려서 한데 모으는 편이 처음엔 쉽고 편하다.
1권 85쪽
응집도가 높다는 것은 하나의 모듈, 클래스가 하나의 책임 또는 관심사에만 집중되어 있다는 뜻이다.
1권 86쪽
결합도란 ‘하나의 오브젝트가 변경이 일어날 때에 관계를 맺고 있는 다른 오브젝트에게 변화를 요구하는 정도’
1권 87쪽
전략 패턴은 자신의 기능 맥락에서, 필요에 따라 변경이 필ㅇ한 알고리즘을 인터페이스를 통해 통쨰로 외부로 분리시키고, 이를 구현한 구체적인 알고리즘 클래스를 필요에 따라 바꿔서사용할 수 있게 하는 디자인 패턴이다.
1권 92쪽
제어의 역전에서 오브젝트가 자신이 사용할 어브젝트를 스스로 선택하지 않는다.
1권 94쪽
프레임워크에는 분면한 제어의 역전 개념이 적용되어 있어야한다.
IoC는 기본적으로 프레임워크만의 기술도 아니고 프레임워크가 꼭 필요한 개념도 아니다.
1권 105쪽
왜 스프링은 싱글톤으로 빈을 만드는 것일까? 이는 스프링이 주로 적용되는 대상이 자바 엔터프라이즈 기술을 사용하는 서버환경이기 때문이다.
1권 143쪽
스프링이란 ‘어떻게 오브젝트가 설계되고, 만들어지고, 어떻게 관계를 맺고 사용되는지에 대한 관심을 갖는 프레임워크'라는 사실을 꼭 기억해두자.
1권 145쪽
스프링으로 개발을 하면서 테스트를 만들지 않는다면 이는 스프링이 지닌 가치의 절반을 포기하는 셈이다.
1권 175쪽
스프링의 창시자인 로드존슨은 “항상 네거티브 테스트를 먼저 만들라"는 조언을 했다.
1권 224쪽
이렇게 DI의 장점을 단순화해서 IoC컨테이너의 도움 없이 코드 내에서 적용한 경우를 마이크로 DI라고도 한다. 또는 코드에 의한 DI라는 의미로 수동DI라고 부룰 수 있다.
1권 384쪽
JavaMail은 확장이나 지원이 불가능하도록 만들어진 가장 악명높은 표준 API중 하나로 알려져있다.
1권 423쪽
단위 테스트의 단위는 정하기 나름이다. 시용자 관리 기능 전체를 하나의 단위로 볼 수 도 있고 하나의 클래스나 하나의 메소드를 단위로 볼 수도 있다. 중요한 것은 하나의 단 위에 초점을 맞춘 테스트리는 점이다. 어쨌든 단위 테스트라는 용어를 사용할 때는 그 의미를 명확히 할 필요가 있다.
1권 434쪽
이렇게 프록시 패턴은 타깃의 기능 자체에는 관여하지 않으면서 접근하는 방법을 제 어해주는 프록시를 이용하는 것이다. 구조적으로 보자면 프록시와 데코레이터는 유사하다.
1권 453쪽
스프링은 ‘&‘을 빈 이름 앞에 붙여주면 팩토리 빈 자체를 돌려준다.
1권 468쪽
스프링은 부가기능을 제공하는 오브젝트를 어드바이스라고 부르고, 메소드 선정 알고리즘을 담은 오브젝트를 포인트컷이라고 부른다.
1권 470쪽
어드바이저 = 포인트컷(메서드 선정 알고리즘) + 어드바이스(부가기능)
1권 475쪽
투명하다는 건 부가기능을 적용한 후에도 기존 설계와 코드에는 영양을 주지 않는다는 뜻이다.
1권 507쪽
AspectJ는 프록시처럼 간접적인 방법이 아니라, 타깃 오브젝트를 뜯어 고쳐서 부각 기능을 직접 넣어주는 직접적인 방법을 사용한다.
1권 536쪽
하지만 인터페이스를 사용하는 프록시 방식의 AOP가 아닌 방식으로 트랜잭션을 적용하면 인터페이스에 정의환 @Transactional은 무시되기 때문에 안전하게 타깃 클래스에 @Transactional을 두는 방법을 권장한다.
1권 545쪽
스프링의 트랜잭션 추상화가 제공하는 트랜잭션 동기화 기술과 트랜잭션 전파 속성 덕분에 테스트도 트랜잭션으로 묶을수 있다.
1권 576쪽
생성자에서 예외가 발생할 수도 있는 복잡한 초기화 작업을 다루는 것은 좋지 않다. 오브젝트를 생성하는 중에 생성자에ㅓ 발생하는 예외는 다루기 힘들고, 상속하기 불편하며, 보안에도 문제가 생길수 있다.
1권 619쪽
즉 인터페이스는 하나의 오브젝트가 여러 개를 구현할 수 있으므로, 하나의 오브젝트를 바라보는 창이 여러 가지 일수도 다는 뜻이다.
1권 624쪽
잘 적용된 DI는 결국 잘 설계된 오브젝트 의존관계에 달려있다.
1권 648쪽
스프링 XML에 담긴 정보는 군더더기나 무의미하게 만들어야 하는 잉여 정보가 아니다. 어쩋든 프레임워크의 도움이 없었다면 더 만흔 양의 자바 코드를 이용해서 작성해야 했던 내용이다.
1권 649쪽
java config의 단점
고객에게 코드를 납품하거나 외부에 제공하는 경우 설정정보의 변경을 위해 소스코드를 제공해야 한다는 불편도 있다.
1권 730쪽
오브젝트에 담긴 로직은 테스트하기도 쉽다. 목 어브젝트 등을 이용하면 심지어 DB가 없어도 테스트를 할 수 있다. 게다가CBD를 비롯한 최신 설계와 개발 기법, 모델리을 중심으로 한 개발방법은 오브게트 기반의 설계와 구현에 잘 들어 맞는다.
1권 736쪽
애노테이션이 단지 코드로 표현하기는 적절치 않은 부가적인 저보를 담고 있고, 그 때문에 환경에 종속도지만 않는다면 여전히 POJO라고 할 수 있다.
1권 749쪽
AOP는 동적으로 동작하면서 개발 정책을 위반한 코드를 잡아내는데도 유용하다.
1권 772쪽
특히 ASM은 워낙 많은 곳에서 사용되면서 서로 버전이 호환이 안 되는 경우가 많아 자주 문제를 일으키는 악명 높은 라이브러리다.
1권 812쪽
때로는 여러 도메인 어브젝트의 기능을 조합해서 복잡한 작업을 진행해야 하는 경우가 있다. 특정 도메인 오브젝트에 담길 수없는 이런 작업은 서비스 계층에서 도메인 계층과 협력을 통해 진행하는것이 바람직하다.
2권 49쪽
이런 방법이 최고라는 자기확신이 강한 기술이나 프레임워크와는 성격이 매우 다르다. 가능한 한 모든 종류의 기술과 개발 방법을 포용하도록 만들어져 있을 뿐 아니라, 언제든지 기존 기능을 확장할 수 있도록 다양한 확장 포인트를 제공해야한다. 그래서 스프링에는 베스트 프랙티스란 없다.
2권 74쪽
그런데, 여러 개의 자식 컨텍스트를 두고 공통적인 빈을 부모 컨텍스트로 뽑아내서 공유하려는 게 아니라면 왜 이렇게 계층 구조로 만들까? 그 이는 전체 애플리케이션에서 웹 기술에 의존적인 부분과 그렇지 않은 부분을 구분하기 위해서다. 스프링을 이요한느 웹 애플리케이션이라고 해서 반드시 스프링이 제공하는 웹 기술을 사용해야하는 건 아니다. 데이터 액세스 계층이나 서비스 계층은 스프링 기술을 사용하고 스프링 빈을 ㅗㅁ나들지만 웹을 담당하는 프레젠테이션 계층은 스프링 외의 기술을 사용하는 경우도 종종 있기 때문이다.
2권 230쪽
PropertySourcePlaceholderConfigurer를 static으로 등록
2권 232쪽
환경 변수 우선 순위
- ServletConfig 파라미터
- SerlvetContext 파라미터
- JNDI로 탐색한 값
- 시스템 프로퍼티 : System.getProperties()로 참조하는 값들. -D옵션으로 지정된 값, JVM 관련정보 java.home 등
- 시스템 환경변수 : System.getenv()로 읽어오는 OS 레벨에 선언된 변수들
- 직접 지정한 속성 파일
2권 537쪽
그래서 이렇게 모든 컨트롤러에 적용해도 될 만큼 많은 곳에서 필요한 프로퍼티 에디터라면 등록하는 방법으 달리해서 한번에 모든 컨트롤러에 적용하는 편이 좋다. 이런 용도로 만들어진 WebBindingInitializer를 이용하면 된다.
2권 539쪽
프로퍼티 에디터는 싱글톤 빈으로 등록해서 공유할 수 없다.
2권 550쪽
Converter
2권 563
WebDataBlinder의 allowedFields, disallowedFields
2권 634쪽
그래서 Rails같은 최신 웹 기술은 요청을 처리하는 단위를 클래스 내부의 메소드로 축소해서 하나의 클래스가 여러 개의 요청을 담당하도록 설계됐다.
2권 681쪽
comments powered by Disqus그렇다면 스프링은 그다지 객체지향적이지도 않으면서 부자연스러운 클래스 프록시를 CGLib이라는 복잡한 바이트코드 생성 기술을 사용하면서까지 지원하는 이유는 무 엇일까? 혹시, 인터페이스를 매번 정의하기가 귀찮은 개발자는 DI를 적용할 때도 대충 타깃 클래스를 사용하다가 프록시 AOP처럼 DI 응용 기술이 필요한 경우에는 이를 이용하라는 뜻일까? 절대 그렇지 않다. 스프링은 여전히 인터페이스를 통한 객체지향적인 합성 기법과 이에 바탕에 둔 DI, 그리고 다양한 DI 활용 방법을 사용하도록 권장한다. 프록시 AOP에서도 마찬가지다. 그럼에도 클래스 방식의 프록시를 지원해주는 이유는 인터페이스를 만들지 않고 개발한 레거시 코드나 외부에서 개발한 인터페이스 없는 라이브러리의 클래스 등에도 원한다면 AOP를 적용할 수 있게 해주려는 것일 뿐이다. 결코 인터페이스를 시용하지 않고 타깃 클래스를 직접 의존하는 DI를 허용하려는게 아님을 기억하자. 자바가 멤버 필드를 public으로 선언해 외부에서 직접 참조할 수 있게 했다고 해서, 그것을 권장하는 게 아닌 것과 마찬가지다.