svn: Repository moved permanently to 'http://nextreesvn/common/'; please relocate
...
원인
SVN이 WebDAV로 서비스 되고 있고 SVN에서 tagging하기 위해 아파치 웹서버로 "PROPFIND /common HTTP/1.1" 요청을 하면 301을 응답합니다. 브라우저로 확인하거나 이클립스 subversive (subversion 플러그인)으로 별 이상없는데 maven release 플러그인에서 commit은 잘 되는데 svn tag 에서 이런 에러가 발생합니다.
지속적인 통합(Continuous Integration - CI)은 개발프로세스에서 꼭 필요한 최선의 실천 개발방법이다. 이것은 효과적인 소프트웨어 개발 주기에 있어 필수적인 부분이다. 아직 사용하고 있지 않다면 지금 시작해야 한다. 품질관리(QA) 활동동안 테스트 실패와 심각한 에러를 식별하기 위해 여러날 기다리지 한고 시스템으로 에러들을 알려주는 능력이 지속적인 통합의 중요한 능력이다. 이 글은 CI 사용의 가치에 대한 글은 아니다. 이글은 maven 기반에서 선택적인 환경설정을 어떻게 하는가에 대한 글이다. 아래에 Hudson 같은 CI 시스템에서 maven 빌드를 실행하기 위한 7가지 팁이 있다.
#1 Snapshot 배포를 자동화하라
내 경험에 의하면, 개발 snapshot을 CI 시스템이 하도록 하는 것이 최선이다. 이것이 저장소의 내용(JAR, WAR, ...)과 소스 컨트롤 시스템과의 동기화를 보장하는 가장 믿을만한 방법이다. 이렇게 하려면 최선의 방법으로 CI와 함께 snapshot을 자동으로 청소해주는 Nexus같은 저장소 관리자가 필요하다. 한 주내에 300기가 바이트가 넘는 snapshot을 생성하는 프로젝트를 관리해 본 적이 있다. 저장소 관리자를 사용하는 것이 정신건강에 좋을 것이다.
#2 로컬 저장소들을 분리하라
좋은 CI의 설정 중 중요한 것 중 다른 하나는 로컬 저장소를 분리기능이다. Maven의 로컬 저장소는 Maven이 다운로드하거나 생성하는 모든 산출을 보관한는 임시 장소이다. 그리고 이것은 멀티 프로세스에 안전하게 설정되어 있지 않다. 충돌의 가능성은 원격에나 있지 로컬에는 있지 않다.
각 프로젝트마다 로컬 저장소를 갖는 것을 선호하는 주요한 이유는 그 회사 저장소의 빌드결과로 프로젝트 빌드가 가능한가 테스트할 수 있는 유일한 방법이기 때문이다. 만약 로컬 저장소를 분리하지 않는다면 어떤 빌드가 생성한 것을 그것이 그 회사의 저장소가 아닌데도 다른 빌드가 볼 것이다. 실제 배포담당자는 CI 기능을 이용하여 코드가 빌드 가능한지 검증하기 때문에 이것은 매우 중요한 사안이다.
팁: 각 빌드에 유일한 로컬 저장소를 정의하려면 -Dmaven.repo.local=xxxx 를 사용한다.
#3 정기적으로 로컬 저장소를 제거(purge)하라
저장소의 내용을 좀 더 깨끗이(validate)하고 디스크 공간을 관리하기 위해 난 매일 방 로컬 저장소를 제거한다. 저장소가 변경되거나 빌드결과물이 제거되면 CI 시스템이 이를 인식한다. 나는 모든 로컬 저장소 제거를 쉽게 하기 위해 /opt/repos/* 같이 하나의 폴더 구조 아래 두는 방법을 좋아한다.
분명 로컬 저장소를 많이 두는 것이 하나의 공통 저장소를 두는 것보다 디펜던시 중복 때문에 더 많은 디스크를 필요로 할 것이다. 그래도 우리의 large grid에서 저장소는 모두 10기가 바이트도 안된다. Snapshot을 관리하고 매일 밤마다 제거하지 않는다면 로컬 저장소는 거대해질 것이다.
팁: 로컬 저장소를 청소하기 위해 CI 시스템 자체의 스케줄을 사용하라. Maven은 헷갈리지만, 누구라도 CI의 UI를 이용하여 수동으로 청소할 수 있는 방법이다.
#4 배치모드로 돌려라
팁: 빌드에서 -B (batch) 모드를 사용하라. 이렇게 하면 디펜던시 다운로드 진행 로깅같은 것을 피할 수 있어 로그가 짧아진다. 또한 사용자 입력을 기다리는 것 때문에 빌드가 멈추는 일이 없게 한다. (전체적으로 배치모드를 사용하려면 settings.xml에 <interactiveMode>false</interactiveMode>를 설정한다.)
#5 Full stack trace를 사용하라
팁: Maven에서 빌드 에러가 났을때 full stack trace를 보기위해서 -e 옵션을 사용하라. 이렇게 해야 빌드 실패 로그나 메일이 왔을 때 빌드를 다시 할 필요없이 바로 문제를 파악하기 쉬울 것이다.
#6 테스트 실패는 표준 콘솔(standard out)으로 출력하라
팁: -Dsurefire.useFile=false 옵션을 사용하라. 이것은 내가 선호하는 옵션인데 surefire가 테스트 실패를 표준콘솔로 출력하게 만든다. 그러면 빌드 실패 로그나 이메일로 이것이 포함된다. 이러면 간단한 stack trace를 보기 위해 시스템에 접속하여 surefire 보고서를 찾고 뒤지는 시간을 절약할 수 있다. (전체적으로 적용하려면 settings.xml의 active profile에 <properties><surefire.useFile>true</surefire.useFile></properties> 를 설정한다.)
#7 항상 snapshot을 검사한다.
팁: -U 옵션을 사용하면 항상 새로운 snapshot인지 검사한다. (전체적으로 사용하려면 settings.xml의 저장소 정의에서 <updatePolicy>always</updatePolicy>를 설정한다.)
정리
위의 설정과 방법을 사용하면 매 빌드마다 저장소에 빌드결과를 올린다. 다음 빌드는 그 빌드만의 깨끗한 저장소를 사용하고 최근 snapshot인지 저장소 관리자를 검사할 것이다. 그리고 적어도 하루에 한번씩은 저장소 관리자로부터 모든 디펜던시를 다운받을 것이다.
당연히 이런 모든 업데이트와 제거는 CI와 저장소 관리자에 어느정도 네트워크 부하를 줄 것이다. 네트워크가 빠르다면 이 방법이 잘 작동할 것이다. 만일 저장소 관리자와 CI 시스템이 멀리 있다면 빌드 결과의 프락시를 두면 매일 로컬 저장소를 제거하여 나타나는 영향을 줄일 수 있다.
Note. Nexus를 다운받는 것이 왜 중요하면 -.-... 당신이 위와 같은 팁들을 따라서 매일 로컬 저장소를 날리고 중앙 maven 저장소에서 모든 것을 다운로드하는 이런 행위는 중앙 maven 저장소 트래픽 문제를 야기할 수 있다.
-- 본인 사족
번역/정리하다보니 몇 일전 Maven 기반 개발환경에서 잊지 말고 해야 할 일 을 작성했는데 비슷한 이야기이네요. 나머지는 지금 하고 있고 여섯번째 팁은 저도 하나 건졌습니다 ^^. 잘 나가다가 마지막에 Nexus 홍보하는 것 같은 기분.... Nexus 말고 Artifactory도 있으니 참고하세요~
지금 사용하는 개발환경이 Subversion, Maven2를 사용하고 있다. Maven 저장소로는 Artifactory를 사용하다가 Nexus로 옮겼다. 그리고 CI (Continuous Integration) 서버로는 Apache Continuum을 사용한다.
나중에 기회가 되면 Artifactory vs Nexus 그리고 Continuum vs Hudson 을 비교 분석해보고 싶다.
이런 기반에서 쓰다보면 Nexus나 Continuum 그리고 Maven에 의해 디스크를 엄청쓴다. 개발 프로젝트가 많으면 일주일만 돌려도 기가바이트 단위로 빌드결과가 쌓인다.
이러다가 디스크 꽉 차서 서버가 제대로 작동하지 않는 경우를 당한적이 있다.
왜 디스크를 이렇게 쓰나?
지금 CI 설정이 Common 프로젝트 그룹 (프로젝트 10개내), 제품 프로젝트 그룹 (프로젝트 20~30개)를 각각 1시간마다 교차해서 smoke 테스트를 돌리고 있다. 즉 30분마다 전 프로젝트 테스트를 계속 수행하고 있다.
(smoke testing: 한 순간이라도 빌드나 테스트가 깨지지 않는지 계속 검사하는거다. 즉 뭔가 이상이 생겨 연기가 나지 않는지 항상 모니터링하는 거나. svn에 잘못된 코드가 올라오면 바로 알려준다.)
그리고 매일 밤마다 전 프로젝트를 배포하는 스케줄을 걸어놓았다.
이렇게 돌리다보니 무수한 개발 스냅샷 버전이 빌드되어 디스크를 굉장히 많이 쓰게 된다. 스냅샷 빌드는 기본적으로 지워지지 않고 날짜/시간 대로 계속 쌓인다.
Continuum 관련 빌드 청소
Maven 빌드가 일어나면 스냅샷은 home 디렉토리 밑의 .m2/repository 에 쌓인다. 이중 스냅샷이 쌓이는 그룹디렉토리를 cron 스케줄로 이용하여 주기적으로 날려도 된다.
하지만 고맙게도 Continuum에 Purge(청소) 기능을 제공한다. Administration 메뉴에서 "Purge Configuration"을 선택하면 DEFAULT 저장소가 있을 것이다. 오른쪽 수정버튼을 이용하여 적당한 스케줄을 걸어놓으면 .m2 밑의 스냅샷을 설정대로 지워진다.
디렉토리를 조사해보니 Continuum의 빌드 결과 정보를 저장하는 디렉토리도 꽤 커진다. Purge 설정에서 Add 하면 buildOutput 청소 설정도 걸 수 있다.
Maven 저장소(Nexus) 스냅샷 청소
스냅샷 deploy를 자주하면 maven 저장소에도 날짜별로 계속 쌓인다. 당연히 Nexus에도 이를 청소해 주는 기능이 있다. "Administration" 메뉴군에 "Scheduled Task"에서 여러 스케줄 작업을 설정할 수 있는데 여기서 반드시 Snapshot을 주기적으로 삭제하는 작업을 걸어두는게 좋다. 특별한 경우가 아니라면 하루 이틀 스냅샷만 남기고 지운다.
이렇게 설정을 하지 않으며 개발하다가 서버가 제대로 동작하지 않는데 갑자기 일어나는 일이라 당황하고 삽질하는 경우도 있다.
물론 요즘 디스크가 싸고 용량도 크지만 만일을 위해 이 설정을 반드시하여 개발팀이 혼란에 빠지는 일이 없도록 사전에 예방하는 것이 좋을 것이다.
Where: <path-to-file> the path to the file to load
<group-id> the group that the file should be registered under
<artifact-id> the artifact name for the file
<version> the version of the file
<packaging> the packaging of the file e.g. jar
이 명령은 파일을 maven 저장소에 로드하고 필요하면 이름도 바뀔 것이다. (maven 규칙에 따라)
10. 메일링 리스트 구독을 취소하려면 어떻게 해야 하나요?
메일링 리스트 구독을 취소하려면 간단히 다음 주소로 메시지를 보낸다.
[mailing-list]-unsubscribe@maven.apache.org
그러니까 users@maven.apache.org 에 메일링 리스트 구독을 했었으면 리스트에서 뺄려면 users-unsubscribe@maven.apache.org에 메시지를 보내야 한다.
11. 테스트를 건너뛰려면 어떻게 하나요?
명령행에서 -Dmaven.test.skip=true 파라메터를 추가한다.
12. 하나의 단위테이스만 실행하려면 어떻게 하나요?
명령행에서 -Dtest=MyTest 파라메터를 사용한다. 주의: 전체 패키지를 지정하지 않는다.(org.apache.x.y.MyTest)
13. 사이트(site) 플러그인에서 특별한 문자셋을 다루려고 해요.
사용하는 IDE에서 정확한 인코딩을 사용하도록 설정한다. 이클립스라면 eclipse.ini 파일에 -Dfile.encoding=ISO-8859-1 을 추가한다.
Windows 개발환경에서 Maven, eclipse 그리고 개발 WAS로 Jetty를 사용하여 개발을 하다가 심각한 문제를 발견했다. Jetty가 구동되면 한번 읽은 정적파일 (css, js, image 등)을 수정할 경우 다음과 같은 에러가 발생한다.
Windows에서만 이런 현상이 발생하는데 그 현상은 하나의 프로세스(jetty)가 파일을 오픈한 경우 다른 프로세스(eclipse)가 그 파일을 쓸 수 없다는 것이다. 이 경우 Jetty를 내렸다 올리면 저장이 가능하기는 하다. 그러나 css나 javascript(js) 파일을 수정할 때마다 Jetty를 재기동하는 것은 여간 귀찮은 일이 아니다.
Maven jetty 플러그인 사용자의 해결책 Jetty의 캐싱기능을 조절하기 위해서는 webdefault.xml 파일이 필요하다. 이 파일은 jetty.jar 압축을 풀면 org/mortbay/jetty/webapp/webdefault.xml 에 있다. 압축을 풀어 이 파일은 프로젝트 폴더내 적당한 디렉토리에 위치해 둔다. 그리고 다음 부분을 false로 수정한다.