CI/CD 자동화에 대한 관심은 지난 3년간 꾸준히 증가했으며, “CI/CD 파이프라인 설정” 검색량은 2025년 한 해에만 34% 상승했습니다. 그럼에도 불구하고 영국 개발 에이전시의 대다수는 여전히 수동 SSH 세션이나 임시 스크립트를 통해 배포합니다. 이러한 격차는 상당한 경쟁적 불이익을 의미합니다. 성숙한 CI/CD 파이프라인을 갖춘 팀은 약 5배 더 자주 배포하고, 배포 후 수정보다 10배 더 저렴한 단계에서 버그를 발견합니다.
이 가이드는 2026년 영국 개발팀이 CI/CD 파이프라인을 구축하는 현실적인 방법을 다룹니다. 플랫폼 선택, 파이프라인 단계의 올바른 구조화, 보안 스캔 통합, 실제 프로덕션에서 작동하는 배포 전략을 다룹니다.
TL;DR
- CI는 모든 커밋을 자동으로 빌드하고 테스트합니다. CD는 수동 개입 없이 검증된 코드를 스테이징 또는 프로덕션에 전달합니다
- GitHub Actions는 2026년 대부분의 영국 팀에게 올바른 기본 선택입니다. 자체 호스팅 러너나 강력한 감사 제어가 필요한 경우 GitLab CI가 더 나은 선택입니다
- 프로덕션 준비 파이프라인은 빌드에서 배포 후 모니터링까지 11개의 단계를 가집니다. 빌드와 테스트만이 아닙니다
- 보안 스캔은 파이프라인에 속합니다. 나중에 추가하는 것이 아닙니다. SAST, 의존성 감사, 시크릿 스캔은 모든 풀 리퀘스트에서 실행되어야 합니다
CI/CD란 실제로 무엇인가
이 용어는 느슨하게 사용되므로 정확하게 정의할 필요가 있습니다. 지속적 통합(CI)이란 공유 브랜치에 대한 모든 커밋이 자동화된 시퀀스를 트리거한다는 것을 의미합니다. 코드는 변경이 수락되기 전에 빌드, 린트 및 테스트됩니다. 목표는 스프린트 끝에 한 주간의 분기된 브랜치를 병합할 때가 아니라, 컨텍스트가 아직 신선한 동안 즉시 통합 문제를 발견하는 것입니다.
지속적 전달(CD)은 자동화를 확장하여 검증된 코드를 최소한의 또는 전혀 없는 수동 단계로 스테이징 또는 프로덕션에 배포할 수 있도록 합니다. 지속적 배포(더 강력한 버전)는 모든 성공적인 파이프라인이 자동으로 프로덕션에 배포된다는 것을 의미합니다. 대부분의 팀은 지속적 전달로 시작하고, 프로덕션 배포 전에 수동 승인 게이트를 추가하며, 테스트 커버리지와 롤백 메커니즘에 충분한 신뢰가 생기면 완전한 지속적 배포로 이동합니다.
실질적인 결과는 CI/CD가 배포를 높은 스트레스의 몇 시간짜리 이벤트에서 주당 수십 번 발생하는 일상적인 백그라운드 프로세스로 변환한다는 것입니다.
플랫폼 선택
플랫폼 선택은 중요하지만 영구적이지 않습니다. 필요하다면 나중에 마이그레이션하되, 지금 맥락에 맞는 올바른 기본값을 선택하세요.
GitHub Actions는 2026년에 새 프로젝트를 시작하는 대부분의 영국 개발팀에게 올바른 선택입니다. GitHub와 깊이 통합되어 있고, 재사용 가능한 액션의 가장 큰 에코시스템, 공개 저장소에 대한 넉넉한 무료 분, 잘 문서화된 설정 형식을 갖추고 있습니다. 호스팅된 러너는 Linux, Windows, macOS를 커버합니다. 이미 GitHub를 사용하는 팀에게는 최소 저항 경로의 이점이 실재합니다.
GitLab CI는 자체 호스팅 러너가 필요한 경우(규정 상의 이유 또는 개인 네트워크 리소스에 액세스하기 위해), 더 강력한 감사 로깅, 또는 팀이 소스 제어, CI, 컨테이너 레지스트리 및 배포를 위한 단일 플랫폼을 선호하는 경우 더 나은 선택입니다. GitLab의 .gitlab-ci.yml 형식은 성숙하고 잘 이해됩니다.
CircleCI는 강력한 병렬성과 Docker 지원을 갖추고 있으며 설정이 읽기 쉽습니다. GitHub Actions 이전의 시장 리더였으며 많은 영국 에이전시가 여전히 사용합니다. 기존 CircleCI 설정이 작동하고 있다면 이를 마이그레이션할 긴급한 이유는 없습니다.
Jenkins는 레거시입니다. 작동하고 많은 대규모 조직이 성공적으로 운영하지만, 2026년의 새 프로젝트에서는 Jenkins 서버를 유지 관리하는 운영 오버헤드가 가치 있지 않습니다. Jenkins를 인계받는 경우 장기적으로 커밋하기 전에 마이그레이션 비용을 평가하세요.
Bitbucket Pipelines는 팀이 Atlassian 스택에 내장되어 있고 소스 제어를 변경할 수 없는 경우 허용됩니다. 기능 세트는 GitHub Actions보다 뒤처지지만 기본을 커버합니다.
파이프라인 단계: 포함할 내용과 이유
완전하고 프로덕션 준비된 파이프라인은 대부분의 튜토리얼이 커버하는 것보다 더 많은 단계를 가집니다. 각 단계 뒤의 이유와 함께 전체 시퀀스는 다음과 같습니다.
단계 1: 빌드
소스를 컴파일 또는 트랜스파일하고, 의존성을 설치하고, 빌드 아티팩트를 생성합니다. Node.js 프로젝트의 경우 npm ci(lockfile을 정확히 사용하기 때문에 npm install이 아님)와 빌드 단계를 의미합니다. Python 서비스의 경우 가상 환경을 만들고 requirements.txt에서 설치하는 것을 의미합니다. 출력은 버전 관리된 아티팩트입니다. 컴파일된 바이너리, 트랜스파일된 JS 번들 또는 wheel 파일입니다.
여기서 의존성을 적극적으로 캐시하세요. package-lock.json을 키로 하는 캐시를 사용한 npm ci는 의존성을 변경하지 않은 후속 파이프라인 실행이 다운로드를 완전히 건너뛴다는 것을 의미합니다.
단계 2: 린트 및 정적 분석
ESLint, flake8, mypy, 엄격 모드의 Pylance 또는 언어에 적합한 동등한 것입니다. 이 단계는 빠르며, 일반적으로 30초 미만이고, 테스트가 실행되기 전에 광범위한 문제 클래스를 잡습니다. 정적 타입 검사(Python의 mypy, JS/TS의 TypeScript tsc --noEmit)는 유닛 테스트가 자주 놓치는 인터페이스 불일치를 잡는 데 특히 가치 있습니다.
여기서 빠르게 실패하세요. 코드가 린트를 통과하지 못한다면 10분짜리 테스트 스위트를 실행할 필요가 없습니다.
단계 3: 유닛 테스트
유닛 테스트 스위트를 실행합니다. 유닛 테스트는 빠르게 진행되어야 합니다. 전체 유닛 테스트 실행이 5분 이상 걸린다면 스위트를 분할하거나 이유를 조사하세요. 테스트 러너가 지원하는 경우 테스트 파일 간에 병렬화하세요(Jest의 --runInBand 끄기, Python은 pytest-xdist).
중요한 점: 유닛 테스트는 외부 서비스에 목(mock)을 사용합니다. CI 환경에는 이 단계에서 실제 데이터베이스 자격증명이나 외부 API 키가 있어서는 안 됩니다.
단계 4: 통합 테스트
통합 테스트는 실제 서비스에 대해 실행됩니다. 테스트 데이터베이스, Redis 인스턴스, 로컬 메시지 큐. 대부분의 CI 플랫폼은 이 목적을 위해 서비스 컨테이너를 지원합니다. GitHub Actions에서는 테스트 실행 기간 동안 PostgreSQL 또는 MySQL 컨테이너를 시작하기 위해 작업 옆에 services 블록을 선언합니다.
이것이 유닛 테스트가 놓치는 버그를 잡는 단계입니다. 의미적으로 잘못된 ORM 쿼리, 트랜잭션 격리 문제, 외래 키 제약 조건 실패. 목이 아닌 실제 데이터베이스에 대해 통합 테스트를 실행하세요.
단계 5: 보안 스캔
보안 스캔은 파이프라인에 속하며, 분기별 예약 스캔에 속하지 않습니다. 이 단계에는 세 가지 구성 요소가 있습니다.
SAST(정적 애플리케이션 보안 테스트). Semgrep은 다국어 팀에게 가장 실용적인 선택입니다. Python, JavaScript, TypeScript, Go, Java 등에 대한 규칙을 가지고 있습니다. Python 전용으로는 Bandit이 일반적인 보안 안티패턴을 잡습니다. GitHub의 CodeQL은 공개 저장소에 무료로 제공되며 패턴 매칭 도구와 다른 클래스의 취약점을 잡습니다. 모든 풀 리퀘스트에서 이 중 하나 이상을 실행하세요.
의존성 감사. Node.js 프로젝트에는 npm audit --audit-level=high, Python에는 pip-audit을 사용합니다. 이것들은 설치된 의존성을 OSV(오픈소스 취약점) 데이터베이스에 대해 확인합니다. 높음 및 심각한 결과에서 파이프라인을 차단하고, 중간 결과는 차단하지 않고 인간 검토를 위해 플래그를 세우세요.
시크릿 스캔. Gitleaks는 실수로 커밋된 자격증명, API 키, 토큰에 대해 커밋 기록을 스캔합니다. 이것이 시크릿이 리모트에 도달하기 전의 마지막 방어선입니다. GitHub의 내장 시크릿 스캔도 활성화할 가치가 있지만, 파이프라인의 Gitleaks는 푸시 후가 아니라 이전에 문제를 잡습니다.
단계 6: Docker 이미지 빌드 및 푸시
배포 대상이 컨테이너인 경우, 여기서 Docker 이미지를 빌드하고 레지스트리에 푸시합니다. latest만이 아니라 커밋 SHA로 태그 지정합니다. 변경 불가능한 태그는 프로덕션에서 실행 중인 정확한 커밋을 항상 식별할 수 있다는 것을 의미합니다. GitHub Container Registry(ghcr.io), AWS ECR 또는 선택한 레지스트리에 푸시합니다.
푸시 전에 빌드된 이미지에 대해 컨테이너 이미지 스캔(Trivy 또는 Grype)을 실행합니다. 이는 의존성 감사가 놓치는 기본 이미지의 OS 수준 CVE를 잡습니다.
단계 7: 스테이징에 배포
검증된 아티팩트를 프로덕션을 반영하는 스테이징 환경에 배포합니다. Infrastructure-as-Code(Terraform, Pulumi)는 스테이징 환경이 프로덕션과 동일하게 정의된다는 것을 의미합니다. 배포 단계는 멱등성을 가져야 합니다. 두 번 실행해도 문제가 발생하지 않아야 합니다.
단계 8: 스테이징에 대한 스모크 테스트
스테이징에 배포한 후 최소한의 엔드투엔드 확인을 실행합니다. 애플리케이션이 시작될 수 있는지, 헬스 엔드포인트가 200을 반환하는지, 기본 로그인 플로우가 작동하는지. 이 테스트들은 2분 이내에 실행되어야 합니다. 목표는 포괄적인 커버리지가 아니라 격리된 테스트에서는 잡을 수 없는 배포 실패를 잡는 것입니다.
단계 9: 수동 승인 게이트
프로덕션에 배포하기 전에 인간이 승인하기 위해 일시 중지합니다. GitHub Actions에서는 필수 검토자가 있는 환경 보호 규칙입니다. GitLab CI에서는 수동 작업 트리거입니다. 이 게이트는 경량이어야 합니다. 스테이징 환경이 올바르게 보이는지 확인하는 한 명의 검토자이지, 긴 사인오프 프로세스가 아닙니다.
지속적 배포를 향해 이동하는 팀의 경우, 배포 빈도와 테스트 커버리지가 충분히 높아지면 이 게이트를 자동화할 수 있지만, 게이트로 시작하는 것이 더 안전한 기본값입니다.
단계 10: 프로덕션에 배포
프로덕션 환경을 대상으로 하는 스테이징과 동일한 배포 단계입니다. 커밋 SHA로 태그된 변경 불가능한 아티팩트로 프로덕션 배포는 결정론적입니다.
단계 11: 배포 후 모니터링 확인
프로덕션 배포 후 파이프라인은 모니터링이 건강한지 확인해야 합니다. 오류율이 높아지지 않았는지, 헬스 엔드포인트가 응답하는지, 레이턴시 급증이 없는지. 관찰 가능성 플랫폼(Datadog, Grafana 또는 기본 HTTP 헬스 체크)에 대한 간단한 확인은 배포가 성공했다는 자동화된 신호 또는 롤백을 트리거하는 알림을 제공합니다.
현실적인 GitHub Actions 설정
아래는 Node.js 애플리케이션을 위한 축약되었지만 현실적인 파이프라인 구조입니다.
1name: CI/CD Pipeline
2
3on:
4 push:
5 branches: [main, develop]
6 pull_request:
7 branches: [main]
8
9jobs:
10 build-and-lint:
11 runs-on: ubuntu-latest
12 steps:
13 - uses: actions/checkout@v4
14 - uses: actions/setup-node@v4
15 with:
16 node-version: '20'
17 cache: 'npm'
18 - run: npm ci
19 - run: npm run lint
20 - run: npx tsc --noEmit
21
22 unit-tests:
23 needs: build-and-lint
24 runs-on: ubuntu-latest
25 steps:
26 - uses: actions/checkout@v4
27 - uses: actions/setup-node@v4
28 with:
29 node-version: '20'
30 cache: 'npm'
31 - run: npm ci
32 - run: npm test -- --coverage
33
34 integration-tests:
35 needs: build-and-lint
36 runs-on: ubuntu-latest
37 services:
38 postgres:
39 image: postgres:16
40 env:
41 POSTGRES_PASSWORD: testpass
42 POSTGRES_DB: testdb
43 options: >-
44 --health-cmd pg_isready
45 --health-interval 10s
46 --health-timeout 5s
47 --health-retries 5
48 steps:
49 - uses: actions/checkout@v4
50 - uses: actions/setup-node@v4
51 with:
52 node-version: '20'
53 cache: 'npm'
54 - run: npm ci
55 - run: npm run test:integration
56 env:
57 DATABASE_URL: postgres://postgres:testpass@localhost:5432/testdb
58
59 security-scan:
60 needs: build-and-lint
61 runs-on: ubuntu-latest
62 steps:
63 - uses: actions/checkout@v4
64 with:
65 fetch-depth: 0
66 - uses: actions/setup-node@v4
67 with:
68 node-version: '20'
69 cache: 'npm'
70 - run: npm ci
71 - run: npm audit --audit-level=high
72 - uses: semgrep/semgrep-action@v1
73 - name: Run Gitleaks
74 uses: gitleaks/gitleaks-action@v2
75
76 deploy-staging:
77 needs: [unit-tests, integration-tests, security-scan]
78 runs-on: ubuntu-latest
79 environment: staging
80 if: github.ref == 'refs/heads/main'
81 steps:
82 - uses: actions/checkout@v4
83 - name: Deploy to staging
84 run: ./scripts/deploy.sh staging
85
86 deploy-production:
87 needs: deploy-staging
88 runs-on: ubuntu-latest
89 environment: production
90 steps:
91 - uses: actions/checkout@v4
92 - name: Deploy to production
93 run: ./scripts/deploy.sh production
unit-tests, integration-tests, security-scan 작업은 build-and-lint 작업이 통과한 후 병렬로 실행됩니다. 이 구조는 커버리지를 희생하지 않고 전체 파이프라인 시간을 줄입니다.
배포 전략
배포하는 방법은 배포하는지 여부만큼이나 중요합니다. 세 가지 전략이 영국 팀의 대부분의 요구를 커버합니다.
롤링 배포. 인스턴스를 하나씩 교체합니다. 대부분의 오케스트레이터(Kubernetes, ECS)로 구현하기 간단합니다. 위험: 새 버전에 버그가 있는 경우 일부 사용자는 롤아웃 창 동안 이전 인스턴스에, 다른 사용자는 새 인스턴스에 접근합니다. 저트래픽 애플리케이션의 좋은 기본값입니다.
블루/그린 배포. 두 개의 동일한 프로덕션 환경을 유지합니다. 트래픽은 블루에서 그린으로 원자적으로 전환됩니다. 새 버전에 결함이 있으면 초 단위로 전환을 되돌립니다. 비용은 두 환경을 동시에 실행하는 것이며, 데이터베이스의 경우 간단하지 않습니다. 다운타임이 허용되지 않고 롤백 속도가 중요한 애플리케이션에 최적입니다.
카나리 릴리스. 트래픽의 작은 비율(5% 또는 10%)을 새 버전으로 라우팅하고, 정해진 기간 동안 오류율과 성능을 관찰한 다음 카나리를 100%로 승격시킵니다. 전체 롤아웃 전에 실제 프로덕션 피드백이 필요한 고트래픽 애플리케이션에 탁월합니다. 로드 밸런서 또는 서비스 메쉬가 트래픽 분할을 지원해야 합니다.
대부분의 영국 팀은 롤링 배포로 시작하고, 트래픽과 중요도가 정당화될 때 블루/그린을 추가하며, 하루에 여러 번 배포하고 각 단계에서 검증된 프로덕션 피드백이 필요할 때 카나리 릴리스를 고려해야 합니다.
시크릿 관리
시크릿은 코드, 설정 파일 또는 소스 제어에 커밋된 환경별 .env 파일에 속하지 않습니다. 올바른 접근 방식:
GitHub Secrets / GitLab CI 변수 는 파이프라인 작업에 필요한 시크릿을 위한 것입니다. 이것들은 저장 시 암호화되고, 로그에서 마스킹되고, 환경 변수를 통해 작업에서 사용 가능합니다.
환경별 시크릿 은 배포 대상 수준에서 설정됩니다. 더 복잡한 요구 사항을 가진 팀을 위한 AWS Parameter Store, Azure Key Vault, Google Secret Manager 또는 HashiCorp Vault입니다. 애플리케이션은 시작 시 파이프라인을 통해 전달된 환경 변수가 아닌 시크릿 스토어에서 시크릿을 읽습니다.
순환. API 키, 데이터베이스 암호, 서비스 자격증명은 일정에 따라 순환되어야 합니다. CI/CD 파이프라인은 한 곳(시크릿 스토어 또는 CI 환경)에서 시크릿을 업데이트하는 것이 다음 배포에 자동으로 전파되기 때문에 순환을 더 쉽게 만듭니다.
파이프라인의 Gitleaks는 개발자가 실수로 시크릿을 커밋할 때를 위한 안전망입니다. 커밋된 시크릿에 대한 수정은 즉시 무효화한 다음 git 기록을 정리하는 것입니다. Gitleaks 알림은 누군가가 그것을 악용하기 전에 지금 그 프로세스를 시작해야 한다는 것을 알려줍니다.
파이프라인 성능
느린 파이프라인은 무시되는 파이프라인입니다. 개발자가 모든 푸시에 대해 15분의 피드백을 기다린다면, 작은 커밋을 푸시하는 것을 멈추고 작업을 배치 처리하기 시작하며, 이는 CI의 목적을 무효화합니다.
파이프라인을 빠르게 유지하는 실용적인 단계:
의존성 설치를 캐시합니다. npm의 경우 package-lock.json에 캐시를 키잉합니다. pip의 경우 requirements.txt에 키잉된 pip 캐시 액션을 사용합니다. 따뜻한 캐시는 2분간의 설치를 5초간의 복원으로 바꿉니다.
독립적인 작업을 병렬로 실행합니다. 빌드, 린트, 유닛 테스트, 통합 테스트, 보안 스캔이 모두 서로 의존하는 것은 아닙니다. 잘 구조화된 파이프라인은 공통 빌드 단계 후에 병렬 작업으로 실행하여 전체 벽시계 시간을 크게 줄입니다.
경로 필터를 사용합니다. 여러 서비스가 있는 모노레포가 있는 경우 서비스 디렉토리의 파일이 변경될 때만 관련 파이프라인 단계를 트리거합니다. GitHub Actions는 푸시 트리거에서 paths 필터를 지원합니다.
타임아웃을 설정합니다. 중단된 작업은 기본 6시간 타임아웃 동안 러너를 점유해서는 안 됩니다. 각 단계에 적합한 작업 수준 타임아웃을 설정합니다. 린트 5분, 유닛 테스트 15분, 통합 테스트 30분.
핵심 요점
- CI/CD는 배포를 고위험 이벤트에서 일상적이고 자동화된 프로세스로 변환합니다. 대부분의 영국 팀의 가장 큰 병목은 도구가 아니라 전혀 구조화된 파이프라인이 없다는 것입니다.
- GitHub Actions는 새 프로젝트의 올바른 출발점입니다. GitLab CI는 자체 호스팅 러너 또는 단일 통합 플랫폼이 필요한 팀을 위한 것입니다.
- 프로덕션 등급 파이프라인은 11개의 단계를 가집니다. 대부분의 튜토리얼은 3개에서 멈춥니다. 건너뛴 단계가 프로덕션 인시던트의 원점입니다.
- 보안 스캔(SAST, 의존성 감사, 시크릿 스캔)은 월간 예약 스캔이 아니라 모든 풀 리퀘스트의 파이프라인에 속합니다.
- 배포 전략은 교환 가능하지 않습니다. 단순성을 위한 롤링 배포, 제로 다운타임 중요성을 위한 블루/그린, 프로덕션 검증이 필요한 고빈도 릴리스를 위한 카나리.
- 느린 파이프라인은 파이프라인이 없는 것만큼 해롭습니다. 적극적으로 캐시하고, 독립적인 작업을 병렬화하고, 모든 작업에 하드 타임아웃을 설정하세요.
자주 묻는 질문(FAQ)
CI/CD 파이프라인 실행에는 얼마나 걸려야 합니까? 푸시에서 스테이징 배포까지의 중요한 경로에서 10분 미만을 목표로 하세요. 린트와 유닛 테스트는 5분 이내에 완료되어야 합니다. 파이프라인이 정기적으로 더 오래 걸린다면 캐싱, 병렬화, 테스트 스위트가 별도의 덜 빈번한 실행에 속하는 느린 테스트를 쌓아두었는지 조사하세요.
모든 커밋에서 전체 테스트 스위트를 실행해야 합니까, 아니면 main에 대한 풀 리퀘스트에서만 실행해야 합니까? 모든 푸시에서 빠른 확인(린트, 유닛 테스트, 보안 스캔)을 실행하세요. main에 대한 풀 리퀘스트와 main에 대한 병합에서 통합 테스트와 스테이징 배포를 실행하세요. 이는 피드백 속도와 리소스 비용 및 러너 분 사이의 균형을 맞춥니다.
CI와 CD의 차이점은 무엇입니까? CI(지속적 통합)는 모든 커밋이 자동화된 빌드 및 테스트 시퀀스를 트리거한다는 것을 의미합니다. CD(지속적 전달)는 검증된 코드를 스테이징 또는 프로덕션에 배포하기 위한 자동화를 확장합니다. 일반적으로 함께 구현되지만 별개의 실천을 나타냅니다.
스테이징 환경이 필요합니까? 예, 실제 사용자가 있는 모든 애플리케이션에 필요합니다. 스테이징은 배포별 실패, 환경 간 설정 차이, 유닛 또는 통합 테스트에서 나타나지 않는 스모크 테스트 문제를 잡는 곳입니다. 프로덕션에서 직접 테스트하는 것은 CI/CD가 제거하기 위해 존재하는 위험입니다.
CI/CD 파이프라인에서 데이터베이스 마이그레이션을 처리하는 가장 좋은 방법은 무엇입니까? 새 애플리케이션 버전이 트래픽을 받기 시작하기 전에 배포 단계의 일부로 마이그레이션을 실행합니다. 마이그레이션이 이전 애플리케이션 버전과 역방향 호환성을 가지도록 하여 롤백이 스키마를 깨뜨리지 않도록 합니다. 그것들을 사용하는 기능과 동일한 마이그레이션에서 파괴적인 스키마 변경(열 삭제, 유형 변경)을 피하세요.
영국 에이전시나 클라이언트에게 CI/CD 투자가 가치 있다는 것을 납득시키려면 어떻게 해야 합니까? 가장 강력한 논거는 재정적입니다. CI에서 발견된 버그는 배포 후 발견된 버그보다 수정 비용이 약 10배 저렴합니다. 잘 운영되는 파이프라인은 각 릴리스의 위험과 스트레스도 줄이며, 이는 팀 유지율과 속도를 직접적으로 향상시킵니다. 대부분의 영국 에이전시는 CI/CD를 채택한 첫 분기 내에 근무 시간 외 긴급 배포의 측정 가능한 감소를 확인합니다.
댓글