태터데스크 관리자

도움말
닫기
적용하기   첫페이지 만들기

태터데스크 메시지

저장하였습니다.

티스토리 툴바


"올바른 성장과 따뜻한 나눔"이 있는 넥스트리
우리팀은 소스 버전관리와 회귀테스트 지속적인 통합은 비교적 잘 되고 있습니다. 그런데 관리가 잘 되고 있지 않는 부분이 데이터베이스 스키마입니다. 물론 ERD도 있고 DDL이나 기초데이터를 Subversion에서 관리하고 있지만 자동통합은 아직 요원합니다.

현재 상황

우리팀의 개발환경은 개인 환경, 통합용 환경 그리고 운영 환경 3개로 분리되어 있습니다.
개인 환경(개발자 PC)에서 개발/테스트를 완료하고 commit하면, 통합환경에서는 subversion에서 CI를 통해 빌드하여 통합환경으로 옮겨지고, 개발이 끝나 릴리즈한 버전은 운영환경으로 이관됩니다.

데이터베이스 스키마 변경이 없을 때에는 대부분 자동화되어 문제가 없는데 스키마 변경할 때는 스키마 변경 DDL을 만들어 일일이 각 환경에 수작업으로 적용해주어야 합니다. 그리 자주 있는 일은 아니지만 실수하기 쉽고 문제가 발생했을때 시간을 낭비하는 요소가 됩니다.

솔루션을 찾았다


데이터베이스 변경 관리를 체계적으로 자동화해 주는 open source(LGPL)로 LiquiBase가 있습니다. 대략적인 feature는 아래와 같습니다. (http://www.liquibase.org/)


  • 확장성
  • 여러 개발자의 변경을 병합
  • 코드 브렌치
  • 여러 데이터베이스 지원
  • 운영 데이터와 다양한 테스트 데이터셋 관리
  • 안전한 클러스터 데이터베이스 업그레이드
  • 자동 업데이트 또는 DBA가 직접 적용할 수 있도록 SQL 스크립트 생성
  • 업데이트를 롤백하는 기능
  • 데이터베이스끼리 비교(diff)하는 기능
  • 기존 데이터베이스에서 시작할 수 있도록 change log를 생성하는 기능
  • 데이터베이스 변경 문서 생성

여기에서는 기본적인 사용방법과 작동방법을 설명합니다.


준비할 것들


Ant, Maven, Spring 등... 여러 방법으로 사용할 수 있는데 여기서는 command line에서 사용하는 방법을 설명합니다. http://www.liquibase.org/download -> 여기에서 다운로드 받고 적당한 디렉토리에 풀어놓습니다.
그리고 그 디렉토리를 path에 추가합니다. 여기에 liquibase.bat 파일이 있는데 이게 실행 파일입니다.

여기서는 MySQL을 대상으로 할 것입니다. test라는 계정과 test라는 데이터베이스를 만들어 놓습니다.

Java로 만든 도구이며 JDBC 드라이버가 필요합니다. MySQL JDBC 드라이버를 구합니다.


작업 디렉토리

적당한 작업 디렉토리를 만들어 아래 내용으로 liquibase.properties 파일을 만듭니다.

#liquibase.properties
driver: com.mysql.jdbc.Driver
classpath: mysql-connector-java-5.0.8-bin.jar
url: jdbc:mysql://localhost/test
username: test
password: test

LiquiBase가 관리할 데이터베이스 정보를 설정합니다. command line에서 옵션으로 줄 수도 있지만 이 파일을 만들어 놓는 것이 편합니다.

그리고 MySQL JDBC 드라이버를 작업 디렉토리에 넣습니다. 설정에서 보면 classpath에 JDBC 드라이버를 잡은 것을 볼 수 있습니다.


첫번째 Change log

드디어 작업할 때가 왔습니다. LiquiBase는 데이터베이스 변경을 XML로 관리합니다. 그리고 변경의 단위를 changeset이라고 합니다. 우선 첫번째 changset을 작업디렉토리에 changelog.xml라는 이름으로 만들어 봅니다.

<databaseChangeLog
  xmlns="http://www.liquibase.org/xml/ns/dbchangelog/1.9"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog/1.9
         http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-1.9.xsd">

    <changeSet id="1" author="dykim">
        <createTable tableName="employee">
            <column name="id" type="int">
                <constraints primaryKey="true" nullable="false"/>
            </column>
            <column name="name" type="varchar(50)">
                <constraints nullable="false"/>
            </column>
            <column name="active" type="boolean" defaultValue="1"/>
        </createTable>
    </changeSet>
 
</databaseChangeLog>

employee 테이블을 하나 만들었습니다. 그리고 작업 디렉토리로 이동하여 다음과 같은 명령을 입력합니다.

c:\tmp\db\liquibase --changeLogFile=changelog.xml update

DB를 살펴보면 위의 changeset에서 정의한 것처럼 employee 테이블이 만들어졌을 겁니다.
그리고 databasechangelog와 databasechangeloglock이 생긴걸 볼 수 있습니다. 이 테이블이 LiquiBase가 데이터베이스를 관리하는 테이블입니다. 이중 databasechangelog 내용을 보면 현재 changeset id 1번이 dykim에 의해 적용되었다는 뜻입니다.



두 번째 Change log

changeset을 두 개 더 추가해 보겠습니다. 또는 changlog를 update해 보니 누군가 아래와 같이 추가했다고 보시면 됩니다.

<databaseChangeLog
  xmlns="http://www.liquibase.org/xml/ns/dbchangelog/1.9"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog/1.9
         http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-1.9.xsd">

    <changeSet id="1" author="dykim">
        <createTable tableName="employee">
            <column name="id" type="int">
                <constraints primaryKey="true" nullable="false"/>
            </column>
            <column name="name" type="varchar(50)">
                <constraints nullable="false"/>
            </column>
            <column name="active" type="boolean" defaultValue="1"/>
        </createTable>
    </changeSet>
    
    <changeSet id="2" author="dykim">
        <addColumn tableName="employee">
            <column name="fixed_salary" type="float" />
            <column name="bonus" type="float" />
        </addColumn>
    </changeSet>
    
    <changeSet id="3" author="dykim">
        <dropColumn tableName="employee" columnName="bonus" />
    </changeSet>
 
</databaseChangeLog>

마찬가지로 동일한 명령을 수행합니다.

c:\tmp\db\liquibase --changeLogFile=changelog.xml update

id 2, 3 changeset이 적용되어 employee 테이블에 컬럼이 추가되었다가 삭제된 결과를 볼 수 있을 겁니다. databasechangelog를 보면 changeset이 적용된 로그를 볼 수 있습니다.

LiquiBase는 change log의 changeset들과 DB의 databasechangelog 테이블에 적용한 상태를 비교하여 DB 스키마를 관리해줍니다.


다른 개발자의 DB로...


다른 개발자가 위 change log를 subversion과 같은 버전관리에서 update를 받고 liquibase update를 하면 그 개발자 DB와 change log를 비교하여 필요한 changeset만 적용해 결국 모든 DB 스키마는 동일해질 것입니다.

other_test로 DB와 계정을 만들고 liquibase.properties 파일을 아래와 같이 고쳐봅니다.

#liquibase.properties
driver: com.mysql.jdbc.Driver
classpath: mysql-connector-java-5.0.8-bin.jar
url: jdbc:mysql://localhost/other_test
username: other_test
password: other_test

other_test DB에도 동일한 스키마가 생겼을 겁니다.

마찬가지로 통합 환경 그리고 운영환경에서도 동일한 방법으로 쉽게 DB를 update할 수 있습니다. 이제는 더 이상 앞에서 말한 수작업은 필요없으며 안전한 DB 스키마관리가 가능하게 되었습니다.

더 기쁜 일은 Ant, Maven 같은 환경을 통해 빌드 프로세스에 넣을 수 있어 완전한 자동화를 구축할 수 있습니다.


저작자 표시 비영리 변경 금지
크리에이티브 커먼즈 라이선스
Creative Commons License
Posted by 행복한아빠
"올바른 성장과 따뜻한 나눔"이 있는 넥스트리
이제는 구조적 프로그래밍을 넘어, 객체지향을 넘어, 컴포넌트를 넘어 ~ 헉헉 서비스를 또 넘어 클라우딩 컴퓨팅의 세계로 가고 있습니다. 아~ 서비스 지향(SOa - a를 작게 쓴 이유는 개인적으로 너무 상업화된 SOA를 싫어해서입니다. 별 다른 이유 없습니다. 이건 내 글이니까요 ^^)도 파악하기 벅찬데 클라우딩이라..

클라우딩

제가 이 글에서 클라우딩을 설명하려고 하는 것은 아닙니다. 클라우딩에 관해서는 SaaS, PaaS, IaaS를 구글에서 찾으시면 친절하게 설명합니다.
클라우딩 컴퓨팅이라는게 서비스가 되었건, 플랫폼이 되었건, 인프라가 되었건 그 자원이 어디에 있는지 용량이 어떻게 되는지 신경쓰지 않고 그 자원을 활용하는 기반이고 이게 비용절감, 적시출시 등의 비즈니스 이득을 준다는 기술입니다.

오늘 저는 DEaaS(Development Environment As A Service)를 이야기해 볼라고 합니다. 이 용어는 어디에도 없습니다. 구글링하지 마세요.^^


이런 환경

A씨: 어제 수정한 소스좀 전달해 주세요.
B씨: 네 여기 있습니다.
A씨: 이런.. 컴파일 에러가 나서 빌드를 할 수 없잖아요~
B씨: 그럼 컴파일된 jar(dll, obj)파일 받으세요.
A씨: 이래서 언제 빌드하고 운영서버에 올릴 수 있겠어요.
지금이야 CVS, SVN 같은 버전관리도구 사용이 보편화되어서 이런 일이 흔하게 발생하지는 않을 겁니다. 그러나 아직도 개발자는 버전관리도구나 파일공유 디렉토리, 테스트 서버, 배포서버 심하면 운영서버까지 일일이 신경쓰고 어디에 무엇을 올려야 할지 알아야 합니다.


클라우딩 개발환경

아래가 클라우딩을 개발환경에 적용한 그림입니다. 역시 구름이 중심에 있네요^^


클라우딩 개발환경에서 개발자가 개발을 진행하는 시나리오입니다.
  1. 개발자는 개발계정하나를 부여받습니다.
  2. 개발자는 개발환경에 접속해서 개발할 모듈이나 컴포넌트를 선택합니다.
  3. 그러면 해당 컴포넌트의 소스와 개발환경이 펼쳐집니다. 와우~
  4. 개발자는 작업을 시작합니다. 이 때 다른 개발자에 의해 만들어진 서비스나 API를 검색하고 사용할 수 있습니다.
  5. 단위 테스트를 수행하고 개별 통합테스트를 수행합니다.
  6. 테스트를 완료하면 commit을 합니다. 개발자는 작업을 종료합니다.
개발자는 개발환경을 가지고 있지 않은 상태에서 작업을 수행하고 자신의 작업이 끝나고 commit 된 소스는 시스템이 식별하여 전체 회귀 테스트를 수행하고 성공하면 배포합니다.
배포된 컴포넌트는 이제 다른 개발자들도 사용할 수 있습니다. 개발자는 다른 사람이 작업한 컴포넌트를 직접 다운로드 받고 자신의 개발환경에 일일이 탑재할 필요없습니다. 그냥 쓰면 됩니다.

더 나아가 개발된 소스에 대한 승인 절차를 거처 운영서버에 알아서 반영됩니다.


현실에서

위의 내용이 꿈 같은 이야기는 아닙니다. 다음과 같은 구성으로 위 시나리오의 2/3는 완성할 수 있습니다.
- Subversion, IDE, Maven, CI 그리고 빌드 스크립트

우리회사는 위와 같은 구성으로 위와 비슷한 개발절차를 진행하고 있습니다. 다만 개발환경(IDE)가 리소스를 많이 사용하기에 개발자의 PC에는 IDE(eclipse)와 Maven 정도는 필요합니다.
조금만 더 정리하면 클라우딩 개발환경을 완성할 수 있지 않을까 생각합니다.


크리에이티브 커먼즈 라이선스
Creative Commons License
Posted by 행복한아빠
"올바른 성장과 따뜻한 나눔"이 있는 넥스트리
우리는 몇 년째 Continuum을 쓰고 있다. 뭐 별 불편없이 우리의 충실한 Continuum은 제 역할을 다 해주고 있어 우리 제품의 건강에 큰 기여를 하고 있다.
그런데 계속 Hudson 이라는 새로운 CI 도구 이야기가 들려오고 있다. 그래서 한번 살펴보니.. 오우~ 깔끔한 인터페이스~ 다시 한번 소프트웨어 신상 중독증인가? 한 번 적용해 볼라고 우리의 Continuum과 Hudson을 비교한 자료를 찾아 봤다. 나 같이 두 개중 하나를 고민하려는 분들한테 도움이 될까해서 번역해 본다.

CI 도구 중 유명한 것은 마틴 파울러 아저씨의 CruiseControl을 비롯해서 아파치 Continuum, Luntbuild 그리고 오늘 이야기할 Hudson과 같이 무수히 많다. (상용제품도 많다.)
이 비교자료는 요길(http://groups.google.com/group/EtoE/browse_thread/thread/b6675c74c03a621b) 참조하는게 좋을 것 같다.

아래는 순전히 개인적인 입장에서 비교한 자료이니 혹~ 하니 넘어가지 말길 바란다.

원문 (http://www.ideyatech.com/2008/06/continuum-vs-hudson/)

Continuum vs. Hudson
Posted by Allan Tan

우리는 지금까지 Continuum을 사용해왔다. Continuum이 우리 빌드 작업에 훌륭한 작업 관리를 해 주지만 JUnit Test 보고만 지원하는 한계가 있어 Hudson으로 바꾸려고 시험해 보고 있다. Hudwon은 이 분야의 신출내기로 멋진 아이콘과 직관적인 인터페이스를 제처두고라도 이 도구는 진짜 경쟁력이 있는 특징으로 꽉 차 있다.

그래서 나는 우리가 사용해봤고 우리가 찾고 있는 기능들을 위주로 Continuum과 Hudson의 비교해 본다.

빌드 관리

이 부분에서는 Continuum이 더 나은 수행을 보여준다. Continuum은 단일 프로젝트에서 여러 개의 작업/스크립트 설정을 지원한다. 프로젝트도 논리적으로 그룹지을 수 있다. Hudwon은 워크스페이스마다 오직 하나의 작업만 지원하는데 매우 제한적이다. 만일 3가지 작업(예를 들어 build-war, deploy, run-test)이 필요하다면 각 작업은 자신의 워크스페이스를 필요로 한다. 이 모든 작업이 같은 소스 코드를 공유하지 않는 것은 납득하기 어렵다.

사용자 관리

나는 유연성보다는 단순성을 좋아하기 때문에 Continuum보다는 Hudsond이 낫다고 본다. 우리팀이 작은 것을 생각하면 다중 프로젝트에 여러 권한을 주어 사람들을 그룹핑할 필요가 없다. 우리가 필요한 것은 개발자의 프로젝트 접근을 제한하는 것이 모두이다. Hudson은 간단하고 사용하기 쉬운 권한 시스템을 가진다. 나는 30분안에 사용자 접근 권한을 설정할 수 있다. Continuum은 이 부분이 좀 너무 복잡한 것 같다. 또한 Continuum은 엄격한 비밀번호 정책을 가지고 있어(역자주-비밀번호에 번호가 포함되어야 함. 그리고 주기적으로 변경해야 함.) 관리를 어렵게 한다.

스케줄링

다시 한번, 단순함 때문에 Hudson이 더 낫다. 스케줄 설정을 하려면 스케줄 옵션에 간단히 "@daily"을 붙이면 된다. 이것을 설정 끝이다. Continuum의 스케줄은 복잡하지 않지만 좀 더 많이 클릭해야 한다. 다시 이야기하지만,유연성 보다는 단순함이 좋다.

전자메일 경고/통지

두 도구 모두 전자메일 지원을 제공하는데 Hudwon이 좀 더 상세한 전자메일 보고를 한다. Hudson은 각 테스트에 대해 JUnit 테스트 보고의 추적을 포함하는데 비해 Continuum은 단지 실패나 성공 빌드에 대한 통지만 제공한다.

결국 우리는 사용하기 쉽고 Junit 테스트 보고 기능을 가지고 있는 Hudwon으로 바꾸기로 결정했다.

Note: Continuum과 Hudson 로고는 각각 아파치 Continuum과 Hudson의 자산이다.

---
나도 아직 Hudson을 써보지는 않았다. Hudson을 쓰고 한번 다시 글을 올려야겠다. Allan Tan 이란 사람 나하고 비슷한 생각을 가진 사람같다. 유연성보다는 단순함....

크리에이티브 커먼즈 라이선스
Creative Commons License
Posted by 행복한아빠
"올바른 성장과 따뜻한 나눔"이 있는 넥스트리
괜찮은 글이 있어 번역했습니다. (http://www.sonatype.com/people/2009/01/maven-continuous-integration-best-practices/By Brian Fox

지속적인 통합(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도 있으니 참고하세요~




크리에이티브 커먼즈 라이선스
Creative Commons License
Posted by 행복한아빠
"올바른 성장과 따뜻한 나눔"이 있는 넥스트리
지금 사용하는 개발환경이 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을 주기적으로 삭제하는 작업을 걸어두는게 좋다. 특별한 경우가 아니라면 하루 이틀 스냅샷만 남기고 지운다.



이렇게 설정을 하지 않으며 개발하다가 서버가 제대로 동작하지 않는데 갑자기 일어나는 일이라 당황하고 삽질하는 경우도 있다.
물론 요즘 디스크가 싸고 용량도 크지만 만일을 위해 이 설정을 반드시하여 개발팀이 혼란에 빠지는 일이 없도록 사전에 예방하는 것이 좋을 것이다.



크리에이티브 커먼즈 라이선스
Creative Commons License
Posted by 행복한아빠
"올바른 성장과 따뜻한 나눔"이 있는 넥스트리

내가 작성한 프로그램의 품질을 측정하기 위한 가장 확실한 방법은 테스트이다. 그러나 아무리 테스트를 한다 하더라도 완벽히 테스트를 할 수 없는게 사실이다. 아무리 테스트 해도 프로그램에 버그는 항상 있기 마련이다.
이를 위해서 프로그램 정적분석이 유용하다. 여러가지 정적 분석 도구가 있는데 코드 스타일을 검사하는 check style도 그 중 하나겠다.
오늘은 유명한 Java 프로그램 분석도구인 Find Bugs를 소개한다. 이는 check style 같이 코드의 건정성을 검사하기 보다는 버그의 가능성이 있는 코드를 검출해 준다. 반가운 것은 LGPL 기반 오픈소스이다.

다운로드 / 설치
http://findbugs.sourceforge.net 에 가면 Download 받을 수 있다. 2009년 10월 7일 현재 받을 수 있는 버전이 findbugs-1.3.9.zip 이다. 이를 받고 적당한 디렉토리에 풀면 설치는 끝이다.

실행
실행하기 위해서는 Java 2 Standard Edition 1.5 이상이 필요하다.
설치한 디렉토리의 bin 디렉토리에 가면 findbugs.bat (windows 기준)가 있다. 이를 실행하면 아래와 같은 화면이 나온다.


분석
먼저 프로젝트를 만들어야 한다. "File > New Project" menu 를 선택하면 프로젝트 생성을 위한 창을 볼 수 있다. 아래 항목에 필요한 것들을 지정하자.

  • Class archives and directories to analyze: 분석할 클래스 있는 아카이브 (jar)나 디렉토리
  • Auxiliary class locations: 분석 클래스가 사용하는 클래스의 위치(jar 또는 디렉토리) - 분석대상은 아님
  • Source directories: 분석 클래스의 소스가 있는 디렉토리 (분석결과를 소스와 보고 싶다면 지정)


"Finish" 버튼을 클릭하면 분석이 시작되고 분석 결과가 나타난다.



검출한 버그를 선택하면 버그 가능성이 있는 부분의 소스 위치 그리고 버그 가능성에 대한 설명을 볼 수 있다.


이클립스 플러그인 설치
위의 오리지널 프로그램도 유용하지만 이클립스를 사용한다면 이클립스 플러그인이 상당히 편리하다.
이클립스 플러그인 업데이트 사이트 URL은 http://findbugs.cs.umd.edu/eclipse/ 이다. (http://findbugs.sourceforge.net/manual/eclipse.html 참조)

이클립스에서 분석
이클립스 플러그인을 선택했다면 Java 프로젝트를 선택하고 오른쪽 마우스 버튼을 클릭하면 팝업메뉴에서 "Find Bugs" 메뉴를 볼 수 있다. "Find Bugs > Find Bugs" 를 선택하면 분석이 시작된다.




이클립스에서 분석결과 보기
분석이 끝나면 버그가 검출된 소스에 Warning 아이콘이 생긴다. 버그가 있는 소스를 열면 아래와 같이 버그가 있는 소스 라인에 벌레 아이콘이 보인다.



벌레 아이콘을 선택하면 분석한 Bug를 브라우징할 수 있는 View가 열리고 여기에서 버그 목록을 살펴볼 수 있다. 아래 그램의 예에서는 equals 메소드에서 파라메터 null 검사를 하지 않았다고 정확하게 짚어준다. (흐미.. 이런 실수를...)



마무리
Find Bugs에서 검출된 모든 버그(?)를 다 수정할 필요는 없다. 일부로 의도한 부분을 Find bugs가 버그라고 검출할 수도 있고 버그 가능성이 있는 것을 알지만 고칠 필요가 없거나 불가능한 부분도 있을 것이다.
그러나 몇번 돌리고 보니 지나칠 뻔한 심각한 버그를 몇 개 잡았다. 코드를 릴리즈 하기 전 한번 쯤 돌려보고 릴리즈 하면 좀 더 나은 품질의 프로그램이 나올 수 있겠다.






크리에이티브 커먼즈 라이선스
Creative Commons License
Posted by 행복한아빠
"올바른 성장과 따뜻한 나눔"이 있는 넥스트리

Application을 만들기 위해서는 요구사항을 수집해야 하는데 이게 그렇게 쉬운 일이 아니다. 고객이 요구사항을 잘 정리해 주는 것도 아니고 요구사항 열심히 정리해봤자 잘 보지도 않고... 사실 고객도 자기가 뭘 원하는지 알지 못하는 경우가 태반이다.

가장 확실한 방법은 application을 빨리 만들고 보여주는 방법이다. 일단 뭔가 실체가 있으면 그 때부터 다양한 요구사항이 쏟아지기 시작한다. "돌 수프(http://en.wikipedia.org/wiki/Stone_soup)" 이야기에서 보듯 뭔가 완벽하지 않아도 뭔가 있으면 좋은 시작점이 될 수 있다.
이걸 흔히 UI Prototype이라고 이야기 한다.

UI Prototype

대부분 UI prototype이나 UI 설계서를 표현하는 방법으로 HTML을 직접 사용하여 작성하거나 Power Pointer를 사용한다. 이 둘 다 엄청 노가다이며 그리 즐거운 작업이 아니다.
이런 작업을 위한 다양한  UI prototype 도구가 있는데 그 중 사용하기 굉장히 간단하고 꽤 유용한 balsamiq mockup (http://www.balsamiq.com/)을 소개한다.

Mockup이란 실제 제작하기 전 만드는 모형을 말하는 데 건축설계사가 집 모형을 만든 것을 보았다면 그게 mockup이다. balsamiq mockup으로 우리가 만들 application의 대략적인 mockup을 아주 쉽게 만들 수 있다.

Mockup

아래는 balsamiq mockup으로 만든 mockup 예제이다.

 
 


마치 손으로 그린 UI 설계 비슷하다. 이런 걸 쉽고 빠르게 만들 수 있으며 빠른 요구사항 수집을 위해 훌륭한 도구인 것 같다. 아래 소개 동영상을 보면 제작하는 과정을 알 수 있다.




한글문제

처음 사용할 때 한글이 입력되지 않아 실망이 컸다. 실망하지 말라. "View" 메뉴에서 "Use System Fonts"를 선택하면 한글 입력도 문제 없다.



즐거운 UI 설계되세요~


크리에이티브 커먼즈 라이선스
Creative Commons License
Posted by 행복한아빠
"올바른 성장과 따뜻한 나눔"이 있는 넥스트리
개발의 역사 중 가장 극단적으로 개발 생산성을 높인 기술이 바로! 복사 & 붙이기가 아닌가 생각한다.  이 기술이야 말로 어떠한 개발방법이나 개발도구 보다 개발자에게 혁신적인 생산성을 가져다 준 기술이라고 합니다.
같이 일하던 사람과 술자리에서 CnP(Copy & Paste) 방법론을 극찬하며 널리 널리 전파하자고 다짐한 적이 있던 것 같다.

이상 농담이고 복사와 붙이기의 해악은 다들 아실 겁니다. 그러나 개발자에 있어서 복사와 붙이기 작업은 굉장히 빈번한 작업임은 틀림 없습니다.

개발하다가 copy & paste를 많이 하는데 이전에 복사했던 내용이 필요할 때가 많이 있습니다. 관련 툴을 찾다가 오픈소스 클립보드 매니저인 Ditto를 발견했습니다.

꽤 쓸만합니다. 다운로드는 http://ditto-cp.sourceforge.net/에서 받으시면 됩니다.

한글화 작업은 http://ditto-cp.wiki.sourceforge.net/Current+Translations에 가시면 받을 수 있습니다. (더 괜찮은 한글메뉴 이름 있으면 알려주세요.)
Korean.xml을 설치디렉토리의 Language (보통 C:\Program Files\Ditto\Language) 밑에 넣고 option에서 language 선택하시면 됩니다. 다음 버전부터 한글메뉴도 추가할거라 합니다.

참고로 ditto 창을 여는 단축키는 Ctrl + ` 입니다. 개발생산성 1% 더 올리시기 바랍니다. ^^
크리에이티브 커먼즈 라이선스
Creative Commons License
Posted by 행복한아빠

Maven FAQ

개발환경 2009/01/20 23:47
"올바른 성장과 따뜻한 나눔"이 있는 넥스트리
  메이븐을 이용하다 개발하다 보면 자주하는 부딪히는 질문들이 있다. 자꾸 Maven 사이트에서 찾아보지 말고 한 번 맘먹고 정리해본다.

원문:  http://maven.apache.org/general.html

자주 물어보는 기술적인 질문들

1. WEB-INF/lib에 JAR가 포함되는 것을 어떻게 막나요? 난 단지 컴파일만 필요합니다.
2. 사용가능한 플러그인 목록을 어떻게 보나요?
3. 내가 어떤 버전의 플러그인을 사용하고 있는지 어떻게 알 수 있나요?
4. Maven 2에서 Ant 타스크를 어떻게 사용할 수 있나요?
5. JVM target과 source를 선택해서 컴파일하려면 어떻게 설정해야 하나요?
6. 나만의 디렉토리 구조를 생성하는게 가능한가요?
7. 소스코드가 어디에 있나요? Maven2 사이트에서 눈을 씻고 찾아봐도 링크를 못찾겠어요.
8. Maven이 디펜던시를 다운로드하지 못하는 것 같아요. 내가 올바로 설치한건가요?
9. 내 로컬 저장소에 넣고 싶은 jar가 있습니다. 어떻게 여기에 복사하나요?
10. 메일링 리스트 구독을 취소하려면 어떻게 해야 하나요?
11. 테스트를 건너뛰려면 어떻게 하나요?
12. 하나의 단위테이스만 실행하려면 어떻게 하나요?
13. 사이트(site) 플러그인에서 특별한 문자셋을 다루려고 해요.
14. 내 디펜던시에 tools.jar를 어떻게 포함하나요?
15. Maven이 내 테스트 클래스를 컴파일만하고 실행하지는 않아요.
16. Maven SNAPSHOT 산출물은 어디에 있나요?
17. Maven XSD 스키마는 어디에?
18. Maven이 작동하지 않아요. 어떻게 도움을 얻죠?
19.실행 디버깅 출력이나 에러 메시지를 어떻게 보죠?
20. Mojo가 뭐죠?

1. WEB-INF/lib에 JAR가 포함되는 것을 어떻게 막나요? 난 단지 컴파일만 필요합니다.
이런 경우에는 provided 스코프(scope)를 사용해야 한다. 이것은 실행시간에 컨테이너나 JDK 같은 것이 제공한다고 Maven에게 알려준다.

2. 사용가능한 플러그인 목록을 어떻게 보나요?
"Available Plugins" 페이지의 그것들의 목록이 있다. 그리고 Maven2 저장소를 검색할 수 있는 몇 가지 정보가 더 있다. 다음을 참조하라.
http://maven.apache.org/plugins

3. 내가 어떤 버전의 플러그인을 사용하고 있는지 어떻게 알 수 있나요?
Maven Help 플러그인의 describe 골을 사용할 수 있다. 예를 들어 install 플러그인의 버전을 찾아보려면 아래와 같이 입력한다.
mvn -Dplugin=install help:describe

plugin 아규먼트로 아티팩트 아이디가 아니라 플러그인 접두사를 주는 것을 주의하라.

4. Maven 2에서 Ant 타스크를 어떻게 사용할 수 있나요?
현재 2가지 방법이 있다.
  • Java, Beanshell 또는 Java 비슷한 스크립트 언어로 만든 플러그인을 사용하기 위해서라면, "Ant 문서에서 소개하는 방법"을 이용하여 Ant 태스크를 쓸 수 있다.
  • 프로젝트에 맞춰서 만든 작은 양의 Ant 스크립트라면 AntRun 플러그인을 사용할 수 있다.

5. JVM target과 source를 선택해서 컴파일하려면 어떻게 설정해야 하나요?
pom에서 source와 target 파라메터를 설정해야 한다. 예를 들어 source와 target의 JVM이 1.5라면 pom에 다음과 같은 내용이 있어야 한다.
  ...
  <build>
  ...
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>2.0.2</version>
        <configuration>
          <source>1.5</source>
          <target>1.5</target>
       </configuration>
     </plugin>
   </plugins>
  ...
 </build>
  ...


6. 나만의 디렉토리 구조를 생성하는게 가능한가요?
물론 가능하다!
<build> 세션의 <sourceDirectory>, <resources>와 그 외 엘리먼트를 설정하면 된다.
덧붙여, 플러그인의 파일이나 디렉토리의 기본설정을 사용하지 않으면 다른 플러그인 설정도 바꿔야 할 수도 있다. (그냥 쓰는게 좋다. 그것이 Maven의 사상이고 관례이다.)

7. 소스코드가 어디에 있나요? Maven2 사이트에서 눈을 씻고 찾아봐도 링크를 못찾겠어요.
소스코드는 subversion에서 찾을 수 있다.: http://svn.apache.org/repos/asf/maven/components/trunk
더 정보가 필요하다면 "Building Maven 2.0"를 보라.

8. Maven이 디펜던시를 다운로드하지 못하는 것 같아요. 내가 올바로 설치한건가요?
아마 Maven이 proxy를 사용하도록 설정해야 할 것이다. Maven이 proxy를 사용하는 방법은 "Configuring a proxy"를 보라.

9. 내 로컬 저장소에 넣고 싶은 jar가 있습니다. 어떻게 여기에 복사하나요?
Maven 저장소의 레이아웃을 이해한다면 jar 파일을 올바를 위치에 바로 복사해도 된다. Maven이 다음에 작동할 때 jar 파일을 찾을 것이다.
Maven 저장소의 레이아웃 이해에 확신이 가지 않는다면, 단 다음과 같이 한줄의 명령으로 jar 파일을 저장소에 로드할 수 있다.
mvn install:install-file
  -Dfile=<path-to-file>
  -DgroupId=<group-id>
  -DartifactId=<artifact-id>
  -Dversion=<version>
  -Dpackaging=<packaging>
  -DgeneratePom=true
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 을 추가한다.
pom에서 출력 인코딩을 설정한다.
  ...
  <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-site-plugin</artifactId>
    <version>2.0-beta-6</version>
    <configuration>
      <outputEncoding>UTF-8</outputEncoding>
   </configuration>
 </plugin>
  ...
mvn이 사용하는 파일 인코딩을 설정한다. MAVEN_OPTS에 IDE와 같이 인코딩을 추가한다. $HOME/.pfofile 에 MAVEN_OPTS="-Dfile.encoding=ISO-8859-1"을 추가하면 된다.

14. 디펜던시에 tools.jar를 어떻게 포함하나요?
다음 코드는 Windows, Linux 그리고 Solaris에서 JDK의 tools.jar를 포함시킨다. (Mac OS X 와 몇가지 free JDK의 runtime에는 이미 포함되어 있다.)
...
  <profiles>
    <profile>
      <id>default-tools.jar</id>
      <activation>
        <property>
          <name>java.vendor</name>
          <value>Sun Microsystems Inc.</value>
       </property>
     </activation>
      <dependencies>
        <dependency>
          <groupId>com.sun</groupId>
          <artifactId>tools</artifactId>
          <version>1.4.2</version>
          <scope>system</scope>
          <systemPath>${java.home}/../lib/tools.jar</systemPath>
       </dependency>
     </dependencies>
   </profile>
 </profiles>
  ...


15. Maven이 내 테스트 클래스를 컴파일만하고 실행하지는 않아요.
surefile 플러그인이 테스트들을 실행한다.  무심코 ${test}에 값을 할당하면 surefile 플러그인이 특정 테스트 클래스들만 수행하도록 설정된다. settings.xml과 pom.xml에 다음과 같이 "test" 속성이 설정되어 있는지 검사한다.
  ...
  <properties>
    <property>
      <name>test</name>
      <value>some-value</value>
    </property>
 </properties>
  ...
또는
 ...
  <properties>
    <test>some-value</test>
 </properties>
  ...


16. Maven SNAPSHOT 산출물은 어디에 있나요?
Maven이나 플러그인의 개발 버전을 빌드하고자 한다면 maven 스냅샷 저장소에 접근할 필요가 있다.
"플러그인 스냅샷 안내"를 보고 settings.xml을 업데이트 해야 한다.

17. Maven XSD 스키마는 어디에?
Maven XSD 는 "여기"에 있고 Maven Settings XSD는 "여기"에 있다.
당신이 즐겨쓰는 IDE는 아마 pom.xml과 settings.xml 편집을 위해 XSD 스키마를 지원할 것이다.
다음과 같이 설정할 필요가 있다.

<project xmlns="http://maven.apache.org/POM/4.0.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
                      http://maven.apache.org/maven-v4_0_0.xsd">
  ...
</project>


<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0
                      http://maven.apache.org/xsd/settings-1.0.0.xsd">
  ...
</settings>

18. Maven이 작동하지 않아요. 어떻게 도움을 얻죠?
"도움 얻기" 페이지에 유용한 리소스를 올려놓았다.

19.실행 디버깅 출력이나 에러 메시지를 어떻게 보죠?
-X 파라메터나 -e 파라메터를 이용해 maven을 실행하면 된다. 더 자세한 정보를 보기 위해 다음과 같이 실행한다.
mvn --help

20. Mojo가 뭐죠?
mojo를 Maven plain Old Java Object를 말한다. 모든 mojo는 maven에서 실행가능한 goal이다. 그리고 플러그인은 하나 이상의 관련된 mojo들의 배포판이다.

크리에이티브 커먼즈 라이선스
Creative Commons License
Posted by 행복한아빠
"올바른 성장과 따뜻한 나눔"이 있는 넥스트리
사용자 삽입 이미지
 Maven 개발으로 Web application 개발시 jetty 플로그인을 사용하면 별도의 WAS를 설치할 필요없이 다음과 같은 명령어로 바로 WebApp을 실행할 수 있다.

prompt> mvn jetty:run

이 플러그인을 실행하기 위해서는 pom.xml 의 플러그인 부분에 jetty 플러그인을 다음과 같이 설치해야 한다.

...
 <build>
  <plugins>
   <plugin>
    <groupId>org.mortbay.jetty</groupId>
    <artifactId>maven-jetty-plugin</artifactId>
    <version>6.1.5</version>
    <configuration>
     <contextPath>/mywebapp</contextPath>
    </configuration>
   </plugin>
  </plugins>
 </build>
...

이 경우 기본 8080 포트에 /mywebapp 를 컨텍스트 루트로 이용해 jetty를 실행한다. 이 포트를 변경하기 위해서 configuration에 다음을 추가한다.

...
 <build>
  <plugins>
   <plugin>
    <groupId>org.mortbay.jetty</groupId>
    <artifactId>maven-jetty-plugin</artifactId>
    <version>6.1.5</version>
    <configuration>
     <contextPath>/mywebapp</contextPath>
     <connectors>
      <connector
       implementation="org.mortbay.jetty.nio.SelectChannelConnector">
       <port>8082</port>
       <maxIdleTime>60000</maxIdleTime>
      </connector>
     </connectors>

    </configuration>
   </plugin>
  </plugins>
 </build>

참조: http://docs.codehaus.org/display/JETTY/Maven+Jetty+Plugin 

크리에이티브 커먼즈 라이선스
Creative Commons License
Posted by 행복한아빠
TAG jetty, maven, port