갑작스럽게 시드니 출장을 다녀와야 했던 데다 며칠 전에 도착한 iPad 2 가지고 놀기 바빠서 미뤘던 메이븐 애트리뷰트 적용기 두번째 이야기.

먼저 메이븐 pom.xml에 애트리뷰트를 적용하면 어떤 모습이 되야 할지 생각해봤다. 가장 이상적인 것은 엘리먼트와 애트리뷰트 양쪽을 모두 사용할 수 있는 것이다. 스프링이 그런 식이다. 스프링도 처음에는 XML 설정에 엘리먼트의 사용 비율이 높았다. 예를 들어 값 하나와 빈 레퍼런스 하나를 프로퍼티로 가지는 빈이라면 다음과 같이 작성해야 했다.

<bean id=”hello” class=”Hello”>
  <property name="name">
    <value>ahnpig</value>
  </property>
  <property name="message">
    <ref bean="hellomessage" />
  </property>
</bean>

id, name 등은 애트리뷰트로 설정할 수 있어서 그나마 메이븐의 100% 엘리먼트 방식보다는 낫긴 했지만, 그래도 설정이 많아지고 애플리케이션의 규모가 커지면 XML을 읽고 수정하기가 매우 벅찼던 기억이 있다. 그래서 1.2인가부터 <value>, <ref> 태그 등을 다음과 같이 <property>의 애트리뷰트로도 설정할 수 있게 했다.

<bean id=”hello” class=”Hello”>
  <property name="name" value=”ahnpig” />
  <property name="message" ref=”hellomessage” />
</bean>

덕분에 설정 파일은 훨씬 간결해졌다. 동시에 스프링은 리스트와 같은 콜렉션을 값으로 설정하는 경우나 이전 버전에서 작성된 XML 설정을 그대로 사용할 수 있게 자식 엘리먼트로 <value>, <ref>를 사용하는 것을 동시에 지원했다.

2.0에서는 더 나아가서 p 네임스페이스를 이용해서 아예 모든 property 설정을 <bean> 태그 안으로 다 가져올 수 있도록도 만들었다. 또한 일정 분량의 설정 자체를 모듈화 해서 아예 전용태그로 만들 수 있는 기능도 제공했다.

뭐, 그렇다고 메이븐에서도 네임스페이스를 이용해서 기존 설정을 더 간결하고 의미를 잘 드러낼 수 있는 방식으로 재정의 하는 것까지는 바라지 않는다. 그저 바라기는 일부 설정 단위를 애트리뷰트로 묶어 낼 수 있는 정도이고, 가능하면 기존 pom.xml 설정과 호환성을 유지할 수 있도록 애트리뷰트와 엘리먼트 양쪽으로 다 설정이 가능하도록 만드는 것이다.

 

하지만 막상 메이븐을 열어보니 애트리뷰트와 엘리먼트의 동시 지원 방식은 쉽지 않아보였다.

스프링과 같이 DI 원리를 충실하게 지켜가며 만들어진 프레임워크라면 당연히 정보를 담고 있는 모델과 이 메타 모델을 직렬화해서 저장해둔 설정파일의 형식이나 구조는 서로 결합되지 않고 깔끔하게 분리되는 것이 기본이다.

메이븐도 Plexus라는 IoC/DI 컨테이너를 사용한다. 메이븐 말고 Plexus를 사용하는 제품이 있는지는 모르겠지만, 아무튼 3.0은 Plexus를 이용해서 나름 충실한 DI 스타일의 개발을 했다고 알고 있다. 심지어 3.1에서는 구글주스 DI도 추가적으로 이용할 수 있게 만드는 계획도 있다고 들었다.

메이븐에서 pom.xml의 정보는 Model 오브젝트와 그 계층구조로 표현된다. pom.xml의 루트 엘리먼트인 <project>가 바로 Model 클래스에 매핑된다. 하위 엘리먼트로 정의되지만 사실상 project의 속성에 해당하는 <modelVersion>, <artifactId>, <name> 따위는 Model 클래스가 프로퍼티 값으로 가지고 있다. 반면에 하나 이상의 정보를 가지고 있어야 하는 <developers>나 <contributors>는 List 프로퍼티로 정의되어 있고, 독립적으로 계층 구조를 가지는 <build>, <dependcie>등은 Build, Dependency  정의되어서 Model의 프로퍼티로 등록되어있다.

결국 pom.xml에는 모두 다 엘리먼트로 만들어지지만 값에 해당하는 부분은 Model 클래스 계층구조 안에서는 String, int와 같이 값으로 정의되고, 하위 구조를 가지는 경우에는 Dependency, Plugin 등의 클래스로 표현된다는 것을 알 수 있다. 이렇게 프로퍼티 값으로 정의되는 부분이라면 XML에서 얼마든지 애트리뷰트로 정의해주어도 문제가 없고, 사실 더 자연스럽다.

Model 클래스 계층구조로 추상적인 메타모델을 가지고 있으니, pom.xml과 같은 외부 설정을 읽고 파싱해서 이를 Model로 만들어주는 부분이 독립적이고, 선택가능하다면 얼마든지 애트리뷰트 확장도 가능하고 XML 외의 소스로부터 프로젝트 Model 정보를 읽어드리는 것이 가능할 것 처럼 보인다.

실제로 IoC/DI가 적용된 부분도 인상적이다.

Model 오브젝트로 표현되는 모델 정보는 ModelReader를 통해서 생성된다. DI 원칙에 충실하게 ModelReader는 인터페이스로 정의되어있고, 이를 구현하는 클래스는 얼마든지 새롭게 만들 수 있다. 그리고 어떤 ModelReader 구현을 사용할지는 IoC/DI를 통해서 ModelProcessor의 구현 클래스로 전달되도록 정의되어있다.

메이븐 모델을 담당하는 역할을 맡은 DefaultModelProcessor의 코드는 다음과 같이 정의되어있다.

@Component( role = ModelProcessor.class )
public class DefaultModelProcessor  implements ModelProcessor {
    @Requirement
    private ModelLocator locator;
    @Requirement
    private ModelReader reader;
    …

스프링의 @Component와 @Autowired에 익숙하다면 이 코드가 어떤 의미를 가지는지 이해할 수 있을 것이다. ModelLocator는 모델이 위치한 폴더를 주면 모델 파일을 찾아내는 책임을 정의한 것이다. 기본은 pom.xml 파일을 찾는 것이지만, 꼭 pom.xml 파일일 필요는 없으니 이 책임을 분리하고 DI로 적용할 수 있게 만든 것이다.

ModelReader는 File이나 InputStream으로 모델 정보를 담은 물리적인 파일 정보를 넘기면 Model 오브젝트 계층구조를 리턴하도록 정의된 메소드를 가진 인터페이스다. 스프링의 BeanDefinitionReader와 비슷하다. XmlBeanDefinitionReader를 사용하면 XML에서, PropertiesBeanDefinitionReader를 사용하면 프로퍼티 파일에서 빈 설정을 읽어오는 것처럼 메이븐도 ModelReader를 구현한 PomXmlModelReader를 DI하도록 해주면 pom.xml에서, GroovyModelReader를 주면 Groovy로 작성된 모델정보를 가져올 수 있다는 식이다. 일단 IoC/DI를 적용해 놓아서 일단 이런 가능성은 열어주긴 했지만 아직까지 ModelReader를 구현한 클래스는 pom.xml을 읽는 DefaultModelReader 뿐이다.

어쨌든 ModelReader 구현을 새롭게 만들거나, 기본 DefaultModelReader를 일부 수정해서 애트리뷰트까지 적용가능하도록 만들면 될 것 같다.

그런데 좀 더 코드를 살펴보니 생각보다 쉽지 않겠다는 생각이 들었다. 메이븐 개발자들이 왜 pom.xml에 애트리뷰트를 사용하도록 쉽게 만들지 못하고 있는지도 알게되었다. 그 이유는 다음에.

Related posts:

  1. Maven POM에 attribute 사용하기 (1)
  2. Maven 3.0과 버전 포맷 문제
  3. Nexus Maven Repository 1.0 출시
  4. Maven 의존관계 수렁에 빠지다
  5. Maven 재도전기 (1)
  6. Maven 다중 리포지토리와 버전 범위를 사용할 때의 주의점
  7. Ruby on Maven
  8. Spring 3.0 (34) R-941 스프링의 Maven 지원정책은?
  9. Maven: The Definitive Guide 사라지다
  10. Maven settings.xml의 비밀번호 암호화
  11. Maven의 새로운 가이드북 – Maven: The Definitive Guide
  12. Maven archetype 설정파일 자동생성기 – ArchetypeXmlWriter
  13. SpringDM과 차세대 OSGi
  14. 스프링에서 자신을 DI하는 빈을 정의할 수 있을까?
  15. Spring 3.0 @MVC 메소드에서 자동으로 리턴 모델에 추가되는 것들

Facebook comments:

to “Maven POM에 attribute 사용하기 (2)”

  1. thanks for share!

  2. thank you for share!

Leave a Reply

(required)

(required)

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

© 2017 Toby's Epril Suffusion theme by Sayontan Sinha