리소스 필터링이 리소스 파일의 내용을 변경하는 것이라면, 리소스 교체는 원본 리소스 파일을 환경에 적합한 다른 리소스 파일로 교체하는 것입니다. 
예를 들어 개발서버 환경에서는 로컬PC 환경과 다른 설정값을 갖는 web.xml 파일이 사용되어야 한다면, 개발서버 환경용 web.xml.dev 파일을 만들고 개발 빌드시에 web.xml.dev => web.xml 식으로 파일 자체를 바꾸는 것입니다.
 
Ant에서 리소스 파일교체는 다음처럼 처리할 수 있습니다.

<copy todir="'target/webapp/WEB-INF" overwrite="true" preservelastmodified="true" verbose="true">
     <fileset dir="'target/webapp/WEB-INF" includes="**/*.dev" />
     <mapper type="glob" from="*.dev" to="*" />
</copy>


Buildr에서는 이렇게 처리할 수 있습니다. 

FileList['target/webapp/WEB-INF/**/*.dev'].each do |file|
    cp file, file.pathmap('%X'), :preserve=>true, :verbose => true
end

*.dev 파일을 골라내기 위해 FileList[glob패턴]을 사용했고, 각 파일들을 순회하면서 이름을 바꿔서 복사합니다.
여기서 pathmap이라는 메소드가 보이는데요, rake에서 String 클래스을 상속하여 추가한 메소드입니다.
pathmap이 받는 패턴 중에서 %X는 파일전체 패스에서 파일 확장자를 제외한 나머지 문자열을 리턴합니다. 'aa/bb.xml.dev'.pathmap('%X')는 'aa/bb.xml'을 리턴하죠.

'Build&Deploy > Buildr' 카테고리의 다른 글

Buildr : 아티팩트 다운로드 받기  (0) 2008.12.17
Buildr : 타스크 의존 관계  (0) 2008.12.11
Buildr : 리소스 필터링  (0) 2008.12.09
Buildr : 파일집합 복사하기  (0) 2008.12.05
Buildr : 파일 집합 선택  (0) 2008.12.01
Posted by 에코지오
,
리소스 설정치환은 리소스 필터링과 리소스 교체로 나눌 수 있습니다. 이 중에서 리소스 필터링은 원본 리소스 파일을 타겟으로 복사하면서 파일 내의 특정 부분을 다른 문자열로 치환하는 방법입니다. Ant, Maven, Buildr에서 이것을 어떻게 처리하는지 살펴봅니다.

1. Ant는 copy 타스크 내부에서 filter 요소를 사용하여 리소스 필터링을 지원합니다. 보통 @토큰@ 형식으로 표현된 내용이 다른 값으로 치환됩니다.

<copy file="${build.dir}/version.txt" toFile="${dist.dir}/version.txt">
  <filterset>
    <filter token="DATE" value="${TODAY}"/>
    <filtersfile file="${user.dir}/dist.properties"/> <!-- 이름/값 쌍을 프로퍼티 파일로 제공 -->
  </filterset>
</copy>

2. Maven에서는 process-resources 단계(또는 'resources:resources' 골)에서 보통 ${프로퍼티} 형식의 문자열이 실제 그 프로퍼티 값으로 바뀝니다.

<resources>
 <resource>
  <directory>src</directory>
  <filtering>true</filtering>
  <excludes>
   <exclude>**/*.java</exclude>
  </excludes>
 </resource>
</resources>

프로퍼티는 여러방식으로 제공됩니다. (1) 메이븐 실행시 -D를 통해서 제공 (2) properties 엘리먼트에 기술 (3) 프로퍼티 파일을 지정 (4) 시스템 프로퍼티. 프로퍼티 파일 형태로 이름/값 쌍을 제공하는 경우 아래처럼 build 밑에 filters 엘리먼트에 파일의 위치를 기술하면 됩니다.

<build>
  <defaultGoal>install</defaultGoal>
  <directory>${basedir}/target</directory>
  <finalName>${artifactId}-${version}</finalName>
  <filters>
     <filter>filters/filter1.properties</filter>
  </filters>
  ...
</build>


3. Buildr의 리소스 필터링은 메이븐과 유사합니다. Buildr에서는 resources 타스크를 통해 리소스의 내용을 필터링합니다. 기본적으로 src/main/resources 디렉토리의 리소스 파일들을 target/resources 디렉토리로 복사하면서 필터링을 수행합니다.

resources.from _('src/etc') # 원본 리소스 파일 디렉토리 변경
resources.include '*.html' # 포함할 파일 패턴
resources.exclude 'scratch/*' # 제외할 파일 패턴

resources
.filter.using 'version'=>'experimental''copyright'=>'Acme Inc (C) 2007' # 치환될 내용 매핑

위의 예제에서 리소스 파일내의 ${copyright} 부분은 'Acme Inc (C) 2007'로 바뀌게 됩니다. 이러한 이름/값 매핑은 당연히 외부 파일 형태로도 제공할 수 있습니다만, Buildr에서는 프로퍼티 형식이 아니라 buildr 파일과 동일한 위치에 있는 profiles.yaml 파일을 사용합니다. profiles.yaml 파일은 서로다른 환경에서 서로다른 설정을 가져가기 위한 것인데요(메이븐의 그것과 똑같은 개념입니다), 여기에 filter 엘리먼트를 추가하면 됩니다.

filter: &alpha1
  version: experimental
  copyright: Acme Inc (C) 2007
 
development:
  filter: *alpha1
test:
  filter: *alpha1

resources 타스크는 compile 타스크 실행시 자동으로 함께 수행됩니다. 아래처럼하면 단독으로 실행됩니다.

buildr 프로젝트이름:resources

그런데 이 리소스 필터링 기능이 resources 타스크가 실행될 때뿐 아니라 빌드의 다른 곳에서도 필요한 경우가 있습니다. 이때는 resources 타스크가 내부적으로 이용하고 있는 filter를 사용하면 됩니다.

filter('src/specs').into('target/specs').
  using('version'=>version, 'created'=>Time.now).run

'Build&Deploy > Buildr' 카테고리의 다른 글

Buildr : 타스크 의존 관계  (0) 2008.12.11
Buildr : 리소스 교체  (3) 2008.12.09
Buildr : 파일집합 복사하기  (0) 2008.12.05
Buildr : 파일 집합 선택  (0) 2008.12.01
Buildr : 의존성(dependencies) 설정하기  (4) 2008.11.19
Posted by 에코지오
,

이전 글에서 리소스 설정치환 방법에 대해 얘기했습니다. 그럼 메이븐 환경에서 리소스 설정치환 작업은 어떤 phase에서, 어떤 리소스를 대상으로 이루어져야 할까요?

1. 클래스패스에 포함되는 리소스

(1) 리소스 필터링 방식
메이븐이 process-resource 단계에서 타겟 디렉토리로 복사된 리소스를 대상으로 필터링을 해줍니다. 이때 원본 리소스는 변경이 없습니다. 그러니까 /src/jdbc.properties 파일에 password=${jdbc.password} 처럼값을 설정해놓으면 /target/classes/jdbc.properties 파일에는 그 부분이 password=my_password 식으로 바뀌어 있다는 말입니다.

(2) 리소스 교체 방식
타겟 디렉토리에 복사된 리소스 파일에 대해서 교체 처리해줍니다. 어차피 process-resource 단계에서는 resources:resources 골이 가장 먼저 실행되기 때문에 교체 작업(ant의 copy 타스크 이용)은 그냥 process-resources 단계에 바인딩하면 됩니다. 역시 원본 리소스 파일은 변경이 없습니다. 예를 들어 /src 밑의 jdbc.properties와 jdbc.properties.dev가 /target/classes 밑에 복사된 후 /target/classes/jdbc.properties.dev 파일이 /target/classes/jdbc.properties 파일을 덮어쓰게 됩니다.

 

2. WEB-INF 밑에 있는 리소스(web.xml, struts-config.xml, applicationContext.xml 등등)

WEB-INF 밑의 리소스에 대한 설정치환은 좀 지저분합니다. 
메이븐은 package 단계에서 war:war를 실행하는데, war:war는 무조건 war:exploded 를 먼저 실행하고 나서 exploded된 웹어플리케이션을 war 파일로 묶어냅니다. 우리가 원하는 것은 exploded 된 웹어플리케이션의 리소스 파일에 대해 리소스설정치환 작업을 하고나서 war 파일로 패키징하는 것인데, 중간에 끼어들 여지가 원천 봉쇄된 것입니다.

뭐 package 단계나 war:war를 실행하지 않으면 되긴합니다. war:exploded를 명시적으로 실행한 뒤에 설정치환을 하면 됩니다. 그런데 설정치환하는 execution을 어느 phase에 바인딩하는게 좋을지... 하여간 원본 리소스 파일을 건드리지 않은 상태로 리소스 치환을 하려니 지저분해지는군요.

만약 원본 리소스를 건드려도 무방하다면 package 전 단계(prepare-package 단계는 maven 2.1부터 지원하기 때문에 2.1 이전 버전이라면 process-resources 단계가 괜찮을까요)에서 원본 리소스를 대상으로 설정치환 작업을 처리하면 됩니다. 
Posted by 에코지오
,

우리가 개발하는 어플리케이션은 최종 사용자에게 서비스되기 전에 여러 장소를 거칩니다.

개발자 로컬PC -> (소스저장소) -> 빌드서버(CI서버) -> 개발서버 -> 테스트서버 -> 스테이징서버 -> 운영서버

불행히도 이렇게 거쳐가는 서버에 따라서 환경/정책이 조금씩 다르기 때문에 우리는 개발소스에 포함된 설정값을 다르게 가져가야 합니다. 예전에는 소스가 서버 사이를 옮겨갈 때마다 수작업으로(vi 에디터로) 설정값을 매번 편집을 해주거나, 설정값을 포함한 파일을 빼고(!) 소스를 옮기기도 했습니다. 여러분은 어떤 방법으로 설정값을 다르게 세팅하셨습나요?

여기, 좀더 우아한 방법이 있습니다.

아, 그보다 먼저 설정값을 포함하는 파일을 보통 뭐라고 부르나요? 설정파일 ? 리소스 파일?  뭐라고 부르든 리소스는 주로 xml, properties 로 작성을 하죠. 레일스에서는 yml인가 이런것도 있더군요. 암튼.

그리고 로컬,개발,운영 등 서버의 환경차이에 따라 리소스 파일을 변환하여 개발소스에 포함된 설정을 달리하는 일을 뭐라고 부르나요? 환경맞춤작업? 리소스변환리소스 설정치환? 이런 거에 대한 공식적인 용어를 들은 바가 없어서 일단은 제목에 리소스 설정치환이라고 임의대로 용어를 지었습니다. 혹시 널리 사용되는 용어를 아시는 분은 알려주세요. 언뜻 profile, portable이란 단어가 떠오르기는 합니다만....

아래는 제가 알고 있는 리소스 설정치환 방법 2가지입니다.(리소스 필터링, 리소스 교체 역시 모두 제가 임의로 만든 용어입니다. 더 나은 용어가 있으면 알려주세요.)

1. 리소스 필터링(filtering)
-빌드시에 설정 파일의 내용을 수정하는 방법
-설정값을 하드코딩하지 않고 정해진 형식의 변수로써 설정. 예를 들어 ${jdbc.password}.
-빌드 실행시 설정 파일 내의 변수는 환경에 적합한 설정값으로 치환됨
-환경별 설정값은 빌드스크립트에 보관됨(메이븐의 경우 프로파일 엘리먼트에)

2. 리소스 교체(replacing)
-빌드시에 기준(로컬) 설정 파일을 다른 파일로 교체하는 방법
-설정 파일을 환경별로 분리하여 관리
  (1)환경별로 별도 디렉토리를 만들어 기준 파일과 동일한 파일명으로 관리.
      예를 들어 /web/WEB-INF/web.xml 이 로컬PC용 설정파일이면,
      개발서버용 web.xml은 /conf/dev/web.xml에 두고 관리.
  (2)기준 설정파일과 동일한 경로에, 다른 파일명으로 관리.
      예를 들어 개발서버용 web.xml을 /web/WEB-INF/web.xml.dev 라는 이름으로 관리.
-빌드실행시 환경에 맞는 파일을 골라서 (1)빌드디렉토리로 이동하거나 (2)파일명을 변경하여 기준 설정 파일을 덮어씀

1번 리소스 필터링의 경우 메이븐에서는 Profile 기능과 Resource Filtering 기능을 이용하면 되고, 2번 리소스 교체의 경우 메이븐에서는 Profile 기능과 Ant의 copy 타스크 조합으로 처리할 수 있습니다. 아래는 메이븐에서 2번을 처리한 예제입니다.

... ...
<plugin>
 <artifactId>maven-antrun-plugin</artifactId>
 <executions>
  <execution>
   <id>resource-changing</id>
   <phase>process-resources</phase>
   <goals><goal>run</goal></goals>
   <configuration> <tasks>
          <copy todir="${project.build.outputDirectory}"
                    overwrite="true" preservelastmodified="true" verbose="true">
               <fileset dir="${project.build.outputDirectory}"
                          includes="**/${conf.replace.pattern}" />
                   <mapper type="glob" from="${conf.replace.pattern}" to="*" />
          </copy>
    </tasks></configuration>
  </execution>
...... .......
..... ........
 <profiles>
  <profile>
   <id>env-dev</id>
   <activation>
    <property><name>env</name><value>dev</value></property>
   </activation>
   <properties>
    <conf.replace.pattern>*.dev</conf.replace.pattern>
   </properties>
  </profile>
  <profile>
   <id>env-prod</id>
   <activation>
    <property><name>env</name><value>prod</value></property>
   </activation>
   <properties>
    <conf.replace.pattern>*.prod</conf.replace.pattern>
   </properties>
  </profile>
 </profiles>
Posted by 에코지오
,