이번 포스팅에서는 제가 CI 구축업무를 받았을 때 고려했던 내용들에 대해서 공유합니다.
신입사원 때 했던 내용을 적는 것이라서 부족한 점이 있으면 양해 부탁드립니다.
CI (Continuous Integration)
CI는 Continuous Integration의 약자로 정상적으로 동작하는 코드를 유지하기 위한 작업들을 말합니다.
거의 모든 개발자들은 협업을 위해 git 같은 형상관리툴을 사용할텐데
main branch의 최신 커밋이 정상동작하지 않으면 공동 작업자들이 모두 제대로 된 작업을 할 수 없기 때문에
프로젝트 진행에 있어서 코드 개발과 같은 수준으로 중요도를 갖는다고 생각합니다.
CI와 테스트
정상 동작하는 코드라는 것을 증명하기 위해서 개발자들은 테스트로 자신의 코드를 검증하고 반영하기를 기대받습니다.
하지만 개발자가 직접 모든 테스트를 수행하는 것은 현실적으로 힘듭니다.
테스트 누락이 있을 수도 있고 새로운 코드 작업과 동시에 테스트 결과를 신경쓰기 힘들기 때문입니다.
그 외에 리소스 문제 등 다양한 문제가 있을 수 있는데 이런 문제들을 해결해주는 것이 CI입니다.
CI는 코드 반영 단계에서 자동으로 테스트를 수행해주며 테스트 결과에 따라 특정 행동을 제한하기 때문에
다른 개발자들이 오류가 있는 코드에 영향을 받지 않도록 합니다.
Pre-merge Test
github를 사용하는 환경을 기준으로 설명하겠습니다.
개발자는 자신의 코드를 main branch에 pull request를 통해 반영합니다.
pull request를 통해 코드 리뷰를 받아서 디자인과 구현에 대한 피드백을 받을 수 있는데요.
이 때 테스트를 수행했는지 물어보거나 테스트 파일을 눈으로 확인인할 수 있지만
CI를 구축하면 pull request 생성 시 자동으로 테스트가 수행됩니다.
Merge 전에 테스트가 수행된다고 하여 Pre-merge (Pre-commit) 테스트라고 합니다.
Pre-merge 테스트를 만들었으면 CI 구축이 끝난 것입니다.
Post-merge Test
그런데 문제가 발생합니다.
분명 Pre-merge 테스트에서 성공했는데 main branch에서 에러가 난다고 하는 이상한 상황이 발생하는데요.
이유는 여러 가지가 있겠지만 pull request 했을 때의 코드 베이스와 merge 후의 코드 베이스가 다를 경우 흔히 발생합니다.
Pre-merge 테스트 후에 다른 사람이 먼저 엄청난 변경점을 갖고 main에 반영이 된 것이지요.
그래서 우리는 Post-merge 테스트를 추가하여 main branch가 업데이트 될 때마다 코드 동작을 테스트 하도록 합니다.
이렇게 되면 코드 관리가 제대로 된다고 할 수 있습니다.
테스트 분리
그런데 코드는 정상으로 동작하는데 정작 테스트가 다 돌아갈 때까지 한참을 기다려야되니 너무 답답합니다.
다른 업무를 시작하긴 불안하고 쳐다보고있기만 하자니 지루하죠.
그래서 다음 단계는 테스트 분리입니다.
테스트의 종류에는 유닛 테스트, 통합 테스트, 시스템 테스트 등 여러 가지가 있고 테스트 하는 요소가 많을 수록 시간이 오래 소요되는데요.
일반적으로 Pre-merge 테스트에서는 유닛 테스트와 통합 테스트 일부를 수행하여 빠르게 테스트하고
시간이 오래 걸리는 시스템 테스트, 장기 테스트, 반복 테스트 등은 Post-merge 테스트에서 수행합니다.
테스트 분배하기
그래서 테스트를 구분하면 빨리 테스트가 끝날까요?
아쉽게도 현실은 그렇지 않습니다.
CI는 Jenkins, Bamboo, Github Action 등 다양한 플랫폼에서 만들 수 있는데
어떤 플랫폼이든 테스트를 수행하는 테스트 서버 세팅하는 방법이 있습니다.
그런 테스트 서버가 단 한 개 밖에 없다면 공동 개발자가 많은 환경에서는
당연하게도 대기 시간이 길어지게 됩니다.
그래서 테스트 서버를 여러 개 두고 병렬로 수행해도 되는 테스트들을 잘 쪼개고
테스트 서버에 분배해야 테스트 시간이 효과적으로 단축됩니다.
예를 들어 Pre-merge 테스트에서 A,B,C 테스트를 하는데
테스트 그룹이 하나라서 오래 걸리는 것 같아서 3개로 쪼갠다고 하여도
한 개의 서버에서 수행되면 A->B->C로 수행되는 시간은 동일합니다.
반대로 테스트 서버가 3개라고 해도 테스트 그룹이 1개라면
1번 서버에서 A->B->C가 순차적으로 수행되어서 2번, 3번 서버는 아무 일도 안하는데
테스트만 오래 걸리게 됩니다.
그래서 여러 대의 테스트 서버를 사용함과 동시에 테스트 그룹을 잘 나누어야 합니다.
리소스 최적화
테스트 분배까지 해서 시간도 잘 줄어들었는데 더 할 일이 있을까요?
네 더 있습니다.
테스트 서버들에서 각 테스트가 돌기 위해서는 소스 코드 빌드가 필요할 수 있는데요.
각 서버에서 각자 빌드을 수행한다면 시간이 오래 걸리게 됩니다.
테스트 서버를 대여해서 사용하는 경우라면 오래 걸리는 만큼 돈을 더 내야되죠.
그래서 테스트 단계를 세분화 하여 빌드는 한번만 하고 빌드된 바이너리 혹은 컨테이너 등으로
여러 테스트 서버에서 테스트만 수행하도록 해야합니다.
빌드된 바이너리를 재사용하는 방법에는 빌드 서버에 보관해두고 copy를 해가는 단순한 방법도 있지만
nexus repository나 habor registry 등을 사용하는 방법이 더 자주 쓰입니다.
CD (continuous delivery)
CD (continous delivery)는 코드로 만들어진 결과물을 사용할 수 있도록 자동화하는 것입니다.
이 단계까지 왔다면 아마 당신은 이미 CI/CD 전문가가 되어있을 것입니다.
Post-merge 테스트 마지막 단계에서 배포용 nexus repository 혹은 harbor에 upload하면 됩니다.
정리
이번 포스트에서는 CI/CD 구축 과정에서 일어나는 상황에 대해서 의식의 흐름대로 글을 적어보았습니다.
결론은 CI/CD를 구축하기 위해서는 여러 종류의 테스트가 잘 갖춰져 있어야하고
nexus repository 혹은 harbor registry를 만들어서 활용해야 하며
여러 테스트 서버를 활용하고 테스트 단계를 세분화해서 테스트 시간을 단축해야 합니다.
여기에는 따로 자세하게 내용을 담지 않겠지만 실제 CI/CD 구축 과정에서는 온갖 이상한 이슈들이 발생합니다.
- 리소스 부족 때문에 VM을 도입하면서 생기는 일
- CI에서 테스트 도중 실패했을 때 디버그가 매우 어려운 환경 (amazon aws)
- 개발 환경과 테스트 환경이 맞지 않아 특정 환경에서 테스트가 실패하는 일
- 제한된 리소스에서의 Post-merge 스케쥴링
등등 상상하기 어려운 부분에서 '왜 안되지?'를 외치게 될 수 있는 영역이 CI/CD라고 생각합니다.
CI 구축 업무를 맡게 된 인프라 담당자에게는 마음의 준비를 할 수 있도록 도와주는 포스트가 되었으면 하고
프로젝트 관리자에게는 CI 업무를 한 명에게 맡기지 않게 했으면 하는 포스트가 되었으면 좋겠습니다.
'학습 > 공통,미분류' 카테고리의 다른 글
코드리뷰 (0) | 2022.04.28 |
---|---|
Intro (0) | 2022.02.16 |
Vagrant Study (0) | 2021.05.10 |
안드로이드 자주쓰는 코드 (0) | 2018.07.30 |
R 프로그래밍 piglatin (0) | 2017.04.04 |