배포 자신 없는 개발자의 구원자 'CI/CD' 한 번에 끝내는 법

#CI/CD #Docker #배포


| 서버 개발자가 꾸는 '배포의 악몽'

단언컨대, Docker는 서버 개발자를 '배포'라는 악몽으로부터 구원했습니다.
Docker가 개발되기 전까지 서버 개발자들은 배포를 할 때마다 마음 한구석이 편하지 않았는데요. 사실 서버 배포의 원리는 서버 머신에서 돌아가고 있는 프로세스를 종료한 후 바이너리를 교체하고 다시 새로운 프로세스를 실행하는 간단한 작업입니다. 그런데 이렇게 단순해 보이는 작업이 말썽을 일으키는 경우가 종종 있었습니다. 실행하는 서버의 환경이 달라질 수 있는 경우가 발생하기 때문입니다.

원래 운영용 서버에 접속하는 경우 함부로 데이터를 삭제하거나 환경변수를 바꿔선 안 됩니다. 그래서 팀 내부적으로도 규칙을 정해두기도 하죠. 그러나 일하다 보면 언제나 예외가 생기기 마련입니다. 로그만 확인하려고 접속한 동료가 실수로 자바 버전을 업데이트하거나, 특정 환경 변수를 바꾸기도 합니다. 이런 경우, 분명 어제까지는 문제 없이 돌아가던 서버는 새롭게 배포하고 나서부터는 갑자기 되지 않기도 합니다. 이런 경우에는 심지어 롤백을 했는데도 서버가 먹통이 되고 말죠. 팀 동료들 간의 소통이 원활하게 되지 않는 경우 사건은 점점 미궁 속으로 들어가게 되고 결국 서버를 처음부터 다시 세팅하면서 문제가 해결됩니다.

배포

[ 분명 손댄 게 없는데… 왜 동작을 안 하는 거죠…? ]


| 서버 배포의 해결사 Docker

Docker는 이런 문제를 일거에 해결했습니다.

Docker는 컨테이너 기반 가상화 플랫폼으로 애플리케이션을 운영 중인 서버와 격리된 환경에서 실행할 수 있는 이점을 제공합니다. 즉, 운영 중인 서버 환경에 영향을 받지 않고 Docker 자체적으로 환경을 만들 수 있다는 뜻이죠. Docker를 띄우는 환경에 Java8이 설치되어 있더라도 Docker에서는 Java 11을 사용할 수 있다는 말이기도 합니다.

도커

[ 서버 환경에 의존하지 않고 Docker에서 구성한 환경을 사용할 수 있습니다. ]

요리로 비유를 해보겠습니다. 파스타를 만들기 위해선 레시피와 재료가 필요합니다. 레시피는 거의 불변하지만 재료는 그렇지 않습니다. 보관이 제대로 되지 않았다면 상할 수도 있고 냉동과 해동을 거치면서 맛이 변하기도 하죠. 그래서 동일한 레시피를 사용했음에도 매번 다른 맛이 나게 됩니다. 그런데 파스타 밀키트를 사용하면 재료가 달라지는 변수를 줄일 수 있습니다. 공장에서 원산지를 바꾸지 않는 이상 오늘 구매한 재료는 어제 구매한 재료와 크게 차이가 나지 않게 되죠. 그래서 밀키트를 활용하면 재료 걱정은 덜고 레시피에만 온전히 집중할 수 있게 됩니다. Docker를 사용하는 것은 밀키트를 사용하는 것과 비슷합니다. 이전에 사용하던 재료(서버 환경)와 상관 없이 밀키트에 있는 재료(Docker 환경)에 자신의 레시피만(서버 바이너리) 적용하면 되거든요.

개발자는 이제 기존 서버 환경을 걱정하지 않아도 되게 됐습니다. 대신 Docker 위에서 실행할 나만의 컨테이너를 만드는 데 집중하면 됩니다.
이것을 Docker 이미지라고 부릅니다.


| Jenkins와 Github로 자동화하기

그런데 Docker 환경에도 단점이 있습니다.

코드를 업데이트할 때마다 새로운 Docker 이미지를 생성해야 한다는 것입니다. 기존 배포 방식에서는 빌드한 파일을 서버에 업로드하고 프로세스를 재실행하면 끝이었습니다. 그런데 이제는 우분투, Centos 같은 베이스 이미지와 java, python 같은 필수 언어 라이브러리 그리고 서버 빌드 파일까지 모두 설치한 Docker 이미지를 배포할 때마다 매번 생성해야 합니다. 파일 크기가 수백 MB 이하라면 큰 문제가 되지 않겠지만 1G를 넘어서게 되면 생성하는 과정에서도 적지 않은 시간과 리소스가 소요되게 되죠. 내가 하는 일은 많지 않지만, 매번 실행 버튼을 누르고 기다리는 것이 번거로운 것은 사실입니다.

다행히 이와 같은 번거로움을 해결할 수 있는 자동화된 CI 툴이 여러 가지 있습니다.

Jenkins와 Github Action이 대표적인 툴인데요 두 가지 툴을 적절하게 이용하면 개발과 Docker 이미지 생성을 자동화할 수 있습니다.
저는 현재 IT 대기업에서 백엔드 개발자로 일하고 있는데요. 저희 팀에서는 CI 작업을 간소화하기 위해 주로 Github Action을 사용합니다. Github Action에서는 깃헙에서 발생할 수 있는 여러 가지 액션에 따라 특정한 작업을 만들어 줄 수 있는 기능을 제공합니다. 이것을 Github Action에서는 Job이라고 부릅니다.

젠킨스

[ Github Action을 이용해 코드 머지 시 자동으로 도커 이미지를 생성되도록 구성할 수 있습니다 ]

예시를 하나 들어보겠습니다.

Main 브랜치에 Pull Request를 만드는 경우는 코드 리뷰와 동시에 테스트가 필요한 코드를 생성했다고 봐도 됩니다. 이런 경우 Github Action을 이용해서 Main 브랜치에 pull request가 생성되는 경우에 Docker 이미지를 만드는 Job을 추가해서 자동으로 Docker 이미지를 만들도록 구성할 수 있습니다. 이것뿐만 아니라 Pull Request가 머지 되는 경우, 메인 브랜치에 새로운 코드를 푸시하는 경우에도 동일하게 Job을 생성할 수 있게 되지요. 이러한 기능은 깃헙 웹훅을 사용해서 Jenkins에서도 동일하게 세팅할 수 있습니다.

Github Action과 Jenkins는 Docker 이미지를 만드는 것뿐만 아니라 다양한 용도로도 무궁무진하게 사용할 수 있습니다. 저는 실무에서 Jenkins의 Schedule 기능을 활용해 매주 월요일마다 유저들에게 이메일을 보내는 배치 프로세스를 만들기도 했고 Github Action을 이용해서 Pull Request가 생성될 때마다 자동으로 테스트 코드를 실행하도록 했죠.


| ArgoCD 를 이용해 똑똑한 배포 관리

Docker 이미지를 만들었다면 이것을 배포하는 작업도 필요하겠죠? 서버 머신에다가 Docker를 실행할 수도 있지만 Kubernetes를 이용해서 배포하는 것이 Docker의 이점을 100% 활용하기에 적합합니다.
Kubernetes에 배포하기 위해선 직접 yaml 파일을 수정하고 kubectl 명령어를 이용해서 배포하는 방법이 있을 수 있고, 아니면 k9s 와 같은 kubernetes 대시보드 툴을 이용해서 바꿀 수도 있습니다.

그러나 이런 방법들은 모두 개발자가 직접 kubernetes에 배포해야 하는 번거로움이 있을 뿐만 아니라 작업자가 여러 명인 경우 형상 관리가 어려워지는 단점이 존재합니다.

특히나 형상 관리 측면에서 생각해 보면 개발자 각자가 개인 로컬 환경에서 배포 명령어를 실행하게 될 텐데요, 사람마다 최신 yaml 버전을 업데이트하지 않고 실행하는 경우가 종종 발생할 수 있기 때문이죠.

argo cd

[ AgroCD 는 주기적으로 Git 코드를 확인하고 Kubernetes 클러스터를 업데이트 합니다. ]

ArgoCD는 이런 문제점을 보완할 수 있는 툴입니다.

ArgoCD는 특정 Github 저장소 파일을 주기적으로 관찰하고 있다가 변경이 생기면 그에 맞춰 Kubernetes 환경을 바꿔줍니다. 공식 문서에서 정의된 표현에 따르면 Github 저장소가 Target State이고, 배포된 서비스가 Target State와 달라지는 OutOfSync가 발생하면 ArgoCD가 Target State와 동일할 수 있도록 바꿔주는 역할을 하죠. ArgoCD가 있으면 개발자는 Github에 업데이트만 하면 되기 때문에 형상 관리 측면에서도 큰 이점을 가져갈 수 있습니다.


| CI/CD를 반드시 배워야 하는 이유

모든 직업이 비슷하지만, 특히 개발자는 다른 직업보다 더욱 정리하고 꼼꼼한 습관이 요구되는 것 같습니다. 작은 오타가 거대한 시스템 오류로 번질 수 있기 때문이죠. 그래서 ‘일잘러’ 개발자가 되기 위해서는 프레임워크, 언어와 같은 지식을 습득하는 것도 중요하지만 번거로운 업무를 단순화할 수 있는 툴을 자유자재로 사용하는 것도 못지않게 중요하다고 생각합니다. 개발자 채용시장에서도 CI/CD를 할 줄 아는 사람을 뽑는 이유는 이런 이점을 무시할 수 없기 때문일 겁니다.

다행히 패스트 캠퍼스에서는 도커부터 Github Action, Jenkins, ArgoCD까지 모든 것을 한 번에 해결할 수 있는 CI/CD 강의가 있습니다.
그동안 개발자에게 필요한 지식을 습득하는 데 집중하셨다면 이번 강의를 통해서 일잘러가 되기 위한 스킬을 연마해 보시면 어떨까요?


💙 '일잘러' 개발자로 성장하기 위한 배포 관리, CI/CD에 대해 알고 싶다면?

[초격차 패키지 : 한 번에 끝내는 CI/CD의 모든 것 : Docker부터 GitOps까지]

ci cd

✔️ 네카라쿠배 CI/CD 툴 완전 정복
실무 CI/CD 툴 3종(Jenkins, Github Actions, ArgoCD)과 관련 37가지 기술 스택을 한 번에
✔️ 실전! 다양한 환경에 CI/CD 구축
로컬환경 뿐만 아니라 현재 트렌드인 클라우드 환경, Kubernetes 환경까지! 현업 수준의 실습 환경
✔️ CI/CD 실무 프로세스 풀 커버
Docker 부터 GitOps 까지 실무의 CI/CD 프로세스 전 과정을 통째로 담은 실습 중심 강의


지금 패캐머들이 읽고있는 BEST 아티클이 궁금하다면

이 글과 연관된 주제의 추천 강의