2018.08.13

"개발 프로세스 자동화의 정수"··· 지속적 통합(CI)·전달(CD)의 이해

Isaac Sacolick | InfoWorld
오늘날 거의 모든 소프트웨어 개발 활동은 팀 단위로 진행되며 그 방식 역시 버전-컨트롤(version-control) 시스템 안에서 관리되는 하나 혹은 복수의 코드 저장소를 기반으로 이뤄진다. 지속적인 변화를 필요로 하는 코드의 특성상 그 분야에서 작업하는 개인 개발자에겐 변경사항을 언제 버전 컨트롤에 반영할지 결정하는 것이 중요해졌다.



물론 단순하고 리스크가 적어 같은 코드베이스에서 작업하는 동료의 활동과 별다른 충돌 없이 편집, 반영이 가능한 변화도 많다. 그러나 며칠에서 몇 주, 때론 수 개월이 소요되기도 하는 팀 단위 대형 개발의 경우 코드 변경사항을 제때 확인해 버전 컨트롤에 반영하는 일 자체가 만만치 않은 일이다. 한발 더 나아가 빌드 오류나 기능 결함 없이 개발팀 통합 코드에 개인의 코딩 내용을 반영하는 경우라면 어려움은 더 커진다.

지속적 통합이 필요한 순간
이런 고민을 해결할 가장 직관적인 방법은 개별 작업을 개별 버전-컨트롤 브랜치에 반영하는 것이다. 이때 개발팀은 모든 팀원이 투입되는 단일 기능 브랜치를 이용할지, 개발자별로 복수의 브랜치를 생성할지 결정해야 한다.

이런 방식이 직관적이긴 하지만 최적은 아니다. 메인 개발 트렁크의 관점에서 보면 각 기능 브랜치에 변화가 발생해 모든 작업물이 각자의 방향으로 갈라진 것이기 때문이다. 이 기능 브랜치가 일정 기간 이상 이용되면 통합의 어려움은 커지고 충돌 해결에 들어가는 시간이 길어지며 오류 발생 위험 역시 커진다.

이러한 단점을 극복하고자 최근의 대규모 개발팀은 변동 내용의 반영 빈도를 늘리는 자동화를 도입했다. 이를 통해 빌드와 기능성을 검증하는 새로운 방법을 확보하고 기능의 개발과 배치 속도를 큰 폭으로 개선하기 시작했다. 이른바 지속적 통합(CI, Continuous Integration)이다.

지속적 통합이란?
지속적 통합이란 일종의 코딩 철학이자, 이와 관련한 일련의 관행을 일컫는 용어이다. 개발 과정에서 소규모 변경사항을 계속 적용하고, 코드를 확인해 저장소를 주기적으로 버전-컨트롤하는 방법론이다.

현대의 애플리케이션 대부분은 다수의 플랫폼과 툴에 맞춘 코드가 필요하므로 개발 팀도 코드 변경사항을 통합, 승인할 수 있는 메커니즘이 필요하다. 지속적 통합은 일관되면서도 자동화된 방식으로 애플리케이션을 제작, 패키징, 테스트하는 것을 목표로 한다. 통합 프로세스의 일관성이 보장되면 개발 팀 역시 더 마음 놓고 코드를 변경할 수 있고, 이를 통해 협업과 소프트웨어의 품질도 개선된다.

지속적 통합의 실제 모습
지속적 통합은 프로세스 역학과 소프트웨어 빌드 자동화가 뒷받침된 개발 철학이다. CI를 실천하는 개발자는 버전-컨트롤 저장소에 계속해서 변경된 코드를 반영하며 모든 팀이 최소한 하루 단위로 코드에 기여하도록 강제하기도 한다. 이렇게 하는 이유는 장기간 방대한 분량의 코드를 쓰고 작업하기보다 이렇게 조금씩 변경사항을 적용해야 코딩의 결함이나, 다른 소프트웨어 품질 문제를 찾기 쉽기 때문이다. 또한, 이렇게 작업 주기가 짧아지면 여러 개발자가 동시에 같은 코드를 수정할 일이 줄어든다.

지속 통합 방식을 채용한 개발팀에서는 버전-컨트롤 설정과 실행 정의를 먼저 시작하는 경우가 많다. 코드 확인은 주기적으로 이뤄지더라도 신기능이나 버그수정은 단기, 장기적 일정에 따라 시행하기 때문이다. CI를 실천하는 개발팀은 프로덕션 준비가 된 기능과 코드를 관리하는 여러 가지 테크닉을 사용한다. 그래서 CI 개발팀에서는 코드를 하나의 개발 브랜치나 트렁크에 몰아 넣는 것을 선호한다. 피쳐 브랜치가 사용될 경우 CI 개발팀은 피쳐 브랜치의 수명이 짧고 개발 브랜치로 주기적으로 통합되는 것을 선호한다.

한편 보다 긴 개발 주기가 필요하면서도 개발 브랜치에 통합된 기능을 관리하는 기술도 있다. 어떤 개발팀에서는 피쳐 플래그를 사용하기도 하는데, 이는 런타임시 기능과 코드를 온/오프 할 수 있는 설정상의 메커니즘이다. 아직 개발 중인 기능은 코드의 피쳐 플래그에 싸여 있으며 마스터 브랜치와 함께 적용되고, 사용될 준비가 될 때까지는 오프 상태를 유지한다.

빌드 프로세스는 모든 소프트웨어와 데이터베이스, 그리고 기타 요소를 패키징하면서 자동화된다. 예를 들어, 자바 애플리케이션을 개발하고 있다고 하자. CI는 HTML, CSS, 자바스크립트 등 모든 정적 웹 서버 파일과 자바 애플리케이션, 그리고 기타 모든 데이터베이스 스크립트를 함께 패키징한다.

CI 툴 대부분은 개발자가 온-디맨드로 빌드를 시작할 수 있다. 버전 컨트롤 저장소 코드에 기여하거나, 혹은 정해진 스케줄에 따라 트리거가 당겨지도록 하는 것이다. 개발팀에서는 팀 사이즈와 일일 코드 기여 수, 그리고 다른 애플리케이션 관련 문제를 고려해 빌드 스케줄을 함께 논의해야 한다. 코드 기여와 빌드는 빠를 수록 좋다. 그렇지 않으면 더 빠르게, 자주 코드를 기여하는 다른 팀의 진척 상황에 방해가 될 수도 있기 때문이다. 이러한 일련의 워크플로우를 가리켜 CI 파이프라인이라고 부른다.


CI를 활용한 개발과 검증
CI는 개발자에게 새로운 워크플로우를 제시한다. 우선 개발자가 각자에게 부여된 ‘로컬’ 환경 상의 IDE나 자신의 에디터 안에서 코드를 편집한다. 이론적으로는 각 개발자가 각자의 로컬 환경에서 구동되는 런타임 환경을 확보하고 몇 가지 기본적인 기능 테스트를 수행하는 것도 가능하다. 이와 함께 각자의 환경 상에서 간단히 구동될 수 있는 자동 유닛 테스트 역시 진행할 수 있다.

이 검증된 기본 테스트를 거친 후 개발자는 작업한 코드를 반영한다. 젠킨스(Jenkins)나 트래비스(Travis)와 같은 CI 플랫폼은 구축된 하나 혹은 복수의 컴포넌트로 모든 코드 요소를 패키징하는 빌드를 촉진한다. 이어 CI 플랫폼은 필요한 정적 코드 분석 툴을 실행하고 빌드 내 문제사항이 있으면 해당 리포트를 개발자에게 전달한다.

문제가 발견되면 팀원이 빌드 파이프라인을 정지하고 전체 팀의 개발 활동에 영향을 주기 전에 빠르게 행동해 문제를 파악, 해결해야 한다. 많은 개발팀이 빌드 성공과 실패율을 기록, 관리하고 이 데이터를 사용해 개발 프로세스의 개선점을 찾아낸다.

소프트웨어 패키징이 완료되면 CI 툴은 구축된 소프트웨어가 타깃 딜리버리 환경에 전달되고 애플리케이션 서버 재실행 등 딜리버리에 필요한 서비스를 개시한다. 이어 자동화 테스트를 진행하도록 지원한다. 이러한 전달 단계를 보통 지속적 전달(CD, Continuous Delivery)이라고 부른다. 전체 지속적 통합 및 전달(CI/CD) 파이프라인에 통합된 테스팅 기능은 지속적 테스팅(continuous testing)의 일부로 편입된다.

CI/CD를 실천하는 개발팀은 사용자에게 더 빠르게 신기능과 강화된 기능을 전달할 수 있다. 자동화 및 워크플로우는 코딩과 기능상의 결함을 줄여준다. 또한, 이러한 워크플로우는 팀 내 콜라보레이션을 강화해 더 스마트하고, 혁신적인 솔루션으로 이어진다. 이 모든 것이 지속적 통합, CI에서 시작된다. ciokr@idg.co.kr 

2018.08.13

"개발 프로세스 자동화의 정수"··· 지속적 통합(CI)·전달(CD)의 이해

Isaac Sacolick | InfoWorld
오늘날 거의 모든 소프트웨어 개발 활동은 팀 단위로 진행되며 그 방식 역시 버전-컨트롤(version-control) 시스템 안에서 관리되는 하나 혹은 복수의 코드 저장소를 기반으로 이뤄진다. 지속적인 변화를 필요로 하는 코드의 특성상 그 분야에서 작업하는 개인 개발자에겐 변경사항을 언제 버전 컨트롤에 반영할지 결정하는 것이 중요해졌다.



물론 단순하고 리스크가 적어 같은 코드베이스에서 작업하는 동료의 활동과 별다른 충돌 없이 편집, 반영이 가능한 변화도 많다. 그러나 며칠에서 몇 주, 때론 수 개월이 소요되기도 하는 팀 단위 대형 개발의 경우 코드 변경사항을 제때 확인해 버전 컨트롤에 반영하는 일 자체가 만만치 않은 일이다. 한발 더 나아가 빌드 오류나 기능 결함 없이 개발팀 통합 코드에 개인의 코딩 내용을 반영하는 경우라면 어려움은 더 커진다.

지속적 통합이 필요한 순간
이런 고민을 해결할 가장 직관적인 방법은 개별 작업을 개별 버전-컨트롤 브랜치에 반영하는 것이다. 이때 개발팀은 모든 팀원이 투입되는 단일 기능 브랜치를 이용할지, 개발자별로 복수의 브랜치를 생성할지 결정해야 한다.

이런 방식이 직관적이긴 하지만 최적은 아니다. 메인 개발 트렁크의 관점에서 보면 각 기능 브랜치에 변화가 발생해 모든 작업물이 각자의 방향으로 갈라진 것이기 때문이다. 이 기능 브랜치가 일정 기간 이상 이용되면 통합의 어려움은 커지고 충돌 해결에 들어가는 시간이 길어지며 오류 발생 위험 역시 커진다.

이러한 단점을 극복하고자 최근의 대규모 개발팀은 변동 내용의 반영 빈도를 늘리는 자동화를 도입했다. 이를 통해 빌드와 기능성을 검증하는 새로운 방법을 확보하고 기능의 개발과 배치 속도를 큰 폭으로 개선하기 시작했다. 이른바 지속적 통합(CI, Continuous Integration)이다.

지속적 통합이란?
지속적 통합이란 일종의 코딩 철학이자, 이와 관련한 일련의 관행을 일컫는 용어이다. 개발 과정에서 소규모 변경사항을 계속 적용하고, 코드를 확인해 저장소를 주기적으로 버전-컨트롤하는 방법론이다.

현대의 애플리케이션 대부분은 다수의 플랫폼과 툴에 맞춘 코드가 필요하므로 개발 팀도 코드 변경사항을 통합, 승인할 수 있는 메커니즘이 필요하다. 지속적 통합은 일관되면서도 자동화된 방식으로 애플리케이션을 제작, 패키징, 테스트하는 것을 목표로 한다. 통합 프로세스의 일관성이 보장되면 개발 팀 역시 더 마음 놓고 코드를 변경할 수 있고, 이를 통해 협업과 소프트웨어의 품질도 개선된다.

지속적 통합의 실제 모습
지속적 통합은 프로세스 역학과 소프트웨어 빌드 자동화가 뒷받침된 개발 철학이다. CI를 실천하는 개발자는 버전-컨트롤 저장소에 계속해서 변경된 코드를 반영하며 모든 팀이 최소한 하루 단위로 코드에 기여하도록 강제하기도 한다. 이렇게 하는 이유는 장기간 방대한 분량의 코드를 쓰고 작업하기보다 이렇게 조금씩 변경사항을 적용해야 코딩의 결함이나, 다른 소프트웨어 품질 문제를 찾기 쉽기 때문이다. 또한, 이렇게 작업 주기가 짧아지면 여러 개발자가 동시에 같은 코드를 수정할 일이 줄어든다.

지속 통합 방식을 채용한 개발팀에서는 버전-컨트롤 설정과 실행 정의를 먼저 시작하는 경우가 많다. 코드 확인은 주기적으로 이뤄지더라도 신기능이나 버그수정은 단기, 장기적 일정에 따라 시행하기 때문이다. CI를 실천하는 개발팀은 프로덕션 준비가 된 기능과 코드를 관리하는 여러 가지 테크닉을 사용한다. 그래서 CI 개발팀에서는 코드를 하나의 개발 브랜치나 트렁크에 몰아 넣는 것을 선호한다. 피쳐 브랜치가 사용될 경우 CI 개발팀은 피쳐 브랜치의 수명이 짧고 개발 브랜치로 주기적으로 통합되는 것을 선호한다.

한편 보다 긴 개발 주기가 필요하면서도 개발 브랜치에 통합된 기능을 관리하는 기술도 있다. 어떤 개발팀에서는 피쳐 플래그를 사용하기도 하는데, 이는 런타임시 기능과 코드를 온/오프 할 수 있는 설정상의 메커니즘이다. 아직 개발 중인 기능은 코드의 피쳐 플래그에 싸여 있으며 마스터 브랜치와 함께 적용되고, 사용될 준비가 될 때까지는 오프 상태를 유지한다.

빌드 프로세스는 모든 소프트웨어와 데이터베이스, 그리고 기타 요소를 패키징하면서 자동화된다. 예를 들어, 자바 애플리케이션을 개발하고 있다고 하자. CI는 HTML, CSS, 자바스크립트 등 모든 정적 웹 서버 파일과 자바 애플리케이션, 그리고 기타 모든 데이터베이스 스크립트를 함께 패키징한다.

CI 툴 대부분은 개발자가 온-디맨드로 빌드를 시작할 수 있다. 버전 컨트롤 저장소 코드에 기여하거나, 혹은 정해진 스케줄에 따라 트리거가 당겨지도록 하는 것이다. 개발팀에서는 팀 사이즈와 일일 코드 기여 수, 그리고 다른 애플리케이션 관련 문제를 고려해 빌드 스케줄을 함께 논의해야 한다. 코드 기여와 빌드는 빠를 수록 좋다. 그렇지 않으면 더 빠르게, 자주 코드를 기여하는 다른 팀의 진척 상황에 방해가 될 수도 있기 때문이다. 이러한 일련의 워크플로우를 가리켜 CI 파이프라인이라고 부른다.


CI를 활용한 개발과 검증
CI는 개발자에게 새로운 워크플로우를 제시한다. 우선 개발자가 각자에게 부여된 ‘로컬’ 환경 상의 IDE나 자신의 에디터 안에서 코드를 편집한다. 이론적으로는 각 개발자가 각자의 로컬 환경에서 구동되는 런타임 환경을 확보하고 몇 가지 기본적인 기능 테스트를 수행하는 것도 가능하다. 이와 함께 각자의 환경 상에서 간단히 구동될 수 있는 자동 유닛 테스트 역시 진행할 수 있다.

이 검증된 기본 테스트를 거친 후 개발자는 작업한 코드를 반영한다. 젠킨스(Jenkins)나 트래비스(Travis)와 같은 CI 플랫폼은 구축된 하나 혹은 복수의 컴포넌트로 모든 코드 요소를 패키징하는 빌드를 촉진한다. 이어 CI 플랫폼은 필요한 정적 코드 분석 툴을 실행하고 빌드 내 문제사항이 있으면 해당 리포트를 개발자에게 전달한다.

문제가 발견되면 팀원이 빌드 파이프라인을 정지하고 전체 팀의 개발 활동에 영향을 주기 전에 빠르게 행동해 문제를 파악, 해결해야 한다. 많은 개발팀이 빌드 성공과 실패율을 기록, 관리하고 이 데이터를 사용해 개발 프로세스의 개선점을 찾아낸다.

소프트웨어 패키징이 완료되면 CI 툴은 구축된 소프트웨어가 타깃 딜리버리 환경에 전달되고 애플리케이션 서버 재실행 등 딜리버리에 필요한 서비스를 개시한다. 이어 자동화 테스트를 진행하도록 지원한다. 이러한 전달 단계를 보통 지속적 전달(CD, Continuous Delivery)이라고 부른다. 전체 지속적 통합 및 전달(CI/CD) 파이프라인에 통합된 테스팅 기능은 지속적 테스팅(continuous testing)의 일부로 편입된다.

CI/CD를 실천하는 개발팀은 사용자에게 더 빠르게 신기능과 강화된 기능을 전달할 수 있다. 자동화 및 워크플로우는 코딩과 기능상의 결함을 줄여준다. 또한, 이러한 워크플로우는 팀 내 콜라보레이션을 강화해 더 스마트하고, 혁신적인 솔루션으로 이어진다. 이 모든 것이 지속적 통합, CI에서 시작된다. ciokr@idg.co.kr 

X