메뉴 바로가기 검색 및 카테고리 바로가기 본문 바로가기

한빛출판네트워크

한빛랩스 - 지식에 가능성을 머지하다 / 강의 콘텐츠 무료로 수강하시고 피드백을 남겨주세요. ▶︎

IT/모바일

내가 Spring을 사랑하는 다섯 가지 이유

한빛미디어

|

2007-03-13

|

by HANBIT

15,121

제공 : 한빛 네트워크
저자 : Bruce A. Tate
역자 : 박찬욱
원문 : Five Things I Love About Spring

15년 전 보다 더 더운 6월 아침에 나는 오래된 fiberglass(섬유 유리로 된) 카약을 타고 있었다. 너무 오래돼 내 손에서 조각들이 떨어져나가곤 했고, 노는 전통적인 whitewater paddle보다 약 2배 정도 길었다. 나는 내 보트보다 수영을 더 많이 해야 했지만, 그리 큰 문제는 아니었다. 15년 후에도 나는 여전히 열중(hooked)하고 있을 것이다. 대략 이 년 전에 하이버네이트 사이트에서 급격히 중요하게 언급된 Spring 프로젝트를 사용해 봤다. 이것은 오래 된 카약과 같은 느낌이었다. 나에게는 완벽하게 잘 맞았다. 가망이 없는 엔터프라이즈 개발에서 Spring은 나의 네 번째 자바 책, Spring : A Developer"s Notebook, 의 주제로 만들었던 것처럼 나의 프로그래밍으로 매우 깊이 들어왔다. 이번 글에서 나는 이 이유에 대해서 당신에게 설명하려 한다.

1. Spring은 매우 좋은 수단을 제공한다.

강에서 나는 팔 근육이 강에서 노를 젓는 동안에 힘을 유지할 수가 없어서, 허리와 등을 조금 더 이용해서 노를 젓는 것을 배웠다. 더 좋은 수단을 얻게 된 것이다. Spring에서는 조금 더 코드의 각 라인에 집중해 일할 수 있다. 당신은 Spring의 많은 코드에서 훌륭한 수단을 찾을 수 있지만, 가장 큰 점은 영속성에 관련된 부분이다. 다음은 하이버네이트 데이터 접근 객체의 메소드에 대한 예이다.
public List getReservations( ) {
  return getHibernateTemplate( ).find("from Reservation");
}
당신이 찾지 못한 것을 말해봐라. 트랜잭션 처리 과정이 없다. Spring은 트랜잭션 관리를 위한 환경 구성 코드를 구축할 수 있게 해준다. 세션을 막아 놓으면서 자원을 관리하지 않는다. 당신만을 위한 환경 설정을 할 필요도 없다. 트랜잭션 레벨에서는 예외가 unchecked이기 때문에, 예외 관리도 할 필요가 없다. 대부분의 상황에서 트랜잭션에 대한 관리에서 자유로워진다. Spring을 사용하지 않고 어떻게 구현했는지 다른 하이버네이트 메소드를 보면 알 수 있다.
public List getBikesOldWay( ) throws Exception {
  List bikes = null;
  Session s = null;
  try {
    s = mySessionFactory.openSession( );
    bikes = s.find("from Bike");
  }catch (Exception ex) {
    //handle exception gracefully
  }finally {
    s.close( );
  }
  return bikes;
}
Spring은 나에게 수단을 제공한다. 나는 더 빨리 코드를 작성할 수 있으며, 유지를 위한 수고도 적다.

2. Spring은 POJO 프로그래밍을 가능하게 해준다.

EJB 2.x가 완패한 후에, 모두들 침략적이지 않고 성가신 모델로 된 모든 빈들 없이 엔터프라이즈 서비스를 구현할 수 있는 방법을 찾았다. EJB를 사용하면 확장 API와 새로운 툴과 개발 과정에 대해 배워야만 한다. Spring을 사용하면, 내가 나의 서비스와 영속성 프레임워크를 선택할 수 있다. POJO로 프로그램을 짜고 환경 설정 파일을 통해서 그 프로그램에 엔터프라이즈 서비스를 추가한다.

Spring: A Developer"s Notebook에서, RentaBike 어플리케이션을 구축했다. 세션 빈과 엔티티 빈 대신에, 나는 데이터 접근 객체로 제공되는 POJO hibRentaBike를 호출했었다. 나는 어디서나 이 서비스를 추가할 수 있다. 컨텍스트(context)를 호출하는 Spring 환경설정 파일은 컨테이너에서 제공되는 모든 빈에 대한 내용과 빈이 필요로 하는 속성들(properties)과 서비스를 함께 담고 있는 XML 파일이다. 여기서 코드를 보자.
대상(the target) :

  
    Bruce"s Bikes
  
  
    
  
  
    
  


인터셉터(the interceptor) :

  
    
  
  
    
      com.springbook.RentABike.transferReservation=
      PROPAGATION_REQUIRED,-ReservationTransferException
      com.springbook.RentABike.save*=PROPAGATION_REQUIRED
      com.springbook.RentABike.*=PROPAGATION_REQUIRED,readOnly
    
  


프록시(the proxy) :

  
    com.springbook.RentABike
  
  
    transactionInterceptor,rentaBikeTarget
  

세 개의 다른 빈-프록시, 대상 객체(the target), 인터셉터-이 있다는 것을 알아두자. 프록시는 POJO를 호출 할 것이고, POJO에 의해 필요한 서비스들이 있을 것이다. 인터셉터는 서비스를 호출하는데 반드시 필요한 서비스 코드를 포함한다. 또한 프록시와 인터셉터에는 대상 객체(the target)에 있는 각 메소드를 어떻게 처리할지에 대해 정의한다. 프록시를 호출해서 RentaBike에 접근을 필요로 하는 어느 누구든지 트랜잭션을 처리하는 인터셉터를 호출하고, 트랜잭션을 시작한 다음 대상 객체(the target : 여기서는 POJO가 됨)를 호출할 수 있다. 대상 객체는 자신의 임무를 수행하고, (트랜잭션을 커밋하는) 인터셉터에게 리턴 한 다음, 다시 프록시에게 리턴하고, 마지막으로 프록시를 호출한 대상에 결과를 리턴 한다.


[그림 1. POJO programming in action]

그림에 나온 것처럼 POJO로 프로그램을 구축할 수 있고, Spring은 당신에게서 나머지 부분을 숨겨준다. 나는 POJO 프로그래머다.

3. 테스트 용이성을 도와주는 의존성 삽입(Dependency Injection)

Spring은 의존성 삽입(DI : Dependency Injection)으로 불리는 디자인 패턴을 통해서 테스트 용이성을 개선했다. 사용자가 한 의존성에 의존할 경우(우리가 서비스라 부르는), 우리는 이 사용자 위한 단일 속성을 만들어야 한다. Spring은 사용자와 서비스를 만들고, 사용자의 속성을 서비스의 값으로 할당한다. 다른 말로 해보면, Spring은 컨텍스트 내에서 빈의 생명주기를 관리하고, 의존성을 결정한다. Spring을 사용하지 않은 의존성 삽입의 한 예를 들어보자. 어플리케이션을 위한 주요한 뷰를 제공하는 사용자(consumer)를 정의했다.
public class CommandLineView {

  private RentABike rentaBike;

  public CommandLineView( ) {
	rentaBike = new ArrayListRentABike("Bruce"s Bikes"); 
  }

  public void setRentABike(RentABike rentABike){
  	this.rentABike = rentABike;
  }

  public void printAllBikes( ) {
    	System.out.println(rentaBike.toString( ));
	Iterator iter = rentaBike.getBikes().iterator( );
	while(iter.hasNext( )) {
	Bike bike = (Bike)iter.next( );
        System.out.println(bike.toString( ));
  }
}

  public static final void main(String[] args) {
    CommandLineView clv = new CommandLineView( );
    clv.printAllBikes( );
  }

}
다음으로 모델 역할을 하는 서비스를 보자. 배열 리스트를 사용한 간단한 구현이다. 이 구현 클래스는 모델(RentaBike)에 대한 의존성을 가지고 있다.
interface RentABike {
List getBikes( );
Bike getBike(String serialNo);
}

public class ArrayListRentABike implements RentABike {
   private String storeName;
   final List bikes = new ArrayList();
   public ArrayListRentABike(String storeName) {
      this.storeName = storeName;
      bikes.add(new Bike("Shimano", "Roadmaster", 20, "11111", 15, "Fair"));
      bikes.add(new Bike("Cannondale", "F2000 XTR", 18, "22222",12,"Excellent"));
      bikes.add(new Bike("Trek","6000", 19, "33333", 12.4, "Fair"));
   }

   public String toString() { 
      return "RentABike: " + storeName; 
   }

   public List getBikes() { 
      return bikes; 
   }

   public Bike getBike(String serialNo) {
      Iterator iter = bikes.iterator();
      while(iter.hasNext()) {
         Bike bike = (Bike)iter.next();
         if(serialNo.equals(bike.getSerialNo())) return bike;
      }
      return null;
   }
}
이제 중개자(assembler)에 대해 보자. 이 중개자는 서비스와 사용자를 초기화하고, rentaBike속성에 값을 할당함으로서 의존성을 결정한다.
public class RentABikeAssembler {
  public static final void main(String[] args) {
    CommandLineView clv = new CommandLineView( );
    RentABike rentaBike = new ArrayListRentABike("Bruce"s Bikes");
    clv.setRentaBike(rentaBike);
    clv.printAllBikes( );
  }
}
물론 Spring은 결과적으로 중개자 역할에 매우 적합할 것이다. 만약 인터페이스로 서비스를 감싼다면, 이 인터페이스를 구현한 컨테이너에 있는 어떤 클래스도 주입(inject)이 가능할 것이다.

의존성 삽입은 당신의 코드가 의존성을 만들고 테스트하는 것을 가능하게 해준다. 예를 들어, 이 예에서 view를 더 쉽게 해주는 테스트를 만들기 위해 스텁(stub) 객체를 만들 수 있다.(stub과 mock에 대해 더 알고 싶으면 “Mocks Aren"t Stubs http://www.martinfowler.com/articles/mocksArentStubs.html ”를 읽어보기 바란다.)

당신이 이미 배열 리스트 버전의 RentaBike의 하이버네이트 구현을 봤다. 나는 완벽한 하이버네이트 구현에서 모든 사용자 인터페이스 테스트를 실행하는 것을 원치 않는다. 대신에 배열 리스트를 사용해서 다른 방법으로 인터페이스를 간단히 구현할 수 있다.

의존성 삽입은 제품 버전(HibRentaBike), 개발 버전(ArrayListRentaBike 리스트)과 테스트 버전(mock 객체)을 묶을 수(wire up)있게 해 준다. 내가 자바로 코딩할 때, mock 객체들을 사용하기 어려운 장소에서 사용을 위해 의존성 삽입을 하기 시작했다.

4. JDBC를 간단하게 만들어버린 제어의 역전(Inversion of Control)

JDBC 어플리케이션은 추악하고, 장황하고, 진저리가 난다. 좋은 추상화 레이어는 이 문제를 해결하는데 도움을 줄 수 있다. Spring은 당신이 쿼리를 사용하는 기본 JDBC 메소드와 단조로운 작업의 많은 부분을 제거해주는 익명 내부 클래스(anonymous inner class)를 커스터마이징이 가능하도록 해준다. 여기서 간단한 예제를 한 번 보자.
JdbcTemplate template = new JdbcTemplate(dataSource); 
final List names = new LinkedList();

template.query("SELECT USER.NAME FROM USER", 
  new RowCallbackHandler() { 
      public void processRow(ResultSet rs) throws SQLException {
        names.add(rs.getString(1));
      }
  }
);
기본 JDBC 메소드로서 사용되는 쿼리 메소드인 템플릿에 대해 생각해보자. Spring은 ResultSet에 있는 각 라인을 위해 익명 내부 클래스에 있는 processRow 메소드를 실행할 것이다. 당신은 컨텍스트에 데이터 소스(data source)를 구성해야 한다. statement를 열거나 닫기, connection, 데이터 소스의 구성, 혹은 트랜잭션 관리에 대한 걱정을 할 필요가 없다. Spring은 SQLException을 일반적인 unchecked 예외 셋으로 감싸주기 때문에 외부 결과 값 셋을 정의하거나 최 하단 수준의 예외를 직접 관리하면 안 된다. 루비나 스몰토크 같은 다른 언어들도 드물게 코드 블록으로 제어의 역전을 사용하지만, 자바에서는 이것이 일반적이지 않다. 제어의 역전은 정말로 나를 동요시킨다.

5. 번창하는 Spring의 커뮤니티

몇몇 오픈소스 프로젝트는 유용하게 사용되기 위해서 커뮤니티의 두드러진 활동이 필요 없는 경우도 있다. 예를 들어보면, JUnit은 대상이 된 작업(job)이 있고, 프로그래밍 모델을 좋아하는 경우 기본적으로 당신이 필요로 하는 모든 것들이 들어 있다. Spring 같은 경량 컨테이너(lightweight container)는 매우 활발한 커뮤니티를 필요로 한다. Spring은 당신이 찾을 수 있는 것 중에서 많은 도움을 받을 수 있는 가장 활발한 커뮤니티 중 하나이다.
  • 서비스 : Spring을 사용하면 보안, 시스템 관리, 작업 흐름 관리에 해당하는 수 백 개의 다른 서비스를 찾을 수 있다. 영속성 관리를 위해서 당신은 JDO, Hibernate, Top Link, JDBC, 혹은 OJB를 붙여서 사용(plug in) 할 수 있다.
  • 지원과 교육 : 상당히 많은 컨설턴트들이 Spring 서비스를 제공하고, 드물지만 세계 각 지에서 교육을 받을 수 있다.
  • 가치 증가 : Spring은 한 해에 몇 개의 주요한 릴리스 버전을 내놓고 있다. 프레임워크 내에서 수행된 매우 훌륭한 테스트와 완벽하게 인자화 된 확장은 각 릴리스의 좋은 품질을 의미한다. Spring은 이미 최근 주요한 릴리스에서 내부적으로 하이버네이트 3를 지원하였고, 새롭고 강력한 web flow 프레임워크를 제공했다.
  • 상업적인 지원 : 필자와 같은 작가는 Spring에 관련된 책을 쓴다. 지금껏 Spring에 관련된 다섯 권의 책을 찾을 수 있고, Spring 컨텐츠들은 더 많이 존재한다. 몇 몇 제품 벤더들은 Spring을 지원한다. Geronimo와 Hibernate와 같은 많은 오픈 소스 프레임워크들이 Spring을 위한 특별한 지원을 하고 있다.
Spring 커뮤니티는 프레임워크를 더욱 쉽게 사용할 수 있도록 해준다. 나는 Spring 개발자를 고용할 수 있고, 그들에게 교육을 받을 수 있다. Spring에 대한 내 지식을 보충하기 위해서 책을 읽을 수 있고, 내가 하고자 원하는 것에 대한 모든 것들에 대해서 컴포넌트를 받을 수 있다. 가까운 시일 내에 어떤 다른 경량 컨테이너를 위한 커뮤니티를 찾을 수 없을 것이다.

[참고 문헌]

더 많은 정보를 읽고 싶다면, 자료를 수 있는 곳이 매우 많다.
역자 박찬욱님은 현재 학생으로, 오픈 소스에 많은 관심을 가지고 있습니다. Agile Java Network에서 커뮤니티 활동을 열심히 하고 있고, 블로그(chanwook.tistory.com)를 재미있게 운영하고 있습니다.
TAG :
댓글 입력
자료실

최근 본 상품0