데브옵스(DevOps)는 도구가 아니라 문화다: CI/CD 파이프라인 실전 구축기
몇 년 전만 해도 개발팀과 운영팀은 완전히 다른 세계에 살고 있었다. 개발자는 "기능 추가했으니 배포해주세요" 하고 운영팀에 공 던지고, 운영팀은 "이게 왜 갑자기 바뀌었어요? 문서도 없는데"라며 불만을 쌓아갔다. 내가 처음 회사에 들어갔을 때도 상황은 비슷했다. 배포는 매주 금요일 오후 5시, 그 시간만 되면 다들 긴장하고, 문제 생기면 주말이 통째로 날아갔다. 지금 생각하면 정말 비효율적이었지만, 그게 당연한 문화였으니까.
데브옵스는 이런 벽을 허물자는 운동에서 시작됐다. 개발(Development)과 운영(Operations)의 합성어라는 건 다들 알지만, 진짜 의미는 "개발자와 운영자가 협력해서 소프트웨어를 더 빠르고 안정적으로 전달하자"는 철학이다. 단순히 CI/CD 도구를 도입한다고 데브옵스가 되는 게 아니다. 조직 문화와 프로세스, 사람의 마인드셋까지 바뀌어야 한다. 이 글에서는 내가 실제로 겪었던 데브옵스 도입 과정과 CI/CD 파이프라인 구축 경험을 솔직하게 풀어보려고 한다.
데브옵스가 필요한 이유: 내가 겪은 레거시 배포의 악몽
내가 다니던 첫 회사는 전형적인 워터폴 방식으로 운영됐다. 스프링 부트로 만든 모놀리식 애플리케이션 하나를 톰캣에 올려서 서비스하고 있었는데, 배포 프로세스가 가관이었다. 개발자가 수동으로 빌드하고, FTP로 서버에 jar 파일을 업로드하고, SSH 접속해서 톰캣을 내리고 올렸다. 문제는 이 과정에서 휴먼 에러가 너무 자주 발생한다는 거였다. "어, 오늘 배포할 때 application-prod.yml을 안 넣었네?" 같은 실수가 한두 번이 아니었다.
더 큰 문제는 배포 주기였다. 보통 2주에 한 번, 길게는 한 달에 한 번 꼴로 배포가 이뤄졌다. 그 사이에 쌓인 변경 사항이 너무 많아서, 막상 배포하고 나면 예상치 못한 사이드 이펙트가 터지기 일쑤였다. "저번 스프린트에서 추가한 기능이 이번 배포에서 왜 안 되지?" 같은 상황이 발생하면 원인을 찾는 데만 하루가 꼬박 걸렸다. 롤백도 쉽지 않았다. 이전 버전의 jar 파일을 찾는 것부터가 모험이었다. 지금 생각하면 정말 원시적인 수준이었지만, 그 당시에는 "원래 이렇게 하는 거 아니야?"라고 생각했다.
이런 경험을 하고 나니 데브옵스의 필요성을 뼈저리게 느꼈다. 배포를 자동화하고, 변경 사항을 작게 나누고, 문제가 생기면 빠르게 롤백할 수 있는 시스템이 절실했다. 그래서 본격적으로 CI/CD 파이프라인을 구축하기로 마음먹었다.
CI/CD 파이프라인의 핵심 개념
CI(Continuous Integration)는 지속적 통합, CD(Continuous Delivery/Deployment)는 지속적 전달/배포를 의미한다. 말은 거창하지만 핵심은 간단하다. CI는 코드 변경 사항을 하루에도 여러 번 메인 브랜치에 병합하고 자동으로 빌드와 테스트를 수행하는 거고, CD는 이렇게 검증된 코드를 자동으로 스테이징이나 프로덕션 환경에 배포하는 거다.
처음에 내가 헷갈렸던 부분은 CD의 D가 Delivery냐 Deployment냐는 차이였다. Continuous Delivery는 프로덕션 배포 직전까지 자동화하고, 실제 배포는 사람이 결정하는 방식이다. 반면 Continuous Deployment는 테스트를 통과하면 자동으로 프로덕션까지 배포된다. 개인적으로는 초기에는 Continuous Delivery 방식을 추천한다. 완전 자동 배포는 생각보다 무섭다. "어? 이게 프로덕션에 이미 올라갔다고?" 하는 순간이 반드시 온다. 실제로 우리 팀도 처음에는 수동 승인 단계를 넣었는데, 이게 초반에는 꽤 안심이 됐다.
CI/CD 파이프라인의 핵심 목표
코드 커밋부터 프로덕션 배포까지 전 과정을 자동화하여 피드백 사이클을 단축하고, 휴먼 에러를 최소화하며, 안정적인 배포를 보장한다. 이를 통해 개발자는 반복 작업에서 해방되어 비즈니스 로직에 집중할 수 있다.
GitHub Actions로 CI/CD 파이프라인 구축하기
CI/CD 도구는 정말 다양하다. Jenkins, GitLab CI, CircleCI, Travis CI, GitHub Actions 등등. 내가 가장 최근에 사용한 건 GitHub Actions다. 이유는 간단하다. GitHub에 코드가 이미 있고, 별도로 서버를 운영할 필요가 없으며, yaml 파일 하나로 워크플로우를 정의할 수 있다는 점이 매력적이었다. Jenkins는 강력하지만, 마스터 노드와 에이전트 노드를 직접 관리해야 하는 부담이 있다. 소규모 팀이나 개인 프로젝트라면 GitHub Actions가 훨씬 실용적이다.
실제로 내가 구축했던 파이프라인을 예로 들어보겠다. Node.js 기반의 백엔드 API 서버였는데, main 브랜치에 푸시되면 자동으로 빌드, 테스트, 도커 이미지 빌드, ECR 푸시, ECS 배포까지 이어지는 워크플로우를 구성했다. yaml 파일로 작성된 워크플로우는 대략 이런 구조였다:
첫 번째 단계는 코드 체크아웃과 의존성 설치다. GitHub Actions의 ubuntu-latest 러너에서 실행되도록 설정하고, Node.js 18 버전을 세팅했다. npm ci 명령어로 package-lock.json 기반의 의존성을 설치하는데, 이게 npm install보다 훨씬 빠르고 재현 가능한 빌드를 보장한다. 두 번째 단계는 린트와 테스트다. ESLint로 코드 스타일을 검사하고, Jest로 유닛 테스트와 통합 테스트를 실행했다. 테스트 커버리지가 80% 미만이면 실패하도록 게이트를 걸어뒀다. 이 게이트 덕분에 "테스트 안 짰는데 일단 올리고 보자" 같은 나쁜 습관을 어느 정도 막을 수 있었다.
세 번째 단계는 도커 이미지 빌드와 푸시다. GitHub Actions에서 AWS 자격 증명을 사용할 수 있도록 OIDC(OpenID Connect)를 설정했다. IAM 역할을 만들어서 GitHub Actions가 임시 자격 증명을 받아 ECR에 푸시할 수 있게 한 거다. 이렇게 하면 액세스 키를 직접 관리할 필요가 없어서 보안상 훨씬 안전하다. 마지막 단계는 ECS 서비스 업데이트다. 새 이미지 태그로 ECS 태스크 정의를 업데이트하고, 서비스를 롤링 업데이트했다. 전체 파이프라인 실행 시간은 보통 5~7분 정도였다.
Jenkins로 구축하는 엔터프라이즈급 파이프라인
GitHub Actions가 편하긴 하지만, 엔터프라이즈 환경에서는 여전히 Jenkins가 많이 쓰인다. 내가 두 번째 회사에서 경험한 Jenkins 파이프라인은 규모가 꽤 컸다. 마이크로서비스가 30개가 넘었고, 각 서비스마다 빌드, 테스트, 정적 분석, 보안 스캔, 배포까지 다양한 단계가 필요했다. Jenkins Pipeline을 Groovy DSL로 작성했는데, 처음에는 문법이 낯설어서 적응하는 데 시간이 좀 걸렸다.
가장 인상 깊었던 건 Declarative Pipeline의 stage 구조였다. 각 단계를 병렬로 실행할 수도 있고, 조건에 따라 특정 stage를 건너뛸 수도 있었다. 예를 들어, 프론트엔드 서비스는 보안 스캔 단계를 생략하고, 결제 서비스는 추가적인 통합 테스트 단계를 포함시키는 식으로 유연하게 구성할 수 있었다. 또한 Jenkins의 Shared Library를 활용해서 공통 로직을 재사용한 점도 기억에 남는다. 도커 이미지 빌드, ECR 푸시, 쿠버네티스 배포 같은 공통 단계를 라이브러리로 만들어두니, 새로운 서비스를 추가할 때 파이프라인을 거의 복사-붙여넣기 수준으로 빠르게 구성할 수 있었다.
하지만 Jenkins의 단점도 분명했다. 플러그인 의존성이 너무 컸다. Jenkins의 강점이 방대한 플러그인 생태계이긴 한데, 반대로 말하면 플러그인 버전 호환성 문제로 고생할 때가 많았다. 특히 보안 취약점이 발견되면 플러그인 업데이트와 Jenkins 재시작이 필요했는데, 이게 생각보다 자주 일어났다. 마스터 노드 장애에 대비한 고가용성 구성도 신경 써야 했고, 빌드 히스토리가 쌓이면서 디스크 용량 관리도 골칫거리였다. 이런 운영 부담을 고려하면, 규모가 작은 팀이라면 GitHub Actions나 GitLab CI 같은 SaaS형 도구가 훨씬 실용적이라는 생각이 든다.
도커와 쿠버네티스를 활용한 배포 자동화
CI/CD 파이프라인에서 빼놓을 수 없는 게 컨테이너다. 도커는 애플리케이션과 그 실행 환경을 하나의 이미지로 패키징해서, "내 컴퓨터에서는 잘 되는데요?"라는 문제를 근본적으로 해결해준다. CI 파이프라인에서 빌드된 도커 이미지는 레지스트리에 저장되고, CD 파이프라인에서 이 이미지를 가져와서 배포한다.
쿠버네티스 환경에서는 배포 전략이 중요하다. 가장 기본적인 건 롤링 업데이트다. 새 버전의 파드를 하나씩 띄우고, 정상적으로 동작하면 기존 파드를 하나씩 내리는 방식이다. 무중단 배포가 가능하지만, 롤백이 느리다는 단점이 있다. 문제가 발견되면 모든 파드가 교체될 때까지 기다려야 하니까. 블루-그린 배포는 이 문제를 해결한다. 기존 버전(블루)과 새 버전(그린)을 동시에 띄워놓고, 트래픽을 한 번에 그린으로 전환하는 방식이다. 롤백도 다시 블루로 트래픽을 돌리면 끝이라서 매우 빠르다. 단점은 리소스가 두 배로 필요하다는 거다.
내가 가장 선호하는 건 카나리 배포다. 새 버전에 트래픽의 5%만 먼저 보내고, 모니터링하면서 에러율이나 레이턴시를 지켜보는 방식이다. 문제가 없으면 점진적으로 트래픽을 늘리고, 문제가 생기면 즉시 롤백한다. Istio나 Linkerd 같은 서비스 메시를 사용하면 트래픽 비율을 세밀하게 제어할 수 있다. 실제로 우리 서비스에서 카나리 배포 덕분에 조용히 넘어갈 뻔한 버그를 잡아낸 적이 있다. 새 버전에서 특정 API의 응답 시간이 200ms에서 2초로 늘어난 걸 카나리 단계에서 발견했고, 바로 롤백해서 장애를 사전에 차단할 수 있었다.
데브옵스 문화 정착을 위한 현실적인 조언
기술적인 파이프라인 구축도 중요하지만, 진짜 어려운 건 문화를 바꾸는 일이다. 내 경험상 데브옵스 도입에서 가장 큰 장벽은 "우리 팀은 달라"는 생각이었다. 개발자들은 "배포는 운영팀 몫이잖아요"라고 생각했고, 운영팀은 "개발자들이 운영 환경을 건드리면 큰일 난다"는 불안감을 가지고 있었다. 이 벽을 허무는 데는 시간이 꽤 걸렸다.
첫 번째로 했던 건 공유된 책임 의식을 만드는 거였다. "You build it, you run it"이라는 말처럼, 개발자가 자신이 만든 코드가 프로덕션에서 어떻게 동작하는지 직접 모니터링하고, 장애가 나면 본인이 온콜을 서는 문화를 만들었다. 처음에는 반발이 있었다. "우리는 개발만 하면 되는 거 아니에요?"라는 불만이 나왔다. 하지만 시간이 지나면서 개발자들이 자신의 코드에 대해 더 책임감을 가지게 되었고, 자연스럽게 테스트 커버리지도 올라가고 코드 품질도 좋아졌다.
두 번째는 실패를 두려워하지 않는 문화를 만드는 거다. 블레임 프리(blame-free) 문화라고도 하는데, 장애가 발생했을 때 "누가 잘못했는가"를 찾기보다 "왜 이런 일이 발생했고, 어떻게 예방할 수 있을까"에 집중하는 거다. 포스트모템(사후 분석)을 작성할 때도 비난하는 어조를 금지하고, 객관적인 사실과 개선 방안만 기록하도록 했다. 이 문화가 정착되면서 팀원들이 더 적극적으로 새로운 시도를 하게 되었고, 배포 주기도 점점 짧아졌다.
세 번째는 점진적인 접근이다. 처음부터 모든 걸 바꾸려고 하면 실패하기 쉽다. 작게 시작해서 성공 사례를 만들고, 그걸 바탕으로 확장해 나가는 게 좋다. 우리 팀은 가장 간단한 서비스 하나를 골라서 CI/CD 파이프라인을 먼저 적용했다. 배포 시간이 30분에서 5분으로 줄고, 장애도 확연히 줄어들자 다른 팀들도 관심을 가지기 시작했다. "야, 너네 어떻게 한 거야?"라는 질문이 들어오기 시작하면 반은 성공한 거다.
모니터링과 피드백 루프의 중요성
CI/CD 파이프라인을 구축했다고 끝이 아니다. 파이프라인이 제대로 동작하는지, 배포된 애플리케이션이 정상적인지 지속적으로 모니터링해야 한다. 프로메테우스와 그라파나는 이 측면에서 정말 강력한 도구다. 나는 보통 네 가지 황금 신호(Four Golden Signals)를 기준으로 모니터링 대시보드를 구성한다: 레이턴시(응답 시간), 트래픽(요청 수), 에러율(5xx 에러 비율), 포화도(CPU/메모리 사용량).
알림도 체계적으로 설정해야 한다. 모든 알림을 개발자에게 보내면 금방 알림 피로가 쌓인다. 중요한 알림만 필터링해서 적절한 채널로 전달하는 게 중요하다. 우리 팀은 PagerDuty와 슬랙을 연동해서, 크리티컬한 알림은 PagerDuty로 전화가 가고, 경고 수준은 슬랙 채널로만 알림이 오도록 설정했다. 또한 주간 배포 리뷰 미팅을 열어서, 그 주에 배포된 내용과 모니터링 지표를 함께 리뷰했다. 이 미팅 덕분에 팀 전체가 서비스의 현재 상태를 공유할 수 있었고, 문제가 될 만한 부분을 사전에 발견할 수 있었다.
로그 중앙 집계도 빼놓을 수 없다. ELK 스택(Elasticsearch, Logstash, Kibana)이나 Loki + Grafana 조합을 사용하면 모든 서비스의 로그를 한곳에서 검색하고 분석할 수 있다. 특히 분산 트레이싱과 로그를 연계하면, "이 요청이 왜 느렸는지"를 추적하는 게 훨씬 수월해진다. 실제로 한 번은 특정 API의 응답 시간이 간헐적으로 10초까지 튀는 현상이 있었는데, 분산 트레이싱으로 추적해보니 특정 마이크로서비스의 DB 커넥션 풀이 고갈되는 게 원인이었다. 로그와 메트릭, 트레이스를 함께 보지 않았으면 원인을 찾는 데 훨씬 오래 걸렸을 거다.
데브옵스의 미래: Platform Engineering과 AIOps
요즘 IT 업계에서 가장 뜨거운 키워드 중 하나가 플랫폼 엔지니어링(Platform Engineering)이다. 데브옵스가 발전하면서 각 팀이 인프라를 직접 관리하는 게 오히려 부담이 되는 상황이 생겼다. 그래서 등장한 게 내부 개발자 플랫폼(IDP, Internal Developer Platform)이다. 개발자에게는 셀프 서비스 방식으로 인프라를 제공하고, 복잡한 운영은 플랫폼 팀이 담당하는 구조다. Backstage(스포티파이가 오픈소스로 공개한 IDP)나 Humanitec 같은 도구가 대표적이다.
AIOps도 주목할 만하다. AI가 장애를 예측하고, 원인을 분석하고, 심지어 자동으로 조치까지 취하는 개념이다. 예를 들어, 과거의 장애 패턴을 학습해서 "이런 메트릭 조합이 보이면 30분 후에 장애가 발생할 확률이 90%입니다" 같은 예측을 해준다. 아직은 초기 단계지만, 머지않아 CI/CD 파이프라인의 중요한 구성 요소가 될 거라고 생각한다. 실제로 구글의 SRE 팀은 이미 AI 기반의 장애 예측 시스템을 운영 중이라고 알려져 있다.
개인적으로 가장 기대하는 건 GitOps 방식의 진화다. ArgoCD나 Flux CD 같은 도구를 사용하면, Git 저장소의 상태가 곧 프로덕션 환경의 상태가 된다. "git push" 한 번으로 인프라 변경부터 애플리케이션 배포까지 모든 게 자동으로 동기화된다. 선언형 인프라와 버전 관리의 이점을 결합한 이 방식은, 앞으로 더 많은 조직에서 표준으로 채택할 거라고 본다.
마치며
데브옵스는 결코 하루아침에 완성되는 게 아니다. 나도 처음에는 "CI/CD 파이프라인만 구축하면 끝이겠지"라고 생각했지만, 막상 해보니 그게 시작에 불과했다. 진짜 중요한 건 도구가 아니라 사람과 문화였다. 개발자와 운영자가 벽을 허물고 함께 협력할 때, 비로소 데브옵스의 진정한 가치가 발휘된다.
혹시 지금 "우리 회사는 아직 데브옵스 도입이 먼 이야기다"라고 생각한다면, 작은 것부터 시작해보길 권한다. 수동 배포 스크립트 하나라도 자동화하고, 배포 체크리스트를 문서화하고, 장애가 났을 때 포스트모템을 작성하는 것부터. 이런 작은 변화들이 모여서 결국 조직 전체의 문화를 바꾼다. 기술은 빠르게 변하지만, 협력과 신뢰의 문화는 그 변화를 지탱하는 튼튼한 기반이 되어줄 거다.
'IT & 비즈니스' 카테고리의 다른 글
| 데이터베이스 인덱싱의 모든 것: 실무에서 겪은 성능 최적화 경험담 (0) | 2026.07.21 |
|---|---|
| MSA와 컨테이너 오케스트레이션 완벽 가이드 | IT 인프라 혁신 (0) | 2026.07.19 |
| Rust 언어의 부상: 메모리 안전성과 시스템 프로그래밍의 새로운 패러다임 (0) | 2026.07.17 |
| WebAssembly(Wasm): 웹 브라우저를 넘어 차세대 범용 컴퓨팅 플랫폼으로의 진화 (0) | 2026.07.16 |
| 양자컴퓨팅(Quantum Computing): 2026년, 0과 1을 넘어서는 미래 컴퓨팅의 새로운 패러다임 (0) | 2026.07.14 |