Maven 같지 않은 Maven 프로젝트 만들기

사용자 삽입 이미지
위 프로젝트는 일반적인 이클립스의 웹 프로젝트와 다름 없이 src와 test 소스 폴더를 가지고 있고, 웹 폴더도 루트바로 밑에 webapp를 사용하고 있습니다. 하지만, 이 녀석은 메이븐 프로젝트 입니다. 맨 아래에 pom.xml 보이시죠?

사부님이 전에 작성하셨던 메이븐 기본 디렉터리 설정 방법과 Arawn님의 메이븐 웹 폴더 설정 플러긴 사용방법을 조합하면 위와 같은 프로젝트를 만들 수 있습니다.

둘 다 pom.xml의 build 엘리먼트 내부에 적절하게 넣어주면 됩니다.

<build>

        <sourceDirectory>${project.basedir}/src</sourceDirectory>
        <scriptSourceDirectory>
            ${project.basedir}/scripts
        </scriptSourceDirectory>
        <testSourceDirectory>
            ${project.basedir}/test
        </testSourceDirectory>
        <resources>
            <resource>
                <directory>${project.basedir}/src</directory>
                <excludes>
                    <exclude>**/*.java</exclude>
                </excludes>
            </resource>
        </resources>

        <plugins>

            <plugin>
                <artifactId>maven-war-plugin</artifactId>
                <version>2.1-alpha-2</version>
                <configuration>
                    <warSourceDirectory>webapp</warSourceDirectory>
                </configuration>
            </plugin>

        </plugins>
<build>

설정 내용은 엘리먼트 이름을 보면 대충 알 수 있으면 자세한 설명은 사부님과 Arawn님의 블로그에 가셔서 보시면 되겠습니다. ㅋㅋ

AspectJ의 @DeclareError를 사용해서 컴파일 시점에 아키텍처 에러 검증하자.

참조: http://www.parleys.com/display/PARLEYS/Home#slide=1;title=Spring%20Architectures;talk=20676612

위 발표자료 내용 주에 아주 잼나는 코드를 건졌습니다. 지난 번 KSUG에서 발표한 내용과 겹치는데 아래 코드는 그때 제가 보여드린 코드보다 좀 더 좋은 것 같아서 가져왔습니다.

@Aspect
public class SystemArchitecture {
  @Pointcut(“execution(* configurator.*.*(..))”)
  public void configuratorLogic () {}
  @Pointcut(“execution(* dao.*.*(..))”)
  public void dao() {}
  @Pointcut(“within(*.dao.*)”)
  public void inDaoLayer() {}
  @Pointcut(“call(* *.service.*.*(..))”)
  public void callServiceLayer() {}
}
@Aspect
public class Layering {
  @DeclareError(“SystemArchitecture.inDaoLayer() && “+
   “SystemArchitektur.callServiceLayer() “)
  public static final String DAOsNotFromServices =
   “DAO must not call Service!”;
 @DeclareError(” (call(* java.sql.*.*(..)) && ” +
  “!within(*.dao.*) ) “)
  public static final String JdbcOnlyInDAOs =
   “JDBC only in DAOs!”;
}

좋은 건 이Aspectj를 사용하면 @DecalreError를 사용해서, 컴파일 시점에 아키텍처 에러를 검증할 수 있다는 것입니다. 제가 준비했던 코드는 cflow를 사용해서 런타임에 검증하는 방법이었습니다. 따라서 테스트 하지 않고 그냥 커밋하면 뭐 어떻게 찾아낼 방법이 없었습니다. 그런데 이 방법을 쓰면 코딩할 때 문제되는 코드를 발견할 수 있으니 훨씬 좋은 것 같습니다. 캬.. 귿..

Spring Architecture – Eberhard Wolff

참조: http://www.parleys.com/display/PARLEYS/Home#slide=1;title=Spring%20Architectures;talk=20676612

아키텍처

The software architecture of a program or computing system is the structure or structures of the system, which comprise software components, the externally visible properties of those components, and the relationships between them.

Wikipedia

객체: Information hiding

클래스: 객체의 타입을 정의. White box 재사용.

재사용:

A Software Component is a unit of composition with contractually-specified interfaces and explicit  context dependencies only. A software component can be deployed independently and is subject to composition by third parties.

C. Szyperski: Component Software – Beyond Object-
Oriented Programming, Addison-Wesley, 1999

컴포넌트: note the plugability.
– 계약 같은 인터페이스
– Only 명시적인 의존성
– 독립적인 배포
– 컴포지션
– 결과: 간편한 재사용(black box)
– 결과: 간편한 수정(인터페이스는 놔두고 내부만 바꿀 수 있으니.)

객체는 컴포넌트인가?
– 계약 같은 인터페이스? 있네, public 메소드
– 명시적인 의존성? 없네. 코드 내부에서 암거나 만들 수 있으니까.
– 독립적인 배포? 대부분은 안 돼지.
– 컴포지션? No.

DI를 사용하는 객체는 컴포넌트?
– 계약 기반인가? 응
– 명시적인 의존성? 응 설정하자나. setter/constuctor injection,
– 독립적인 배포? Yes. Everything else is injected
– 컴포지션? Yes. DI 컨테이너를 사용해서 조합하니까.

계층
– 각각의 계층은 하위 계층에만 의존해. -> 더 나은 의존성 관리(계층을 쉽게 바꿀 수 있으니까..)
– Typical technical
– 퍼사드를 사용할 수 있음.

스프링을 사용하는 컴포넌트
– 스프링 설정 파일을 각각의 컴포넌트 별로 만든다.
– 추가적인 기반 설정 파일은 javase.xml로..
– Facade를 인터페이스로 추가하고, bean 설정 파일에서 의존성을 정의한다.
– 각각의 컴포넌트는 JAR 파일로.
– 자신만의 빌드 스크립트를 가지고 있고
– 그들 컴포넌트를 묶을 때는 classpath*을 사용한다.

ApplicationContext applicationContext =
 new ClassPathXmlApplicationContext(
  “classpath*:/config/applicationContext.xml”);

스프링 설정 파일 + Facade 사용했을 때 컴포넌트 체크 리스트
– Contractually-specific 인터페이스? Yes. Facade 사용했으니까.
– Only explicit context depedencies? No. 스프링 빈 의존성이 명시적이지 않을 수도 있다.
– 독립적인 배포 가능? Yes. 설정 파일 + 참조하는 클래스
– A way of composition? Yes. 스프링 DI.

계층은 어떤가?
– ApplicationContext 계층 구조를 사용해서 구현했다.
– DispatcherServlet과 ApplicationContext 같은 예.
– 예제 코드

ApplicationContext environmentApplicationContext =
 new ClassPathXmlApplicationContext(
  “javase.xml”);

ApplicationContext persistenceApplicationContext =
 new ClassPathXmlApplicationContext(
  new String[] { “classpath*:*-persistence.xml” },
 environmentApplicationContext);

ApplicationContext logicApplicationContext =
 new ClassPathXmlApplicationContext(
  new String[] { “classpath*:*-logic.xml” },
  persistenceApplicationContext);

ApplicationContext guiApplicationContext =
 new ClassPathXmlApplicationContext(
  new String[] { “classpath*:*-gui.xml” },
  logicApplicationContext);

Vertical Slices.
– 예제 코드

ApplicationContext environmentApplicationContext =
 new ClassPathXmlApplicationContext(“javase.xml”);

ApplicationContext catalogApplicationContext =
 new ClassPathXmlApplicationContext(
  new String[] { “classpath*:/catalog-*.xml”},
 environmentApplicationContext);

ApplicationContext configuratorApplicationContext =
 new ClassPathXmlApplicationContext(
  new String[] { “classpath*:/configurator-*.xml” },
 catalogApplicationContext);

ApplicationContext trackingApplicationContext =
 new ClassPathXmlApplicationContext(
  new String[] { “classpath*:/tracking-*.xml”},
configuratorApplicationContext);

이후 발표는…
– 스프링 JavaConfig를 사용해서 스프링을 사용해서 컴포넌트 설정 예제
– 스프링 DM을 사용하여 컴포넌트 개발 예제
가 이어집니다.