이 장에서는 Tigris.org에서 제공하는 SVNANT를 이용하여 Apache ANT 내에서 SVN을 관리하는 방법에 대해 다루어보도록 하겠습니다.


이 글은 Apache ANT와 SVN를 이해하고 사용할 수 있다는 전제 하에 작성되었습니다. Apache ANTSVN(혹은 SCM)에 대해 잘 모르시는 분들은 필요한 그 각각에 대한 내용를 먼저 숙지하시기 바랍니다.

SVNANT를 이용하기 위해서는 JSDK와 ANT가 각각 설치되어 있어야 합니다.


지금이 때가 어느 때인데, Maven이 대세(?)인 이 시대에 먼 ANT냐, 그리고 Maven에도 SCM Plugin이 있으니 ANT는 필요 없다...라고 하실 수 있습니다만, 여전히 ANT를 이용하여 빌드자동화 및 배포자동화를 수행하는 프로젝트가 적지 않은데, 거기에는 몇 가지 이유가 있습니다. 여전히 Maven을 숙달하지 못한 개발자들이 많다는 것과 기존 프로젝트를 리뉴얼하는 경우 Maven을 적용하기 어렵다는 것이 가장 큰 이유가 될 것입니다. 그리고 더불어, 이클립스 Maven 플러그인의 간헐적인 오작동, 사내 Maven Repository 설치 곤란과 그로 인한 속도저하 등등의 기술적인 문제도 Maven의 선택을 막는 데에 일조하고 있습니다.


자 이제 시작해볼까요.


목차

  1. Download and Installation
  2. SVNANT Configuration
  3. SVNANT Tasks
    1. checkout
    2. copy
    3. diffSummarize
    4. update
  4. Conclusion


1. Download and Installation

SVNANT는 [여기]에서 다운로드 받으실 수 있습니다. 이 글을 쓰고 있는 시점에 배포되어 있는 SVNANT는 버전 1.3.1 입니다.

다운로드 완료 후 압축을 해제하면 다음과 같은 디렉토리 구조를 확인할 수 있습니다.

이제 lib 디렉토리 내에 있는 모든 jar 파일들을 $ANT_HOME/lib 디렉토리에 복사합니다. 이렇게 복사하는 것만으로 SVNANT에 대한 설치가 완료됩니다.


2. SVN ANT Configuration

SVNANT는 당연히 ANT 스크립트 내에서 실행됩니다. 하지만 SVNANT의 Task들은 ANT의 기본 Task가 아니므로 이를 사용하기 위해 별도의 설정이 필요합니다. 다음과 같이 말이죠. 

<?xml version="1.0" encoding="utf-8"?>
<project name="svn-info" basedir=".">
	<property file="build.properties"/> <!-- 설정파일로 build.properties 사용 -->
		
	<path id="ant.classpath"> <!-- SVNANT를 위한 추가 클래스패스 설정 -->
            <fileset dir="${ant.lib.dir}">
                <include name="**/*.jar"/>
            </fileset>
        </path>
	    
	<taskdef classpathref="ant.classpath" resource="net/sf/antcontrib/antlib.xml"/> <!-- ant-contrib task 설정 파일 -->
	<taskdef classpathref="ant.classpath" resource="org/tigris/subversion/svnant/svnantlib.xml"/> <!-- SVNANT task 설정 파일 -->
	
	<svnSetting
		id="svn.settings"
		username="${svn.user.id}"
	        password="${svn.user.pw}"
		svnkit="true"
		javahl="false"/> <!-- SVNANT 사용을 위한 svnSetting 정보 -->
</project>

이 ANT Script는 build.properties 파일을 사용하고 있습니다. 위에서 사용한 대부분의 변수들, 즉 ${ant.lib.dir}이나 ${svn.user.id} 등은 모두 build.properties 파일 내에 정의되어 있습니다.


예전 버전에서는 <svn> 태그 내에 SVN에 대한 설정 정보(username, password 등)들을 입력하였습니다. 하지만 1.3.0 버전 이후로는 <svnSetting> 태그를 이용하여 SVN 설정 정보를 처리하도록 변경되었습니다. 추후 <svn> 태그에서 이 설정 정보를 이용하게 될 것입니다.


3. SVNANT Tasks

SVNANT의 전체 Task들은 [여기]에서 확인할 수 있습니다. 이 글에서는 자주 사용하는 몇 가지만 다루도록 하겠습니다.


(1) checkout

당연한 얘기지만, 프로젝트 소스를 최초 체크아웃할 때 사용합니다. 참고로 svn checkout과 svn update의 차이는 [여기]서 확인하시기 바랍니다.

<svn refid="svn.settings"> 
	<checkout
		url="${svn.repository.url}/${svn.source.branch.name}/${projectName}" 
		destPath="${source.root.dir}/${projectName}"/> 
</svn>
  • url : 체크아웃 받고자 하는 프로젝트의 Full URL
  • destPath : 체크아웃받은 프로젝트가 저장될 로컬 디렉토리. 반드시 프로젝트 명을 추가해야 프로젝트 내에 파일이 체크아웃된다.

(2) copy
말 그대로 복사하는 기능입니다. 하지만 우리가 일반적으로 생각하는 파일/디렉토리 복사와는 다소 다르게 동작합니다. 자세한 내용은 Copy Documentation을 참고하시기 바랍니다. 아래 예제는 trunk에서 branches로 바로 Merge하는 예제입니다. Merge를 하는 데 Delete를 하는 이유는, SVNANT의 Copy 기능이 overwrite를 지원하지 않기 때문입니다. 묻지도 따지지도 않고 Target을 삭제한 뒤 Copy하는 것이므로 함부로 사용하면 안 됩니다.
	<property name="srcFile" value="x2-spring-core/src/main/java/org/x2framework/spring/X2Constants.java"/>
	
    <!-- File Merge를 수행한다. -->
	<target name="copy-svn-file">
		<propertyregex 
			property="targetDirectory"
			input="${srcFile}"
			regexp="^(.+)/([^/]+)$"
			select="\1"
		/>
		
		<echo message="copy file started : src=[${srcFile}] dest=[${targetDirectory}]"/>
		
        <svn refid="svn.settings">
        	<delete url="${svn.repository.url}/${svn.target.branch.name}/${srcFile}"
        	        force="true"
        	        message="delete file for merging"
        	/>
        </svn>
        <svn refid="svn.settings">
            <copy
            	srcUrl="${svn.repository.url}/${svn.source.branch.name}/${srcFile}"
                revision="${revision}"
            	destUrl="${svn.repository.url}/${svn.target.branch.name}/${targetDirectory}"
            	makeParents="true"
                message="merging from source"/>
        </svn>
        
        <echo message="copy file finished : src=[${srcFile}] dest=[${targetDirectory}]"/>
        
	</target>


(3) diffSummarize

Documentation에는 설명되어 있지 않지만, diff와 동일하게 동작합니다. 차이점이라면 diff는 파일의 내용까지 비교해주는 반면, diffSummarize는 revision 간 변경된 파일 목록만 보여줍니다. 특정 revision에서 배포된 파일 목록만 확인하고 싶다면 diffSummarize를 이용하면 됩니다.

<target name="diff-revision-of-directory">
	<svn refid="svn.settings">
	    <diffSummarize
	    	oldUrl="${svn.repository.url}/${svn.source.branch.name}"
	    	newUrl="${svn.repository.url}/${svn.source.branch.name}"
	    	oldTargetRevision="${oldRevision}"
	    	newTargetRevision="${newRevision}"
	    />
	</svn>
</target>

(4) update

저장소의 내용을 working directory로 갱신할 때 사용합니다. copy와 마찬가지로 revision 값을 이용하여 특정 revision으로 업데이트 할 수 있습니다.

<svn refid="svn.settings">
  <update
    dir="${source.root.dir}/${projectName}"
    recurse="true"/>
</svn>


4. Conclusion

간략하게나마 SVNANT를 이용하여 SVN을 ANT로 제어하는 방법을 살펴보았습니다. 개발/테스트/운영 환경을 위한 브랜치가 따로 있고, 테스트가 완료된 소스만 운영 서버로 merge를 해야 할 때, merge할 목록을 텍스트 파일로 만들고 그 파일을 ANT로 로딩하여 순차적으로 merge를 처리하도록 하면, merge부터 빌드, 배포까지 손쉽게 처리할 수 있습니다.


신고
Posted by Layered 트랙백 0 : 댓글 0

댓글을 달아 주세요