[Step by Step] 지속적인 통합 (Continuous Integration)

변경 내역

  1. 2006.07.29 작성.

이 글은 월간 마이크로소프트웨어(일명 마소) 2006년 5월호 Step by Step 칼럼에 기고한 글입니다. 물론 구성이나 내용 상의 차이가 있을 수 있습니다.

최재훈 | .NET과 MSSQL을 주로 다루는 개발자다. 이 분야에서 인정 받는 프로페셔널이 되기 위해 꾸준히 노력하고 있다. 객체지향과 데이터베이스에 관심을 갖고 있지만, 기술보다는 사람에 대한 믿음이 중요하다고 생각한다. 최근에는 문제해결법에 관심을 기울이고 있다.

소프트웨어 개발업에 종사한다면, 누구나 한번쯤 개발방법론에 관한 이야기를 하거나 듣게 된다. CMM, RUP, Extreme Programming, 그리고 그 외의 수많은 방법론이 세상에 존재한다. 그 중에서 개발자들이 가장 관심을 갖는 방법론은 Extreme Programming일 것이다. XP가 주장하는 것 중에는 정말 Extreme한 내용도 있기 때문에, 이 방법론의 유효성을 두고 10여 년간 논쟁이 끊이지 않았다. 그러나 논란이 확산됨에 따라 XP의 Best Practices 중 일부는 다른 진영의 인정을 받게 됐다. 지속적인 통합(Continuous Integration)은 그 중 하나다. 물론 지속적인 통합은 XP만의 고유한 개념은 아니었고, 이미 수많은 사람들이 사용하던 방법이었다. 그러나 XP 진영이 지속적인 통합을 가장 힘주어, 지속적으로 강조해왔다.

그렇다면 지속적인 통합이란 무엇일까? 결코 어려운 개념은 아니지만, 한마디로 설명하기에 쉽지도 않다. 지속적인 통합은 본래 각각의 개발자가 자신이 수정한 소스 코드를 되도록 자주 소스 코드 저장소에 커밋하고, 다른 사람이 수정한 소스 코드는 없는지 수시로 확인하는 일련의 행동을 의미한다. 이렇게 자주 커밋/확인 과정을 하지 않으면, 누가 벌써 버그를 고쳐놨네. 헛수고했네.라는 말을 자주 하게 될 것이다. 팀 단위의 개발에서 생각보다 많이 이런 경우를 접하게 된다. 버그 수정 건을 생각해보자. 오류의 반이 모듈의 15%에서 발견된다.고 한다. (『소프트웨어 공학의 사실과 오해』 중, 로버트 L 글래스) 말인 즉, 모듈 전체에 골고루 개발자가 분배되지 않고 특정 부분에 몰리게 된다는 것이다. 그렇다고 메써드 하나하나를 수정할 때마다 팀원들에게 전체공지를 보낼 수도 없는 노릇이다. 가장 좋은 방법은 수시로 커밋하고, 변경사항을 확인하는 것이다.

언뜻 쉬운 개념 같다. 그러나 실제로는 양상이 꽤 복잡하게 전개된다. 소스 코드를 수정하고 커밋하는 일련의 과정을 생각해보자. 나초보씨는 아침 일찍 출근한다. 차 한잔 마시고 졸린 뇌세포를 깨운다. 아웃룩을 열어서 지난 저녁에 도착한 메일이 없는지 확인한다. 유쾌하지 않게도 버그 리포트가 도착해 있었다. 파일 삭제 버튼을 클릭했는데도 유저 인터페이스엔 아무런 반응이 없고 파일도 삭제되지 않는다고 한다. 나초보씨는 한숨을 내쉰다. 먼저 TortoiseSVN으로 Subversion 저장소에서 최신버전의 소스 코드를 내려 받는다. 테스트와 디버깅을 여러 차례 거치니 문제의 원인이 드러났다. 파일 삭제 메써드는 구현되어 있었지만, 어이없게도 파일 삭제 버튼의 클릭 핸들러와 파일 삭제 메써드가 연결되어 있지 않았다. 핸들러와 메써드를 연결하는 코드를 작성하고, 똑 같은 문제가 발생하지 않도록 파일 삭제와 관련된 단위 테스트 코드를 작성한다. 빌드와 단위 테스트를 다시 해보고 아무런 문제가 발생하지 않는다는 것을 확인한다. 이제 변경된 소스코드와 단위 테스트 코드를 커밋한다. 다행히 그 사이에 해당 코드를 수정한 다른 사람은 없었다.

이상적으로 일이 풀렸을 때는 이것으로 끝이다. 그러나 문제 발생 소지는 여전히 존재한다. 앞선 경우와 약간 다른 상황을 생각해보자. 나초보씨는 최신버전의 소스 코드를 내려 받았다. 단위 테스트 코드를 실행시켜보니, 이전과는 달리 오류 메시지가 보인다. 누군가 두 경로를 조합하는 PathJoin 함수를 수정했다. 결과적으로 잘못된 파일 경로가 만들어져서 파일을 삭제하는데 실패한 것이다. 이미 단위 테스트 코드가 만들어져 있는 상황이었으므로, 소스 코드를 수정한 후에 단위 테스트만 해봤으면 이런 일은 벌어지지 않았을 것이다. 알고 보니 옆자리에 앉은 ‘정말귀찮아’씨가 범인이었다. 그의 말에 따르면 너무나 간단한 코드라서 문제가 발생할 줄 몰랐다고 한다.

이제 ‘정말귀찮아’씨는 원흉이 됐다. 하지만 그에게만 책임이 있다고 할 수 있을까? 문제의 근본적인 원인은 일련의 과정이 너무 복잡하다는데 있다. 빠르게, 그리고 자주 커밋/확인 과정을 거치려면 각 작업에 드는 노력과 시간이 얼마 안 돼야 한다. 그렇지 않으면 개발자의 의욕을 꺾게 된다.

다행스럽게도 일련의 복잡한 과정을 자동화하기 위한 소프트웨어가 많이 나와 있다. 더욱이 무료로 사용할 수 있는 소프트웨어도 많다. 자바의 경우에는 Ant라는 빌드 스크립트 언어와 CruiseControl이라는 Continuous Integration System 조합을 많이 사용한다. ‘정말귀찮아’씨는 이클립스를 사용한다. 소스 코드를 수정하고 나면 컴파일해 본다. 빌드가 성공하면 JUnit 단위 테스트 버튼을 또 클릭한다. 단위 테스트도 통과하면 변경된 내용으로 Jar 파일을 생성한다. 한번의 수정작업을 위해 여러 번의 확인 과정을 거쳐야 한다. 이제 이클립스라는 IDE에서 벗어나 빌드 프로세스를 Ant 빌드 스크립트로 빼낸다. 이제 한번 빌드 스크립트를 클릭(이클립스에서 바로 빌드 스크립트를 실행시킬 수도 있다.)하면 빌드, 단위 테스트, 그리고 Jar 생성까지의 과정이 한번에 이뤄진다.

지속적인 통합 과정

<그림 1> 지속적인 통합 과정

CruiseControl은 매우 간단한 기능을 수행한다. 주기적으로, 또는 정해진 시각에 소스버전 시스템을 확인해서 변경사항이 있는지 검토한다. 변경사항이 있으면 새 버전을 내려 받아서 빌드, 단위 테스트 등을 한다. 만약 오류가 발생하면 사용자에게 이메일 등으로 보고한다. 이제 ‘정말귀찮아’씨의 경우와 같이 누군가가 잘못된 소스 코드를 커밋하더라도 CI System에 조기에 경고를 보내줄 것이다. 문제가 곯아서 터지기 전에 문제를 발견할 수 있게 됐다.

XP에는 4가지 주요 가치를 내세운다. 단순성, 의사소통, 피드백, 용기가 그것이다. 지속적인 통합은 반복적으로 이뤄지는 개발과정의 일부를 자동화함으로써 단순화시킨다. 단순화된 통합 과정은 개발자가 수시로 커밋하고 테스트하는 것을 쉽게 만들어준다. 결과적으로 서로가 똑 같은 작업을 하고, 나중에야 이를 깨닫는 상황을 피할 수 있게 도와준다. 예기치 않은 문제 발생시에는 CI System이 바로 보고할 것이므로 재빨리 대처할 수 있게 된다. 매 순간 빌드 가능하고 일련의 테스트를 통과하는, 즉 작동하는 코드를 갖고 있다고 확신할 수 있기 때문에 망설이지 않고 기능 개선 등에 나설 수 있게 된다.

참고 문헌

최 재훈

블로그, 페이스북, 트위터 고성능 서버 엔진, 데이터베이스, 지속적인 통합 등 다양한 주제에 관심이 많다.
Close Menu