콘텐츠로 이동

GitLab CI/CD Standard (운영 기준)

0. 전제

다음 환경 기준으로 작성:

  • 규모: 프로젝트 5~20개 / 서버 소수
  • 인력: 1~2명 (소수 정예)
  • 멀티 스택 환경: Node.js, Express, Next.js, Nuxt.js, PHP, Laravel, C++ 등
  • 운영 서버: Linux / Windows 혼합 가능
  • Docker 사용 범위: Runner 빌드 환경 및 Release Storage 서버의 AIStor 실행 용도
  • 배포 방식: 운영 서버가 Release Storage에서 빌드 결과물을 직접 가져가는 pull 배포

인프라 전제:

  • GitLab 서버, Runner 서버, Release Storage 서버, 운영 서버는 논리적, 물리적으로 분리 가능한 구성으로 보며, 분리 운영을 전제로 작성함.
  • GitLab 서버는 외부 비공개로 유지하며, 운영 서버는 GitLab 서버에 직접 접근하지 않음.
  • Release Storage 서버는 운영 서버가 접근 가능한 별도 서버로 구성함.

운영 원칙:

  • build -> publish -> operation server pull deploy 구조 유지
  • {YYYYMMDD-HHMMSS}-{declared_version}-{CI_COMMIT_SHORT_SHA} 기반 immutable package version 운영
  • 인증은 목적별 계정 및 Access Key로 분리
  • 빌드: Runner 서버
  • CI 내부 산출물 보관: GitLab Generic Package Registry
  • 운영 배포 기준 저장소: Release Storage (S3-compatible Object Storage)
  • 운영: download, verify, extract, activate, report 수행

금지 사항:

  • 운영 서버에 write 권한 Access Key 배치 금지
  • .env 및 서버 고유 설정 파일을 패키지에 포함 금지
  • 운영 서버에서 배포 파일을 수동 수정한 뒤 재사용 금지
  • Generic Package Registry에 업로드된 package version/file overwrite 금지
  • Release Storage 의 releases 경로 Release Object overwrite 금지
  • Release Storage 의 current/{RELEASE_ENV}.json 외 object overwrite 금지
  • 운영 서버가 GitLab 서버에 직접 접근하도록 구성 금지

인프라 구성 (CI/CD 흐름)

graph LR
    A[Developer] --> B[GitLab]
    B --> C[Build Runner]
    C -->|"Build"| D[Build Output]
    D -->|"Package and Upload"| E[GitLab Generic Package Registry]
    C -->|"Publish Release Package and Metadata"| F[Release Storage]

    G[Production Server]
    G -.->|"Polling current RELEASE_ENV json"| F
    G -->|"Pull release package"| F
    G -->|"Verify and Activate"| H[Service]

운영 기준:

  • CI/CD는 중앙 제어(GitLab, Runner)와 운영 서버를 분리함
  • 운영 서버는 Release Metadata를 기준으로 상태를 판단하고 직접 배포 수행함
  • CI/CD는 운영 서버에 직접 접근하지 않음

1. 개요

GitLab CI/CD 파이프라인의 실행 표준을 정의함.

CI/CD 흐름 (Pull 기반 상태 수렴)

본 구조는 CI/CD가 배포를 실행하는 것이 아니라, 배포 상태를 선언하고 운영 서버가 스스로 수렴하는 pull 기반 구조임

graph LR
    subgraph CI["GitLab / CI Infra"]
        A[Code Push / Merge] --> B[Detect]
        B -->|"1. Detect"| C[Build Runner]
        C -->|"2. Build"| D[Build Output]
        D -->|"3. Package + Upload"| E[GitLab Generic Package Registry]
        C -->|"4. Publish Release Package + Metadata"| G[Release Storage]
        C -->|"5. Publish current/{RELEASE_ENV}.json"| G
    end

    subgraph PROD["Production Servers"]
        H[Server]
        H -.->|"6. Poll current/{RELEASE_ENV}.json"| G
        H -->|"7. Pull release package"| G
        H -->|"8. Verify sha256 + Activate"| I[Service]
    end

Pipeline 구조:

detect → build → package → set_release_state

역할:

  • Detect

    • 현재 브랜치 기준 release target 여부 판단
    • release target 기준은 Release Yaml 파일 (.ops/ci/release-branch-versions/{CI_COMMIT_BRANCH}.yaml) 존재 여부임
    • push pipeline 에서는 release target branch 의 commit 반영을 release 진행 대상으로 판단함
    • Web(New Pipeline) pipeline 에서는 release target branch 선택 자체를 수동 release 실행 요청으로 판단함
    • 현재 브랜치와 동일한 release 선언 파일만 처리함
    • dotenv 생성
  • Build

    • print_detect_summary: detect 결과 출력 (디버깅/검증용)
    • build_target: 애플리케이션 빌드 수행
    • Build Runner (Docker Executor)에서 실행
  • Package

    • 빌드 결과물 압축
    • GitLab Generic Package Registry 업로드
    • CI 내부 산출물 보관 및 검증 기준으로 사용
  • set_release_state

    • 실제 배포 실행이 아니라 Release Storage publish 단계
    • Build Runner 에서 실행 가능
    • Release Storage publish 전 최종 package metadata 검증 수행
    • 검증된 package / sha256 / release metadata 를 Release Storage 의 releases 경로에 publish 함
    • 최종적으로 current/{RELEASE_ENV}.json 을 Release Storage 에 publish 하여 배포 상태를 선언함
    • resource_group 으로 동일 브랜치 동시 실행을 방지함
    • resource_group: release-state-${CI_COMMIT_BRANCH}

운영 기준:

  • current/{RELEASE_ENV}.json 은 Release Pointer 이므로 마지막에 갱신함
  • 운영 서버는 Release Storage 의 current/{RELEASE_ENV}.json 을 polling 한 뒤 직접 배포를 수행함

2. Stage 정의

stages:
  - detect
  - build
  - package
  - set_release_state

운영 기준:

  • stage 순서 고정

3. Runner 사용 기준

Stage Runner Executor
detect (MR) MR runner docker
detect (branch) build runner docker
build build runner docker
package build runner docker
set_release_state build runner docker

운영 기준:

  • detect (MR) → MR Runner 사용
  • detect (branch) / build / package / set_release_state → Build Runner만 사용

4. Tag 규칙

build:
  tags:
    - example.com_build_runner_tag

set_release_state:
  tags:
    - example.com_build_runner_tag

운영 기준:

  • 모든 Job은 tag 필수
  • Job tag와 Runner tag 반드시 일치
  • run untagged jobs 사용 금지

5. Branch 정책

  • release target branch 는 CI/CD YAML rules 에 하드코딩하지 않음.
  • release target branch, release publish 및 release 대상 여부는 아래 파일 존재 여부로 판단함.

Release Yaml 파일:

.ops/ci/release-branch-versions/{CI_COMMIT_BRANCH}.yaml

Pipeline source 별 정책:

Pipeline source 대상 detect build package set_release_state
merge_request_event MR O (sanity check only) X X X
push feature/* X X X X
push develop X X X X
push release target branch O O O O
Web(New Pipeline) release target branch O O O O
Web(New Pipeline) Release Yaml 파일 없는 branch O skip skip skip

운영 기준:

  • MR pipeline 은 branch 승격 경로 검증만 수행함
  • release job 은 MR pipeline 에서 실행하지 않음
  • feature/*, develop 는 release job 실행 대상에서 제외함
  • Protected Variable 을 사용하는 경우 release target branch 도 Protected Branch 로 등록해야 함
  • GitLab CI/CD 는 release package 와 release state publish 까지만 수행함
  • 운영 서버 deploy 는 운영 서버의 polling runtime 이 수행함

6. Pipeline 생성 규칙

Pipeline source 기준:

merge_request_event
push
Web(New Pipeline)

운영 기준:

  • merge_request_event

    • MR sanity check 만 수행함
    • release job 은 실행하지 않음
  • push

    • develop, feature/* 를 제외한 branch 에서 release 감지 job 을 실행함
    • 실제 release publish 여부는 Release Yaml 파일 존재 여부로 판단함
  • Web(New Pipeline)

    • 경로 : Project → Build → Pipelines → New pipeline
    • GitLab UI 에서 수동 실행하는 pipeline 임
    • 별도 variable 입력 없이 branch 만 선택함
    • Release Yaml 파일 이 존재하는 branch 를 선택하면 수동 release 실행 요청으로 처리함
    • New Pipeline 실행 시 새 PACKAGE_VERSION 이 생성되고 release package/state publish 가 진행됨
    • 강제 release 실행

7. Release 기반 실행 규칙

  • Release Yaml 파일
  • release target branch, release publish 및 release 대상 여부의 판단 기준
  • 파일 내용의 version 은 사람이 관리하는 declared version 임

판단 규칙:

.ops/ci/release-branch-versions/{CI_COMMIT_BRANCH}.yaml

운영 기준:

  • 현재 브랜치명과 동일한 Release Yaml 파일 파일이 있으면 release target branch 로 판단함
  • 하나의 pipeline 은 하나의 target environment 만 처리함
  • target environment 이름은 CI_COMMIT_BRANCH 기준으로 결정함

TARGET_CHANGED 결정 기준:

조건 TARGET_CHANGED TARGET_CHANGE_REASON
release yaml 없음 false not_release_target
Web(New Pipeline) + release yaml 있음 true manual_web_pipeline
push + release yaml 있음 + target yaml 변경됨 true declared_version_changed
push + release yaml 있음 + target yaml 변경 없음 true commit_sha_changed
기타 pipeline source false unsupported_pipeline_source

예:

pre-production branch → pre-production.yaml 처리
production branch     → production.yaml 처리
ko-dev-test branch    → ko-dev-test.yaml 처리

운영 기준:

  • 실제 immutable deploy identifier 는 PACKAGE_VERSION
  • PACKAGE_VERSION{YYYYMMDD-HHMMSS}-{declared_version}-{CI_COMMIT_SHORT_SHA} 형식

8. Detect 단계 기준

  • Detect 단계는 현재 브랜치 기준 release target 여부와 release 진행 여부를 판단함.

운영 기준:

  • release target 여부는 Release Yaml 파일 존재 여부로 판단함
  • Web(New Pipeline) 은 release target branch 에서 수동 release 실행 요청으로 처리함
  • push pipeline 은 release target branch 의 commit 반영으로 처리함
  • target Release Yaml 파일 이 변경된 push pipeline 은 declared_version_changed 로 기록함
  • target Release Yaml 파일 변경이 없는 push pipeline 은 commit_sha_changed 로 기록함
  • Detect 결과는 dotenv 형태로 후속 stage 에 전달함

주요 변수:

CHANGED_ANY
CHANGED_TARGET_COUNT
CHANGED_TARGETS
PIPELINE_SOURCE
COMMIT_SHA
COMMIT_SHORT_SHA
PACKAGE_DATETIME
TARGET_ENV_NAME
TARGET_ENV_KEY
TARGET_CHANGED
TARGET_CHANGE_REASON
TARGET_RELEASE_FILE
TARGET_DECLARED_VERSION
TARGET_PACKAGE_VERSION

운영 기준:

  • CHANGED_ANY=false 인 경우 build/package/set_release_state 수행 금지
  • TARGET_CHANGED=false 인 경우 후속 build/package/set_release_state 수행 금지
  • TARGET_CHANGE_REASON 은 release 진행 또는 skip 사유를 나타냄

8.1 Stage 간 dotenv contract

  • CI/CD pipeline은 stage 간 상태 전달을 dotenv 파일 기준으로 수행함.

운영 기준:

  • 각 stage는 다음 stage와 dotenv 기반 contract를 사용함
  • stage 간 상태 전달은 artifact + dotenv 방식으로 수행함
  • 다음 stage는 이전 stage 결과를 직접 재계산하지 않음

예:

Stage 출력
detect version-change.env
build build.env
package package.env

9. Release Metadata 기준

  • set_release_state 단계는 release metadata를 갱신함.

운영 기준:

  • CI/CD는 운영 서버 접근 권한을 가지지 않음
  • set_release_state 단계는 Release Storage 의 release metadata만 갱신함
  • 실제 배포는 운영 서버가 polling 후 직접 수행함
  • set_release_state 단계는 remote execute 단계가 아니라 release state publication 단계임

10. Version 정책

Package Version 형식:

<YYYYMMDD-HHMMSS>-<declared_version>-<CI_COMMIT_SHORT_SHA>

예:

20260527-064037-1.2.2-bcd4acde

운영 기준:

  • immutable package version 사용
  • 동일 package version overwrite 금지
  • Release Yaml 파일version 은 declared version 으로 사용함
  • package version 은 timestamp + declared version + commit short sha 기반으로 생성함
  • 같은 commit / 같은 declared version 이라도 New Pipeline 실행 시 pipeline created time 이 달라지면 새 package version 이 생성됨
  • pipeline retry 는 동일 pipeline 기준이므로 package version 이 바뀌지 않아야 함

11. CI/CD 스크립트 구조

# .gitlab-ci.yml

include:
  - local: '.ops/ci/set-release-state-pipeline.yaml'

CI/CD 로직은 .ops/ 디렉토리를 기준으로 구성함.

.ops/
├── cd/
│   ├── env/
│   │   ├── .release-storage.env
│   │   └── .service.env
│   ├── opt/
│   │   └── bin/
│   │       └── poll-release.sh
│   ├── poll-release-hooks/
│   │   └── 01-after-prepare-release.sh
│   └── bootstrap.sh
│
└── ci/
    ├── release-branch-versions/
    │   ├── pre-production.yaml
    │   ├── production.yaml
    │   └── {release-target-branch}.yaml
    │
    ├── scripts/
    │   ├── 01-detect-version-change.sh
    │   ├── 02-build.sh
    │   ├── 03-package.sh
    │   └── 04-update-release.sh
    │
    └── set-release-state-pipeline.yaml

운영 기준:

  • CI/CD 로직은 .gitlab-ci.yml에 직접 작성하지 않음
  • 모든 프로젝트는 동일한 .ops/ 구조를 사용함
  • build 로직만 프로젝트별로 변경함
  • .ops/ci → CI 실행 흐름 정의 (detect → build → package → set_release_state)
  • .ops/cd → 배포 정책 및 실행 스크립트 관리
  • GitLab UI (Run pipeline)를 통해 수동 실행 가능함
  • UI 실행 시에도 동일한 pipeline 구조를 사용함
  • release target 여부는 Release Yaml 파일 존재 여부로 판단함
  • New Pipeline 실행 시 release target branch 이면 수동 release publish 를 수행함
  • 현재 브랜치와 동일한 release 선언 파일만 처리함
  • 하나의 pipeline은 하나의 target environment만 처리함

12. 보안 기준

운영 기준:

  • Merge Request Runner 는 민감정보에 접근하지 않음
  • Build Runner 는 Protected Runner 로 구성함
  • release target branch 는 Protected Branch 로 등록함
  • GitLab Protected Variable 은 Protected Branch / Protected Tag 에서만 사용함
  • Build / Package 단계의 Generic Package Registry upload 는 CI_JOB_TOKEN 기준으로 수행함
  • set_release_state 단계의 Release Storage publish 는 GitLab CI/CD Protected Variable 로 주입된 S3 compatible credential 기준으로 수행함
  • 운영 서버는 Release Storage read-only 권한만 사용함
  • 운영 서버는 GitLab 서버에 직접 접근하지 않음

금지:

  • 운영 서버에 write 권한 token 또는 access key 저장 금지
  • .gitlab-ci.yml에 민감 정보 하드코딩 금지
  • Merge Request Runner 에 release publish 권한 제공 금지
  • Build Runner tag 를 MR Runner 와 공유 금지