DevSecOps 보안 테스트 파이프라인을 CI/CD에 통합하는 방법
DevSecOps 보안 테스트 파이프라인에 SAST, SCA, SBOM, DAST, 정책 게이팅을 연결하고 운영하는 실무 기준을 정리한다.
2026-08-14 · 최초 발행 2025-12-24
코드 변경부터 런타임까지 이어지는 보안 검사
DevSecOps 보안 테스트 파이프라인은 개발·빌드·배포의 전 구간에 보안 검사를 녹이고 자동화하는 방식이다. 애플리케이션, 인프라, 공급망에서 발생하는 취약점을 이른 시점에 찾아 차단하면서 배포 속도와 품질을 함께 관리한다.
검사 결과는 단순 리포트로 끝나지 않는다. 정책 기반 게이트로 평가하고, 티켓·대시보드·서명·감사 로그를 연결해 조치와 검증이 이어지는 폐쇄 루프를 만든다. 수동 스캔을 특정 시점에 수행하던 방식과 달리, 코드 변경 단위로 검사를 지속한다는 점이 핵심이다.
보안·개발·운영 조직은 Policy as Code와 SBOM·서명 같은 표준 아티팩트를 공유하며 품질 기준을 맞춘다.
빠른 피드백과 배포 후 검증을 함께 설계한다
Shift-left에서는 PR 단위로 SAST, SCA, Secrets, IaC 스캔을 빠르게 실행해 개발자 피드백 루프를 줄인다. 캐시와 증분 스캔은 빌드 시간을 통제하는 수단이다.
Shift-right는 스테이징과 프로덕션에서 DAST·IAST, 런타임 취약점·행위 탐지를 연계한다. 배포 뒤의 검증 결과를 다시 반영해 실제 리스크를 낮춘다.
정책은 심각도, CWE/CVE, 라이선스, 베이스라인, 허용 기간(예외 만료)을 코드로 다룬다. OPA/Conftest, SARIF 규격, 저장소 브랜치 보호 규칙을 결합하면 차단과 허용 판단을 일관되게 적용할 수 있다.
SBOM은 CycloneDX/SPDX 형식으로 생성·보관해 공급망을 추적하는 기반이 된다. CVE DB 업데이트와 동기화하면 재평가를 자동화할 수 있으며, 아티팩트와 이미지에 Cosign/Sigstore 서명을 적용하고 배포 시 검증하면 무결성을 보증할 수 있다.
대규모 실행 환경에서는 변경 파일·모듈 단위의 범위 제한, 병렬 실행, 증분 스캔으로 시간을 관리한다. 스테이지별 타임아웃과 리트라이를 두고, 스캐너 컨테이너화·SCA DB 및 언어 빌드 캐시·중앙 취약점 DB 미러링을 활용해 병렬 처리에 대응한다.
티켓 시스템(Jira)과 양방향으로 연동하고 SLO/SLI(예: 고위험 MTTR, 빌드 실패율)를 모니터링한다. 예외 승인 워크플로우도 표준화해야 한다. 정책 버전, 스캔 결과, 서명 정보를 모두 남기면 감사 시점에도 결정을 재현할 수 있다.
| 테스트 유형 | 성능(시간/자원) | 확장성 | 일관성 | 안정성(오탐/과탐) | 운영 편의 |
|---|---|---|---|---|---|
| SAST | 중간 | 높음 | 높음 | 오탐 중간 | IDE/CI 연동 용이 |
| SCA | 빠름 | 높음 | 높음 | 안정적 | SBOM 연계 용이 |
| IaC Scan | 빠름 | 높음 | 높음 | 낮음 | 규정 준수에 유리 |
| Container Scan | 중간 | 높음 | 높음 | 안정적 | 이미지 파이프라인 친화 |
| DAST | 느림 | 중간 | 중간 | 과탐 가능 | 스테이징 필요 |
파이프라인 입력과 산출물의 연결
입력은 코드 변경(PR/Push), 의존성 선언파일, IaC 템플릿, 컨테이너 Dockerfile, 대상 URL이다.
PR 단계에서는 Secrets, SAST, SCA, IaC 스캔을 병렬로 수행한다. 심각도 임계를 넘거나 금지된 라이선스를 사용하면 실패 조건이 된다. 빌드 단계에서는 SBOM을 만들고 이미지를 빌드·스캔하며, 베이스 이미지의 고위험 미해결 또는 서명 검증 실패를 차단 조건으로 둔다. 스테이징 단계에서는 DAST/IAST와 취약점·커버리지·가용성 정책 평가를 실행한다.
결과물은 SARIF/JSON 리포트, SBOM, 서명 메타데이터, 이슈 티켓, 대시보드 지표로 남긴다. 허용 요청에는 만료일과 대체통제를 명시하고 정책 저장소 PR에서 승인한다. 타임아웃이 발생하면 스캐너를 격리한 뒤 재시도 1회를 수행하며, 계속 실패하면 소음 억제 로깅과 차단으로 처리한다.
GitHub Actions로 구성한 보안 검사 예시
전제조건은 다음과 같다.
- Runner: ubuntu-latest
- 레지스트리 권한(OIDC 또는 PAT), 대상 URL 준비
- 액션 버전은 예시, 최신 정보 확인 필요
name: security-pipeline
on:
pull_request:
push:
branches: [ main ]
jobs:
security:
runs-on: ubuntu-latest
permissions:
contents: read
security-events: write
id-token: write
env:
SEVERITY_THRESHOLD: HIGH
TARGET_URL: https://staging.example.com
steps:
- uses: actions/checkout@v4
# Secrets Scan
- name: Gitleaks
uses: gitleaks/gitleaks-action@v2
with:
args: detect --source . --no-git -v --redact --exit-code 1
# SAST (Semgrep)
- name: Semgrep SAST
uses: returntocorp/semgrep-action@v1
with:
config: p/ci
generateSarif: "1"
publishToken: ${{ secrets.SEMGREP_APP_TOKEN }}
continue-on-error: false
# SCA + FS Scan (Trivy)
- name: Trivy FS (SCA)
uses: aquasecurity/trivy-action@0.20.0
with:
scan-type: fs
format: sarif
output: trivy-fs.sarif
severity: CRITICAL,HIGH
# IaC Scan (tfsec)
- name: tfsec
uses: aquasecurity/tfsec-action@v1.0.3
with:
additional_args: --soft-fail-severity=MEDIUM
# Build image
- name: Build image
run: |
docker build -t ghcr.io/org/app:${{ github.sha }} .
# SBOM (Syft)
- name: SBOM (CycloneDX)
uses: anchore/sbom-action@v0
with:
image: ghcr.io/org/app:${{ github.sha }}
format: cyclonedx-json
output-file: sbom.cdx.json
# Container Scan (Trivy Image)
- name: Trivy Image
uses: aquasecurity/trivy-action@0.20.0
with:
image-ref: ghcr.io/org/app:${{ github.sha }}
format: sarif
output: trivy-image.sarif
severity: CRITICAL,HIGH
# Upload SARIF to GitHub Security tab
- name: Upload SARIF
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: |
trivy-fs.sarif
trivy-image.sarif
semgrep.sarif
# DAST (OWASP ZAP baseline)
- name: ZAP Baseline
uses: zaproxy/action-baseline@v0.12.0
with:
target: ${{ env.TARGET_URL }}
cmd_options: "-a -m 5" # 5분 제한
continue-on-error: true
# Policy Gate (간단 샘플)
- name: Gate - Fail on HIGH/CRITICAL
run: |
# 실패 기준을 확장하려면 SARIF 파서 사용 권장
if grep -qi "CRITICAL\|HIGH" trivy-image.sarif; then
echo "Gate: severity threshold exceeded"
exit 1
fi
# Optional: Cosign sign (레지스트리 로그인 필요)
- name: Cosign Sign
if: ${{ github.ref == 'refs/heads/main' }}
run: |
cosign sign ghcr.io/org/app:${{ github.sha }} --yes
소음, 성능, 예외를 정책으로 다룬다
보안 검사는 탐지량만으로 운영할 수 없다. 베이스라인·허용 리스트·최대 신규 취약점 수 같은 상대 기준을 함께 적용해야 하며, 무조건 차단하는 정책은 개발 생산성을 떨어뜨릴 리스크가 있다.
PR에서는 증분·샘플링을 적용하고, main 병합과 릴리스 태그에서는 전체 스캔을 수행한다. DAST는 스테이징 배포 뒤 예약 실행하는 방식이 적합하다.
도구가 늘어날수록 결과는 SARIF로 통합하고, 정책은 OPA로 공통화하며, SLO를 공통 메트릭으로 사용해 이질적인 도구를 운영 표준 안에 묶는다.
취약점 조기 발견 비율은 4070%p 향상하고, 고위험 MTTR은 3060% 단축되며, 릴리스 차단 건수 대비 재작업 시간은 20~40% 감소할 수 있다. SBOM 보급률 90% 이상과 이미지 서명 적용률 95% 이상도 달성 가능하다. 수치는 조직 성숙도에 따라 변동, 최신 정보 확인 필요.
이 체계는 개발자의 자율 보안 문화를 정착시키고 보안팀의 감사·거버넌스 역량을 강화한다. 릴리스 신뢰도와 금융·의료 규제 같은 규정 준수 대응력도 함께 높일 수 있다.