Spring Boot, Jenkins, Kubernetes 및 보안 스캔을 활용한 엔드‑투‑엔드 CI/CD 파이프라인 구축

발행: (2026년 1월 6일 오전 04:29 GMT+9)
8 min read
원문: Dev.to

Source: Dev.to

위에 제공된 소스 링크만으로는 번역할 실제 텍스트가 포함되어 있지 않습니다. 번역을 원하는 본문 내용을 그대로 복사해서 알려주시면, 요청하신 대로 마크다운 형식과 코드 블록을 유지하면서 한국어로 번역해 드리겠습니다.

왜 이 프로젝트를 만들었는가

저는 CI/CD 개념과 도구들을 사용해 본 적이 있지만, 도구를 아는 것과 완전한 시스템을 구축하는 것 사이에는 항상 격차가 있었습니다.
대부분의 튜토리얼은 “파이프라인이 성공적으로 실행되었습니다” 라는 단계에서 멈추고, 실제 CI/CD 시스템은 다음과 같은 요소들을 포함합니다:

  • 버전 관리 전략
  • 웹훅
  • 코드 품질 게이트
  • 보안 스캔
  • 쿠버네티스 롤아웃
  • 실패, 재시작 및 광범위한 디버깅

저는 Git 푸시부터 시작해 쿠버네티스에서 실행되는 완전하게 배포되고, 보안이 강화되며, 관찰 가능한 Spring Boot 애플리케이션까지 이어지는 진정한 엔드‑투‑엔드 CI/CD 파이프라인을 구축하기로 결심했습니다. 이 블로그에서는 제가 만든 내용, 발생한 문제, 해결 방법, 그리고 배운 교훈을 기록합니다.

파이프라인 개요

레이어기술
애플리케이션Spring Boot
버전 관리Maven + /release API
SCMGitHub
CI/CDJenkins (Pipeline as Code)
코드 품질SonarQube
노출Ngrok
컨테이너Docker
보안Trivy
오케스트레이션Kubernetes
데이터베이스MongoDB
알림Jenkins Mailer

파이프라인은 로컬에서 실행되지만 프로덕션 시스템처럼 동작합니다:

Git push → automatic Jenkins trigger
→ Maven build & tests
→ Application versioning with /release endpoint
→ Docker image build (immutable)
→ SonarQube code quality gates
→ Trivy image security scanning
→ Kubernetes deployment & rollout
→ Email notifications
→ MongoDB‑backed persistence

GitHub 푸시 및 Jenkins 트리거

  1. 개발자가 코드를 GitHub에 푸시합니다.
  2. Ngrok을 통해 노출된 웹훅이 Jenkins 파이프라인을 자동으로 트리거합니다—수동 시작이 필요 없습니다.
  3. Jenkins가 저장소를 클론하고 빌드를 실행합니다.

Maven 빌드 및 테스트

mvn clean test

보장:

  • 코드가 컴파일됩니다.
  • 단위 테스트가 통과합니다.
  • 진행하기 전에 빌드가 배포 가능함을 확인합니다.

SonarQube Quality Gates

  • Jenkins는 분석 보고서를 SonarQube에 전송합니다.
  • 파이프라인은 Quality Gate 결과를 기다립니다.
  • 게이트가 실패하면 빌드가 중단되어 엔지니어링 표준이 자동으로 적용됩니다.

Docker 이미지 빌드 (멀티‑스테이지)

멀티‑스테이지 Dockerfile이 사용됩니다:

  • Build stage – Maven과 모든 빌드 종속성을 포함합니다.
  • Runtime stage – JRE와 컴파일된 JAR만 포함합니다.

Result: 더 작고, 보다 안전한 프로덕션 이미지.

Trivy를 이용한 보안 스캔

이미지를 레지스트리에 푸시하기 전에 Trivy가 스캔합니다:

trivy image 
  • CriticalHigh 취약점을 감지합니다.
  • 파이프라인을 심각도에 따라 실패하도록 구성할 수 있어, 취약한 이미지가 배포에 도달하지 않도록 보장합니다.

쿠버네티스 배포 및 롤아웃

모든 검사가 통과된 후:

docker push /:${BUILD_NUMBER}
kubectl apply -f deployment.yaml
kubectl rollout status deployment/

젠킨스 컨테이너 문제 및 해결책

문제해결책
Jenkins가 Docker 컨테이너 내부에서 실행되지만 Docker 이미지를 빌드해야 하므로 /var/run/docker.sock에 대한 권한 문제가 발생합니다.- 호스트 Docker 소켓을 젠킨스 컨테이너에 마운트합니다 (-v /var/run/docker.sock:/var/run/docker.sock).
- 젠킨스 이미지 내부에 docker 그룹을 추가하고 jenkins 사용자를 해당 그룹에 포함시킵니다.
Jenkins(컨테이너)가 Windows 호스트에서 127.0.0.1을 사용해 쿠버네티스 API 서버에 접근하지 못했습니다.젠킨스 컨테이너를 --add-host=localhost:host-gateway 옵션으로 실행하여 컨테이너의 localhost를 호스트 게이트웨이와 매핑하면 KIND 클러스터와 통신할 수 있습니다.
배포가 여전히 :latest 태그를 참조하고 있으면 이미지가 변경되어도 쿠버네티스가 새로운 롤아웃을 트리거하지 않습니다.동적 이미지 태깅을 구현합니다: deployment.yamlIMAGE_PLACEHOLDER를 고유 버전 ${BUILD_NUMBER} 로 교체합니다. 이렇게 하면 모든 변경에 대해 롤아웃이 보장되고, 결정적인 롤백 및 추적 가능한 이미지 버전을 제공합니다.

/release Endpoint

Spring Boot 애플리케이션은 /release 엔드포인트를 노출하여 다음을 반환합니다:

  • 애플리케이션 버전
  • Jenkins 빌드 번호
  • 런타임 환경 메타데이터

이를 통해 파드 내부에서 실행 중인 빌드를 애플리케이션에서 직접 쉽게 확인할 수 있습니다.

맞춤형 Jenkins Docker 이미지

맞춤형 Jenkins 이미지는 다음 도구들이 사전 설치된 상태로 빌드됩니다:

  • Maven
  • Docker CLI
  • Kubectl

이점:

  • 환경 전반에 걸친 재현성.
  • 새 팀원의 빠른 온보딩.
  • 일관된 도구 버전.

교훈

  • Shift‑left 보안: Trivy는 배포 전에 중요한 CVE(예: Tomcat RCE)를 식별했습니다.
  • 네트워크 경계가 중요: Jenkins, SonarQube, Kubernetes, Docker 간의 통신 관리가 가장 큰 과제였습니다.
  • 이벤트 기반 파이프라인: 수동 트리거를 제거하고 GitHub 웹훅에 의존함으로써 파이프라인을 진정한 CI/CD로 전환했습니다.
  • 자동화가 신뢰를 구축: 시스템 간의 상호 작용을 이해하고 실패를 체계적으로 처리함으로써 DevOps를 스크립트 수준에서 엔지니어링 수준으로 끌어올립니다.

참고문헌

  • GitHub 저장소:
  • LinkedIn 프로필:
Back to Blog

관련 글

더 보기 »

기술은 구원자가 아니라 촉진자다

왜 사고의 명확성이 사용하는 도구보다 더 중요한가? Technology는 종종 마법 스위치처럼 취급된다—켜기만 하면 모든 것이 개선된다. 새로운 software, ...

에이전틱 코딩에 입문하기

Copilot Agent와의 경험 나는 주로 GitHub Copilot을 사용해 인라인 편집과 PR 리뷰를 수행했으며, 대부분의 사고는 내 머리로 했습니다. 최근 나는 t...