Skip to content

2014 07 14 패키지 배포와 버전 관리에 관하여

krikit edited this page Oct 21, 2014 · 2 revisions

사내 혹은 오픈소스로 패키지를 배포할 때 버전 관리와 더불어 여러 가지 고려해야할 사항들에 대해 그간의 제 경험에 비추어 말씀드려 보려 합니다.

개요

  • 버전이란 소프트웨어, 문서 혹은 기타 모든 수정(개정)이 발생하는 (전자) 저작물의 이력을 관리하기 위해 번호 혹은 식별자를 부여한 것을 말합니다.
  • 버전(형상) 관리란 이러한 버전을 부여하는 방식과 이력을 다루는 전반적인 절차를 의미합니다.
  • 본 문서의 버전 관리에 관한 주요 컨셉은 Semantic Versioning을 따르고 있습니다.

버전 체계

  • 버전은 크게 major 버전, minor 버전, 패치의 3개의 번호로 부여합니다.
    • 예: 1.0.0 ; 2.1.0 ; 3.0.1
    • 그러나 패치 번호는 0인 경우에 한해서 생략할 수 있습니다.
      • 예: 1.0 ; 2.1
  • 각 번호 체계의 의미는 아래와 같습니다.
    • major 버전: 가장 큰 버전 단위. API 혹은 사전의 하위 호환성이 깨질 경우 판올림합니다.
    • minor 버전: 하위 호환성이 유지되는 상황에서 (정기적으로) 배포되는 경우의 판올림합니다.
    • 패치: 기존 배포된 버전의 심각한 오류를 수정하여 재배포하는 경우 사용합니다.

SO 버전

  • SO(shared object) 버전이란 공유 오브젝트(라이브러리) 버전의 (하위) 호환성 정보를 시스템에 제공하여 런타임에 올바른 버전의 오브젝트와 다이내믹 바인딩이 이루어지도록 하는 메카니즘을 말합니다. 이때 공유 오브젝트 내에 정의된 soname 필드를 사용하게 됩니다.
  • 링크 시 soname 지정 방법
# Linux
gcc -fPIC *.o -o libmy_pkg.so.1.2 -soname=libmy_pkg.so.1
ln -s libmy_pkg.so.1.2 libmy_pkg.so.1
ln -s libmy_pkg.so.1 libmy_pkg.so
# Mac
gcc -fPIC *.o -o libmy_pkg.1.2.dylib -soname=libmy_pkg.1.dylib
ln -s libmy_pkg.1.2.dylib libmy_pkg.1.dylib
ln -s libmy_pkg.1.dylib libmy_pkg.dylib
# CMake
set_target_properties(my_pkg PROPERTIES SOVERSION 1 VERSION 1.2)

Windows DLL은 잘 모르겠습니다. (있을 것 같은데 말이죠..)

패키징

  • 패키지는 다음과 같은 이름으로 압축하여 배포합니다.
[패키지 이름]-[버전 번호]-[arch]-[suffix].tar.gz

예: my_pkg-1.1-win32.zip, your_lib-2.0-x86_64.tar.gz

  • 각각에 대한 상세 가이드라인은 아래와 같습니다.

    • 패키지 이름: 소문자를 사용하고 dash(-)보다는 underscore(_)를 사용합니다. 패키지 이름은 저장소(git, svn) 이름과 일치시킵니다.
    • 버전 번호: 버전 체계 참조
    • arch: architecture, os, platform 등을 의미하며 아래 중 하나를 사용합니다.
      • x86_64: Linux 64비트
      • i386: Linux 32비트
      • win32: Windows 32비트
      • osx_64: Mac OS X 64비트
    • suffix: 부가적인 정보
      • alpha, beta, rc 등 stage 정보
      • 실험 버전의 경우 커밋 번호
      • redhat6 등 기타 정보
  • 패키지의 압축을 풀면 나오는 일반적인 레이아웃은 아래와 같습니다.

    • readme.md: 가장 먼저 읽어봐야 할 텍스트(markdown) 형식의 문서
    • bin/: 실행 가능한 바이너리(혹은 스크립트) 유틸리티
    • doc/: 문서. 일반적으로 doxygen으로 자동 생성한 API 문서
    • example/: API를 이용한 샘플 코드
    • include/: 패키지가 외부에 제공하는 API 헤더
    • lib/: API 라이브러리. LD_LIBRARY_PATH 환경 변수에 추가
    • pylib/: python API 라이브러리. PYTHONPATH 환경 변수에 추가

소스 관리

  • 배포한 패키지는 문제가 발생할 경우에 대비하여 배포 시의 상태로 복원이 가능하도록 관리되어야 합니다.
  • 최초의 정식 배포 버전은 1.0으로 하고 매번 배포 후 다음 절차를 수행합니다.
    • SCM 저장소에 표시합니다.
      • git: 버전 번호 앞에 'v'를 붙여 태깅합니다.
      • svn: trunk 디렉토리 전체를 tag 아래에 버전 번호로 생성하여 복사합니다.
    • 버전 번호가 소스코드 혹은 어딘가 파일에 명기되어 있는 경우, 다음 버전의 개발 시작 전에 다음 배포할 버전으로 즉시 판올림합니다.
      • 따라서, 현재 개발중인 버전은 아직 배포되지 않은 버전입니다.
    • 이슈 트래커를 사용한다면 해당 프로젝트(패키지)에 다음 배포할 버전을 추가합니다.

배포

정규 버전

  • 버전 정책에 따라 공식적으로 릴리즈 노트와 함께 배포하는 버전을 말합니다.

패치(핫픽스) 버전

  • 정식 배포한 패키지에 문제가 발생하면 일단 배포했던 상태로 소스코드를 복원합니다.
    • git: checkout을 이용하여 해당 태그(버전)로 이동합니다.
    • svn: switch를 이용하여 해당 태그로 이동합니다.
  • git의 경우 소스 코드의 변경이 발생하므로 버전 태그 앞에 'v'대신 'b'를 붙여 브랜치를 생성합니다.
  • 문제점을 수정하고 커밋합니다.
  • 패치 번호를 판올림하여 패키징 및 배포합니다.
    • 예: 1.0 --> 1.0.1 ; 3.0.1 --> 3.0.2
  • 중요한 변경 사항의 경우 master 브랜치(svn의 경우 trunk)에도 반영합니다.

실험(비공식) 버전

  • 때로는 정식 배포 전에 차후 추가될 feature를 미리 써보고 싶거나, 기존 버전에서 발생한 버그가 새로운 버전에서는 해결 되었으나 급하게 사용해야할 때가 있습니다. 이러한 경우 정식 배포 및 핫픽스 배포와는 별도로 비공식적인 실험 버전을 배포합니다.
  • 실험 버전의 경우 현재 master 브랜치(svn의 경우 trunk)에 문제가 없다면 바로 패키징하여 배포하면 됩니다.
  • 실험 버전은 아래와 같은 이름으로 압축하여 배포하되 공지 없이 필요한 사람에게 알려주면 됩니다.
 [패키지 이름]-[버전 번호]-[arch]-[커밋 번호].tar.gz
  • 커밋 번호는 아래와 같이 명명합니다.
    • git: 커밋 해쉬 코드 7자리
      • 예: my_pkg-1.1-win32-6dc6a18.zip
    • svn: 리비전 번호
      • 예: your_lib-2.1-osx_64-r1234.tar.gz
  • 실험 버전은 별도의 태그나 브랜치를 생성하지 않고 핫픽스 지원도 하지 않는 것을 원칙으로 하고 추후 개발이 완료되면 정식 버전 사용을 유도합니다.

이슈 트래커

  • 이슈 트래커란 소프트웨어 개발 과정에서 발생하는 이슈(버그, feature 등)를 추적, 관리하는 도구를 말합니다. 대표적인 것으로 JIRA, Redmine, Trac, Mantis 같은 것들이 있고, 요즘 핫한 Trello도 있습니다.
  • 이슈 트래커는 다음과 같은 특징을 갖습니다.
    • 사용자가 버그를 등록할 수도 있고, 기획자나 프로젝트 오너가 기능 요구사항(feature)을 등록할 수도 있으며, 물론 개발자가 리팩토링 같은 할일을 등록할 수도 있습니다.
    • 이슈는 대부분 다음 워크 플로우에 따라 관리됩니다.
      • 등록(open) --> 담당자 할당(assigned) --> 수정(resolved, 처리) --> 닫힘(closed)
      • 시스템이나 조직에 따라 할당과 수정 사이에 분석 단계가 있다거나, 이슈를 닫지 않고 폐기하는 단계가 존재하기도 합니다.
    • 프로젝트는 버전 정보를 등록하고 버전 변경(배포와 추가)에 따라 변경 기록(change log)과 로드맵(마일스톤)을 일목 요연하게 정리하는 기능이 있습니다.
      • 현재 개발 버전에서 수정이 완료된 이슈들은 이 버전이 배포될 때 릴리즈 노트에 변경 기록으로 리스트업합니다.
      • 담당자가 할당되고 수정(개발) 계획이 잡힌 이슈는 처리 완료되어 배포될 버전을 예상할 수 있는데, 이러한 미래에 배포할 버전 별로 수정(개발)할 이슈 목록을 로드맵이라합니다.
      • 예: Mantis의 경우 Mantis 자신을 개발하면서 이슈 관리를 Mantis로 하고 있는데, 버전에 따른 변경 기록로드맵을 보면 이해하기 편할 것입니다.
      • 참고로, 변경 기록은 배포와 함께 고정되는 것이고 당연히 로드맵은 아직 배포하지 않았으므로 다른 버전으로 이동이 가능합니다.
  • 이슈 트래커는 보통 프로젝트 단위를 소스코드 저장소와 동일하게 연동하여 아래와 같은 부가적인 효과도 얻습니다.
    • 소스 커밋 시 이슈 번호(혹은 링크)를 기록하는 식으로 커밋 로그를 간편하게 작성할 수 있습니다.
    • 이슈 번호와 함께 커밋로그를 작성할 경우 해당 이슈가 자동으로 닫힙니다.
    • 코드 리뷰 시 이슈 번호가 있으므로 배경 설명을 따로 할 필요가 없습니다.

참고로, Trac은 자체 위키 기능과 svn 연동 기능을 갖는 최초의(?) 이슈 트래커로서 센세이션을 일으켰으나.. Redmine이 나오며 망했고, JIRA는 Confluence(위키), Stash(git)와 연동되는 명실상부한 최고의 상용 툴이라 생각합니다. Mantis는 단순하고 오덕같은 UI로 나름 매니아층을 형성하고 있는 툴이라고 개인적으로 생각합니다. ^^; Trello는 너무 이쁜 칸반보드입니다. 끝.

스크럼

스크럼의 경우 직접 경험해 보지 않고 이론적으로만 알고있는 내용으로서, 효과나 부작용에 대해서까지 자세히 알지 못하는 점을 인지하고 읽어주시기 바랍니다.

  • 스크럼(scrum)은 반복, 점진적으로 소프트웨어를 개발하는 애자일 소프트웨어 공학의 하나의 방법론을 말합니다.
    • 참고: http://ko.wikipedia.org/wiki/스크럼_(애자일_개발_프로세스)
    • 특징(키워드)
      • 제품 백로그: 개발할 제품의 기능(feature)대해 우선순위와 함께 정렬된 목록
      • 스프린트: 반복적으로 수행하는 하나의 개발 주기
      • 스프린트 백로그: 이번 스프린트에 진행할 자세한 할일 목록과 할일 별 예측 시간. 제품 백로그에서 최상위 우선순위부터 이번 스프린트에 가능한 만큼 가져옵니다.
      • 일일 스크럼: 날마다 짧게 (서서) 진행되는 진척 상황 미팅
      • 스프린트 회고: 스프린트 종료와 함께 좋았던 점, 개선할 점 등을 서로 이야기하는 자리
  • 하나의 프로젝트를 하나의 스크럼팀으로 지속적으로 (애자일하게) 개발할 경우, 정기적으로 배포를 수행하고 이에 따라 매 스프린트 종료와 함께 배포하는 방법이 좋습니다.
  • 스프린트 백로그는 이슈 트래커에 등록하여 진척 상황을 파악하는데 활용합니다.
    • 번 다운(burn down) 챠트가 지원되면 예측치 대비 완료된 일들과 이번 스프린트에서 완료할 수 있는 일들을 그림으로 볼 수 있습니다.
    • 칸반(kanban) 보드가 지원되면 To Do, Doing, Done 상황을 일목요연하게 파악할 수 있습니다.
  • 스프린트가 진행되는 동안 치고 들어오는 업무는 제품 백로그에 쌓아놓고 다음번 스프린트(배포 버전)에서 수행합니다.
    • 만약 당장 해야만 한다면 현재 스프린트 백로그에서 뒤에서 부터 빼고 집어넣고, 그것도 불가능하면 스프린트를 중간에 깨야할 지를 결정해야합니다.
Clone this wiki locally