11장
지속적인 통합을 활성화하고 연습하라
- 버전 관리를 통해 트렁크를 온전히 유지할 수 있다.
- 여러 사람이 서로 다른 부분을 동시에 작업할 수 있다.
- 작업이 길어질수록 병합이 어려워지고 무시될 수 있기 때문에 일상 업무의 일부분으로 커지기 전에 해결해야 한다.
HP 레이저젯 펌웨어(2014)
-
기존 문제
- 6 ~ 12개월 기준 1,2개의 기능만 신규 추가 가능
- 95%는 브랜치 병합, 수동 테스트 등 비생산적인 업무에 사용
- 하나의 브랜치로 오랜기간 작업을 진행함 => 병합 시, 많은 시간 소요.
-
해결 방안
- 트렁크(메인) 기반 개발
- 지속적인 통합을 위해 테스트 자동화 수행
- 모든 제품에 공통으로 적용/관리할 수 있는 신규 아키텍쳐 설계
-
결과
- 하루 빌드 횟수 증가 => 커밋 횟수 증가 => 매일 7.5만 ~ 10만 라인 코드 변경 가능
- 회귀 테스트 시간 6주 => 1일로 감소
- 개발 비용 40% 감소
- 새로운 기능 개발 시간 5% => 40% 증가
소규모 배치 개발과 트렁크에 코드를 드물게 커밋할 때 발생하는 일
대부분의 브랜치 전략은 아래 두 가지 케이스를 따르고 있다.
- 개인 생산성 최적화
- 개인 브랜치에서 혼자 작업
- 메인으로 병합 및 협업이 어려움.
- 팀 생산성 최적화
- 개발 기간동안 모든 사람이 같은 브랜치에서 작업
- 작업 결과가 모든 사람의 코드에 영향을 미칠 수 있음.
위 특징으로 인해 브랜치 수가 늘어날 수록 병합이 어려워지고 병합에 따른 기존 코드 재작업이 늘어날 수 있다.
이 문제를 해결하기 위해선 트렁크 기반 개발이 필요하다.
트렁크 기반 개발 프랙티스를 적용하라
- 트렁크를 기준으로 코드를 자주 커밋, 병합해야 한다.
- 잦은 커밋으로 변경사항이 적어지며, 모든 자동화 테스트를 실행할 수 있다.
=> 테스트 오류에 대해선 경고를 받을 수 있다.(젠킨스 알림 등 병합 전 테스트로 체크)
- 상대적으로 적은 양을 병합하므로 병합 시간이 줄어들고 문제를 좀더 빨리 수정할 수 있다.
- 병합 전 배포 파이프라인 등을 통해 자동화 테스트를 수행하고 일관된 코드 품질을 유지할 수 있다.
결론
- 트렁크 베이스로 주기적으로 코드를 병합할 수 있도록 한다.
- 주기적인 코드 푸시(1일) 로 병합 및 테스트에 대한 부담을 줄인다.
- 이로 인해 기능 출시에 대한 낮은 위험도를 가져갈 수 있다.
12장
리스크가 낮은 출시를 자동화하고 활성화하라
페이스북 사례 설명
- 변경 사항을 작업한 작업자를 모아 일일이 체크하고 내보낸다.
- 작업한 팀의 판단력과 과거 경험에 크게 의존하게 됨.
- 작업한 내용은 카나리 배포로 테스트 후 전체 반영하여 안전하게 배포
- 한 번의 배포에서 처리 가능한 변경 사항의 개수가 일정함을 확인
- 배포 속도를 증가시켜 변경 사항을 많이 처리할 수 있도록 개선함.
12장의 주요 내용
- 배포가 힘들면 빈도가 줄게 되고, 배포 작업의 크기가 커진다.
- 그로 인해 변경 사항을 반영하기 어려워지며 예상치 못한 문제에 대응하기도 어려워진다.
- 이를 해결하기 위해선 배포를 더 빈번하고 쉽게 수행할 수 있어야 한다.
-> 이를 위해선 코드 배포가 자동화되고 반복 및 예측 가능해야 한다.
- 이하 원활한 배포를 위한 프랙티스 제공.
배포 프로세스를 자동화하라
기존 제품 적용 방안
- 기존 업무가 존재하는 경우, 아래와 같이 자동화 해야 한다.
- 점진적인 문서화 => 수동 단계 자동화(코드 패키징, 자동화된 스모크 테스트, DB 마이그레이션 스크립트...)
- 또한 자동화에 맞춰 아키텍쳐를 재설계 해야 한다.(비용은 누가,,?)
- 위 과정에서 중요한 부분은 "배포 프로세스의 자동화와 최적화에 중점을 둬야 한다" 는 점이다.
배포 파이프라인
- 모든 환경에 동일한 방법으로 배포
- 파이프라인 등을 활용해 동일한 방법으로 배포되도록 해야 한다.
- 이를 통해 여러 번 배포가 성공함을 확인하고 프로덕션에 배포할 수 있다.
- 배포에 대한 스모크 테스트
- 의존성을 가지는 외부 서비스에 대한 연결 테스트를 해야 한다.
-> 파이프라인 실행 및 빌드 / 프로덕션 환경이 상이한 경우는 어떻게?
- 시스템을 통한 단일 테스트 트랜잭션 실행(단위 테스트?)
- 일관된 환경의 유지 보장
CSG 인터내셔널, 일일 배포
문제 점
- 개발 팀과 운영 팀이 별도 존재하여 상황을 공유하지 않음.
- 테스트 환경은 운영과 상이하여 프로덕션의 오류를 온전히 잡기 어려움
해결 방안
- 개발 팀과 운영 팀을 아우르는 공유 운영팀을 구성하여 공통 관리.
- 프로덕션 출시 전, 테스트 환경에 매일 배포하여 테스트 오류를 검증하고 지속적으로 수정함.
- 테스트 환경과 프로덕션 환경을 최대한 유사하게 설정하여 프로덕션에서의 오류를 재현할 수 있도록 노력함.
결과
- 일일 배포와 프로덕션 출시 빈도가 2배로 증가
- 프로덕션 사고 감소
- 배포 리드 타임 14일 -> 1일로 단축
자동화된 자체 서비스 배포를 활성화하라
- 변경 사항 제출 전 자동화된 테스트 스위트를 적용하여 보완할 수 있다.
- 빌드
- 빌드 결과물은 모든 프로덕션 환경에서 배포될 수 있어야 한다.
- 테스트
- 로컬, 테스트 시스템에서 자동화된 테스트가 온전히 동작해야 한다.
- 배포
- 배포 스크립트를 실행시켜 접근 권한을 가진 모든 환경에 패키지를 배포할 수 있어야 한다.
코드 배포를 배포 파이프라인과 통합하라
배포 자동화는 아래 기능들을 포함해야 한다.
1. 지속적으로 통합된 패키지가 프로덕션 환경 배포에 적합함을 보장한다.
2. 누가 작업했는지, 결과가 어떤지 등 기록을 남기고 추적이 가능해야 한다.
3. 스모크 테스트를 진행하여 연결 정보/설정이 올바른지 확인해야 한다.
4. 배포 성공 여부를 빠르게 확인할 수 있도록 피드백을 제공한다.
엣시 사례
- 모든 사람이 매일 배포할 수 있도록 장려함.
- 수많은 테스트가 진행되므로 병렬 처리하여 실행 시간을 줄였다.(최대 11분으로 임의 지정)
- 스모크 테스트, GUI 테스트 등 자동화된 테스트로 최대한의 오류를 검출하고 배포 안정성을 높힘.
- 2011년 하루 25 -> 50회 배포로 늘어나며 코드를 프로덕션에 빠르게 반영할 수 있게 됨.
출시와 배포를 분리하라
-
배포
- 주어진 환경에 소프트웨어의 특정 버전을 설치하는 것
- 특히, 고객에게 기능을 출시하는 것과 밀접하게 관련돼 있다.
=> 기능을 출시하기 위해 진행하는 행위?
- 개발과 운영은 빠르고 빈번한 배포를 성공으로 이끄는 데 필요한 권한을 부여한다.
-
출시
- 모든 고객이나 고객 세그먼트에 기능을 사용할 수 있게 만드는 행위
- 코드와 환경은 기능 출시가 애플리케이션 코드의 변경을 필요로 하는 방법에 따라 아키텍쳐화돼야 한다.
=> 가치 흐름을 고객에게 전달하는 행위?
- 제품 책임자는 출시에 따른 성공적 비즈니스 결과를 책임진다.
-
환경 기반 출시 패턴
- 개발/운영 등 2개 이상의 환경에 배포하는 경우
- 새로운 코드를 실제 고객 환경이 아닌 별도의 환경으로 배포
- 운영 환경의 트래픽을 전환하여 출시를 진행한다.
- 예) 블루 그린 배포, 카나리아 출시, 클러스터 면역 체계
-
애플리케이션 기반 출시 패턴
- 애플리케이션에서 조작하여 특정 사용자에게만 기능을 출시하는 패턴
- 내부 직원에게 출시하여 테스트 후 완료되면 전체 고객에게 기능을 제공할 수 있다.
- 예) 다크 론치
환경 기반 출시 패턴
-
블루 그린 배포
독립적인 세트를 구성하여 테스트 후 트래픽을 전환하여 출시하는 방식.

-
데이터베이스 변경 처리하기
두 가지 환경의 애플리케이션이 공존하기 때문에 데이터 변경 처리를 위해 아래와 같은 방법을 사용할 수 있다.
- 2개의 데이터베이스 생성(블루/그린)
1) 블루/그린 애플리케이션 각각 데이터 베이스를 구성
2) 블루 읽기 전용 전환 및 그린 데이터 베이스 복원
3) 출시 후 블루 -> 그린 수동 마이그레이션
- 애플리케이션 변경과 데이터 베이스 변경 분리
1) 데이터 베이스 추가 변경건 우선 반영 => 블루/그린 둘다 호환되어야 한다.
2) 애플리케이션 반영
-
카나리아 및 클러스터 면역 시스템 출시 패턴
카나리 배포 - 일부 사용자들에게 기능을 출시하여 검증하는 방식
클러스터 면역 체계(System) - 클러스터에 점진적으로 적용하고 문제 발생 시 자동 롤백되도록 하는 시스템

더 안전한 출시를 가능하게 하는 애플리케이션 기반 패턴
-
기능 토글을 구현하라
출시된 기능을 외부에서 선택적으로 활성화/비활성화 하는 패턴
예) 설정 파일 교체를 통해 플래그 전환, redis에 저장된 예약어 값 변경 등.
- 쉬운 롤백 - 토글하여 기능을 빠르게 숨길 수 있다.
- 성능의 우아한 감소 - 부하가 심할 경우, 기능을 숨겨 부하를 낮출 수 있다.
- 서비스 지향 아키텍쳐 통한 탄력성 증대 -
- A/B 테스팅 수행 - 새로운 기능을 테스트하고 비즈니스 지표를 쌓을 수 있다.
-
다크 론치를 수행하라
배포된 기능을 고객에게 숨기고 테스트를 진행한다.
이를 통해 대규모 변경 사항이나 위험한 변경 사항에 대해 유사 프로덕션 환경에서 안전하게 테스트를 수행할 수 있다.
예) 일부 사용자에게 배포된 기능을 수행 후 결과를 기록하고 폐기한다.
이후 기능 수정 및 사용자 수와 빈도를 적당히 늘리면서 시뮬레이션한다.
기능을 적용할 사용자 수를 적절히 조절하는 것이 중요하다.
지속적인 전달과 지속적인 배포에 대한 조사
- 지속적인 전달
- 지속적인 배포를 위한 전제 조건
- 트렁크에 대한 작은 배치 작업, 단기간 기능 브랜치 작업 후 트렁크가 출시가능한 상태를 유지하는 것
- 지속적인 배포
- 프로덕션 환경에 배포하거나 개발자거 커밋하는 모든 변경 사항이 자동으로 프로덕션에 배포되는 것.
- 지속적인 통합(CI) -> 지속적인 전달 -> 지속적인 배포(CD)
팀 구성원들은 시스템을 배포 가능 상태로 유지하는 것을 우선한다.
결론
- 출시와 배포를 일상 업무로 만들면 배포 리드 타임을 줄일 수 있다.
-> 이로 인해 업무를 중단하지 않아도 고객에게 가치를 빠르게 전달할 수 있다.
- 개발과 운영이 함께 작업하기 때문에 운영 분야의 인도적 작업이 이뤄진다.