 |  |
|
난이도 : 중급 Paul Duvall, CTO, Stelligent Incorporated
2008 년 2 월 04 일 자동화는 개발 팀만을 위한 것이 아니라, 소프트웨어를 개발에서 제품화 하는 데에도 적용할 수 있습니다.
사람을 위한 자동화
시리즈 중 이번 시간에는, 자동화 전문가 Paul Duvall이 Ant와 Java™ Secure Channel을 사용하여 여러 대상 환경에 소프트웨어를 원격에서 전개하는 방법을 설명합니다.
 |
시리즈 소개 개발자로서, 사용자를 위해 프로세스를 자동화 하고 있습니다. 하지만, 정작 우리들 자신의 개발 프로세스를 자동화 할 수 있는 기회를 간과하고 있습니다. 따라서,
사람을 위한 자동화
시리즈에서는 소프트웨어 개발 프로세스를 자동화 하는 방법을 연구하고, 자동화를 적용할 시기와 방법을 설명합니다. |
|
많은 팀들이 소프트웨어를 개발 환경에서 제품으로 이동시켜야 한다는 것을 뒤늦게야 깨닫는 다는 사실을 아는가? 여러 주, 심지어 여러 달에 이르기까지 범위가 정해진 전개 타임라인 만든 팀들이 떠오른다-필자가 생각하기에 이것은 시간 낭비이다. 자동화 빌드에서와 같이 자동화를 활용하고, 전개 설정에 드는 시간을 줄여서 이러한 인프라스트럭처 비효율성을 줄여보는 것은 어떨까?
1초만 생각해 보자: 소프트웨어를 전개하는데 있어서의 비효율성이라 한다면, 품질 좋은 애플리케이션을 사용자에게 제공하는데 드는 시간이 지연되는 것을 들 수 있다. 더욱 안타까운 것은, 대부분의 프로젝트에서 전개에 따른 고통이 수반되고, 이러한 사실에 기반하여 전개하는 것을 마치 (1초 만에 상처를 입힐 수 있는) 밴드를 떼어내는 것으로 생각한다.
지연 문제 외에도, 비효과적인 전개 인프라스트럭처는 팀이 변화에 잘 적응할 수 없도록 하고, 이는 너무 많은 기능들을 하나의 릴리스(릴리스는 자주 발생하는 일이 아니기 때문이다.)에 몰아넣고 싶은 충동을 느끼게 한다. 점점 악순환이 되어간다: 비즈니스는 사용자에게 소프트웨어를 빠르게 제공하고 싶지만, 너무 오래 걸리기 때문에, 모든 사람들은 기회를 최대화 할 수 있는 초대형 릴리스를 계획한다.
무통(painless) 전개도 가능하다!
전개의 기본 프로세스에는 컴파일, 데이터 변경 사항들 통합(데이터베이스 테이블), 배포판(예를 들어, JAR와 WAR)을 다른 머신에 전개하기, 머신 리소스 관리하기 등이 포함된다. 그럼에도 불구하고, 실제로 설치 미디어 생성, 테스팅, 사용자 문서 생성을 포함하여 자동화 될 수 있는 것들은 훨씬 더 많다. 이 글에서는, 어떻게 하면 이 모든 프로세스들을 자동화 빌드 프로세스의 일부로 만들 수 있는지를 설명하겠다. 특히, 다음의 프로세스에 대해 배우게 될 것이다:
- 바이너리를 원격 머신에 전개하기
- 설정 프로퍼티를 공개하기
- MySQL RDBMS를 원격으로 업데이트 하기
- Jakarta의 Tomcat Servlet 컨테이너를 원격에서 설정하기
이러한 프로세스를 자동화 함으로써, 소프트웨어를 보다 빠르게 고객들에게 전달하고, 여러분의 두통을 줄일 수 있다.
필요한 툴들
전개 자동화의 중심이 되는 툴은 빌드 스크립트이다; 필자는 Ant를 사용하고 있다. 필자의 Ant 스크립트는 (스테이징 및 실행 환경에 맞춘) 프로퍼티 파일을 사용하고, Ant sql 태스크를 통해 MySQL 데이터베이스와 연결되고, Java Secure Channel (JSch)을 사용하여 파일을 (Secure-Copy protocol (SCP)을 통해) 원격 머신에 복사하고, Tomcat 서비스를 (SSH를 통해) 중지 및 시작한다.
그림 1은 이러한 프로세스를 아키텍처 관점에서 묘사한 것이다. 이상적인 빌드 프로세스는 소스 코드(설정 파일)를 체크하고, 컴포넌트를 로컬에서 컴파일 및 압축한 다음, SQL 문을 원격에서 실행하고, 배포판을 전개하고 Tomcat을 재 시작하기 때문에 모든 소프트웨어 에셋들이 버전 관리 저장소에 저장되어야 한다.
그림 1. 원격 전개를 위한 구현 구조
여러분은 이 모든 프로세스를 자동화 할 수 있고, 이렇게 함으로써 하나의 명령어 또는 마우스 클릭으로 전개를 수행하거나, 인간이 개입하지 않고 실행되도록 스케줄링 할 수도 있다. 매력적이지 않은가?
프로퍼티 공개하기
파일 위치, 호스트 이름, 데이터베이스 이름, 포트 넘버(대상 환경마다 다양함) 같은 설정 값들은 하드 코딩 되어서는 안된다. (예를 들어, 소스 코드에서). 이러한 애트리뷰트들은 .properties 파일에서 보다 적절하게 관리된다. 이러한 프로퍼티들을 공개함으로써, 같은 빌드 스크립트를 사용하여 한 환경에서 컴파일 하고, 소스 코드를 수정 또는 재 컴파일 하지 않고 다른 환경에 전개할 수 있다.
 |
프로퍼티의 규칙 하나의 값이 한 환경에서 다른 환경으로 변한다면, 이것을 외부 .properties 파일에 둔다. 빌드 스크립트 내 하나의 값에 대해 한 개 이상의 레퍼런스가 있다면, 빌드 스크립트 (build.xml)에 있는 프로퍼티로 가야 한다. 하나의 값에 대해 단 하나의 레퍼런스가 있다는 것을 알고 있다면, 프로퍼티로 갈 필요가 없다. (이는 가정일 뿐이다.) |
|
Listing 1은 Ant 빌드 스크립트에서 프로퍼티를 정의하는 예제로서, .properties 파일을 시스템 매개변수(예를 들어, test.properties)로서 전달할 수 있는데, 여기에는 특정 대상 환경에 대한 모든 값이 포함된다. property.file.location은 C:\Documents and Settings\patrick.henry\test.properties 같은 경로로 바뀐다. 예를 들어, 명령행에서, 다음과 같이 타이핑 할 수 있다: ant -Dproperty.file.location=C:\Documents and Settings\patrick.henry\test.properties.
Listing 1. 프로퍼티 애트리뷰트 공개하기
<property file="${property.file.location}" />
|
예제 대상 환경 .properties 파일은 Listing 2에 나타나 있다. 이 파일의 애트리뷰트 값은 대상 환경들 마다 다양하지만, 애트리뷰트 이름은 언제나 같다.
Listing 2. 프로퍼티 파일의 예제 애트리뷰트와 상응하는 값
db.database=brewery
db.username.system=root
db.password.system=sa
db.username=root
db.password=sa
db.hostname=my-hostname.domain.com
db.driver=com.mysql.jdbc.Driver
db.port=3306
db.url.system=jdbc:mysql://${db.hostname}:${db.port}/
db.url=jdbc:mysql://${db.hostname}:${db.port}/${db.database}
|
프로퍼티 애트리뷰트와 값을 공개함으로써, 다중 대상 환경들을 지원할 수 있는 보다 유연한 빌드 및 전개 아키텍처를 만들 수 있다.
단순함
소프트웨어를 또 다른 환경에 전개하는 것은 힘든 과정이 되어서는 안된다. 다시 말해서, "deploy(전개)"라고 타이핑 하는 것만큼 쉬워야 한다. 다행히도, Ant 같은 빌드 시스템들은 이를 현실로 만들어 준다. 일련의 단계들을 순서대로 실행하는 하나의 워크플로우를 논리적으로 정의함으로써, 이를 호출하는 하나의 명령어를 만들 수 있다.
Listing 3의 depends 애트리뷰트에 열거된 Ant 타겟(target)들은 자동화 전개 과정을 세세하게 정의한다. 우선, 스크립트는 이전에 생성된 생성물들을 로컬 환경에서 (clean 타겟을 사용하여) 제거되고, 소스 코드를 컴파일 하고, 데이터베이스를 원격에서 생성하며, 테스트 데이터를 적용하고, 데이터베이스를 시작하고, 마지막으로 WAR 파일을 대상 환경에 있는 Tomcat 컨테이너에 원격으로 전개한다.
Listing 3. 원격 전개로 실행된 핵심 타겟
<target name="build"
depends="clean, compile, refresh-database, remote-tomcat-deploy" />
|
데이터베이스를 리프레시 하고 에셋들을 원격에서 전개하는 일은 쉬운 일은 아니지만, 똑똑한 스크립팅을 사용하면 빠르게 할 수 있다!
DBA 자동화
테스트 대상 환경을 설정할 때, 데이터베이스 설정하기, 테스트 데이터 삽입하기, 오래된 엔트리 제거하기, 기타 반복적인 (종종 에러를 만드는) 프로세스 같이 많은 수동 프로세스가 발생한다. 전개하는 동안 데이터베이스를 다루는 것이 이제 더 이상 고통스러운 일이 아니다.
기존 데이터베이스를 없애고, 데이터베이스를 만들고, 데이터베이스 사용자를 만드는 등의 Data Definition Language (DDL) 문 다음에, insert 문 같은 Data Manipulation (DML) 문은 쉽게 스크립팅 될 수 있고, Ant 빌드 스크립트의 일부로 실행될 수 있다. 게다가, 이러한 문들은 원격에서 실행될 수 있다.
예를 들어, Listing 4에서처럼, 대상 환경 .properties 파일에서) db.url.system 프로퍼티를 전달함으로써, 빌드 스크립트는 원격 데이터베이스에 대해 SQL 문을 실행할 수 있다:
Listing 4. 데이터베이스를 생성하고 데이터를 삽입하는 스크립트
<target name="refresh-database" depends="create-database,insert-data" />
<target name="create-database">
<sql driver="${db.driver}"
url="${db.url.system}"
userid="${db.username.system}"
password="${db.password.system}"
src="${database.dir}/create-database.sql">
<classpath>
<pathelement location="${mysql-connector.jar}"/>
</classpath>
</sql>
</target>
...
<target name="insert-data">
<sql driver="${db.driver}"
url="${db.url}"
userid="${db.username}"
password="${db.password}"
src="${database.dir}/insert-data.sql">
<classpath>
<pathelement location="${mysql-connector.jar}"/>
</classpath>
</sql>
</target>
|
Listing 5의 insert-data.sql 파일에 있는 콘텐트는 Listing 4의 insert-data 타겟으로부터 호출된다. DDL이든 DML이든 어떤 SQL 문도 Ant sql 태스크를 사용하여 비슷한 방식으로 실행될 수 있다.
Listing 5. 데이터를 삽입하는 SQL 문
insert into beer(id, beer_name, date_received) values
(1, 'Samuel Adams Lager','2006-12-09');
insert into beer(id, beer_name, date_received) values
(2, 'Guinness Stout','2006-12-29');
insert into beer(id, beer_name, date_received) values
(3, 'Olde Saratoga Lager','2007-02-14');
insert into beer(id, beer_name, date_received) values
(4, 'Sierra Nevada Pale Ale','2007-05-14');
|
이제 원격 데이터베이스를 업데이트 했으니, 다음 단계는 일부 에셋들을 Tomcat을 실행하는 원격 환경에 전개하는 단계이다.
배포와 전개
원격 전개를 실행하는 일은 로컬 전개와 전혀 다르지 않고, 다만, 한 장소에서 다른 장소(빌드 머신에서 대상 환경으로)로 안전하게 복사될 수 있는 다른 채널이 필요하다. 대부분의 기업에서, 보안은 최우선 순위이기 때문에, 단순한 FTP와 telnet은 작동하지 않는다. 이 경우, SCP와 SSH가 이 일을 수행할 수 있다. Ant를 사용하면 이러한 채널을 활용하는 것이 쉽다; 사실, 필자도 JSch에서 sshexec와 scp 태스크를 사용하여 원격에서 파일을 복사하고 원격 머신에서 명령어를 실행한다.
 |
실행 환경으로 가기 특정 소프트웨어 애플리케이션(예를 들어, Software as a service 또는 SaaS)은 전개의 빈도를 바꾸고 있음에도, 실행 환경으로 가는 일은 쉬운 일이 아니다. 여러분은 애플리케이션과 데이터베이스 롤백(rollback)을 추가하여 소프트웨어 시스템을 이전 상태로 되돌릴 수 있어야 한다. 이와 같은 추가는 수백만 달러를 잃느냐, 버느냐 간 차이가 될 수 있다. 소프트웨어 시스템 자체를 테스트 하는 것과 마찬가지로, 자동화 전개 프로세스 역시 엄격하게 테스트 되어야 한다. |
|
SCP로 파일을 안전하게 복사하기
SCP는 한 머신에서 다른 머신으로 에셋들을 안전하게 복사하는 기능을 제공한다. SCP를 지원하는 다양한 툴들이 있다. Ant에서, JSch는 SCP를 사용하여 인간의 개입 없이, 또는 필자가 더 좋아하는 표현으로, 자동으로 에셋(예, JAR 파일)들을 복사한다.
Listing 6에서, (JSch에서 제공된) scp 태스크는 (이 경우) WAR 파일을 빌드 머신에서 원격 머신으로 복사한다. JSch 라이브러리(jsch-0.1.36.jar)는 scp 태스크를 활용할 수 있도록 Ant의 classpath에 있어야 한다.
Listing 6. WAR 파일을 한 머신에서 다른 머신으로 안전하게 복사하기
<target name="copy-tomcat-dist">
<scp file="${basedir}/target/brewery.war"
trust="true"
keyfile="${ssh.key.file}"
username="${ssh.username}"
passphrase=""
todir="${ssh.server.username}:${ssh.server.password}@${ssh.server.hostname}
:${tomcat.home}/webapps" />
</target>
|
scp 태스크를 호출할 때, 복사하고자 하는 로컬 파일의 위치와 로컬 개인 SSH 키 파일(보안 인증에 사용되는 Listing 6의 ssh.key.file)의 위치를 제공해야 한다. 마지막으로, scp가 로컬 파일(들)을 배치할 원격 머신의 위치(Listing 6의 ssh.server.hostname)도 제공해야 한다.
SSH로 프로세스를 원격에서 호출하기
SCP와 마찬가지로, 원격 머신에서 명령어를 실행하려면 SSH 같은 보안 메커니즘이 필요하다. Listing 7에서, JSch sshexec
Ant 태스크를 사용하여 원격 머신에 있는 Tomcat 컨테이너를 중지하고 나서 재시작 한다. 아마도, 이것은 빌 프로세스가 WAR 파일 같은 일련의 에셋들을 안전하게 복사했던 것과 같은 머신일 것이다.
Listing 7. 원격 Tomcat 인스턴스 중지 및 재시작
<target name="remote-tomcat-stop>
<sshexec host="${ssh.hostname}"
port="${ssh.port}"
keyfile="${ssh.key.file}"
username="${ssh.username}"
passphrase=""
trust="true"
command="${tomcat.home}/bin/shutdown" />
<sleep seconds="${sleep.time}" />
</target>
...
<target name="remote-tomcat-start">
<sshexec host="${ssh.hostname}"
port="${ssh.port}"
username="${ssh.username}"
passphrase=""
trust="true"
keyfile="${ssh.key.file}"
command="${tomcat.home}/bin/startup" />
<sleep seconds="${sleep.time}" />
</target>
|
Listing 7에서, Tomcat이 있는 머신 이름, Tomcat용 포트 넘버(주로 8080), 개인 키 파일(ssh.key.file)을 제공하여, 빌드 스크립트가 안전하게 머신에 액세스 하여 특정 명령어를 실행하도록 하였다. 이 경우, 필자는 shutdown 명령어 다음에 startup 명령어를 호출했다.
이것으로 모든 것을 다 수행했다: 원격 데이터베이스를 설정했고, 웹 애플리케이션을 원격 머신으로 이동했으며, Tomcat의 인스턴스를 보냈다. 따라서, 새로운 버전의 애플리케이션이 실행되어 사람들은 정상적으로 테스트 및 사용할 수 있게 되었다.
사람을 위한 전개 자동화
전개 프로세스를 자동화 하는 것이 얼마나 쉬운 일인지를 보여주었다. 개발한 소프트웨어를 고객에게 전달하는 작업이 수동 프로세스가 되어서도 안되며, 개발 팀의 빌드 프로세스와 분리되어서도 안된다. 사실, 이러한 접근 방식을 사용하여, 소프트웨어를 릴리스 하는 것은 버튼을 누르는 것만큼이나 쉽고, 물론 개발팀은 기능을 고객들에게 자주 제공할 수 있다.
참고자료 교육
제품 및 기술 얻기
-
JSch: 보안 통신을 위한 Java Secure Channel 다운로드.
-
Ant: Ant 다운로드 및 소프트웨어 구현.
-
Tomcat: Tomcat 웹 컨테이너 다운로드 및 웹 애플리케이션 구현.
-
DbUnit: DbUnit 다운로드 및 XML을 사용한 데이터 관리.
-
예제 코드: 본 기술자료의 예제 스크립트.
토론
필자소개
기사에 대한 평가
|  |