티스토리 툴바


Matlap2013/05/11 13:54

이글은 CAPTIG(Computer Vision And Pattern Recognition Technical Interest Group)에서 토론된 내용을 정리한 글입니다.

http://cafe.naver.com/ipexpert 은 현재 비밀 카페로 유지되고 있습니다.

==================================================


MATLAB으로 코딩하는 주 이유는 

1. 제가 생각하는 바를 표현하는데 무지 하게 시간이 적게 걸린다는 장점 때문입니다. 어떤 알고리즘을 검증하거나 새로운 것을 만들 때 MATLAB으로 구현을 하면 빠르게 구현을 할 수 있습니다.
   전산과에서도 알고리즘을 담당하는 분야에서는 MATLAB을 많이 사용하는 것으로 알고 있습니다.


2. (이미 잘 알고 있는 입장에서는) 배우는데 하루면 충분하지 않을까 하는 생각이 들 정도로 배우기도 쉽습니다.
   디버깅도 너무 쉽습니다.
   많은 소스가 공개되어 있고, 소스 이해가 다른 언어에 비해서 쉬워서
   다른 사람의 소스로부터 내용을 배우는 것이 쉽습니다.

   저는 인터넷에서 어떤 개념을 찾을 때 keyword + matlab 으로 찾습니다.
   그리고 위와 같은 조합을 google에서만 찾는 것이 아니라 google image에서도 찾습니다. 그러면 그림 및 plot이 함께 나와 있는 알고리즘을 쉽게 찾을 수 있습니다. (CVIP의 장점)


3. Research 기관에서 Computer vision or image processing 관련 연구자를 찾을때 거의 99% 연구 기관에서 사용하는 툴이 C++와 MATLAB 임을 job search 사이트에서 알 수 있습니다. 
   나머지 툴들은 추가 사항입니다.


4. 특정 회사가 만들기 ㅤㄸㅒㅤ문에 비교적 자료나 버젼 문제나 메뉴얼 문제(Help file이 좋음)들이 자유롭습니다. MATLAB과 유사한 무료 버젼으로 GNU에서 만든 Octave라는 것이 있는데, 저도 무료나 cross platform을 무지하게 좋아합니다만,     버젼 컨트롤 문제나 문서화 부분에서는 회사의 서비스를 받는 쪽이 편한 것이지요.


단점은...
1. 결국 이렇게 검증된 아이디어를 다시 C++로 만들어야 하는데, 이것도 만만치 않은 과정이지만, 제 경험에 의하면 이것이 더 빠르다는 생각이 듭니다.
그냥 처음부터 C++, OpenCV와 같은 것으로 덤벼들면 언어를 모르기 때문에 그 자체로부터 생기는 문제와 알고리즘 구현에서 생기는 문제를 따로 분리하는데 생각보다 어려움이 많고요,(사실 전자에만 올인 하기도 벅찰 경우가 있는데요.) 디버깅 시간도 오래걸리고요, 그것이 논리적인 문제인 경우에는 정말 어려움이 많습니다.
장점처럼 써져버렸는데, C++로 다시 만들어야 하는 부분이 단점입니다.


하지만 저희 연구실 처럼 real time software 를 만들어서 진짜 outdoor 환경에서 테스트를 하는 랩의 경우에 MATLAB으로 뭐를 fancy 하게 보여줘도, "그래서 뭐" 그런 분위기까지는 아니더래도 그 코드는 무용지물이 됩니다.
그것을 결국 C++로 만들어서 다른 소프트웨어들과 연동을 하면서 작업이 이루어져야 합니다.


2. 가격이 많이 비쌉니다.
   그래도 사줘야 한다고 생각합니다. MATLAB이 과학 기술의 발전에 끼친 영향도 무시 못할 겁니다. 등등이 생각나는데 다른 분들의 의견을 어떤신가요?


3. MATLAB의 다양한 툴박스의 함수 사용법만 알고 그냥 풀기 위한 용도로 사용을 한다면,

배우는 학생이나 researcher의 입장에서는 OpenCV보다 더 나쁜 툴이 될 수도 있습니다.


====================================================== 

토론1

한마디로 얘기하자면, "fast prototyping"이죠.
프로그래밍이 쉽고, 코드가 간결하고, 이미 준비되어 있는 함수가 많기 때문에 이럴 수 있습니다. 프로그래밍이 쉬운건.. 언어 중에 짜기가 제일 쉽다는 말이 있을 정도이고 코드가 간결한건 for문을 쓰지 않고 할 수 있는 특징적인 문법이 있는게 대표적이고, 준비되어 있는 함수가 많은건 Toolbox라는, 용도에 따른 라이브러리 모임때문입니다.


토론2

단점 1도 결국 장점이 아닌가 싶은데요... 큰 data이면서 real time을 요구하는 경우가 아니라면 매트랩만으로도 충분히 커버가 가능한 것 같습니다. 저희랩 같은 경우에는 대부분을 매트랩만으로 구현을 하고 있습니다. 새로운 알고리즘을 목적으로 하는 연구자의 입장에서는 매트랩은 더할 나위없이 좋은 툴인건 분명한 것 같습니다.


토론3

매트랩이 분명 좋지만, 회사에서는 매트랩 코딩 후 c++으로 바꿀 수 있는 시간적 여유조차 주어지지 않는다는 거겠죠. ( => 회사는 리서치 기관이 아니니까요. 그러나 아래도 말씀드렸듯이 알고리즘 자체가 논리적으로 틀렸을 경우에는 그것을 C++ 상에서 잡는 것보다는 MATLAB 상에서 테스트 하고 잡아내는 것이 무지하게 빠르고 편합니다.)


토론4

c++로 영상처리 코딩이 익숙해짐 속도 차이가 없습니다... 특히 동영상 데이타를 접근하고 분석하는 경우 c++이 훨 좋은데.... 매트랩으로 하는 경우 동영상 처릴 하는 경우 속도가 문제가 되던데요...c에서 매트랩 라이브러리 콜 하니 속도가 문제가 되던데요... ( =>저도 요즘들어서는 ***님의 말씀처럼 C++로 구현을 해도 속도가 별로 차이가 없다는데 동감합니다. 단 코딩이 익숙해졌다는 가정에 있어야 하는데, 코딩 익숙해 질려면 몇년 걸리기도 하고, 학부 수준에서 코딩이 익숙해 진다음에 FFT 같은것 C++ 구현하기가 쉽지 않고요, 대학원 수준에서도 어려움 알고리즘이라면 개념이 혼동스러울때가 많은데 그것을 C++로 곧장 구현하다가는 개념적인 문제가 생길수도 있다고 생각합니다.)


토론5

Python + OpenCV도 사실 MATLAB의 대안이라고 생각이 되더군요... 어떤 부분에서는 MATLAB만큼 빠르게 Prototype을 만드는 방법은 정말 없다고 생각되거든요. 한가지 확실한것은 Prototype이 확실하면 그 다음에는 별 어려움 없이 구현도 된다고 생각합니다. 실제 한번 짜보고 나서 다시 짜는 일이 의외로 첨부터 다 생각하는 것 보다 빠를 수가 있거든요. 일을 나눠서 주기도 좋고요. (=> 제가 Python에 대한 언급을 이 글에서는 하지 않았는데, Job search를 하다보면 Python도 역시 C++ / MATLAB에 추가하여 많이 사용하고 있는 듯 합니다. 즉 다량의 데이터 분석에서 너무 편하거든요. 이것도 MATLAB 처럼 다양한 툴박스(?)가 제공되어 있는 형태이고요.
불편하지만 참을만한 것은,  담당하는 회사가 없으니까, documentation이라던지, 버젼 컨트롤이라던지 하는 이슈를 스스로 찾아가면서 해야한다는 점입니다. 저는 처음 배우면서 이 부분이 가장 불편했는데, 그것 빼고는 아주 만족스러워서 계속 활용할 예정입니다.)


토론6

MATLAB으로 짠 코드는 상용으로는 절~대 쓰일 수 없다고 봅니다만.. ***님 말하신데로 속도 문제 때문에.. 그 럼 대안이 뭔가.. 뭐 역시 C 아니면 C++이겠죠. 하지만 아직 영상처리에서 큰 인기는 끌지 못하지만 Java도 주목할 만 하다고 봅니다. 눈여겨보는 1인 기업이 있는데 철저히 Java를 씀으로써 생산성과 품질을 동시에 거두고 있더군요. (=> JAVA역시 속도 때문에 꺼린다는 이야기를 많이 들었습니다. 뭐 그 이야기를 뒷받침 할만한 뭔가를 읽어본 적은 없지만, 앞서 말씀드렸듯이 인더스트리에서 C++을 주로 쓰는 이유도 이유라면 이유가 될 수 있겠지요. JAVA는 현재 가장 많이 사용되고 있는 언어임에도 불구하고 영상처리에서 많이 활용을 안하고 있는 이유가 이런 문제인 가 봅니다. )

저작자 표시

'Matlap' 카테고리의 다른 글

MATLAB 으로 코딩을 하는 이유  (0) 2013/05/11
Posted by 세계유목민
VCS2013/04/13 08:54

PPT 깔끔하게 요약 정리한 내용 (Git관련)


Eclipse를 활용한 효율적인 팀 개발 및 배포 전략

0. 목차

0. 소개

이 문서는 오픈 소스 자바 어플리케이션을 개발하기 위해 이클립스가 어떻게 사용될 수 있는지에 대해 설명한다.

팀 개발을 위해서 CVS 등의 버전관리 툴과 함께 이클립스를 사용하는 방법에 대하여 알아보고, Ant, Maven 등을 통한 빌드 자동화 시스템에 대해서 알아보도록 한다. Eclipse 는 버전 3.1 을 이용하였다.

CVS 와 Ant 등을 이용한 개발 프로세스는 다음과 같다.



1. CVS 등을 통한 효율적인 팀 개발

소프트웨어 개발 환경에서 기술적으로 가장 중요한 것은 소스 버전 관리이다. 개발팀에서 작성하는 모든 소스는 버전 관리가 되어야 한다. 프로그램 소스는 물론이고 스크립트, SQL, 각종 문서, 설정 파일들까지 포함해야 한다. 소스 버전 관리의 목적은 작업 기록의 보존을 통해 문제가 발생했을 때 원인을 추적하거나 이전 상태로 되돌리기 위한 것이다. 또한 이러한 정보로 버그 추적이나 감사(audit), 퍼포먼스, 품질 관리 목적에 사용할 수도 있다.

보통 소스 버전 관리를 위해서 CVS(Concurrent Versions System)를 많이 사용한다. CVS는 80년대부터 개발되어 오고 있으며, 오픈 소스 개발을 위한 사실 상의 표준이 되어 버린 버전 제어 도구이다. CVS를 좀 더 개선한 Subversion도 있고 여러 가지 상용 툴도 있지만 여전히 CVS가 오픈소스 공동체에서 가장 많이 쓰이며 IDE와도 잘 통합되어 있다.

소스 관리는 사실 SCM(Software Configuration Management)의 일부분이기도 하다. SCM은 소스에 대한 버전 관리 뿐 아니라 소프트웨어의 기능성 수준에 대한 변동 기록, 버그 수정 내역, 요구사항의 변화 등을 종합적으로 관리하는 것을 말한다. 소프트웨어의 새 버전이 발표되면 보통 릴리스 노트(Release Notes)가 같이 배포되는데 이런 것이 SCM의 대표적인 산출물이다.

상용 SCM 툴도 많지만 보통은 소스 관리에 CVS를 쓰고 이외에는 이슈 트래커를 쓰는 것으로 SCM의 대부분의 영역이 커버됩니다. 소스 외의 형상 관리는 사실 업무 요청 관리와 기능적으로 아주 비슷하기 때문이다. 오픈소스와 친한 사람이라면 버그질라(bugzilla)를 접해본 적이 있을 것이다. 버그를 보고하고 버그가 수정되는 과정을 기록으로 남기고 조회할 수 있게 해주는 시스템이다.

여기서는 eclipse 에서 제공하는 CVS 기능과 기타 plugin 을 통해 소스코드를 개발 팀과 공유하는 기능을 알아보고, 효율적인 버전관리 방법에 대해 살펴보도록 하자.

1.1 CVS 및 기타 버전관리툴 소개

1.1.1 CVS 개념

먼저 몇 가지 기본적인 CVS 개념을 살펴보자.

CVS vocabulary

Repository
The repository is where the files are stored, often on a server. Sometimes also called a depot (e.g. with Perforce). 
Commit
A commit (or, more rarely, install, submit, check-in or ci) occurs when you copy the changes you made on the local files to the directory (the version control software takes care of knowing which files changed since the last time the two were synchronized). 
Change
A change represents a specific modification to a document under version control. The granularity of the modification considered a change varies between version control systems. 
Change List / Change Set 
On many version control systems with atomic multi-change commits, a changelist identifies the set of changes made in a single commit. This can also represent a sequential view on the source code, allowing source to be examined as of any particular changelist ID. 
Check-Out
A check-out (or checkout or co) copies a working copy from the repository (it can be seen as the opposite of an import). 
Update
An update (or sync) copies the changes that were made to the repository into your working directory (it can be seen as the opposite of a commit). 
Merge / Integration
A merge or integration brings together (merges) concurrent changes into a unified revision. 
Revision 
A revision or version is one version in a chain of changes. 
Import
The term import is used to describe copying the local directory tree in its entirety from your machine to the repository. 
Export
An export is similar to a check-out except that it creates a clean directory tree without version control metadata (often used prior to publishing the contents). 
Conflict
A conflict occurs when two changes are made by different parties to the same document or place within a document. Since the software may not be intelligent enough to decide which change is 'correct', a user is required to resolve the conflict. 
Resolve
The act of user intervention to address a conflict between different changes to the same document.

CVS 저장소

CVS 서버는 다수의 모듈(modules)을 포함하고 있는 저장소(repository)를 관리한다. java.net의 저장소의 경우 개별 프로젝트는 자신만의 모듈을 가지고 있다.

모듈은 디렉토리와 함께 버전이 부여된 파일을 포함하고 있다. 버전이 부여된 파일은 하나의 파일에 대한 이력을 나타내며, 다수의 개정 이력(revisions)을 포함한다. 파일에 변경이 가해질 때마다, 새로운 개정본(revision)이 생성된다. .java, .xml, .properties 등의 텍스트 기반 파일의 경우, 각각의 개정본은 이전 개정본에서 개정된 내역만을 포함하며, .exe, .jar, .pdf 등의 이진 파일의 경우, 각각의 개정본은 완전한 파일 내용을 포함하게 된다.

CVS는 또한 개정본 생성자와 개정본에 대한 주석, 그리고 개정본 번호도 함께 기록한다. 개정본 번호들은 자동으로 갱신되는데, 대부분의 경우, 파일의 첫번째 개정본 번호는 1.1이고 이후에는 1.2 등의 순서로 갱신된다.

repository
    moduleA/
          versionedFile1
             (revision number="1.1" user="dave" comment="Created")
             (revision number="1.2" user="mike" comment="New cache implementation")
             (revision number="1.3" user="lucy" comment="Fixed defect D113")
          versionedFile2
             (revision number="1.1" user="dave" comment="Created")
             (revision number="1.2" user="dave" comment="Updated after feedback from Lucy")
          directory1/
                versionedFile3
                   (revision number="1.1" user="lucy" comment="Initial version")
                ...
    moduleB/
        ...
저장소 접속과 권한

CVS 클라이언트는 다양한 프로토콜을 사용하여 서버에 접속할 수 있다. 가장 일반적으로 사용되는 프로토콜은 다음과 같다:

  • pserver, CVS를 위한 간단한 프로토콜로 java.net을 이용하여 일반적인 작업을 하는 정도에 적합하다.
  • ssh, 추가적인 보안을 위해 SSL을 사용하지만, 보통은 인증서 생성과 같이, 대개 약간의 추가적인 설정 작업이 요구된다.
    접근 권한은 모듈 단위로 설정된다. java.net 저장소의 경우, java.net에 로그인한 모든 사용자는 누구라도 모든 프로젝트 모듈들에 대해서 읽기 권한을 갖게 된다. 프로젝트 모듈에 대한 쓰기 권한은 모듈을 등록한 소유주나 프로젝트 개발자들에만 부여된다.
작업을 수행하기 위한 파일 사본 가져오기(checkout)

저장소에 접속한 이후에는 하나 이상의 모듈을 가져올 수 있다. 이를 checkout 이라고 하는데, *체크아웃*을 하면 CVS에서 여러분의 컴퓨터로 모듈의 최신 내용이 복사되어, 여러분은 모듈 복사본을 가지고 원하는 작업을 수행할 수 있게 된다.

동기화(synchronize), 갱신(update), 작업 공간의 수정 사항 반영(commit)

CVS 클라이언트를 사용하여 로컬 파일과 저장소 파일 사이의 *동기화*를 할 수 있다. 동기화 과정에서 로컬 파일과 CVS의 최신 모듈 사이의 차이점을 볼 수 있다. 이러한 차이들은 다음과 같이 분류 할 수 있다:

  • Incoming changes - 저장소에 변경이 생겼지만 로컬 파일에는 반영이 안된 경우.
  • Outgoing changes - 여러분의 로컬 파일에 변경이 생겼지만 저장소에는 반영이 안된 경우.
    CVS 클라이언트에서 저장소의 변경 사항(incoming changes)의 일부 혹은 전부를 반영하여 로컬 파일을 갱신(update)할 수 있다. 모듈에 대한 쓰기 권한을 가지고 있는 경우, 로컬 파일의 변경 사항(outgoing changes) 중 필요한 만큼을 저장소에 반영(commit)하는 것도 가능하다.
충돌(conflict)

CVS는 자동적으로 저장소의 변경 사항과 작업 공간의 변경 사항 가운데서 충돌하는 내용을 감지한다. 개발자 A와 B가 동시에 같은 파일을 수정하고, A가 먼저 이를 저장소에 반영(commit)하고 난 후에 곧바로 B가 자신이 변경한 내용을 저장소에 반영하려고 할 때 이러한 충돌이 발생한다.

아래 다이어그램을 보자. 숫자로 된 화살표는 일의 발생 순서를 나타낸다. Alice가 Bob보다 먼저 변경사항을 저장소에 반영하고 Bob이 동기화를 하게 되면 Bob은 상충이 발생했다는 것을 알게 된다.

충돌나는 변경 사항 해결하기

파일에서 상충되는 변경 사항이 발견 될 경우, 파일을 저장소에 반영하기 전에 상충되는 변경 사항에 대해 병합(merge, integrate)을 수행해야 한다. CVS는 한 파일의 서로 다른 행의 변경 사항들에 대한 병합은 자동으로 수행한다. 다만 같은 행에서 변경이 발생할 경우, 개발자가 직접 병합 을 실행해야 한다. 나중에 보겠지만 이클립스는 개발자의 병합을 돕는 매우 훌륭한 GUI를 제공한다.

수정중인 작업자 추적

CVS에서는 동시 수정 가능 잠금 방식(optimistic locking)을 사용하여 누구라도 CVS 저장소에 접근에 동시에 파일을 수정 가능하지만, 누가 어떤 것을 수정하고 있는지 알아낼 수 있도 있다. 파일 수정 작업을 시작할 경우, 클라이언트가 이 사실을 서버로 알리도록 설정될 수 있다. 만약 누군가 파일을 수정하려고 하면 이미 그 파일이 수정 중이라는 경고를 받을 수 있다. 이것은 수정 사항의 충돌을 피하는 유용한 방법이다.

(저장소의 파일을)동시 수정 가능 잠금 방식(Optimistic locking)

버전 관리 도구에 따라 저장소에 위치한 파일을 한 사람이 가져가는 경우 해당 파일에 대해 잠금(locking)을 적용한다. 잠금 상태에서는 체크아웃 한 사람이 파일을 다시 저장소로 보내기 전까지는 아무도 파일에 대한 수정 작업을 할 수 없게 된다.

이렇게 엄격하게 잠금을 하는 방식의 버전 관리의 단점은, 종종 다른 개발자들의 수정 작업이 끝날 때까지 대기해야 한다는 점이다. 또한 체크아웃하고 나서 체크인하지 않을 경우, 자신도 모르게 수정도 하지 않는 파일을 잠궈 버리게 된다.

CVS는 잠금을 필요로 하지 않는 동시 수정 가능 방식을 사용한다. 개발자들은 CVS의 충돌 사항을 발견하는 기능을 통해, CVS에서 가져온 파일을 동시에 수정할 수 있다. 충돌나는 사항이 발견될 경우, CVS에서는 이를 해결해주는 도구를 제공한다. 이러한 방식은 위험해 보일 수 있지만, 실제 개발 환경에서는 매우 유용한 방식이다.

아예 충돌이 나는 일 자체를 피하고 싶다면 CVS가 제공하는 파일에 대한 작업자 추적 정보를 이용할 수 있다.

태그(tagging)

개발할 때 여러분은 종종 다음과 같은 이정표(milestones)들에 도달하게 된다:

  • "기본 시스템은 작동중이고 모든 테스트는 통과 했음"
  • "account 작업 전의 리팩토링"
  • "account 작업 후의 리팩토링"
  • "릴리즈 1.4"
  • "발견된 D113에 대한 수정 완료"
    이러한 이정표를 표시해두는 것(marking)은, 변경 사항을 추적하고, 필요한 경우, 이전 상태로 파일들을 되돌릴 수 있도록 보장해주는데 있어 필수적이다.
    CVS에서는 모듈에 태그를 붙임으로써 이정표를 표시하게 된다. 태그는 모듈 안에 있는 각각의 파일들에 대한 단일 개정본(single revision)을 취합한다.

    태그의 이름은 이정표와 관련있다. ALL_TESTS_PASS와 같은 것은 직관적인 예다.

사용자는 모듈의 태그가 부여된 개정본을 저장소에서 가져올 수 있다. 설령 태그가 삭제되거나 변경되었다 하더라도 태그가 붙었던 버전의 모듈 내용물은 항상 같을 것이다.

분기(branches)와 HEAD

분기(branch)는 일련의 독립적인 개발 흐름을 유지하기 위해 쓰인다. 기본적으로 저장소의 내용과 작업 공간의 내용의 동기화를 위해 update나 commit 명령을 사용하면, HEAD라고 불리는 기본 분기(trunk 라고도 불리운다) 상에서 작업이 이루어진다.

사용자는 필요에 따라 새로운 분기를 생성할 수 있다. 분기는 항상 루트 태그(root tag)라 불리는 태그부터 반드시 시작되어야 하며, 루트 태그의 이름에는 특별한 규칙이 없다.

분기를 사용하는 목적인 대개 공식 배포(release)의 병렬적인 개발을 관리하기 위함이다. 예를 들어 어플리케이션의 1.4 버전을 공식 배포(Release) 했고 계속해서 HEAD 분기에서 2.0 버전을 개발하기 시작했다고 해보자. 만약 치명적인 버그가 1.4 에서 발견되었다는 사용자의 보고가 있다면 RELEASE1-4-0을 루트 태그로 사용하여 분기를 만들 수 있다. 


분기 상에서 작업을 시작했을 때, 모듈 내용은 1.4 정식 배포 버전과 완전 동일할 것이다. 이후부터 저장소와의 동기화는 해당 분기에만 적용될 것이다.

태그는 HEAD에서 정의되는 것과 마찬가지로 다른 분기에서도 정의 될 수 있다. 가능하다면 한 수준 정도(one level)의 분기를 고수하는 것이 가장 좋지만, HEAD 이외의 분기에서도 또 다른 분기를 만들 수 있다.

태그가 부여된 버전은 변하지 않는다.

모듈의 태그가 부여된 버전에 대해서는 변경 사항을 저장소에 반영할 수 없고, 수정을 하려면 루트 태그를 사용하여 분기를 생성해야 한다.

CVS에서는 분기에 속한 변경 사항들만 저장소에 반영 할 수 있다. HEAD는 기본 분기로 특수한 형태의 분기이다.

분기의 병합(merge)

필요한 경우에 변경 사항을 특정 분기에서 다른 분기로 병합 할 수 있다. 예를 들어 위 그림에서, 버그를 수정한 1.4.1의 변경 사항을 2.0.0 정식 배포판에 포함시키기 위해서 HEAD 분기로 병합을 할 수 있다. 두 개의 분기 사이의 병합은 저장소와 작업공간의 변경 사항 동기화와 유사하며, 마찬가지로 상충이 발생하는 경우는 이클립스 GUI를 활용하면 좀 더 수월하게 해결할 수 있다.

이력(history) 및 차이점 보기(diff)

CVS는 개별 파일이나 파일 조합의 변경 이력을 볼 수 있는 다양한 방법을 제공한다. 또한, CVS를 이용하면 각각의 수정본, 태그 그리고 분기들 사이의 차이를 볼 수 있다.

참고 자료
  • 이클립스 3.1 도움말의 CVS를 이용한 팀 프로그래밍은 개념 수준의 개요를 제공한다.
  • CVS를 이용한 오픈 소스 개발이라는 책은 매우 좋은 내용을 담고 있지만 명령 행을 통해 CVS를 사용하는 것을 전제하고 있다. 기본적인 개념을 설명하는 장에서 CVS에 관련된 거의 대부분의 사항을 다루고 있다.

1.1.2 기타, SubVersion, VSS(Visual Source Safe), Perforce

  • Subversion
  • VSS
  • Perforce
    • 상용이나 오픈소스 프로젝트를 위한 라이센스 지원
    • 편리한 GUI 툴 제공
    • 대부분의 IDE 플러그인 지원
      작업중인 내역변경된 내역브랜치 관리

1.2 eclipse 설정과 기본 사용법

cvsnt설치 및 eclipse 에서 cvs연결하는 방법은 다음의 사이트들을 통해 익힐수 있다.

제대로 연결 되었다면 CVS Repositories perspective 에서 다음 화면을 볼수 있다.

1.3 SCM Best Practices

지금까지는 사용법에 관해 알아보았다. 실제 팀내 개발이 제대로 이루어지려면 모든 개발자들이 사용법 숙지를 기본으로 해야 한다.

프로젝트가 커지고 모듈이 많아지고 릴리스가 계속 되고 있는 복잡한 제품을 관리하고 있다면 이런 것 외에 알아야 할 것이 더 있다.
업계에서 알려진 효율적인 버전관리법에 대해 알아보도록 하자.

1.3.1 GUI 툴 사용

자동화와 관련된 것이 아니라면 콘솔창은 매우 불편하다. 우리의 두뇌를 명령어 익히는 작업에서 보다 고차원적인 일을 하도록 유도해야 한다.

eclipse를 사용한다면 대부분의 SCM 이 plugin 형태로 지원되므로 history, diff, merge등을 편하게 사용할 수 있다. Windows 사용자라면 TortoiseCVS(추천), WinCVS 등을 이용하면 revision graph 등 CVS 를 좀 더 편하게 사용할 수 있고, Araxis Merge 같은 상용 merge 툴을 사용해도 좋다.

1.3.2 개발자 작업공간(Workspace or Sandbox)

개발자가 빌드, 테스트, 디버그를 하는 공간이다.

  • 워크스페이스를 공유하지 말라.
  • 관리되지 않는 워크스페이스에선 작업하지 말라.
  • 코드라인과 항상(자주) 동기화 시켜라.
  • 자주 체크-인(check-in) 하라. process 를 수립하는 것이 좋다.

1.3.3 소스 코드 라인(Codelines)

소스 파일들의 의미있는 집합을 얘기한다.

  • 각 코드라인마다 정책을 정하라.
  • 코드라인마다 책임자를 두어라.
  • 메인라인(mainline, trunk)을 유지하라.

1.3.4 브랜칭(Branching)

새로운 코드라인을 만드는 것을 의미한다.

  • 필요할 때만 브랜치 하라.
  • 단순 복사가 브랜치는 아니다.
  • 정책이 틀려질때 브랜치하라.
  • 최대한 늦게 브랜치하라.(충분히 검토하고 하라)
  • 코드 동결시키기 보다는 브랜치하라.

1.3.5 변경사항 전파(Propagation)와 병합(Merging)

한쪽 코드라인에서 변경된 사항을 다른 쪽에도 반영시키는 것을 말한다.

  • 원본에 대한 변경은, 브랜치 된 이후 가장 적게 변화된 브랜치에서 하라.
    (ex. 릴리즈 브랜치에서 버그를 코친후 변경사항을 메인라인에 병합(merge) 한다.)
  • 일찍, 자주 전달하라.
  • 적합한 사람에 병합을 맡겨라
    (ex. 소스(source) 코드라인 책임자 또는 대상(target) 코드라인 책임자)

1.3.6 소프트웨어 빌드(Builds)

소스 파일을 제품으로 바꾸는 과정이다.

  • 소스와 툴이 제품이 된다.
  • 원본 소스를 모두 체크-인 하라.
  • 빌드된 오브젝트들을 소스와 분리하라.
  • 공통적인 빌드 툴을 사용하라.
  • 자주 빌드하라.
  • 빌드 로그와 산출물을 모두 저장하여 유지하라.

1.3.7 조직에서 제도화하기(Process]

위의 모든 과정들의 규칙.

  • 변경 패키지를 추적하라. (변경 패키지란, 특정 버그나 기능추가로 변경된 파일들의 묶음을 의미)
  • 변경 패키지의 전달(propagation) 내역도 추적하라.
  • 요구사항과 변경 패키지를 구별하라.
  • SCM에 있는 모든 프로세스, 정책, 문서, 제품, 컴포넌드, 코드라인, 브랜치, 작업 에 책임자를 두어라.
  • 문서는 항상 최신버전으로 유지하고, 활용하라.

1.3.8 결론

"툴은 잘 사용했을 때 좋은 것이다".

단순히 CVS , Subversion, Clearcase, perforce, accurev, 등의 SCM 툴을 설치하고 명령어 몇개를 사용한다고만 해서 제대로 쓰고 있다는 것은 아니다. 프로그래밍 언어만 안다고 해서 프로그래밍을 잘 안다고 할 수 없듯이, SCM 툴을 활용하는 데도 그만한 시간과 노력이 필요하다.

이슈 추적 시스템

여기에서 직접 소개하지는 않았지만 Issue(bug) tracking system(버그 추적 시스템, 이슈 추적 시스템)의 사용도 고려해 봐야한다. 
버그를 추적하고 메모를 기록하고 작업 목록을 유지하는 훌륭한 도구이다. 모든 문제점과 기능 요청 사항을 한 곳에 모을 수 있으므로 프로젝트 관리에 도움을 준다.
유명한 것으로 버그질라MantisTUTOSAtlasian의 JIRA등이 있다.

2. 빌드 및 배포 자동화

프로젝트 컴파일은 귀찮은 일이다. 믿을 만하고 반복가능하게 만들어야 한다. 일관성과 정확성을 보장하는 훌륭한 방법은, 팀이 하는 모든 일을 자동화하는 것이다. XP(Extreme Programming)의 지속적인 통합(Continuous Integration)에서는 빌드 자동화를 가장 중요하게 다룬다. 빌드는 비어 있는 디렉토리 하나를 가지고 프로젝트를 밑바닥에서부터 만드는 과정으로, 무엇이건 여러분이 생산해 내고 싶은 최종 제품을 만들어 낸다.

프로젝트 빌드의 전형적인 단계

자동화의 기본적인 개념 및 프로세스는 비슷하다. (0.소개 부분의 그림 참조)

  1. Check-out : 저장소(repository)에서 소스코드를 가져온다. update 를 통해 가져오기도 한다.
  2. Build, test : 툴에서 제공하는 파일(ex. build.xml, makefile, project.xml 등)을 이용하여 빌드한다. 회귀테스트 등을 수행한다.
  3. Deploy : 실제 사용자에게 보내질 전체 제품을 만든다.(ex. CD, 웹사이트에 배포) 예제와 문서 등이 포함되기도 한다.
  4. Test : 테스트를 실행한다.

잘 관리되고 있는 프로젝트는 매일 빌드(daily builds)를 한다. 매일 야밤에 빌드를 수행하여 그 성공/실패 결과를 이메일등을 통해 개발자들에게 알리거나 다음날 아침에 확인할 수 있게 한다.

이런 빌드를 자동화하기 위해 여러가지 툴을 사용할 수 있는데, 유닉스/리눅스 환경에선 오래 전부터 make를 사용해 왔다. Makefile 이라는 파일에 빌드를 위한 스크립트를 작성한후 make 명령을 실행하면 빌드가 된다.

하지만 make에서 지원하는 기능이 너무 빈약해서 빌드가 복잡할 경우 Makefile에 모든 빌드 과정을 기술해야 하기 때문에 Makefile이 복잡해져서 유지보수가 힘들다는 문제가 있다. 그래서 자바 진영에서는 make를 넘어서는 툴을 만들고자 했고 그래서 2000년 7월 Ant가 등장했다. 그러나 Ant 역시 한계가 있었기 때문에 Ant를 한 단계 더 발전시킨 Maven이 등장했다. 현재 대부분의 오픈소스 자바 프로젝트는 Ant나 Maven 둘 중의 하나를 빌드 도구로 사용하고 있다.

2.1 Ant

Ant는 구조적으로는 make를 그대로 이어 받았다. build.xml에 빌드 설정을 해두고 ant 명령을 실행하면 빌드 작업이 수행된다. Ant는 자주 하는 작업인 컴파일, 압축, 복사, 메일, SCM 등의 태스크를 미리 갖추어 놓았기 때문에 make보다 훨씬 간단하게 빌드 설정을 할 수 있다. 전체 태스트 목록은http://ant.apache.org/manual/tasksoverview.html 에서 확인하기 바란다.

Ant의 표준 빌드 파일인 build.xml의 예를 보자.
test 패키지에 있는 HelloAnt.java 파일을 컴파일하고, jar 압축하고, 배포하고, 실행하는 작업을 수행한다.

build.xml
 
<?xml version="1.0" encoding="euc-kr"?>

<project name="Hello Ant" default="dist">
       	<!-- 프로퍼티를 지정 합니다. -->
        <property file="build.properties"/>
        <property name="base.dir"  value="."/>
        <property name="dist.dir"  value="dist"/>
        <property name="build.dir" value="build"/>
        <property name="src.dir"   value="src"/>
        <property name="jar.file"  value="${version}_helloworld.jar"></property>
        <property name="dist.file"  value="${version}_helloworld.zip"/>

        <target name="prepare">
        	<tstamp>
        		<format property="DSTAMP" pattern="yyyy.mm.dd" />
        		<!-- <format property="TSTAMP" pattern="HH:mm" /> -->
        	</tstamp>
        	<echo message="Build Start!! ======> ${DSTAMP}-${TSTAMP}" />
        </target>


        <target name="clean" depends="prepare">
        	<delete dir="${dist.dir}"/>
            <delete dir="${build.dir}"/>
        </target>
        
        <!-- 소스 컴파일 -->
        <target name="compile" depends="clean">
  			<mkdir dir="${build.dir}"/>
  			<javac deprecation="off" srcdir="${src.dir}" destdir="${build.dir}" 
  					listfiles="no" failonerror="true">
  				<classpath>
  					<pathelement path="${base.dir}/lib" />
  					<fileset dir="${base.dir}/lib">
  						<include name="*.jar" />
  					</fileset>
  				</classpath>
  			</javac>

        </target>
        
        <!-- 빌드 디렉토리에 컴파일이 끝난 클래스를 jar 파일로 묶음 -->
        <target name="mkjar" depends="compile">
        	<mkdir dir="${dist.dir}"/>
        	<jar destfile="${dist.dir}/${jar.file}"
                     basedir="${build.dir}" />
        </target>
        
        <!-- 배포할 라이브러리와 소스등을 배포용 디렉토리로 복사하고 배포용 디렉토리를 zip으로 묶음 -->
        <!-- jar와 소스, lib 아래의 jar를 배포용 디렉토리에 복사 후 zip으로 묶음 -->
        <target name="dist" depends="mkjar">
        	<copy todir="${dist.dir}/lib">
        		<fileset dir="lib" />
        	</copy>
        	<copy todir="${dist.dir}/src">
        		<fileset dir="src" />
        	</copy>
        	
        	<zip destfile="${DSTAMP}_${TSTAMP}_${dist.file}">
        		<fileset dir="${dist.dir}/." />
        	</zip>
        </target>
        
        <!-- HelloWorld 클래스를 호출하여 실행 -->
        <target name="run">
        	<java classname="test.HelloAnt">
        		<classpath>
        			<pathelement location="${dist.dir}/${jar.file}" />
        			<pathelement path="${base.dir}/lib" />
        			<fileset dir="${base.dir}/lib">
        				<include name="*.jar" />
        			</fileset>
        		</classpath>
        	</java>
        </target>
        
</project>

build.xml을 이용한 실행은 콘솔창에서

 
 ant <targe 이름>

식으로 입력하면 된다.

Eclipse 에서는 Ant 과 통합되어 있으므로 다음처럼 실행할 수 있다.

Eclipse 에서 ant 빌드

사실 Ant 개발자들은 Ant가 make보다 훨씬 선언적으로 빌드를 정의할 수 있다는 점을 장점으로 내세우지만 이건 사실 javac, copy와 같은 태스크를 미리 자바 클래스로 코딩해 놓았기 때문에 그런 것일 뿐 실제적으로는 Make의 메커니즘과 큰 차이가 없다. 그런 반면 build.xml을 선언적으로 작성할 수 있게 하기 위해 build.xml의 문법에 스크립트적인 요소를 최소한으로 줄였고 또 XML 자체가 프로그래밍이 필요한 부분을 기술하기에는 적합하지 않기 때문에 Ant의 파워는 오히려 make보다 낮아진듯 하다.

그리고 실제로 자바 클래스 컴파일에 파일 몇 개 복사하는 정도라면 아주 간단하게 빌드 파일을 작성할 수 있지만, 복잡해지기 시작하면 build.xml은 점점 이해하기 힘든 코드가 됩니다. 그래서 Ant에서는 build.xml에 주석을 충분히 달아놓을 것을 권고하고 있다.

하지만 복잡해서 주석을 많이 필요로 하는 상황은 좋지 않다. 주석은 Sun 에서도 권장하고 있지 않고, 마틴파울러의 리팩토링에서는 나쁜 냄새라고 얘기한다. 되도록 주석없이 쉽게 이해할 수 있도록 빌드 스크립트를 유지 해야 한다.

하지만 프로젝트 규모가 커지고 기능들의 추가/제거가 많아지면 빌드의 구조도 바뀌고 확장 된다. 결국 Ant도 make보다는 조금 사정이 나아졌지만 본질적으로는 make와 동일한 문제를 갖고 있다.

2.2 Maven 2

Maven은 이런 점들을 해결하고 나아가 종합적인 *프로젝트 관리*까지 지원한다. Maven은 현재 버전 2.2까지 나와 있다, Maven 1.x 버전과 2.x 버전간에는 개념을 제외한 파일 호환성이 없으므로, 기존 프로젝트 유지보수 등 특별한 이유가 있지 않는 한 2.x를 사용하길 권장하고 있다. 여기서도 Maven 2를 기준으로 설명한다. (Maven 1 보다 달라진 점은 http://maven.apache.org/maven1.html#changed 에서 보기 바란다.)

Project object model(POM)

Maven 2 프로젝트의 핵심은 POM(project object model)이다. POM 은 프로젝트에 대한 상세한 설명과 버전 정보, SCM, 의존성, 리소스, 팀 멤버, 구조 등을 포함한다. POM은 프로젝트의 홈디렉토리에 XML 파일(pom.xml) 형식으로 저장된다.

pom.xml
 
<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">

   <modelVersion>4.0.0</modelVersion>
   <groupId>com.javaworld.hotels</groupId>
   <artifactId>HotelDatabase</artifactId>
   <packaging>war</packaging>
   <version>1.0-SNAPSHOT</version>
   <name>Maven 2 Quick Start Archetype</name>
   <url>http://maven.apache.org</url>
   <dependencies>
      <dependency>
         <groupId>junit</groupId>
         <artifactId>junit</artifactId>
         <version>3.8.1</version>
         <scope>test</scope>
      </dependency>
   </dependencies>
</project> 

Maven 2 디렉토리 구조

Maven은 대부분의 것을 표준화 하기 위해 노력하는데, 이것이 장점이다. 다른 Maven 프로젝트에서 일했던 개발자라도 쉽게 구조와 조직에 익숙해 질수 있도록 해준다. 디렉토리 구조나 코딩 규칙 등를 다시 만드느라 시간을 쓸 필요가 없다.

Maven 2는 디렉토리 구조를 꼭 지켜주기를 권고하는 데, 이유는 다음과 같다.

  • POM 파일을 작고 간단하게 해준다.
  • 프로젝트를 이해하기 쉽게 하고, 인수 인계를 편하게 해준다.
  • plug-ins 과 통합을 쉽게 해준다.

Maven 2 의 표준 디렉토리 구조는 다음과 같다. 프로젝트의 홈디렉토리에 pom.xml 이 존재하고 두 개의 하위 디렉토리가 있다. src 에는 모든 source가, target 에는 생성된 모든 것이 들어간다.

Maven 2 표준 디렉토리 구조

src의 하위 폴더는 명확한 목적이 있다.

  • src/main/java: Your Java source code goes here (strangely enough!)
  • src/main/resources: Other resources your application needs
  • src/main/filters: Resource filters, in the form of properties files, which may be used to define variables only known at runtime
  • src/main/config: Configuration files
  • src/main/webapp: The Web application directory for a WAR project
  • src/test/java: Unit tests
  • src/test/resources: Resources to be used for unit tests, but will not be deployed
  • src/test/filters: Resources filters to be used for unit tests, but will not be deployed
  • src/site: Files used to generate the Maven project Website

프로젝트 라이프사이클(Project lifecycles)

프로젝트 라이프사이클은 Maven 2 의 핵심영역이다. 대부분의 개발자는 컴파일(compile), 테스트(test), 배포(deploy)등의 빌드 단계(phase) 개념은 알 것이다. Ant에는 이같은 이름의 target 이 있다. Maven 1 에서는 이와 관련되 plug-in 을 직접 호출한다. 예를 들어 소스를 컴파일하려면 java plug-in 을 사용한다.

 $maven java:compile

Maven 2 에서는, 이 개념이 잘 알려지고 잘 정의된 라이프사이클 단계(phase)의 집합으로 표준화 되었다. Maven 2 사용자는 plug-in 호출없이 라이프사이클 단계(phase)를 호출하면 된다.

 $mvn compile
Maven 2 라이프사이클 단계(phase)

중요한 라이프사이클 단계는 다음과 같다.

  • generate-sources: Generates any extra source code needed for the application, which is generally accomplished using the appropriate plug-ins
  • compile: Compiles the project source code
  • test-compile: Compiles the project unit tests
  • test: Runs the unit tests (typically using JUnit) in the src/test directory
  • package: Packages the compiled code in its distributable format (JAR, WAR, etc.)
  • integration-test: Processes and deploys the package if necessary into an environment where integration tests can be run
  • install: Installs the package into the local repository for use as a dependency in other projects on your local machine
  • deploy: Done in an integration or release environment, copies the final package to the remote repository for sharing with other developers and projects

다른 단계에 대해서는 여기 를 참조하기 바란다.

Maven 2 의 라이프사이클 단계에 익숙해지면, 어떤 Maven 프로젝트에 가더라도 두렵지 않을 것이다.

라이프사이클의 단계를 호출하면 이전의 단계도 역시 호출한다. 따라서 라이프사이클 단계는 갯수에 제한은 있지만, 이해하기 쉽고, 잘 조직되었으며, Maven 2 프로젝트에 쉽게 적응할 수 있게 도와 준다.

Transitive dependencies

Maven 2 에서 눈에 띄는 부분이 transitive dependency 관리이다. Linux의 urpmi 를 사용해 봤다면 어떤 개념인지 알것이다. Maven 1 에서는 필요한 모든 JAR 파일을 직/간접적으로 선언해 줬어야 한다. Hibernate 을 쓰려면 에 어떤 JARs 들이 필요한지 알고 있는가? Maven 2 에서는 이런 걸 몰라도 된다. 그냥 어떤 라이브러리가 필요한지 Maven 에게 알려주기만 하면 알아서 처리해준다.

프로젝트에 Hibernate 을 사용한다고 생각해 보자. 그냥 다음처럼, pom.xml 의 dependencies 섹션에 새로운 dependency 를 추가하기만 하면 된다.

<dependency>
      <groupId>hibernate</groupId>
      <artifactId>hibernate</artifactId>
      <version>3.0.3</version>
      <scope>compile</scope>
</dependency>

이게 전부다. Hibernate 3.0.3 을 실행하기 위해 다른 JARs(버전에 따라)를 찾아다닐 필요가 없다. Maven 이 알아서 해 준다.

Maven 2 의 dependencies 부분은 Maven 1 과 유사하다. 가장 중요한 차이점은 다음에 설명할 scope 태그이다.

Dependency scopes

실제 엔터프라이즈 애플리케이션에서 보면, dependencies 있는 모든 것이 배포될 필요는 없다. 어떤 JARs 는 유닛 테스트에만 필요할 수 있고, 또 어떤 것은 애플리케이션 서버에서 런타임 시에만 필요할 수 있다. Maven 2 에서는 dependency scoping 이라는 테크닉을 이용해서 특정 JARs 가 정말 필요할 때만 사용될 수 있게 한다. 필요하지 않을 때는 classpath 에서 제거된다.

Maven 은 4가지의 dependency scopes 를 제공한다 :

  • compile: A compile-scope dependency is available in all phases. This is the default value.
  • provided: A provided dependency is used to compile the application, but will not be deployed. You would use this scope when you expect the JDK or application server to provide the JAR. The servlet APIs are a good example.
  • runtime: Runtime-scope dependencies are not needed for compilation, only for execution, such as JDBC (Java Database Connectivity) drivers.
  • test: Test-scope dependencies are needed only to compile and run tests (JUnit, for example).

프로젝트 커뮤니케이션(Project communication)

어느 프로젝트에서나 중요한 부분은 내부 커뮤니케이션이다. 만병통치약은 아니지만, 프로젝트 웹사이트에 정보를 집중화시키면 팀내의 가시성을 향상시킬 수 있다. Maven은 프로젝트에 대한 각종 문서가 집약된 사이트를 생성하도록 해준다. 적은 노력으로 수준높은 프로젝트 웹사이트를 재빠르게 만들어 올릴 수 있다.

보통 Maven 사이트는 다음 정보를 만든다 :

  • General project information such as source repositories, defect tracking, team members, etc.
  • Unit test and test coverage reports
  • Automatic code reviews and with Checkstyle and PMD
  • Configuration and versioning information
  • Dependencies
  • Javadoc
  • Source code in indexed and cross-referenced HTML format
  • Team member list
  • And much more

Maven 으로 관리되는 프로젝트는 여기 http://maven.apache.org/powered.html 에서 볼수 있다.

3. 토론

  • 이 외의 다른 방법으로 관리를 하고 있는가?
  • 팀내에 이런 툴을 도입하는데 따른 문제는 없었는가?
  • 진정 효율적인가?
  • 전사적으로 또는 모든 개발자가 사용하기 위해 어떤 노력을 해야 하는가?


출처: http://www.javajigi.net/pages/viewpage.action?pageId=2240



참고문헌

저작자 표시

'VCS' 카테고리의 다른 글

Eclipse를 활용한 효율적인 팀 개발 및 배포 전략  (0) 2013/04/13
CentOS 6.x install GitWeb  (0) 2013/04/12
CentOS 6.3: Configuring a git server  (0) 2013/04/12
CentOS 6.x Git server 구축  (0) 2013/04/10
CentOS 6.x Git  (0) 2013/04/08
Quick Wins with Git  (0) 2012/05/10
Posted by 세계유목민
VCS2013/04/12 15:44

$ yum install gitweb

$ echo "\$projectroot = '/home/repos/';" > /etc/gitweb.conf



가상호스트 설정 httpd.conf 설정 후 아파치 재시작


<VirtualHost *:80> ServerName gitserver DocumentRoot /var/www/gitweb <Directory /var/www/gitweb> Options ExecCGI +FollowSymLinks +SymLinksIfOwnerMatch AllowOverride All order allow,deny Allow from all AddHandler cgi-script cgi DirectoryIndex gitweb.cgi </Directory> </VirtualHost>

저작자 표시

'VCS' 카테고리의 다른 글

Eclipse를 활용한 효율적인 팀 개발 및 배포 전략  (0) 2013/04/13
CentOS 6.x install GitWeb  (0) 2013/04/12
CentOS 6.3: Configuring a git server  (0) 2013/04/12
CentOS 6.x Git server 구축  (0) 2013/04/10
CentOS 6.x Git  (0) 2013/04/08
Quick Wins with Git  (0) 2012/05/10
Posted by 세계유목민
TAG gitweb