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) 존재 여부임 pushpipeline 에서는 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 은 실행하지 않음
-
pushdevelop,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 실행 요청으로 처리함pushpipeline 은 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 와 공유 금지