본문 바로가기

WEB_Programming/Spring

스프링 2.5 소개 -로드존스-

October 2007

Discussion


2005년 5월 이 기사를 개정하고난 이후로, 스프링 프레임 워크는 계속해서 대중화 되면서 성장하였다. 그리고 엔터프라이즈 자바 개발의 사실상 표준이 되었다. 그것은 버젼 1.2에서 2.5로 발전하면서 넓은 사업분야와 프로젝트들에서 채용되었기 때문이다. 이 아티클에서는 어떠한 스프링 세트들을 획득하고 어떻게 엔터프라이즈 자바 개발에서 도움을 줄 수 있을지에 대해서 설명한다.


Why Spring ?

나는 스프링은 몇가지 이유에 의해서 유일하다고 믿는다.

  • 그것은 다른 알려진 프레임워크가 할 수 없는 매우 중요한 위치에 있다. 스프링은 당신의 비즈니스 객체를 관리하는 방법을 제공하는데 포커스를 두고 있다.
  • 스프링은 포괄적이고, 모듈화 되어 있다. 스프링은 layered architecture이다. 이 의미는 당신이 어떠한 부분을 선택하더라도 그 부분을 독립적으로 사용할 수 있음을 의미한다. 아키텍셔 상에서 여전히 변화없이 말이다. 또한 당신의 학습곡선으로 부터 최대한의 값을 획득할 수 있다. 당신이 오직 단순한 JDBC를 이용하기 위해서 스프링의 사용을 결정한 예라도 당신은 스프링을 이용하여 당신의 비즈니스 객체 모두를 관리할 수 있게 될 것이다. 그리고 존재하는 프로젝트 속으로 점점 스프링에 대해 쉽게 소개할 수 있을 것이다.
  • 스프링은 당신이 작성한 코드를 쉽게 테스트 할 수 있도록 도움을 줄 수 있도록 개발 되었다.
  • 스프링은 점점더 중요한 통합 기술의 집합체이다. 크거나 혹은 작은 벤더에 의해서 그 역할이 인식되고 있다.
  • 스프링 프레임 워크는 스프링 포트폴리오의 핵심이다. 엔터프라이즈 자바 개발을 위해 완전한 솔루션이 증가하고 있으며, 그것은 스프링 프레임워크 그 자체가 개발되었고 스프링의 접근 방식이 그것을 말해준다.

스프링은 대부분 일반적인 애플리케이션의 인프라스트럭쳐에 관련되어 있다. 그것은 다른 프레임워크가 가지지 못한 위치이다.


2003년 2월 오픈소스 프로젝트를 시작한 이래 스프링은 아주긴 전통을 가지게 되었다. 오픈소스 프로젝트는 나의책인 2002년 후반에 기술된 Expert One-on-One J2EE Design and Development에 기제된 인프라스트럭쳐 코드로부터 시작되었다. Expert One-on-One J2EE는 스프링 뒷단의 인프라스트럭쳐에 대한 이야기로 되어 있다. 어쨌든 핵심 아키텍쳐의 개념은 2000년으로 거슬러 올라가며, 성공적인 상업프로젝트를 개발하기위한 인프라 스트럭쳐에 대해 나의 경험을 반영했다. 현재는 40명의 개발자 대부분이 스프링의 개발과 Interface21에서 풀타임을 가동하여 지원을 아끼지 않고 있다. 무수한 오픈소스 커뮤니티에서 더욱 향상시키기 위한 도움을 주고 있으며 개인적으로 획득한 경험을 반영하고 있다.


Architecture benefits of Spring


스펙 정의서를 다운로드 받기전에 우선 스프링이 프로젝트에서 가져오게되는 이점에 대해서 살펴보자

  • 스프링은 효과적으로 미들티어 객체를 조직화 할 수 있다. 스프링은 알려진 J2EE API들을 스트럿츠나 다른 프레임워크에 맞물려 돌아가는 시스템을 구성하고자 할때 수도관을 관리하듯이 도움을 줄 수 있다. 그리고 스프링의 configuration management service는 어떠한 아키텍쳐리에어에서든 어떠한 실행환경에서든 사용할 수 있도록 한다.
  • 스프링은 많은 프로젝트에서 보여주는 싱글톤의 증식을 막아준다. 내 경험상 이것은 매우 중요한 문제이다. 이것은 객체지향의 테스트 능력을 줄이는 역할을 하기 때문이다.
  • 스프링은 사용자가 필요로 하는 다양한 프로퍼티 파일 포맷을 줄여준다. 애플리케이션이나 프로젝트를 통해서 일관성 있는 수동설정을 도와준다. 혹시 javadoc 문서를 읽거나 소스코드를 보고 특정 클래스에서 시스템 프로퍼티를 찾거나 매직 프로퍼티 키에 대해서 고민해 본적이 있는가? 스프링은 클래스의 자바빈 프로퍼니 혹은 생성자 아규먼트를 손쉽게 찾아 볼 수 있도록 한다. Inversion of Control과 Dependency Injection을 이용하여 이러한 것을 단순하게 얻을 수 있도록 해준다.
  • 스프링의 기능은 좋은 프로그래밍 습관을 장려한다. 클래스보다 인터페이스 프로그래밍을 통해 개발 비용을 줄여준다. 거의 제로에 가깝다.
  • 스프링은 가능한한 작은 API를 이용하여 애플리케이션을 개발 할수 있도록 디자인되었다. 대부분의 비즈니스 객체는 스프링 애플리케이션에서 어떠한 의존성도 없이 구현된다.
  • 스프링을 이용하여 개발된 애플리케이션은 테스트가 매우 용이하다. 어떠한 유닛테스트 시나리오를 위해서 스프링 프레임워크는 mock 객체와 테스트 지원 클래스를 제공한다. 스프링은 또한 유니크한 "integration testing"기능을 스프링 TestContext 프레임워크나 기존의 JUnit 3.8 지원 클래스를 제공하여 당신이 쉽고 빠르게 코드를 테스트 할 수 있고, 데이터베이스 엑세스 를 수행하는 경우에도 테스트를 진행할 수 있도록 한다.
  • 스프링은 가능하면 인프라 스트럭쳐를 가장 lightweight한 상황에서 문제를 해결할 수 있도록 도움을 준다. 스프링은 EJB와 다르게 많은 애플리케이션에 적합한 기능을 제공한다. 예를 들어 스프링은 AOP를 이용하여 EJB 컨테이너 사용없이 트랜잭션 관리를 할 수 있도록 한다. 또한 당신이 단일 데이터베이스 작업을 원하는 경우 혹은 2 phase commit를 원하지 않은경우에 JTA구현 없이도 가능하다.
  • 스프링은 데이터 엑세스를 위해 일관성 있는 프레임워크를 제공한다. JDBC를 이용하거나 Toplink, Hibernate, JPA, JDO implementation과 같은 O/R mapping을 사용한다 하더라도 말이다.
  • 스프링은 일관성 있고, 단순한 프로그래밍 모델을 다양한 영역에서 지원하며 아키텍쳐 개념을 "glue"하게 만들었다. 당신은 이러한 스프링이 JDBC, JMS, JavaMail, JNDI와 다른 많은 API에서 일관성을 보여줄 것이다.

스프링은 근본적으로 POJO(Plain Old Java Objects)를 이용하여 애플리케이션을 구현가능하도록 되어 있다. 그것은 당신의 비즈니스 로직에만 포함된 POJO를 컴포넌트화 할 수 있게 하며 엔터프라이즈 애플리케이션에서 필요로 하는 많은 값을 다룰 수 있는 프레임워크가 된다. 비록 당신이 애플리케이션의 작성자를 초기에 고려하지 않고 있는 상황에서도 말이다. 이것의 목적은 상세한 프레임워크를 요구하는 것이으로 복잡한 개발을 감추어준다. 때문에 당신의 비즈니스 로직은 추상화되어 인프라스트럭쳐에 관련되게 된다. 그것은 또한 삶을 더욱 길고 즐겁게 만들어 준다. 즉, 코드를 작성하는 투자에 비해 결과를 향상시켜주기 때문이다. 당신의 비즈니스에 차지하는 비즈니스 로직은 변화된다. 이러한 추상화만을 이용해서라도 인프라스트럭쳐에 관련된 당신의 코드가 인프라 스트럭쳐의 변화에 의해서 반드시 변경되어야 하는 사항을 최소화 시켜주게 된다.


그러므로 스프링은 가장 단순하면서도 당신의 문제점을 가능하면 줄여줄수 있게 된다. 그러므로 충분히 해볼만한 것이다.


What does Spring do?


스프링이 제공하는 많은 기능들. 그것들에 대해서 주요한 부분에 대해서 간단하게 살펴볼 것이다.


Mission statement

스프링의 주요한 이점은 엔터프라이즈 자바를 쉽게 이용하고 좋은 프로그래밍 습관을 만들어준다. 그것은 POJO베이스 프로그래밍 모델에 의해서 가능하며 광범위한 환경에서 적용될 수 있다. 우리는 현대 엔터프라이즈 자바를 위한 최종 프로그래밍 모델이라고 믿고 있다.

스프링은 바퀴를 다시 만드는 작업(reinvent the wheel)을 하지 않는다. 그러므로 당신은 더이상 스프링에서 로깅 패키지, 커넥션풀, 분산트랜잭션 관리자와 같은 것을 만들 필요가 없다. 이러한 모든 것들은 오픈소스 프로젝트(Commons Logging과 같이 로그를 출력하는것이나 Commons DBCP와 같은것들)을 당신의 애플리케이션 서버나 컨테이너에서 찾을 필요가 없다. 동일한 이유에서 O/R mapping레이어도 우리는 필요하지 않다. 그냥 좋은 솔루션 TopLink, Hibernate, JPA, JDO와 같은 것을 이용하면 된다.

스프링은 기존에 존재하는 기술을 쉽게 사용할 수 있도록 하며, 단순하고 강력한 프로그래밍 모델이다. 예를 들어 비록 우리가 비즈니스 모델에 하위레벨의 트랜잭션 협조가 없더라도 우리는 JTA혹은 다른 트랜젝션 전략 레이어 상위의 추상화를 제공하고있으며 이것은 더욱 포터블하고 코드를 쉽게 만들며, 테스트를 용이하게 만들어 주는 부분이 된다.

스프링의 이점은 내부적인 일관성에서 나온다. 모든 개발자들은 동일한 허밍시트로 노래를 부르면 된다. 누군가가 기초적인 개념에 대해 충분히 알고 싶다면 Expert One-on-One J2EE Design and Development를 확인하면 된다. 그리고 우리는 Inversion of Control과 같은 중심 개념에 대해 이야기한 적이 있다.

스프링은 애플리케이션 서버와 웹 컨테이너사이에 포터블을 제공한다. (사실, 이러한 핵심기능은 다른 컨테이너에서는 요구되지 않은 것이다.) 물론 포터블리티를 제공하는 것은 언제나 도전이다. 그러나 우리는 웹로직, 톰캣, 레진, JBoss Jetty, Geronimo, WebSphere 그리고 어떠한 다른 애플리케이션 서버에서든 지원하도록 하고, 개발자의 관점에서 비 표준적인것과 플랫폼에 특정적인 부분을 피할것이다. 스프링의 비 침략적(non-invasive)는 POJO적 접근은 포터빌리티에 어떠한 희생도 없이 개발 환경에 있어 다양한 어드베티지를 제공한다.


Inversion of control container

스프링의 코어는 org.springframework.beans 패키지에 있다. POJO와 함께 동작하도록 디자인 되어 있다. 이 패키지는 일반적으로 사용자에 의해서 직접적으로 사용 되어지지는 않는다. 그러나, 더 많은 스프링의 기능에 대한 기반이 된다.

다음 조금더 상위의 추상화는 bean factory이다. 스프링 빈 팩토리는 이름에 의해 설정된 객체를 검색 가능하게 하는 일반적인 팩토리이며, 객체간의 관계성을 관리해준다.

"bean"이라는 단어는 스프링의 초기 버젼에서 JavaBean 객체를 설정하기위한 의도로 만들어 졌다. 1.0 이후로 스프링은 어떠한 Java 객체든지 점근가능하고 변경가능한 메소드를 설정하기 위해 사용되었다. 그리고 2.5에서는 더욱 유연하게 만들어 졌다. 그러나 "Spring Bean"이라는 용어는 여전히 공통의 용어로 남아있다. "Spring-managed object"는 더욱 정확한 용어다. 단지 객체설정만을 하기위한 것이 아니다. 실행환경에서 연속적으로 관리할 수 있는 것이다. 일예로, 매 호출마다 엔터프라이즈 서비스에 적용된다.


빈 팩토리는 3개의 객체 라이프 사이클을 지원한다.

  • Singleton : 이 케이스는 하나의 공유 인스턴스를 잘 알려진 이름으로 가지고 lookup방식으로 검색할 수 있게 된다. 이것은 기본적인 방법으로 상태를 가지지 않는 서비스 객체를 지원하기 위해 종종 사용되는 모드이다.
  • Prototype 혹은 non-singleton : 이 케이스는 매번 독립적인 객체를 생성하는 방식이다. 예를 들어 이것은 각 호출자에게 매번 구별되는 객체 래퍼런스를 가지도록 허용하는 방법이다.
  • Custom object “scopes”, which typically interact with a store outside the control of the container. Some of these come out of the box, such as request and session (for web applications). Others come with third party products, such as clustered caches. It is easy to define custom scopes in the event that none of those provided out of the box is sufficient, through implementing a simple interface. 

스프링은 객체 사이에 관계에 대해 관리하는 컨테이너이기 때문에, POJO관리를 위한 투명한 풀링 서비스, 핫 스와핑의 지원, 호출자에게 영향을 주거나 쓰레드 안정성의 손실 없이 허용하는 타겟의 참조를 간접적으로 실행시간에 스왑할 수 있어 그 가치를 더해준다. Defendency Injection(짧게 논의했던)의 매력중의 하나는 이러한 투명성이 API의 추가 없이 가능하다는 것이다.


org.springframework.beans.factory.BeanFactory은 단순한 인터페이스이다. 이것은 다른 방법으로 구현된 것이라도 상관없다. BeanDefinitionReader 인터페이스는 BeanFactory 그 자체를 구현하기 위한 서로 분산된 메타데이터 포맷을 지원하는 인터페이스이다. 그러므로 일반적인 BeanFactory 구현은 스프링에 서로다른 메타디에터 타입을 이용할 수 있도록 지원해준다. 당신은 단순하게 BeanFactory 혹은 BeanDefinitionReader을 쉽게 구현할 수 있으며, 필요에 의해서 찾아쓸수 있다. 가장 공통적으로 BeanFactory 정의는 다음과 같다.

  • XmlBeanFactory. 이것은 단순하게 파싱된다. 직관적인 XML구조로 정의되어 클래스의 정의와 객체 이름을 프로퍼티로 지정하는 것이 가능하다.
  • DefaultListableBeanFactory: 이것은 프로퍼티 파일들에서 정의된 것을 파싱하고, 프로그램적으로 BeanFactories 를 생성한다.

각 빈의 정의는 POJO(클래스 이름에 의해 정의되거나 프로퍼티에 의해 초기화 혹은 생성자 아규먼트에 의해서 생성된 JavaBean) 혹은 FactoryBean일 수 있다. FactoryBean 인터페이스는 간접적인 레벨로 추가된다. 보통 AOP를 이용하여 프록시를 생성할때나 다른 접근에 유용하다. 예를 들어 프록시는 트랜잭션 관리에 대한 선언을 추가할 수 있다. 이러한 개념은 EJB의 인터셉터와 유사하다. 그러나 실제로는 더욱 간단하고 더욱 강력하다.


BeanFactories 는 계층적으로 부분화 되어 있다. 그들의 부모에서 정의한 내용을 상속받을 수 있다. 이것은 전체 어플리케이션을 통틀어 공통적인 설정을 공유할 수 있도록 하고 있다. 또한 컨트롤러 서블릿과 같은 개인적인 리소스에 독립적인 객체 셋을 가지고 있다고 하더라도 이러한 계층을 상속받을 수 있다. 이러한 JavaBean의 사용에 대한 모티브에 대해서는 Expert One-on-One J2EE Design and Development의 4장에 기술되어 있으며 서버사이드에서 PDF로 공유되어 있다.


이러한 빈 팩토리의 개념을 통해서 스프링은 Inversion of Control 컨테이너라 할 수 있다. (난 컨테이너라는 단러를 상당히 싫어한다. 이것은 EJB와 같은 무거운 컨테이너를 마법의 비젼처럼 보이게 한다. 스프링 빈 팩토리는 한줄의 코드로 어떠한 특정 디플로이 과정없이 생성가능한 컨테이너이다.)

스프링은 Dependency Injection로 알려진 Inversion of Control의 향을 풍긴다. - 이 이름은 마틴파울러와 로드존선 그리고 피코컨테이너 팀이 2003년 말에 만들어낸 단어이다.


Inversion of Control의 개념은 종종 Hollywood Principle라고 표혀된다. "Don't call me, I'll call you" IoC는 발생되는 책임을 프레임워크로 넘긴다. 그리고 애플리케이션 코드에서 떨어져 있다. 당신의 코드가 클래스 라이브러리 어디에 존재하든 IoC 프레임워크는 당신의 코드를 호출한다. 많은 API에서 라이프사이클 콜백을 수행한다. EJB의 세션을 위해 setSessioncontext 메소드와 같이 이러한 접근을 보여준다.


Depencendy Injection은 IoC로 부터 나왔다. 컨테이너 API에 의존된 것을 명시적으로 제거하였다. 일반적인 Java 메소드는 의존성을 collaboration objects 혹은 configuraton value을 애플리케이션 객체 인스턴스에 입력하는 것과 같이 주입한다. 이러한 설정은 EJB와 같이 전통적인 컨테이너 아키텍쳐와 연관되어 있다. 콤퍼넌트는 아마도 "객체 X가 어디있는가 내 일을 위해서 필요해"라며 컨테이너에게 말할것이다. 그럼 Dependency Injection 컨테이너 에의해서 실행 시간에 필요한 X객체를 반환한다. 컨테이너는 이러한 기본적인 메소드 시그너쳐(보통 프로퍼티나 생성자를 이용한다.)를 기반으로 해서 객체를 생성한다. 이러한 것은 XML과 같은 속성을 통해 이용가능하다.


Dependency Injection의 2가지 주요한 묘미는 Setter Injecton(자바 빈의 setter메소드를 이용)을 이용하는 것과 Contructor Injection(생성자 아규먼트 이용)이 있다. 스프링은 두가지를 모두 세세하게 지원하고 있다. 그리고 하나의 객체에 2가지 설정을 모두 지원 할수 있는 복합적인 방법또한 제공한다.


Dependency Injection은 가능하면 모든 형태를 지원할려고 한다. 스프링은 콜백 이벤트의 영역을 지원하며 전통적인 룩업 방식의 API를 필요하면 언제든지 이용할 수있다. 어쨌든 우리는 순수한 Depencency Injection 접근에 대해서 추천하고 있다.


Depencendy Injection 은 중요한 이점이 있다. 예를 들면 :

  • 실행시간에 컴포넌트는 룩업을 필요로 하지 않기 때문에 더욱 작성과 관리가 용이하다. 스프링의 IoC에서 setter 메소드를 이용하거나 생성자 아규먼트를 이용하여 그들의 의존성을 표현하고 있다. 예를 들어 환경 설정파일을 읽을 수 있도록 코드를 작성하여, JNDI룩업이 필요하지 않다.
  • 동일한 이유로 테스트가 매우 편리하다. 자바 프로퍼티는 매우 단순하다. 핵심 자바와 쉬운 테스트 : JUnit와 TextNG테스트 메소드를 가지고 있는 코드를 작성하여 객체와 셋과의 연관관계를 생성할 수 있도록 되어 있다.
  • 좋은 IoC 구현은 강력한 타입으로 구성되어 있다. 만약 일반적은 factory를 이용하여 look up을 수행하고자 한다면 요구되는 타입으로 반드시 변경해 주어야 한다. 이것은 중요한 문제는 아니지만 세련되지 못한 부분이 있다. IoC에서서는 타입에 상당히 독립적으로 구성되며, 프레임워크가 클래스 타입 변환을 수행해준다. 이 의미는 타입이 맞지 않은경우 프레임워크 설정에 따라 에러 코드가 나타나게된다. 그러므로 코드에서 타입 변환에 대해서 걱정할 필요가 없다.
  • 의존성은 명시적이다. 예를 들어 애플리케이션이 프로퍼티 파일을 로드할려고 하는 경우 혹은 데이터베이스 인스턴스에 연결하려 한다면 코드를 읽어보지 않으면 명확하게 나타나지 안는다. (테스트를 어렵게 만들고 배포에 대한 유용성도 떨어진다.). Dependency Injection 접근에서 dependencies는 명시적이며, 생성자 혹은 빈의 프로퍼티에 대한 증거를 제시하는 것이다.
  • 대부분 비즈니스 객체에서 IoC 컨테이너 API는 의존되어 있지 않다. 이것은 기존 코드를 이용하기 쉽게 하고, 태부 혹은 외부의 IoC컨테이너에 객체를 사용하기 쉽게한다. 예를 들어 스프링 사용자는 Jakarta Commons DBCP 데이터소스 설정을 수행한다. 거기에는 어떠한 커스텀 코드도 필요하지 않다. 우리는 이러한 IoC컨테이너를 비침략적이라 부른다. 이것은 다신의 코드가 그 API에 의존되지 않게 만드는 것이다. 대부분의 POJO는 스프링 빈에서 컴포넌트가 된다. 존재하는 자바 빈이나 다양한 아규먼트 생성자를 가진 객체는 개별적으로 잘 동작한다. 그러나 스프링은 정적 펙토리 메소드나 IoC컨트롤러에 의해서 관리되는 특정 객체의 특정 메소드의 유니크한 인스턴스 객체를 제공한다.

이것은 마지막으로 강조하고 싶은 포인트이다. 의존성 주입은 기존의 EJB와 같은 컨테이너 아키텍쳐와는 다르다. 컨테이너상에서 애플리케이션의 의존성은 최소화 한다. 이 의미는 당신의 비즈니스 객체는 잠재적으로 다른 프레임워크에 의존성 주입이 가능하다는 것이다. 아무런 코드 변환도 없이 말이다.


내 경험과 스프링 사용자의 경험에서 IoC의 이상 강조하기는 어려울 것이다.


스프링 빈 팩토리는 매우 경량이다. 사용자는 애플릿 내부에서 스탠드얼론 스윙 애플리케이션에서 성공적으로 사용한 경험이 있을 것이다. 거기에는 특별한 개발 과정이 없다. 또한 같이 연동될 적절한 시간이라는 것이 없다. (비록 어떤 객체는 초기화 시간이 필요한 것도 있지만). 이러한 능력은 대부분의 애플리케이션을 생성하고 초기화 하는데 매우 다양화 할 수 있다.


스프링 빈 팩토리 개념은 스프링을 통해 사용되었다. 그리고 스프링의 키가 된 것은 내부적으로 일관적으로 이용한다는 것이다. 스프링은 또한 프레임워크 전체 기능을 통틀어 기본 개념으로 사용되어있는 유일한 IoC컨테이너이다.


애플리케이션 개발을 위한 가장 중요한 점은 하나 혹은 더 이상의 빈 팩토리가 비즈니스 객체의 레이어에 잘 정의되어 제공되는 것이다. 이것은 로컬 세션 빈과 유사하면서도 더욱 강력하다. 잘 정의된 브즈니스 레이어는 성공적인 아키텍쳐의 가장 중요한 부분이다.


스프링 ApplicationContext는 빈 팩토리의 하위 인터페이스이이며 다음과 같은 것을 제공한다.

  • 메시지 룩업, 국제화 지원
  • 이벤트 메커니즘, 애플리케이션 객체를 출판하거나 선택적으로 이벤트 공지를 등록하는 기능
  • 특정 애플리케이션 스펙이나 컨테이너 행동에 대해서 커스터마이즈된 일반적인 빈의 정의
  • 유동적인 파일과 리소스 접근