본 콘텐츠의 이미지 및 내용은 AI로 생성되었습니다.
본 콘텐츠의 이미지 및 내용을 무단으로 복제, 배포, 수정하여 사용할 경우 저작권법에 의해 법적 제재를 받을 수 있습니다.
이미지 로딩 중...
AI Generated
2025. 11. 5. · 24 Views
GitLab CI로 만드는 실전 프로젝트 완벽 가이드
GitLab CI/CD를 활용하여 실제 프로젝트에 자동화 파이프라인을 구축하는 방법을 배웁니다. 테스트부터 배포까지 전 과정을 실무 중심으로 다루며, Docker, Kubernetes 연동까지 단계별로 설명합니다.
들어가며
안녕하세요!
여러분이 GitLab CI로 만드는 실전 프로젝트 완벽 가이드에 대해 궁금하셨다면 잘 찾아오셨습니다. 이 글에서는 실무에서 바로 사용할 수 있는 핵심 개념들을 친근하고 이해하기 쉽게 설명해드리겠습니다.
현대 소프트웨어 개발에서 Python는 매우 중요한 위치를 차지하고 있습니다. 복잡해 보이는 개념들도 하나씩 차근차근 배워나가면 어렵지 않게 마스터할 수 있습니다.
총 9가지 주요 개념을 다루며, 각각의 개념마다 실제 동작하는 코드 예제와 함께 상세한 설명을 제공합니다. 단순히 '무엇'인지만 알려드리는 것이 아니라, '왜' 필요한지, '어떻게' 동작하는지, 그리고 '언제' 사용해야 하는지까지 모두 다룹니다.
초보자도 쉽게 따라할 수 있도록 단계별로 풀어서 설명하며, 실무에서 자주 마주치는 상황을 예시로 들어 더욱 실용적인 학습이 되도록 구성했습니다. 이론만 알고 있는 것이 아니라 실제 프로젝트에 바로 적용할 수 있는 수준을 목표로 합니다!
목차
- GitLab_CI_기본_구조 - .gitlab-ci.yml 파일 작성법
- 파이프라인_스테이지_설계 - 빌드, 테스트, 배포 단계
- Docker_이미지_빌드 - 컨테이너 기반 배포
- 환경_변수_관리 - 시크릿과 설정 분리
- 조건부_파이프라인 - 브랜치별 실행 전략
- 캐싱_전략 - 빌드 속도 최적화
- 아티팩트_관리 - 빌드 결과물 공유
- Kubernetes_배포 - 자동화된 클러스터 배포
- GitLab_CI_기본_구조
1. GitLab CI 기본 구조 - .gitlab-ci.yml 파일 작성법
2. 파이프라인 스테이지 설계 - 빌드, 테스트, 배포 단계
3. Docker 이미지 빌드 - 컨테이너 기반 배포
4. 환경 변수 관리 - 시크릿과 설정 분리
5. 조건부 파이프라인 - 브랜치별 실행 전략
6. 캐싱 전략 - 빌드 속도 최적화
7. 아티팩트 관리 - 빌드 결과물 공유
8. Kubernetes 배포 - 자동화된 클러스터 배포
1. GitLab CI 기본 구조
여러분이 매번 코드를 푸시할 때마다 수동으로 테스트를 돌리고, 빌드하고, 서버에 배포하는 작업을 반복하고 있나요? 팀원이 늘어날수록 이런 수동 작업은 실수를 유발하고, 배포 시간이 지연되며, 결국 생산성을 크게 떨어뜨립니다. 실제로 많은 팀이 "누가 배포했지?", "어떤 버전이 운영에 올라갔지?"와 같은 질문에 답하지 못해 문제를 겪습니다. 특히 긴급한 핫픽스가 필요할 때, 배포 프로세스가 복잡하면 서비스 장애 시간이 길어질 수밖에 없습니다. 바로 이럴 때 필요한 것이 GitLab CI입니다. .gitlab-ci.yml 파일 하나로 모든 빌드, 테스트, 배포 과정을 자동화하여 코드 푸시만으로 전체 프로세스가 돌아가게 만들 수 있습니다. 여러분의 파이프라인이 한 번 실행될 때마다 30분씩 걸린다면, 개발자들은 코드를 자주 푸시하지 않게 됩니다. 그 결과 머지 충돌이 늘어나고, 문제 발견이 늦어지며, 결국 배포 주기가 길어집니다. 많은 팀이 모든 작업을 하나의 거대한 스크립트로 만들어 실행합니다. 그러면 테스트 하나만 실패해도 전체를 다시 돌려야 하고, 어디서 시간이 오래 걸리는지 파악하기도 어렵습니다. 바로 이럴 때 필요한 것이 스테이지 설계입니다. 작업을 논리적으로 분리하고 병렬 실행하여 파이프라인 속도를 극적으로 개선할 수 있습니다. 여러분이 개발 환경에서는 잘 돌아가던 애플리케이션이 운영 서버에서 갑자기 동작하지 않는 경험을 했나요? Python 버전이 다르거나, 시스템 라이브러리가 없거나, 환경 변수가 달라서 발생하는 이런 문제는 배포 때마다 개발자를 괴롭힙니다. 실제로 "내 컴퓨터에서는 되는데요"라는 말은 개발팀의 고질적인 농담이자 실제 문제입니다. 각 환경마다 설정을 다르게 관리하면 일관성을 보장할 수 없고, 새로운 개발자 온보딩에도 시간이 오래 걸립니다. 바로 이럴 때 필요한 것이 Docker 이미지 빌드 자동화입니다. GitLab CI에서 이미지를 빌드하고 레지스트리에 푸시하면, 모든 환경에서 동일한 컨테이너가 실행되어 환경 차이로 인한 문제를 원천 차단할 수 있습니다. 여러분이 데이터베이스 비밀번호나 API 키를 코드에 직접 작성한 적이 있나요? 그리고 그 코드를 실수로 퍼블릭 저장소에 푸시해서 보안 사고를 겪거나, 운영 환경의 설정을 개발 환경에서 사용해 실제 고객 데이터를 건드린 경험이 있을 겁니다. 많은 개발자가 .env 파일을 Git에 커밋하거나, 설정 값을 코드에 하드코딩합니다. 그 결과 환경별로 다른 설정이 필요할 때 코드를 수정해야 하고, 시크릿이 노출되는 보안 리스크가 발생하며, 팀원마다 다른 설정을 사용하게 됩니다. 바로 이럴 때 필요한 것이 GitLab CI의 환경 변수 관리입니다. 시크릿과 설정을 코드에서 완전히 분리하고, 환경별로 다른 값을 안전하게 주입하여 보안과 유연성을 동시에 확보할 수 있습니다. 여러분이 개발 브랜치에 코드를 푸시할 때마다 운영 배포 파이프라인이 실행되거나, 문서만 수정했는데 전체 빌드가 돌아가서 시간과 리소스를 낭비한 경험이 있나요? 또는 특정 파일이 변경되었을 때만 관련 테스트를 실행하고 싶었던 적이 있을 겁니다. 많은 팀이 모든 브랜치에서 동일한 파이프라인을 실행합니다. 그 결과 개발 중인 기능 브랜치에서 불필요한 배포 작업이 실행되고, Runner 자원이 낭비되며, 파이프라인 대기 시간이 길어집니다. 중요한 배포는 대기하는데 중요하지 않은 작업이 먼저 실행되는 상황이 발생합니다. 바로 이럴 때 필요한 것이 조건부 파이프라인입니다. rules 키워드로 브랜치, 파일 변경, 변수 등에 따라 작업을 선택적으로 실행하여 효율성을 극대화할 수 있습니다. 여러분이 매번 파이프라인을 실행할 때마다 모든 의존성을 처음부터 다시 다운로드하고 설치하느라 5-10분씩 낭비하고 있나요? Python의 pip, Node.js의 npm, Maven의 dependencies처럼 거의 변하지 않는 것들을 매번 다시 받는 것은 엄청난 시간과 네트워크 대역폭 낭비입니다. 많은 개발자가 캐싱 없이 파이프라인을 실행합니다. 그 결과 간단한 코드 한 줄 수정에도 전체 의존성 설치를 기다려야 하고, Runner가 많은 시간을 단순 다운로드에 소비하며, 외부 패키지 저장소의 일시적 장애에도 파이프라인이 실패합니다. 바로 이럴 때 필요한 것이 캐싱 전략입니다. GitLab CI의 cache 기능으로 의존성, 빌드 결과물, 컴파일 캐시 등을 재사용하여 파이프라인 속도를 3-10배 향상시킬 수 있습니다. 여러분이 빌드 작업에서 생성한 바이너리나 컴파일된 파일을 다음 배포 작업에서 사용하려고 했는데, 파일이 사라져서 다시 빌드해야 했던 경험이 있나요? GitLab CI의 각 job은 기본적으로 격리된 환경에서 실행되므로, job 간 파일 공유가 자동으로 되지 않습니다. 많은 개발자가 job마다 동일한 빌드를 반복하거나, 외부 스토리지에 수동으로 업로드/다운로드합니다. 그 결과 빌드 시간이 배로 늘어나고, 버전 불일치가 발생하며(테스트한 버전과 배포한 버전이 다름), 수동 작업으로 인한 실수가 생깁니다. 바로 이럴 때 필요한 것이 아티팩트 관리입니다. GitLab CI의 artifacts 기능으로 job 간 파일을 안전하게 전달하고, 빌드 결과물을 보관하며, 배포 가능한 패키지를 관리할 수 있습니다. 여러분이 Kubernetes 클러스터에 애플리케이션을 배포할 때마다 로컬에서 kubectl 명령어를 수동으로 실행하고, 배포가 제대로 되었는지 일일이 확인하느라 시간을 낭비하고 있나요? 그리고 팀원마다 다른 kubectl 버전을 사용하거나, 잘못된 네임스페이스에 배포하는 실수를 경험했을 겁니다. 많은 팀이 Kubernetes 배포를 수동으로 하거나, 복잡한 스크립트를 작성합니다. 그 결과 배포 과정이 일관되지 않고, 롤백이 어려우며, 누가 언제 무엇을 배포했는지 추적하기 힘듭니다. 특히 긴급 배포 시 실수로 잘못된 이미지를 배포하는 심각한 사고가 발생할 수 있습니다. 바로 이럴 때 필요한 것이 GitLab CI의 Kubernetes 배포 자동화입니다. GitLab과 Kubernetes를 연동하여 코드 푸시만으로 클러스터에 자동 배포하고, 배포 히스토리를 관리하며, 문제 발생 시 즉시 롤백할 수 있습니다.
개념 이해하기
간단히 말해서, GitLab CI는 코드 저장소에 있는 .gitlab-ci.yml 파일을 읽어 자동으로 작업을 실행하는 시스템입니다. 이 파일에는 "언제, 무엇을, 어떻게" 실행할지를 정의합니다. 예를 들어, master 브랜치에 코드가 머지되면 자동으로 테스트를 실행하고, 통과하면 Docker 이미지를 빌드한 후 운영 서버에 배포하는 전체 워크플로우를 코드로 관리할 수 있습니다. 기존에는 Jenkins를 별도로 설치하고 복잡한 플러그인을 설정해야 했다면, GitLab CI는 GitLab에 내장되어 있어 별도 인프라 없이 바로 시작할 수 있습니다. GitLab CI의 핵심 특징은 세 가지입니다: YAML 기반의 선언적 설정, 스테이지별 작업 분리, 그리고 Runner를 통한 분산 실행입니다. 이러한 특징들이 복잡한 배포 파이프라인도 명확하게 관리할 수 있게 해줍니다. 간단히 말해서, 스테이지는 파이프라인을 여러 단계로 나누어 관리하는 방법입니다. 각 스테이지는 순차적으로 실행되지만, 같은 스테이지 내의 여러 job은 병렬로 실행됩니다. 예를 들어, test 스테이지에서 unit_test, integration_test, lint를 동시에 돌려 시간을 3배 단축할 수 있습니다. 모든 테스트가 통과해야만 다음 build 스테이지로 넘어갑니다. 기존에는 Jenkins의 stage 블록을 Groovy로 작성해야 했다면, GitLab CI는 간단한 YAML로 동일한 효과를 낼 수 있습니다. 스테이지 설계의 핵심은 세 가지입니다: 의존성 명확화 (테스트 없이 배포 불가), 병렬성 극대화 (독립적인 작업은 동시 실행), 실패 빠른 감지 (빠른 작업을 앞에 배치)입니다. 이러한 원칙들이 파이프라인을 효율적으로 만듭니다. 간단히 말해서, Docker 이미지 빌드는 애플리케이션과 모든 의존성을 하나의 패키지로 만드는 과정입니다. GitLab CI에서는 Docker-in-Docker(dind) 또는 kaniko를 사용하여 파이프라인 안에서 이미지를 빌드합니다. 예를 들어, 코드가 master에 머지되면 자동으로 Dockerfile을 빌드하여 GitLab Container Registry에 푸시하고, 그 이미지를 Kubernetes에 배포하는 전체 과정을 자동화할 수 있습니다. 기존에는 개발자가 로컬에서 이미지를 빌드하고 수동으로 레지스트리에 푸시해야 했다면, 이제는 코드 푸시만으로 모든 것이 자동화됩니다. Docker 빌드의 핵심 특징은 세 가지입니다: 재현 가능한 빌드 환경, 멀티 스테이지 빌드로 이미지 크기 최적화, 그리고 레이어 캐싱을 통한 빌드 속도 향상입니다. 이러한 특징들이 프로덕션급 컨테이너 이미지를 안정적으로 만들어냅니다. 간단히 말해서, 환경 변수는 코드 외부에서 설정값을 주입하는 메커니즘입니다. GitLab CI에서는 프로젝트 설정의 CI/CD Variables에서 변수를 정의하면, 파이프라인 실행 시 자동으로 환경 변수로 주입됩니다. 예를 들어, 개발/스테이징/운영 환경별로 다른 DATABASE_URL을 설정하고, API 키는 마스킹(masked)하여 로그에 노출되지 않게 하며, protected 옵션으로 main 브랜치에서만 사용 가능하게 제한할 수 있습니다. 기존에는 Jenkins의 Credentials 플러그인으로 복잡하게 관리해야 했다면, GitLab은 UI에서 직관적으로 변수를 추가하고 즉시 사용할 수 있습니다. 환경 변수 관리의 핵심은 세 가지입니다: 보안을 위한 마스킹과 암호화, 환경별 분리(Environment Scope), 그리고 파일 타입 변수로 인증서 같은 큰 데이터 처리입니다. 이러한 기능들이 안전하고 유연한 설정 관리를 가능하게 합니다. 간단히 말해서, 조건부 파이프라인은 특정 조건을 만족할 때만 작업을 실행하는 메커니즘입니다. GitLab CI의 rules는 if, changes, exists 조건을 지원합니다. 예를 들어, src/ 디렉토리의 Python 파일이 변경되었을 때만 테스트를 실행하고, docs/만 변경되었다면 문서 빌드만 실행하며, main 브랜치에서만 프로덕션 배포를 허용하는 식으로 세밀하게 제어할 수 있습니다. 기존의 only/except는 단순한 브랜치 필터만 가능했다면, rules는 복잡한 논리 조건과 파일 변경 감지까지 지원하여 훨씬 강력합니다. 조건부 실행의 핵심은 세 가지입니다: 변경된 파일 기반 실행(changes), 브랜치/태그 패턴 매칭(if), 그리고 수동 실행 제어(when: manual)입니다. 이러한 기능들이 파이프라인을 지능적으로 만들고 자원 낭비를 막아줍니다. 간단히 말해서, 캐싱은 파이프라인 실행 간에 파일을 저장하고 재사용하는 메커니즘입니다. GitLab CI의 cache는 주로 의존성 디렉토리를 저장합니다. 예를 들어, Python의 venv/, Node.js의 node_modules/, Maven의 .m2/repository/ 등을 캐싱하면 다음 파이프라인에서 pip install이나 npm install이 거의 즉시 완료됩니다. 파일이 변경되지 않았다면 캐시에서 복원하고, 변경되었다면 새로 설치 후 캐시를 업데이트합니다. 기존에는 Jenkins의 복잡한 캐싱 플러그인을 설정해야 했다면, GitLab CI는 간단한 cache 키워드로 자동으로 처리됩니다. 캐싱 전략의 핵심은 세 가지입니다: 적절한 캐시 키 설계(파일 변경 시만 갱신), 캐시 정책(pull/push 분리), 그리고 캐시 범위(브랜치별 vs 전역)입니다. 이러한 요소들이 최적의 성능과 정확성을 보장합니다. 간단히 말해서, 아티팩트는 job이 생성한 파일을 다음 job에 전달하거나 보관하는 메커니즘입니다. GitLab CI에서 artifacts를 정의하면, 해당 파일들이 자동으로 압축되어 GitLab 서버에 업로드되고, 다음 스테이지의 job들이 자동으로 다운로드하여 사용할 수 있습니다. 예를 들어, build 스테이지에서 생성한 Docker 이미지 태그 정보나 컴파일된 바이너리를 deploy 스테이지에서 그대로 사용할 수 있습니다. 또한 GitLab UI에서 아티팩트를 다운로드하여 로컬에서 검토할 수도 있습니다. 기존에는 빌드 서버의 특정 디렉토리에 저장하거나 S3에 수동 업로드해야 했다면, GitLab CI는 자동으로 처리하고 UI에서 쉽게 접근할 수 있습니다. 아티팩트 관리의 핵심은 세 가지입니다: 필요한 파일만 선택적으로 저장, 적절한 만료 기간 설정, 그리고 리포트 아티팩트로 테스트 결과 시각화입니다. 이러한 기능들이 효율적인 빌드 파이프라인을 만들어줍니다. 간단히 말해서, Kubernetes 배포는 컨테이너화된 애플리케이션을 클러스터에 자동으로 배포하고 관리하는 프로세스입니다. GitLab CI에서는 kubeconfig 파일이나 서비스 어카운트 토큰을 환경 변수로 저장하고, kubectl 명령어로 Deployment, Service, Ingress 등을 업데이트합니다. 예를 들어, main 브랜치에 코드가 머지되면 자동으로 Docker 이미지를 빌드하고, 해당 이미지로 Kubernetes Deployment를 업데이트하며, 롤아웃이 성공할 때까지 대기한 후 Slack으로 알림을 보낼 수 있습니다. 기존에는 Helm 차트를 로컬에서 수동으로 배포하거나, ArgoCD 같은 별도 도구를 설치해야 했다면, GitLab CI는 간단한 kubectl 명령어로 즉시 시작할 수 있습니다. Kubernetes 배포의 핵심은 세 가지입니다: 선언적 배포(YAML 매니페스트), 롤링 업데이트로 무중단 배포, 그리고 자동 헬스체크와 롤백입니다. 이러한 기능들이 안정적이고 예측 가능한 배포를 만들어줍니다.
코드 예제
# .gitlab-ci.yml - Kubernetes 배포
deploy_k8s:
stage: deploy
image: bitnami/kubectl:latest
environment:
name: production
url: https://app.example.com
kubernetes:
namespace: production
before_script:
# kubeconfig 설정 (GitLab 환경 변수 사용)
- mkdir -p ~/.kube
- echo "$KUBE_CONFIG" | base64 -d > ~/.kube/config
script:
# 새 이미지로 Deployment 업데이트
- kubectl set image deployment/myapp myapp=$CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA -n production
# 롤아웃 완료 대기 (최대 5분)
- kubectl rollout status deployment/myapp -n production --timeout=5m
# 배포 확인
- kubectl get pods -n production -l app=myapp
after_script:
# 실패 시 자동 롤백
- |
if [ "$CI_JOB_STATUS" == "failed" ]; then
kubectl rollout undo deployment/myapp -n production
echo "Deployment failed, rolled back to previous version"
fi
only:
- main
when: manual # 수동 승인 필요
동작 원리
이것이 하는 일: 이 설정 파일은 GitLab에게 "코드가 푸시되면 test → build → deploy 순서로 작업을 실행하라"고 지시합니다. 첫 번째로, stages 섹션에서 전체 파이프라인의 실행 순서를 정의합니다. test가 실패하면 build는 실행되지 않는 식으로, 각 스테이지는 이전 스테이지가 성공해야만 진행됩니다. 이렇게 하면 테스트가 실패한 코드는 절대 배포되지 않습니다. 두 번째로, 각 작업(job)은 어떤 스테이지에 속하는지, 어떤 Docker 이미지를 사용할지, 무슨 스크립트를 실행할지를 명시합니다. test_job은 python:3.11 이미지 안에서 실행되며, 의존성을 설치하고 pytest를 돌립니다. only 키워드로 merge_requests와 main 브랜치에서만 실행되도록 제한했습니다. 세 번째로, GitLab Runner가 이 설정을 읽고 실제 작업을 수행합니다. Runner는 물리 서버일 수도, 클라우드 VM일 수도 있으며, 여러 개를 등록하여 병렬로 작업을 처리할 수 있습니다. 마지막으로, 각 작업의 실행 결과는 GitLab UI에서 실시간으로 확인할 수 있습니다. 로그를 보며 어디서 실패했는지 즉시 파악하고, 재실행도 버튼 클릭 하나로 가능합니다. 여러분이 이 설정을 사용하면 코드 품질이 자동으로 검증되고, 실패한 빌드는 배포되지 않으며, 전체 과정이 투명하게 기록됩니다. 팀 전체가 동일한 프로세스를 따르게 되어 "내 컴퓨터에서는 되는데"라는 문제가 사라집니다. 이것이 하는 일: 이 설계는 lint → test → build → deploy 순서로 진행하되, test 스테이지의 두 작업은 동시에 실행하여 시간을 절약합니다. 첫 번째로, lint 스테이지를 가장 앞에 배치했습니다. 코드 스타일 검사는 몇 초면 끝나므로, 문제가 있다면 즉시 파이프라인을 중단하여 불필요한 테스트 실행을 방지합니다. flake8과 black 검사가 실패하면 뒤의 무거운 작업들은 아예 실행되지 않습니다. 두 번째로, test 스테이지에서 unit_test와 integration_test를 분리했습니다. 이 둘은 서로 독립적이므로 GitLab이 자동으로 병렬 실행합니다. 만약 Runner가 2개 이상 있다면, 각각 다른 Runner에서 동시에 돌아가 시간이 절반으로 줄어듭니다. 세 번째로, build 스테이지는 모든 테스트가 통과해야만 실행됩니다. Docker 이미지를 빌드하는 작업은 시간이 오래 걸리므로, 테스트가 실패한 코드는 빌드조차 하지 않아 리소스를 아낍니다. $CI_COMMIT_SHA로 커밋별 고유한 태그를 만들어 정확한 버전 추적이 가능합니다. 마지막으로, deploy 스테이지(이 예제에는 없지만)는 빌드된 이미지를 실제 환경에 배포합니다. 각 스테이지가 명확한 책임을 가지므로, 파이프라인을 보는 것만으로도 전체 흐름을 이해할 수 있습니다. 여러분이 이 설계를 사용하면 파이프라인 실행 시간이 크게 단축되고, 문제를 조기에 발견하며, 각 단계의 성공/실패를 명확히 알 수 있습니다. 또한 병렬 실행으로 Runner 자원을 효율적으로 활용합니다. 이것이 하는 일: 이 작업은 Docker 이미지를 빌드하고, 커밋 해시로 태그를 달아 GitLab Container Registry에 푸시합니다. 첫 번째로, docker:dind 서비스를 활성화하여 파이프라인 내에서 Docker 명령어를 실행할 수 있게 합니다. Docker-in-Docker는 컨테이너 안에서 Docker 데몬을 실행하는 기술로, 격리된 환경에서 안전하게 이미지를 빌드할 수 있습니다. DOCKER_TLS_CERTDIR로 TLS 인증서 경로를 설정하여 보안을 강화합니다. 두 번째로, before_script에서 GitLab의 내장 변수들($CI_REGISTRY_USER, $CI_REGISTRY_PASSWORD)을 사용하여 자동으로 로그인합니다. 이 변수들은 GitLab이 자동으로 제공하므로 별도 설정이 필요 없습니다. 프라이빗 레지스트리에 접근 권한이 자동으로 부여됩니다. 세 번째로, --cache-from 옵션으로 이전 빌드의 레이어를 재사용합니다. 예를 들어 pip install 같은 의존성 설치 단계는 requirements.txt가 변경되지 않았다면 캐시에서 가져와 빌드 시간을 10배 이상 단축할 수 있습니다. $CI_COMMIT_SHORT_SHA로 각 커밋마다 고유한 태그를 만들어 롤백이 쉬워집니다. 마지막으로, 동일한 이미지에 두 개의 태그를 답니다: 커밋 해시 태그로 정확한 버전 추적이 가능하고, latest 태그로 항상 최신 이미지를 참조할 수 있습니다. 두 태그 모두 푸시하여 배포 시 선택의 폭을 넓힙니다. 여러분이 이 설정을 사용하면 매 커밋마다 일관된 이미지가 자동으로 빌드되고, 버전별로 관리되며, 어떤 환경에서든 동일하게 작동하는 컨테이너를 배포할 수 있습니다. 또한 문제가 생기면 이전 커밋의 이미지로 즉시 롤백할 수 있습니다. 이것이 하는 일: 이 설정은 GitLab UI에 저장된 환경 변수들을 안전하게 가져와 배포 스크립트에서 사용합니다. 첫 번째로, environment: staging으로 환경을 지정하면, GitLab은 해당 환경에 스코프된 변수들만 로드합니다. 예를 들어 DATABASE_URL을 staging 환경에는 postgres://staging-db, production 환경에는 postgres://prod-db로 다르게 설정할 수 있습니다. 동일한 코드로 환경별 다른 인프라에 배포되는 것입니다. 두 번째로, $API_TOKEN 같은 민감한 변수는 GitLab UI에서 "Masked" 옵션을 켜면 로그에 [masked]로 표시되어 절대 노출되지 않습니다. 또한 "Protected" 옵션을 활성화하면 protected 브랜치(main, release 등)에서만 이 변수에 접근할 수 있어, 개발 브랜치에서 실수로 운영 API를 호출하는 사고를 방지합니다. 세 번째로, $KUBE_CERT 같은 파일 타입 변수는 인증서나 큰 JSON 파일을 안전하게 전달합니다. GitLab이 자동으로 임시 파일을 생성하고 경로를 변수에 할당하므로, 스크립트에서는 파일 경로로 직접 사용할 수 있습니다. 파이프라인 종료 시 자동으로 삭제되어 보안이 유지됩니다. 마지막으로, 변수 우선순위는 "파이프라인 트리거 시 전달 > job 레벨 variables > 프로젝트/그룹 CI/CD 변수 > GitLab 내장 변수" 순입니다. 이를 이해하면 같은 이름의 변수를 여러 곳에서 정의해도 어떤 값이 사용될지 예측할 수 있습니다. 여러분이 이 방식을 사용하면 코드에 시크릿이 전혀 포함되지 않고, 환경별로 자동으로 올바른 설정이 적용되며, 팀원들이 민감한 정보를 직접 알 필요 없이 파이프라인이 작동합니다. 또한 변수 변경이 코드 수정 없이 즉시 반영됩니다. 이것이 하는 일: 이 설정은 각 작업이 실행되어야 하는 정확한 조건을 정의하여 불필요한 실행을 방지합니다. 첫 번째로, test_python 작업은 두 가지 조건으로 실행됩니다. Merge Request에서 Python 파일이 변경되었을 때와, main 브랜치에 직접 푸시했을 때입니다. changes는 Git diff를 분석하여 지정한 패턴과 매칭되는 파일이 변경되었는지 확인합니다. 만약 문서만 수정했다면 이 테스트는 아예 실행되지 않아 시간을 절약합니다. 두 번째로, deploy_prod는 프로덕션 배포의 민감성을 고려하여 when: manual로 설정했습니다. main 브랜치에서도 자동 배포되지 않고, GitLab UI에서 수동으로 버튼을 클릭해야 실행됩니다. 이렇게 하면 배포 타이밍을 제어할 수 있고, 실수로 배포되는 사고를 방지합니다. 단, 버전 태그(v1.2.3)를 푸시하면 자동 배포되도록 예외를 두어 릴리스 프로세스를 간소화했습니다. 세 번째로, build_docs는 문서 관련 파일이 변경되었을 때만 실행됩니다. docs/ 디렉토리나 mkdocs.yml 설정 파일이 변경되면 문서를 빌드하지만, 코드만 변경되었다면 건너뜁니다. 이렇게 하면 문서 빌드 시간(수 분)을 절약하고, 파이프라인이 더 빨리 완료됩니다. 마지막으로, rules는 위에서 아래로 평가되며, 첫 번째로 매칭되는 rule이 적용됩니다. 따라서 순서가 중요합니다. 가장 구체적인 조건을 위에, 일반적인 조건을 아래에 배치하세요. 여러분이 이 전략을 사용하면 파이프라인 실행 시간이 절반 이하로 줄어들고, Runner 자원이 효율적으로 사용되며, 중요한 배포는 수동 승인으로 보호할 수 있습니다. 또한 변경 범위에 맞는 테스트만 실행되어 피드백이 빨라집니다. 이것이 하는 일: 이 설정은 Python 가상환경과 pip 캐시를 저장하여 다음 파이프라인에서 재사용합니다. 첫 번째로, 캐시 키를 requirements.txt 파일의 체크섬으로 설정했습니다. 이 파일이 변경되면 의존성이 바뀐 것이므로 새로운 캐시를 생성하고, 변경되지 않았다면 기존 캐시를 그대로 사용합니다. 이렇게 하면 불필요한 pip install을 건너뛰어 시간을 절약하면서도, 의존성 변경 시에는 정확하게 업데이트됩니다. 두 번째로, install_deps 작업은 policy: pull-push로 캐시를 읽고 쓰기 모두 합니다. 처음 실행 시에는 캐시가 없으므로 의존성을 새로 설치하고 캐시를 생성합니다. 이후 실행에서는 캐시를 복원하고, 새로운 패키지가 추가되었다면 캐시를 업데이트합니다. .pre 스테이지를 사용하여 다른 모든 작업보다 먼저 실행되게 했습니다. 세 번째로, test_app 작업은 policy: pull로 캐시를 읽기만 합니다. 테스트는 의존성을 변경하지 않으므로 캐시를 업데이트할 필요가 없습니다. 여러 테스트 작업이 병렬로 실행될 때, 모두 pull만 하면 동시에 캐시를 읽을 수 있어 경합 문제를 방지합니다. 마지막으로, PIP_CACHE_DIR 환경 변수로 pip의 내부 캐시 위치를 프로젝트 디렉토리 안으로 변경했습니다. 기본 위치는 시스템 전역이라 캐싱되지 않으므로, 반드시 프로젝트 내부로 변경해야 합니다. venv/도 함께 캐싱하여 가상환경 생성 시간도 절약합니다. 여러분이 이 전략을 사용하면 의존성 설치 시간이 10분에서 10초로 줄어들고, 네트워크 문제에 덜 민감해지며, 동일한 의존성을 사용하는 여러 job이 캐시를 공유하여 전체 파이프라인이 빨라집니다. requirements.txt가 변경되지 않는 한 매번 즉시 시작할 수 있습니다. 이것이 하는 일: 이 설정은 빌드 결과물을 아티팩트로 저장하고, 테스트 리포트를 GitLab UI에 통합하며, 배포 시 정확한 버전을 사용하도록 보장합니다. 첫 번째로, build_app은 dist/ 디렉토리와 빌드 로그를 아티팩트로 저장합니다. name으로 커밋 해시를 포함한 고유한 이름을 지정하여 나중에 어떤 버전인지 쉽게 식별할 수 있습니다. exclude로 소스맵 파일을 제외하여 아티팩트 크기를 줄였고, expire_in: 1 week로 오래된 아티팩트를 자동 정리하여 스토리지 비용을 절감합니다. when: on_success로 빌드가 성공한 경우에만 저장되도록 제한했습니다. 두 번째로, test_app은 특수한 reports 아티팩트를 사용합니다. JUnit XML 형식의 테스트 결과를 업로드하면 GitLab이 자동으로 파싱하여 Merge Request에 테스트 통과/실패 현황을 표시합니다. 커버리지 리포트도 마찬가지로 GitLab UI에서 시각화되어, 코드 리뷰 시 테스트 커버리지 변화를 즉시 확인할 수 있습니다. 별도로 파일을 열어볼 필요가 없습니다. 세 번째로, deploy_app은 dependencies로 build_app의 아티팩트만 다운로드합니다. 기본적으로 이전 스테이지의 모든 아티팩트를 다운로드하지만, dependencies를 명시하면 필요한 것만 받아 다운로드 시간을 단축합니다. dist/version.txt를 읽어 정확히 어떤 빌드 버전을 배포하는지 확인하고, 동일한 dist/ 디렉토리를 S3에 업로드하여 테스트한 것과 정확히 같은 파일이 배포됩니다. 마지막으로, 아티팩트는 GitLab UI의 파이프라인 페이지에서 "Download artifacts" 버튼으로 언제든 다운로드할 수 있습니다. 운영 이슈가 발생했을 때, 해당 배포의 정확한 빌드 결과물을 다운로드하여 로컬에서 디버깅할 수 있습니다. 여러분이 이 방식을 사용하면 빌드를 한 번만 하고 여러 스테이지에서 재사용하며, 테스트 결과가 GitLab UI에 자동으로 표시되고, 배포된 버전을 정확히 추적할 수 있습니다. 또한 만료 기간으로 스토리지를 자동 관리하여 비용을 절감합니다. 이것이 하는 일: 이 배포 작업은 새로운 Docker 이미지로 Kubernetes Deployment를 업데이트하고, 롤아웃 성공 여부를 확인하며, 실패 시 자동으로 이전 버전으로 롤백합니다. 첫 번째로, before_script에서 kubeconfig를 설정합니다. GitLab CI/CD 변수에 저장된 $KUBE_CONFIG (base64 인코딩된 kubeconfig 파일)를 디코딩하여 kubectl이 클러스터에 접근할 수 있게 합니다. 이렇게 하면 인증 정보가 코드에 노출되지 않고, 팀원 모두가 동일한 인증으로 배포합니다. 서비스 어카운트 토큰 방식도 가능하지만, kubeconfig가 더 유연합니다. 두 번째로, kubectl set image로 Deployment의 컨테이너 이미지를 새로운 버전으로 업데이트합니다. $CI_COMMIT_SHORT_SHA를 이미지 태그로 사용하여 정확히 어떤 커밋이 배포되는지 추적할 수 있습니다. Kubernetes는 즉시 새로운 Pod를 생성하기 시작하고, 기존 Pod는 단계적으로 종료됩니다(롤링 업데이트). 세 번째로, kubectl rollout status로 배포가 성공적으로 완료될 때까지 대기합니다. 새로운 Pod가 Ready 상태가 되고, 이전 Pod가 모두 종료되어야 명령어가 종료됩니다. 5분 이내에 완료되지 않으면 타임아웃되어 파이프라인이 실패하고, after_script에서 자동 롤백이 실행됩니다. 이렇게 하면 문제가 있는 버전이 운영에 오래 남아있지 않습니다. 마지막으로, environment 설정으로 GitLab의 Environments 기능과 통합됩니다. 배포 히스토리가 GitLab UI에 기록되고, 각 배포마다 "View deployment" 버튼으로 실제 애플리케이션에 접근할 수 있으며, 환경별로 누가 언제 무엇을 배포했는지 투명하게 추적됩니다. 여러분이 이 방식을 사용하면 배포 과정이 완전히 자동화되고, 실패 시 자동 롤백으로 서비스 중단 시간이 최소화되며, 모든 배포가 GitLab에 기록되어 감사(audit) 가능합니다. 또한 동일한 스크립트로 모든 환경(staging, production)에 일관되게 배포할 수 있습니다.
핵심 정리
핵심 정리: .gitlab-ci.yml 파일로 전체 CI/CD 파이프라인을 코드로 관리하며, stages로 순서를 제어하고 jobs로 실제 작업을 정의합니다. 코드 변경마다 자동 실행되며, 테스트 실패 시 배포가 차단됩니다. 핵심 정리: 스테이지를 논리적으로 분리하고 빠른 검사를 앞에 배치하며, 같은 스테이지 내 작업은 병렬 실행됩니다. 각 스테이지는 이전 스테이지 성공 시에만 실행되어 불필요한 작업을 방지합니다. 핵심 정리: Docker-in-Docker로 파이프라인 내에서 이미지를 빌드하고, 커밋 해시 태그로 버전을 관리하며, 레이어 캐싱으로 빌드 속도를 최적화합니다. GitLab Container Registry에 자동 푸시되어 배포 파이프라인과 연결됩니다. 핵심 정리: GitLab CI/CD Variables에서 환경 변수를 관리하고, Masked로 로그 노출을 방지하며, Environment Scope로 환경별 분리합니다. 파일 타입 변수로 인증서 같은 큰 데이터도 안전하게 전달할 수 있습니다. 핵심 정리: rules로 브랜치, 파일 변경, 변수 등 다양한 조건을 조합하여 작업 실행을 제어합니다. changes로 변경된 파일 기반 실행, when: manual로 수동 승인을 구현하며, 조건은 위에서 아래로 평가됩니다. 핵심 정리: 캐시 키를 의존성 파일(requirements.txt, package-lock.json)의 체크섬으로 설정하여 파일 변경 시만 갱신합니다. install 작업은 pull-push, 나머지는 pull 정책을 사용하며, 프로젝트 디렉토리 내부에 캐시를 저장해야 합니다. 핵심 정리: artifacts로 job 간 파일을 전달하고, reports로 테스트 결과를 GitLab UI에 통합하며, expire_in으로 자동 정리합니다. dependencies로 필요한 아티팩트만 선택적으로 다운로드하여 효율성을 높입니다. 핵심 정리: kubeconfig를 환경 변수로 저장하고 kubectl로 Deployment를 업데이트하며, rollout status로 성공 확인 후 실패 시 자동 롤백합니다. GitLab Environments와 통합하여 배포 히스토리를 관리하고 when: manual로 수동 승인을 구현합니다.
실전 팁
💡 .gitlab-ci.yml을 처음 작성할 때는 GitLab의 CI Lint 도구(CI/CD > Pipelines > CI Lint)로 문법 검증을 먼저 하세요. YAML 들여쓰기 오류가 가장 흔한 실수입니다.
💡 only와 except 대신 최신 rules 키워드를 사용하면 더 복잡한 조건도 깔끔하게 표현할 수 있습니다. only는 곧 deprecated될 예정입니다.
💡 각 job에 tags를 지정하여 특정 Runner에서만 실행되도록 할 수 있습니다. 예를 들어 GPU가 필요한 작업은 gpu 태그가 있는 Runner로만 보내세요.
💡 파이프라인이 너무 길어지면 include 키워드로 여러 YAML 파일로 분리하세요. 공통 설정은 템플릿화하여 재사용성을 높일 수 있습니다.
💡 before_script와 after_script를 활용하면 모든 job에 공통으로 실행되는 초기화/정리 작업을 중복 없이 관리할 수 있습니다.
2. 파이프라인_스테이지_설계
💡 가장 빠르게 실패할 수 있는 작업(lint, 타입 체크)을 첫 스테이지에 배치하세요. 파이프라인이 평균적으로 더 빨리 실패하면 피드백이 빨라집니다.
💡 needs 키워드를 사용하면 스테이지 순서를 무시하고 특정 job이 완료되면 바로 다음 job을 실행할 수 있습니다. DAG(Directed Acyclic Graph) 파이프라인으로 더 최적화할 수 있습니다.
💡 job의 timeout을 설정하여 무한정 대기하는 상황을 방지하세요. 예를 들어 통합 테스트는 10분 이상 걸리면 뭔가 문제가 있는 것입니다.
💡 retry 키워드로 네트워크 이슈 등 일시적 실패를 자동 재시도할 수 있습니다. 단, 테스트 실패는 재시도하면 안 됩니다 - retry: { max: 2, when: runner_system_failure }로 제한하세요.
💡 스테이지는 너무 많으면(10개 이상) 관리가 어려우므로, 보통 4-6개 정도가 적당합니다. 복잡한 로직은 스크립트 파일로 분리하세요.
3. Docker_이미지_빌드
💡 보안이 중요하다면 Docker-in-Docker 대신 kaniko를 사용하세요. kaniko는 privileged 모드 없이 이미지를 빌드할 수 있어 더 안전합니다.
💡 멀티 스테이지 Dockerfile을 사용하여 빌드 도구는 최종 이미지에서 제외하세요. Python 앱이라면 빌드 스테이지에서 컴파일하고, 런타임 스테이지에는 필요한 파일만 복사하여 이미지 크기를 절반 이상 줄일 수 있습니다.
💡 .dockerignore 파일로 불필요한 파일을 빌드 컨텍스트에서 제외하세요. .git, node_modules, 테스트 파일 등을 제외하면 빌드 속도가 크게 향상됩니다.
💡 이미지 태그에 날짜나 빌드 번호를 추가하면 더 명확한 버전 관리가 가능합니다: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA-$(date +%Y%m%d)
💡 정기적으로 오래된 이미지를 정리하세요. GitLab Container Registry의 cleanup policy를 설정하여 30일 이상 된 태그를 자동 삭제하면 스토리지 비용을 절감할 수 있습니다.
4. 환경_변수_관리
💡 절대 API 키나 비밀번호를 .gitlab-ci.yml에 직접 작성하지 마세요. 파일은 Git 히스토리에 영구 저장되므로 나중에 삭제해도 이전 커밋에서 볼 수 있습니다.
💡 Expand variable reference 옵션을 끄면 변수 내에서 다른 변수를 참조($OTHER_VAR)할 수 없게 됩니다. 보안상 중요한 변수는 이 옵션을 꺼서 의도치 않은 확장을 방지하세요.
💡 그룹 레벨 변수를 사용하면 여러 프로젝트에서 공통 변수(조직 공통 Docker 레지스트리 등)를 재사용할 수 있습니다. 중복을 줄이고 일관성을 높입니다.
💡 CI_COMMIT_SHA, CI_PIPELINE_ID 같은 GitLab 내장 변수들을 적극 활용하세요. 모든 내장 변수 목록은 GitLab 문서에서 확인할 수 있으며, 이들은 자동으로 제공됩니다.
💡 민감한 변수는 정기적으로 로테이션하세요. API 키를 6개월마다 갱신하고, 이전 키는 즉시 폐기하는 프로세스를 만들면 보안 사고 발생 시 피해를 최소화할 수 있습니다.
5. 조건부_파이프라인
💡 changes는 Merge Request 파이프라인과 브랜치 파이프라인에서만 작동합니다. 태그 파이프라인에서는 작동하지 않으므로, 태그 배포에는 if 조건을 사용하세요.
💡 rules와 only/except를 동일한 job에서 함께 사용할 수 없습니다. only/except는 deprecated되었으므로 모든 조건을 rules로 마이그레이션하세요.
💡 when: manual과 allow_failure: false를 조합하면 수동 작업을 실행해야만 파이프라인이 성공 상태가 됩니다. 필수 승인 프로세스를 구현할 수 있습니다.
💡 exists 조건으로 특정 파일의 존재 여부를 확인할 수 있습니다. 예: exists: ["Dockerfile"]이면 Dockerfile이 있을 때만 Docker 빌드를 실행합니다.
💡 복잡한 조건은 가독성을 위해 YAML anchor(&)와 alias(*)로 재사용하세요. 공통 rule을 정의하고 여러 job에서 참조하면 유지보수가 쉬워집니다.
6. 캐싱_전략
💡 캐시와 아티팩트의 차이를 이해하세요. 캐시는 성능 최적화(선택사항)이고, 아티팩트는 job 간 파일 전달(필수)입니다. 빌드 결과물은 아티팩트로, 의존성은 캐시로 관리하세요.
💡 브랜치별로 다른 캐시를 사용하려면 캐시 키에 $CI_COMMIT_REF_SLUG를 추가하세요: key: "$CI_COMMIT_REF_SLUG-requirements"로 설정하면 각 브랜치가 독립적인 캐시를 갖습니다.
💡 캐시가 너무 커지면(GB 단위) 복원 시간이 오래 걸립니다. 필요한 디렉토리만 캐싱하고, node_modules/.cache 같은 중간 캐시는 제외하세요.
💡 Fallback 캐시 키를 설정하여 정확히 매칭되는 캐시가 없을 때 비슷한 캐시를 사용할 수 있습니다: key: { files: ["package-lock.json"], prefix: "$CI_COMMIT_REF_SLUG" }
💡 GitLab Runner의 캐시는 분산 스토리지(S3, GCS)를 사용하도록 설정하세요. 로컬 디스크 캐시는 Runner가 여러 대일 때 공유되지 않아 효과가 떨어집니다.
7. 아티팩트_관리
💡 아티팩트 크기를 최소화하세요. 불필요한 파일(node_modules, .git 등)을 제외하고, 압축 가능한 형식을 사용하며, 큰 바이너리는 외부 스토리지(S3, Artifactory)를 고려하세요.
💡 reports:dotenv 아티팩트로 환경 변수를 다음 job에 전달할 수 있습니다. 빌드 job에서 echo "IMAGE_TAG=v1.2.3" > build.env를 생성하면 배포 job에서 $IMAGE_TAG로 사용 가능합니다.
💡 master 브랜치나 태그의 아티팩트는 만료 기간을 길게(6개월-1년) 설정하세요. 운영 배포 기록은 장기 보관이 필요하지만, 기능 브랜치는 짧게(1주일) 해도 됩니다.
💡 artifacts:untracked: true로 Git에 추적되지 않는 모든 파일을 아티팩트로 저장할 수 있지만, 용량이 커질 수 있으므로 명시적으로 paths를 지정하는 것이 좋습니다.
💡 테스트 프레임워크가 JUnit XML을 지원하는지 확인하세요. pytest는 --junitxml, Jest는 jest-junit, Go는 go-junit-report를 사용하여 GitLab과 통합할 수 있습니다.
8. Kubernetes_배포
💡 Helm을 사용하면 복잡한 Kubernetes 리소스를 패키지로 관리할 수 있습니다. helm upgrade --install myapp ./chart --set image.tag=$CI_COMMIT_SHORT_SHA로 간단히 배포하세요.
💡 Blue-Green 배포나 Canary 배포를 구현하려면 Istio, Flagger 같은 서비스 메시를 고려하세요. 트래픽을 점진적으로 전환하여 위험을 최소화할 수 있습니다.
💡 Deployment의 readinessProbe와 livenessProbe를 반드시 설정하세요. 이것이 없으면 애플리케이션이 준비되지 않았는데도 트래픽을 받아 에러가 발생합니다.
💡 kubectl diff -f k8s/로 배포 전에 어떤 변경이 적용될지 미리 확인할 수 있습니다. 예상치 못한 변경을 사전에 발견하여 실수를 방지하세요.
💡 GitLab의 Kubernetes Agent를 사용하면 클러스터가 GitLab에 연결(pull 모델)하여 더 안전합니다. 방화벽 뒤의 클러스터도 kubeconfig 없이 배포할 수 있습니다.
마치며
오늘은 GitLab CI로 만드는 실전 프로젝트 완벽 가이드의 핵심 개념들을 함께 살펴보았습니다.
이번 글에서 다룬 9가지 개념은 모두 실무에서 자주 사용되는 중요한 내용들입니다. 처음에는 어렵게 느껴질 수 있지만, 실제 프로젝트에서 하나씩 적용해보면서 익숙해지시길 바랍니다.
이론만 알고 있기보다는 직접 코드를 작성하고 실행해보는 것이 가장 빠른 학습 방법입니다. 작은 프로젝트라도 좋으니 직접 구현해보면서 각 개념이 실제로 어떻게 동작하는지 체감해보세요. 에러가 발생하면 디버깅하면서 더 깊이 이해할 수 있습니다.
학습하다가 막히는 부분이 있거나, 더 궁금한 점이 생긴다면 주저하지 말고 질문해주세요. 질문이나 궁금한 점이 있다면 언제든 댓글로 남겨주세요. 함께 성장하는 개발자가 되어봅시다!
다음에는 더 심화된 내용으로 찾아뵙겠습니다. 즐거운 코딩 되세요! 🚀
관련 태그
#GitLab #CI/CD #Docker #Kubernetes #Pipeline
이 카드뉴스가 포함된 코스
댓글 (0)
함께 보면 좋은 카드 뉴스
Istio 보안 완벽 가이드
마이크로서비스 환경에서 필수적인 Istio 보안 기능을 실무 중심으로 설명합니다. mTLS부터 인증, 인가까지 단계별로 학습하여 안전한 서비스 메시를 구축할 수 있습니다.
Istio 트래픽 관리 완벽 가이드
Istio의 트래픽 관리 기능을 마스터하는 완벽 가이드입니다. VirtualService와 DestinationRule을 활용한 라우팅부터 트래픽 분할, 헤더 기반 라우팅까지 실무에 필요한 모든 내용을 다룹니다.
Istio 설치와 구성 완벽 가이드
Kubernetes 환경에서 Istio 서비스 메시를 설치하고 구성하는 방법을 초급 개발자도 쉽게 이해할 수 있도록 실무 스토리와 비유로 풀어낸 가이드입니다. istioctl 설치부터 사이드카 주입까지 단계별로 학습합니다.
서비스 메시 완벽 가이드
마이크로서비스 간 통신을 안전하고 효율적으로 관리하는 서비스 메시의 핵심 개념부터 실전 도입까지, 초급 개발자를 위한 완벽한 입문서입니다. Istio와 Linkerd 비교, 사이드카 패턴, 실무 적용 노하우를 담았습니다.
Helm 마이크로서비스 패키징 완벽 가이드
Kubernetes 환경에서 마이크로서비스를 효율적으로 패키징하고 배포하는 Helm의 핵심 기능을 실무 중심으로 학습합니다. Chart 생성부터 릴리스 관리까지 체계적으로 다룹니다.