본문으로 바로가기

41

CI/CD

사람이 손으로 배포하면 반드시 사고가 난다. 그 일을 기계에게 똑같은 순서로 시키는 것

먼저 보면 좋은 강의: 웹 요청의 해부, 지연 시간과 처리량, 컨테이너

단계별로 보기

스페이스바로 재생/정지, 좌우 화살표로 단계 이동, R로 처음으로 돌아갑니다.

대기 중1 / 4 단계 — 접수했습니다, 12번째로 대기 중입니다

개발자가 코드를 올립니다. 빌드 큐가 즉시 접수하고 번호표를 줍니다. 여기서 거절이 없다는 게 핵심입니다. 퇴근 직전에 스무 명이 한꺼번에 몰려도 마찬가지입니다. 빌드 기계가 바쁘다고 개발자를 돌려보내면, 그 개발자는 자기 코드가 검사됐는지도 모른 채 집에 갑니다.

이 강의를 마치면

  • 지속적 통합(CI)이 '합치는 순간 바로 검사한다'는 뜻임을 설명한다.
  • 빌드·검사·보관·배포가 각각 다른 단계이며 앞 단계가 통과해야 뒤가 시작됨을 구분한다.
  • 빌드 요청이 몰릴 때 큐가 그것을 흡수하는 이유를 설명한다.
  • 배포를 자주·작게 하는 것이 가끔·크게 하는 것보다 안전한 이유를 설명한다.

금요일 밤의 배포

옛날 방식은 이랬습니다. 몇 달간 각자 만든 것을 배포 전날 한꺼번에 합칩니다. 안 맞는 부분이 우수수 쏟아집니다. 밤새 맞춥니다. 금요일 밤에 서버에 올립니다. 누군가 설정 파일 하나를 빠뜨립니다. 주말이 사라집니다.

무엇이 문제였을까요? 배포가 어려웠던 게 아닙니다. 문제를 뒤늦게 발견한 것이 문제였습니다.

두 사람이 각자 만든 부품이 안 맞는다는 사실은 합치는 순간 알 수 있습니다. 그런데 합치는 걸 석 달 미뤘으니, 석 달 뒤에 알게 된 것입니다. 그 사이에 두 사람은 안 맞는 부품 위에 계속 뭔가를 쌓아 올렸습니다.

CI — 합치는 순간 바로 검사한다

지속적 통합(CI)의 아이디어는 어이없을 만큼 단순합니다.

석 달에 한 번 합치지 말고, 하루에 여러 번 합쳐라. 그리고 합칠 때마다 기계가 즉시 전부 검사하게 하라.

개발자가 코드를 올리면 몇 분 안에 기계가 자동으로 이렇게 합니다.

  1. 가져온다 — 방금 올라온 코드를 받는다
  2. 만든다 — 실행 가능한 형태로 조립한다 (빌드)
  3. 검사한다 — 준비된 시험을 전부 돌린다 (테스트)
  4. 알린다 — 하나라도 실패하면 즉시 개발자에게 알린다

포인트는 몇 분입니다. 방금 자기가 뭘 고쳤는지 기억하고 있을 때 알려주면 5분이면 고칩니다. 석 달 뒤에 알려주면 며칠이 걸립니다. 같은 버그인데 비용이 100배 차이 납니다.

이 단계가 CI/CD 전체에서 가장 중요합니다. 뒤의 모든 자동화는 "여기서 걸러졌다"를 전제로 하기 때문입니다. 검사가 부실하면 CI/CD는 불량품을 더 빨리 내보내는 장치일 뿐입니다.

CD — 검사를 통과한 것만, 기계가 올린다

검사를 통과했습니다. 이제 서비스에 올려야 합니다.

먼저 창고에 넣는다

검사를 통과한 결과물은 곧바로 서버에 올리지 않고 먼저 창고(레지스트리)에 넣습니다. 앞 강의의 그 창고입니다. 이름표를 붙여서요.

왜 한 단계를 더 거칠까요? 두 가지 때문입니다.

  • 똑같은 것이 올라간다는 보장. 검사한 그 물건과 배포된 물건이 같은 물건임을

확신할 수 있습니다. 서버마다 다시 만들면 미묘하게 달라질 수 있습니다.

  • 되돌릴 수 있다. 37번이 문제면 창고에 있는 36번을 다시 꺼내면 됩니다.

되돌리기가 새 배포보다 어려우면 아무도 되돌리지 못하고, 그럼 장애가 길어집니다.

그리고 배포한다

창고에서 새 이미지를 꺼내 컨테이너를 교체합니다. 여기서도 원칙이 있습니다. 한꺼번에 다 바꾸지 않습니다. 열 대 중 두 대만 새것으로 바꾸고, 지켜보고, 괜찮으면 두 대 더 바꿉니다. 문제가 보이면 남은 여덟 대는 그대로 두고 되돌립니다.

이렇게 하면 사고가 나도 사용자의 20%만 잠깐 겪고 끝납니다.

빌드 요청은 고르게 오지 않는다

이 강의가 시뮬레이션으로 보여주려는 부분입니다.

개발자 스무 명이 하루 종일 고르게 코드를 올릴까요? 아닙니다. 점심 직후와 퇴근 직전에 몰립니다. 평소에는 초당 5건이던 것이 그 시간에는 초당 60건이 됩니다.

빌드는 느립니다. 컴파일하고 테스트를 전부 돌려야 하니 몇 분씩 걸립니다. 빌드 기계가 초당 20건밖에 못 처리하는데 60건이 몰리면 어떻게 될까요?

나쁜 설계는 이렇게 답합니다. "자리가 없으니 거절합니다." 개발자에게는 "빌드 서버가 바쁩니다. 나중에 다시 시도하세요"라는 오류가 뜹니다. 이건 최악입니다. 개발자는 자기 코드가 검사됐는지 안 됐는지 모르는 상태로 퇴근하게 됩니다.

좋은 설계는 이렇게 답합니다. "접수했습니다. 12번째로 대기 중입니다."

개발자 → [빌드 큐]  ← 요청은 여기서 즉시 접수된다
            ↓
         빌드 실행기  ← 자기 속도대로 하나씩 꺼내 돈다
            ↓
          창고

이게 CI 서버의 본질입니다. CI는 즉시 처리하는 시스템이 아니라 접수하고 줄을 세우는 시스템입니다. 몰릴 때 큐가 길어지는 것은 고장이 아니라 정상 동작입니다. 개발자는 몇 분 더 기다릴 뿐, 아무도 거절당하지 않습니다.

이게 왜 되는가

앞선 강의에서 "들어오는 속도가 나가는 속도보다 빠르면 줄은 계속 길어진다"고 배웠습니다. 여기서는 왜 괜찮을까요?

몰림이 끝나기 때문입니다. 퇴근 시간의 몰림은 20분이면 지나가고, 그 뒤로는 초당 5건입니다. 빌드 기계는 초당 20건을 처리하니 밀린 줄을 금방 따라잡습니다. 큐는 평균을 감당할 수 있을 때 봉우리를 흡수해 줍니다. 평균 자체가 용량을 넘으면 큐는 터지는 시점을 미룰 뿐입니다. 그때는 큐가 아니라 빌드 기계를 늘려야 합니다.

정리 — 진짜 얻는 것

CI/CD의 이득을 "배포가 빨라진다"로 이해하면 절반만 이해한 것입니다. 진짜 이득은 이것입니다.

손으로, 가끔, 크게기계로, 자주, 작게
한 번에 나가는 변경수백 개한두 개
사고 시 원인 찾기수백 개 중에서한두 개 중에서
되돌리기무섭다버튼 하나
배포하는 날두렵다아무 날

작게 자주 나가면 사고가 나도 범인이 뻔합니다. 방금 나간 한 개니까요. 크게 가끔 나가면 사고가 났을 때 수백 개 중에 범인을 찾아야 합니다.

그래서 역설적인 결론이 나옵니다.

배포가 무서워서 덜 하는 조직이, 배포를 자주 해서 익숙해진 조직보다 훨씬 위험합니다.

이 강의가 단순화한 것

교육용 모형은 언제나 무언가를 생략합니다. 무엇을 생략했는지 아는 것도 학습의 일부입니다.

전제한 것

  • 이 강의는 등록된 부품만으로 CI/CD를 흉내 낸다. 'CI 서버'와 '운영 서버'는 서버 부품으로, '아티팩트 창고'는 저장소 부품으로, '배포 실행기'는 워커 부품으로 대신 표현했다.
  • 실제 빌드는 수 분에서 수십 분이 걸리지만, 흐름을 보여주기 위해 밀리초 단위로 압축했다.
  • 테스트는 항상 정확하게 통과/실패를 판정한다고 가정한다. 실제로는 간헐적으로 실패하는 불안정한 테스트가 큰 문제다.
  • 배포 중 롤백과 부분 교체(카나리)는 본문에서 설명만 하고 시뮬레이션하지는 않는다.

다루지 않은 것

  • 브랜치 전략과 코드 리뷰, 머지 큐
  • 블루/그린, 카나리, 롤링 배포의 세부 절차
  • 비밀 값(시크릿) 관리와 빌드 공급망 보안
  • 데이터베이스 스키마 변경을 코드 배포와 함께 안전하게 내보내는 문제

더 읽을거리: Continuous Delivery — Martin Fowler · DORA — Accelerate State of DevOps

이제 직접 만들어 보세요

읽어서 아는 것과 만들어서 아는 것은 다릅니다. 컴포넌트를 배치하고 트래픽을 흘려서 실제로 동작하는지 확인해 보세요.

실습 과제 열기

이 강의에 물어보기

하루 5번

이 강의 본문만 근거로 답합니다. 강의에 없는 내용은 지어내지 않습니다.