목공책 하나 들이셔요~

2014년 1월 30일 목요일

Mercurial 서버 hgweb 설치하기

소스 컨트롤 관리도구(Source Control Management Tool, 이하 SCM)은 소스코드의 형상을 관리하고 팀이 협업하여 개발을 할 수 있도록 지원하는 매우 중요한 인프라입니다.

CVS로 대중화된 SCM은 이후 Subversion으로 대폭 물갈이 되었는데 이들 중앙집중식 SCM의 문제점들이 심각해지면서 새로운 개념이 나오기 시작합니다.

이 새로운 개념은 분산형 버전 컨트롤 시스템(Distributed Version Control System, 이하 DVCS)이라고 불리며, 2단계 레포지토리를 가지는 특징이 있습니다. 로컬 레포지토리는 개발자 개인의 로컬 저장소에서 유지 관리되며, 특정 마일스톤에 다다르면 중앙에 있는 레포지토리로 변경 내용들을 올릴 수 있습니다.

개인이 코딩하는 동안은 불완전하거나 테스트되지 않은 코드들이 있기 때문에 이 코드 변경이 다른 팀원에게 전달되면 문제를 일으킬 수 있습니다. DVCS를 이용하면 개인은 자신의 로컬 레포지토리를 이용하여 자유롭게 버전 관리를 하고, 검증된 코드들은 중앙 레포지토리에 올려서 다른 팀원들이 안전한 코드를 내려받게 할 수 있습니다.

DVCS는 현재 Mercurial과 Git가 대세를 이루고 있습니다. 둘이 비슷하기도 하지만 많은 차이점을 가지고 있기도 합니다. 개발자들간에 Mercurial이 낫네, Git가 낫네... 하면서 논쟁들이 있지만 저는 Mercurial을 더 선호합니다. Mercurial이 기존에 많이 사용되던 Subversion에 좀 더 가깝고, 개념이 비교적 단순하면서 깔끔하기 때문입니다.


저는 Mercurial을 좋아합니다. 그리고 저희 팀도 Mercurial을 선택했습니다. 왜냐하면 제가 팀장이니까요. ^^

Mercurial의 로컬 레포지토리는 소스가 있는 파일시스템에서 .hg 디렉토리 아래에 보관됩니다. 반면 Mercurial의 중앙 레포지토리는 별도로 설치를 해야 합니다. 이 글에서는 Mercurial의 중앙 레포지토리 역할을 할 Mercurial 서버를 설치하는 법에 대해서 알아봅니다.

Mercurial 서버의 종류

Mercurial의 중앙 레포지토리를 운영하는 방법과 지원도구들은 10여종이 있습니다. 저는 Mercurial Server를 Linux에서 돌릴 것이기 때문에 Windows에서만 지원되는 몇몇 완성도 높은 솔루션은 제외시켜야 했습니다. 그리고 인터넷 상에서 Mercurial 중앙 레포지토리를 호스팅하는 서비스들도 있는데, 오픈소스 프로젝트가 아닌 보안이 필요한 회사의 개발팀을 위해서는 그리 적절치 않습니다.

이것들을 제하고 남은 Mercurial 서버 솔루션은 대략 세가지로 압축됩니다.

hg serve

Mercurial의 실행파일인 hg에는 기본적인 서버 기능이 포함되어 있습니다. 실행방법은 매우 간단합니다. 로컬 레포지토리가 있는 즉 .hg 디렉토리가 있는 곳으로 이동 후 "hg serve"라는 명령을 입력하면 됩니다. hg serve는 기본적으로 8000번 포트를 오픈하여 Web으로 서비스를 제공합니다. 그러므로 웰브라우저를 띄워 http://localhost:8000 으로 접속하면 다음과 같은 레포지토리를 브라우징할 수 있는 화면을 만날 수 있습니다.


다른 PC에서 hg serve로 오픈된 레포지토리에 접근하여 소스를 내려 받으려면 "hg clone http://<host-name>:8000 prj-name" 과 같은 식으로 입력하면 됩니다.

하지만 간단하게 구현된 것이라 많은 기능들이 누락되어 있습니다. 하나의 레포지토리만 지원하며, 인증이나 보안과 같은 중요한 기능이 빠져 있습니다. 그러므로 hg serve는 인트라넷에서 다른 팀원이 소스를 가져갈 수 있도록 임시로 Mercurial 서버를 띄우는 용도로 사용될 수 있습니다.

상시적인 중앙 레포지토리로 역할을 하기 위해서는 아래 언급하는 hgweb이나 SCM-Manager를 이용해야 합니다.

hgweb

hgweb은 Mercurial에서 공식적으로 제공하는 Mercurial 서버입니다. 그래서 여러개의 레포지토리와 보안 및 인증 기능을 제공합니다. Mercurial 자체가 Python으로 작성되었는데, hgweb 또한 Python으로 작성된 CGI입니다. 그러므로 CGI를 구동할 수 있는 웹서버가 따로 있어야 합니다. 보통 Apache나 IIS를 많이 사용합니다. hgweb은 일반 CGI인 hgweb.cgi, Fast CGI를 위한 hgweb.fcgi, WSGI를 위한 hgweb.wsgi 등의 종류가 있습니다.

자세한 설치방법은 이 링크를 클릭해서 확인해 보시기 바랍니다. 유저 인터페이스는 hg serve의 그것과 매우 유사합니다.

설치 방법이 적힌 URL을 보면 아시겠지만 hgweb을 설치하고 설정하는 것은 다소 까다롭습니다.

SCM-Manager

SCM-Manager는 java로 개발된 범용의 중앙 레포지토리 서버로서 Mercurial, git, Subversion 모두를 지원합니다. 별도의 설정파일 없이 Web UI를 통해서 설정할 수 있어 매우 쉽습니다. 그리고 Windows와 Linux 모두 설치 가능합니다. 설명만 보면 아주 좋은 중앙 레포지토리 서버임에 틀림 없습니다.


하지만 저는 hgweb을 사용하기로 합니다. 설정은 좀 어렵지만 도전 과제라고 생각하면 되고, 중앙 레포지토리로 사용할 서버에 이미 Apache가 설치되어 있는데다가 회사 방화벽을 새로 뚫기가 좀 번거로워서 그냥 뚫려있는 Apache에 WSGI로 올리기로 했습니다.

hgweb 설정하기

설치 환경을 정리해 봅니다. OS는 RedHat Linux이고 Mercurial은 2.8.2 소스 배포판을 깔아서 설치합니다. Apache서버에 hgweb.wsgi를 설치할 것이며, 등록된 사용자만 접근할 수 있는 비공개 설정을 할 것입니다.

(1) Mercurial 설치

먼저 중앙 레포지토리로 삼을 서버에 Mercurial의 Source Release 최신 버전을 다운로드 받습니다. 지금 현재는 2.8.2 버전이네요. 다운로드를 받은 뒤 root 계정에서 다음 명령을 실행하면 Mercurial이 설치됩니다. Python은 미리 설치되어 있어야 합니다.

tar zxf mercurial-2.8.2.tar.gz
cd mercurial-2.8.2
python setup.py install

제대로 설치되었다면 python을 실행한 뒤 import mercurial 을 쳤을 때 에러가 나지 않습니다.

설치 편의를 위해서 mercurial 레포지토리를 관리하는 계정을 하나 만듭니다. 이름은 편의상 mercurial로 합니다. 스크립트와 레포지토리는 mercurial계정의 홈디렉토리인 /home/mercurial 에 놓이게 됩니다.

(2) hgweb.wsgi 수정하고 hg.conf 만들기

hgweb의 WSGI파일은 소스 배포판의 경우 contrib 디렉토리 아래에 있습니다. Ubuntu에서 Synaptic으로 Mercurial을 설치한 경우에는 /usr/share/doc/mercurial-common/examples 디렉토리에 hgweb.cgi, hgweb.fcgi, hgweb.wsgi 파일들이 있습니다.

어찌되었든 hgweb.wsgi파일을 /home/mercurial/hgweb 디렉토리에 옮겨 놓습니다. 그리고 이 파일을 편집합니다. 편집할 내용은 hgweb의 설정이 들어갈 hgweb.config파일의 경로를 지정하는 겁니다. 다음과 같이 수정합니다.

config = "/home/mercurial/hgweb/hgweb.config"

hgweb.wsgi파일이 지정한 hgweb.config 파일의 내용은 다음과 같이 작성합니다.

[paths]
/ = /home/mercurial/repos/**

[web]
baseurl =
allow_push = *
push_ssl = False
descend = True
allow_archive = gz, zip, bz2
encoding = UTF-8

여기서 중요한 것은 paths 항목입니다. 위와 같이 저장하면 repos 디렉토리 아래에 있는 레포지토리들이 보이게 됩니다. 다른 경로에 레포지토리가 있다면 아래에 계속 추가하면 됩니다.

(3) Apache httpd.conf 수정하기

저는 서버에 Mercurial 레포지토리를 위한 별도의 도메인 이름을 할당했습니다. 그러므로 Apache에서 Virtual Host를 설정하고 그곳에 Mercurial 설정을 넣습니다. Apache 홈디렉토리 아래 conf/httpd.conf 파일을 열어서 제일 아래 다음과 같이 추가합니다.

<VirtualHost *:80>
    ServerName hg.some.domain
    ServerAdmin admin@some.domain
    ErrorLog "|/usr/local/sbin/cronolog /home/mercurial/logs/error_log.%Y%m%d"
    CustomLog "|/usr/local/sbin/cronolog /home/mercurial/logs/access_log.%Y%m%d common
    
    DocumentRoot "/home/mercurial/hgweb"
    WSGIScriptAlias / "/home/mercurial/hgweb/hgweb.wsgi"
    <Location "/">
        AuthType Basic
        AuthName "Central Repositories"
        AuthUserFile /home/mercurial/hgweb/hgusers
        Order allow,deny
        Allow from all
        Require valid-user
    </Location>
</VirtualHost>

레포지토리로 사용하는 디렉토리에 Apache가 쓰기를 할 수 없으면 오류가 발생하게 됩니다. 저는 mercurial이라는 사용자를 만들었고, 레포지토리는 mercurial 홈 디렉토리 아래의 repos에 두므로 Apache를 mercurial 계정으로 실행하면 쓰기 권한에 문제가 없습니다. 그러므로 다음과 같이 httpd.conf를 수정하여 User와 Group을 설정합니다.

<IfModule !mpm_winnt.c>
<IfModule !mpm_netware.c>
User   mercurial
Group   mercurial
</IfModule>
</IfModule>

이렇게 할 상황이 안된다면 레포지토리 디렉토리에 Apache가 실행되는 계정에서 쓸 수 있도록 권한을 잘 설정해야 합니다.

(4) 웹 인증을 위한 사용자 등록하기

위 httpd.conf 설정에서 Basic Authentication을 한다고 설정했으므로 해당 사용자를 등록해야 합니다. 사실 Basic은 암호가 평문으로 전송되기 때문에 다소 보안에 취약한 점이 있습니다. 보안이 중요하다면 Basic 인증 + SSL을 세팅하던가 Digest Authentication을 설정하시기 바랍니다. 일단은 Basic 인증으로 설명 드립니다.

위 httpd.conf 설정에서 계정 정보 파일이 /home/mercurial/hgweb/hgusers 라고 지정했습니다. 그러므로 해당 디렉토리에 가서 다음과 같이 계정 파일을 만들고 첫 사용자를 등록하면 됩니다.

htpasswd  -c  hgusers   username

이후 사용자를 추가하려면 다음과 같이 하면 됩니다.

htpasswd hgusers  otheruser

이렇게 httpd.conf를 수정하고 사용자 계정을 만들었으면 Apache를 재시작합니다. 그리고 웹 브라우저로 설정한 IP와 포트로 접속하면 아이디와 암호를 묻는 창이 뜨고 제대로 입력하면 다음과 같이 나와야 합니다.


잘 동작되는지 테스트하기

일단 hgweb에 잘 접속이 된다면 실제로 로컬에 있는 레포지토리를 push하여 잘 되는지 확인합니다.

(1) 사용자 이름 설정하기

팀을 이루어 작업하게 되므로 변경한 내용에 자신의 이름이 기록되도록 먼저 설정해야 합니다. 이를 위해서 Mercurial을 설치한 후 사용자의 홈 디렉토리에 .hgrc 파일을 만들어 다음과 같이 사용자를 등록합니다. 이 사용자 명은 누가 변경했는지 지정해주는 역할을 합니다.

[ui]
username = Your Name <your@email.adress.com>

(2) 로컬 레포지토리에서 작업하고 push 해보기

보통은 로컬에서 먼저 hg init으로 프로젝트를 만들고 첫 변경작업을 합니다. 그리고 어느 정도 골격이 잡히면 중앙 레포지토리로 올리게 됩니다. 프로젝트 명이 test라고 하면 다음과 같은 명령으로 중앙에 push할 수 있습니다.

hg push http://some.domain/test

하지만 실행해보면 "HTTP Error 404 : Not Found"라는 에러가 발생할 겁니다. 이것은 hgweb이 존재하지 않는 레포지토리를 새로 만들어주지는 않기 때문입니다.

그러므로 중앙 레포지토리 서버로 접속하여 그곳에서 직접 레포지토리를 만들어야 합니다. 서버의 /home/mercurial/repos 디렉토리로 이동하여서 다음과 같은 명령을 입력합니다.

hg init test

이렇게 하면 빈 레포지토리가 생깁니다. 이제 다시 자신의 컴퓨터로 돌아와서 아까 입력한 hg push 명령을 실행하면 잘 올라감을 확인할 수 있습니다.


그런데 실제로 레포지토리 서버의 test 디렉토리에 들어가보면 작업한 파일들은 없고 .hg 디렉토리만 생성되어 있음을 볼 수 있습니다. 이것은 Mercurial의 push 동작이 체인지셋만 업로드하기 때문입니다. 실제 파일들을 보려면 해당 레포지토리에 가서 hg update를 실행하면 됩니다만... 중앙 레포지토리에서는 그럴 필요는 없습니다.

이제 웹브라우저에서 레포지토리 서버로 접속하면 다음과 같이 test 라는 프로젝트가 보입니다. 이 웹 인터페이스를 통해서 변경 사항이라 브랜치 트리 등을 확인할 수 있고 전체 소스를 압축한 파일을 다운로드 받을 수도 있습니다.


(3) 다른 사용자가 로컬 레포지토리로 당겨오기

이제 중앙에 test 프로젝트가 있으므로 다른 팀원이 이 프로젝트를 당겨올 수 있습니다. 다음과 같은 명령으로 프로젝트를 당겨올 수 있는지 확인합니다.

hg  clone  http://some.domain/test

정상적으로 수행되었으면 test라는 디렉토리가 생성되고 소스코드와 레포지토리가 생성됩니다. 팀원은 코드를 변경할 수 있고 나중에 다시 중앙 레포지토리에 push할 수 있습니다. 하지만 그 전에 다른 사람이 변경한 내용이 중앙 레포지토리에 있는지 확인해야 합니다. 이를 위해 hg pull 명령을 사용합니다. 충돌이 있다면 merge한 다음 commit하고 push하면 됩니다.

이에 대한 자세한 내용은 아래 관련글을 참고하시기 바랍니다.


관련글 :
  - [Hg] 2. 팀을 위한 Mercurial 셋팅

참고 URL
  - Mercurial 서버 종류들 : http://mercurial.selenic.com/wiki/PublishingRepositories
  - SCM Manager에 대한 설명 : https://bitbucket.org/sdorra/scm-manager/wiki/Home

댓글 없음:

댓글 쓰기