우리는 왜 CI/CD에 실패하였는가?
프로젝트를 진행하면서 CI/CD 를 통한 자동화 배포 프로세스를 구축하는 경우가 많다.
우테코에서 이번 팀 프로젝트를 진행하면서 깃들다팀 역시 CI/CD 프로세스를 구축했으나 결론적으로 CI/CD를 제대로 성공시키지 못했다는 생각을 떨쳐버릴수 없었다.
이번 글에서는 필자가 생각하는 CI/CD란 무엇인지, 그리고 어떤 부분이 문제였는지 한번 작성해 보도록 한다.
CI/CD란 무엇인가?
많은 글과 주변 크루들의 이야기를 들어봤을때 CI/CD에 대한 의견이 많이 갈리는것을 볼 수 있었다. redhat에서 작성한 글과 그 외의 여러 글들을 통해 필자가 이해한 CI/CD에 대해 설명해보겠다.
지속적 통합
지속적 통합은 우리가 pr을 날리고 머지하는 행위라고 말하고싶다. 지속적 통합의 목표는 “머지데이”의 문제점을 제거하기 위함에있다. 과거, CI/CD 가 정착화되지 않았을때 “머지데이”는 많은 인력 리소스를 낭비시켰다. 필자의 경우만 하더라도, 학부시절 팀 프로젝트를 진행하면 서로 변경한 소스를 합치는데 있어서 많은 고통이 있었다(부끄럽게도 학부시절에 Git과같은 버전관리 시스템을 전혀 사용하지 않았다).
CI 프로세스 (출처: redhat)
위 그림을 살펴보면 Build, Test, Merge까지의 과정을 CI라고 말하고있다. 결국 이 프로세스가 의미하는것은 정상적으로 동작하는, 그리고 충돌이 없는 코드의 병합 을 말한다.
Github를 기준으로 말하자면, PR을 올리고 빌드, 테스트를 검증하고 머지하여 특정 브랜치에 코드가 병합하는 과정까지를 의미한다고 볼 수 있다.
지속적 전달
지속적 전달은 솔직히 말하자면 이름이 잘못된것같다. 이 과정의 목적은 즉시 배포 가능한 코드의 확보 라고 말하고싶다.
Github를 예로 들자면, PR들이 특정 브랜치로 Merge됐다면, 그 브랜치의 코드는 언제든 배포 가능한 상태여야 한다는 것을 의미한다.
따라서 필자는 PR이 Merge될때마다 CI와 같이 Build, Test를 진행하여 코드가 정상적으로 동작하는지 확인해야 한다고 생각한다. 이와 관련하여 혹자는 “PR을 올렸을때 이미 Build와 Test를 진행하고 정상인 것을 확인하였는데 뭐하러 또 다시 이를 확인해야 하는가?” 라고 물을지도 모른다. 이에대한 답변은 우테코의 prolog 프로젝트에서 필자가 작성한 글을 인용하여 답변하도록 하겠다.
지속적 배포
이부분은 모두가 동의하는것 같다. 코드를 Merge 했다면, 적절한 서버로 어플리케이션을 자동 배포하는 그 행위를 의미한다. 레드헷에서는 지속적 배포란 개발자가 애플리케이션에 변경 사항을 작성한 후 몇 분 이내에 애플리케이션을 자동으로 실행할 수 있는 것을 의미합니다. 라고 명시하고 있다.
우리는 왜 CI/CD에 실패하였는가?
엄밀히 말하자면 필자는 CD보다는, CI에 실패했다고 생각하고 있다. 이전글에서도 말했듯, CI의 가장 큰 목적은 머지데이의 안좋은점을 제거하는데 있다고 생각한다. 하지만 프로젝트를 진행하면서 나름 치밀하게 CI/CD를 구축했다고 생각했음에도 불구하고 언제나 코드를 머지할때면 수 많은 Merge Confilict에 치이고 말았다.
이러한 상황은 필자를 “이게 정말 CI가 구축된것이 맞는가?” 란 의문으로 이끌었다.
이에대한 분석을 진행한 결과, 결국 모든 문제는 PR에서 부터 시작됐다는 결론을 내리게 됐다.
1. PR의 크기가 너무 크다
필자가 속한 깃들다팀은 모든 PR에 대하여 팀원들의 Approve가 있어야지만 PR의 Merge가 가능하도록 컨벤션을 만들었다. 그 말인 즉슨, 팀원들이 코드를 읽고, 피드백을 남겨야 한다는 것을 의미하게 된다.
위 숫자를 보자, 필자가 속한 팀의 PR Line수를 3개정도만 임의로 가져온 것이다. 기본적으로 항상 1000줄에 가까운 Line수를 보인다. 이러게 많은 Line의 추가와 File Changes는 코드리뷰의 병목을 가져올수밖에 없다. 각각의 팀원들도 자신이 맡은 일이 있기때문에 다른 팀원의 코드에 많은 리소스를 쏟을 수 없다. Line의 기술블로그 를 읽어보면 코드리뷰에 대하여 많은 팁을 제공하고 있으며 공통적으로 하는 말은 리뷰의 시간과 리소스를을 짧고, 적게 가져가자로 귀결된다. 그렇다. 결국 이러한 큰 PR단위가 CI를 망치는 주된 원인이 된 것이다.
아직까지는 감이 오지 않는 독자가 있을것이다. 그렇다면 필자는 큰 PR단위가 무엇이 문제이기에 CI를 망쳤다고 주장하는것일까?
2. PR이 너무 많이 쌓인다.
큰 PR단위는 결국 리뷰의 병목을 발생시키고 PR이 쌓이도록 유도한다. CI의 목적이 무엇인가? 이름 그대로 코드의 지속적 통합이다. 하지만 PR이 쌓인다는것은, 지속적인 통합이 진행되지 않고, 통합이 계속 미뤄진다는 것을 의미한다. 이제 눈치를 챘는가?? 큰 PR이 지속적으로 쌓이면 어떤 문제가 발생할지…….
3. 결국에는 또 다시 머지데이로…
그렇다. 큰 PR이 수십개 쌓이는 순간 머지데이의 늪에 또 다시 빠지게 된다. 수십개의 파일 변경과 수천라인의 PR이 적개는 몇개, 많게는 수십개 쌓였다면 이를 머지하는데 또 다시 다른 PR과의 병합을 해결해야 한다. 또한 지속적인 코드 병합에 실패하면서 지속적 통합이라는 그 근본에도 접근하지 못하게 된다. 이것이 과연 올바른 CI라고 할 수 있을까?
실제로 프로젝트를 진행하면서 이렇게 쌓인 PR은 데모데이 전날에 다함께 모여 후다닥 Merge하는 형태로 이어졌다. 이것도 머지데이의 차이점이 무엇인가? CI를 힘들게 구축해놓고 또 다시 과거의 머지데이를 반복하는꼴이 돼버렸다.
결론.
이번 글에서는 왜 필자의 프로젝트에서 구축한 CI가 실패한 CI라고 생각했는지에 대하여 작성해봤다. 정말 아이러니하게도. CI프로세스 자체는 제대로 구축되어 있었으나, 그 실패의 원인은 전혀 다른곳에 있었다.
작은 PR 법칙이 왜 존재하는지 또 다시 체감하였다. 그렇다면 이를 깨닫고 필자는 작은PR법칙을 잘 지키고 있냐고 물어본다면 대답은 NO다. 아직까지는 PR의 크기를 나누고, Issue의 발행 단위를 제대로 나누는 연습을 더 해야한다고 생각한다. 이론적으로는 이해했지만 아직까지 적용하기에는 내공이 부족한 것 같다.
이 글을 통해 CI/CD 프로세스를 구축하는것만으로 만족하지 말고 힘들게 구축한 프로세스를 제대로 활용할 수 있는 힌트가 되었으면 한다.
reference
https://blog.banksalad.com/tech/banksalad-code-review-culture/ https://engineering.linecorp.com/ko/blog/effective-codereview/#send-pull-request-early