DevSecTest, 보안 스캔을 파이프라인에 붙이는 것과 내재화하는 것의 차이

DevTest에 SAST·DAST·SCA·SBOM·정책 코드화를 결합한 DevSecTest 파이프라인 설계와 CodeQL·Trivy·cosign 구현 예시를 정리한다

2026-08-12 · 최초 발행 2025-12-18

DevTest는 코드 작성부터 머지·빌드·배포 전까지 자동화 테스트를 통합하는 연속 테스트 운영체계다. 테스트 피라미드를 따라 단위·통합·계약·E2E를 표준화하고 파이프라인 안에 품질 게이트를 건다. DevSecTest는 여기에 보안을 얹은 형태다 — SAST·DAST·SCA·IaC 스캔과 비밀관리·서명·SBOM을 CI/CD에 통합하고, 정책 코드화로 보안 기준을 자동 집행한다. 두 개 다 Shift-Left 전략의 구현체지만, 도구를 몇 개 더 끼워 넣는 문제가 아니라 프로세스·정책·데이터·아키텍처를 아우르는 운영체계를 만드는 문제라는 점이 핵심이다.

위협 모델링이 왜 코드보다 먼저인가

Security-by-Design은 설계 단계에서 위협 모델링을 하고, 그 결과를 사용자 스토리와 테스트 케이스로 풀어내는 데서 시작한다. CWE/OWASP Top 10 기준을 정책으로 만들어 린트·SAST 규칙과 연결해야 "취약점이 발견됐다"가 아니라 "이 규칙을 왜 어겼다"가 리포트에 남는다. 나중에 스캐너를 붙이는 것보다, 무엇을 막을지 미리 정의하고 그 기준으로 도구를 고르는 순서가 오탐을 줄인다.

테스트 피라미드 쪽도 DevTest와 원리는 같다. 단위 테스트 비중을 늘리고 계약·통합 테스트로 상호작용을 검증하며 E2E는 필수 최소한만 남긴다. 병렬 실행·캐시·플레이키 테스트 억제 전략으로 파이프라인 시간을 최적화하는 것도 동일하다. 차이는 이 위에 무엇을 더 얹느냐다.

게이트를 정책으로 선언한다는 것

품질 게이트는 심각도·커버리지·성능 기준을 정책으로 선언하고 파이프라인이 자동으로 집행하게 만든다. 실패하면 즉시 차단하고, 위험을 감수해야 하는 상황이면 예외 승인과 감사 로그로 통제 일관성을 지킨다. 도구체인 쪽에서는 SAST/DAST/SCA/IaC 스캔, SBOM 생성·서명, 취약점 티켓 자동화를 연계하고, 커밋→아티팩트→배포 사이의 변경 추적과 근본원인 분석용 메타데이터를 계속 유지해야 나중에 "이 취약점이 언제 들어왔는가"를 답할 수 있다.

환경 동형성도 빠뜨리면 안 된다. 컨테이너·IaC로 환경을 동일하게 맞추고 임시(preview) 환경에서 실효성을 검증한다. 테스트 데이터는 합성 데이터·마스킹·시딩으로 재현성과 개인정보 보호를 동시에 잡는다.

성공실패임계치 통과임계치 미달심각도 'High' 이상 발견문제 없음개발자 'git push''pre-commit' 훅: 'lint' /'secrets scan'CI: 'build' 'unit test'피드백: '로컬 수정' '재시도''SAST' / 'SCA' / 'IaC' 스캔품질 게이트: '정책 검사'('policy-as-code')컨테이너 이미지 빌드'SBOM' 생성레지스트리 푸시 서명('cosign')스테이징 배포 'DAST'승인 '프로덕션' 배포모니터링 / 런타임 보호 ('RASP'/ 'WAF')피드백 루프: '티켓' 생성'MTTR' 측정

입력은 코드·의존성·IaC 정의·시크릿이고, 처리는 테스트·정적/동적 분석·정책 게이팅·서명·배포이며, 출력은 신뢰된 아티팩트·SBOM·취약점 티켓·지표(MTTR, 결함 유출률)다.

도입은 표준 수립부터 조직 확산까지

먼저 목표 지표(결함 유출률, 커버리지, 취약점 SLA, MTTR)를 정하고, 심각도 임계치·품질 게이트·예외 승인 절차를 정책 코드화 초안으로 만든다. 그다음 공통 CI 템플릿과 리유저블 워크플로우로 파이프라인을 템플릿화하고, 샘플 서비스 1~2개로 파일럿을 돌려 피드백을 반영한다. 세 번째 단계에서 SAST/SCA/IaC 스캔과 SBOM을 기본값화하고 시크릿 스캐닝을 상시화하며, 합성 데이터·마스킹 정책과 테스트 데이터 카탈로그를 운영한다. 마지막으로 품질 대시보드와 자동 티켓팅, 예외 승인 저장소를 운영하면서 분기별로 정책을 재점검하고 거버넌스 리뷰·교육 체계를 갖춘다.

이 체계는 영역마다 다르게 적용된다. 마이크로서비스는 서비스 템플릿에 테스트·보안 스텝을 사전 탑재하고 변경 위험도 기반 선택적 스캔·증분 분석으로 속도를 지킨다. 모바일/프런트엔드는 SCA·라이선스 준수·서드파티 스크립트 무결성 검증에 E2E 스모크와 DAST 라이트웨이트 스캔을 병행한다. 데이터/ML 파이프라인은 데이터 스키마 테스트·드리프트 감지·민감정보 정책 검사에 모델 컨테이너 SBOM·서명·런타임 정책까지 더한다.

DevTest와 DevSecTest, 지표로 나눠보면

구분 성능 확장성 일관성 안정성 운영 편의
DevTest 캐시·병렬화로 테스트 시간 최적화 파이프라인 샤딩·템플릿 확산 테스트 데이터·피라미드 표준화 플레이키 테스트 억제·재시도 제어 리포트 통합·개발자 편의 도구
DevSecTest 증분 SAST/SCA·병렬 스캔 분산 스캔·중앙 정책 엔진 SBOM·서명·정책 코드화 오탐 관리·취약점 기준선 티켓 자동화·SLA 추적 대시보드

CodeQL·Trivy·cosign·ZAP을 엮은 실제 파이프라인

전제조건은 GitHub Actions와 Docker 런타임, CodeQL 권한 활성화, Trivy·ZAP Docker 이미지에 대한 네트워크 접근, 컨테이너 이미지 레지스트리와 OIDC 기반 cosign 키리스 서명(또는 키 제공)이다.

name: ci-devsectest
on:
  push:
    branches: [ "main" ]
  pull_request:

jobs:
  build-test-secure:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      security-events: write
      id-token: write   # cosign keyless
    env:
      IMAGE: ghcr.io/owner/app:${{ github.sha }}
      SEVERITY: HIGH,CRITICAL

    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-node@v4
        with:
          node-version: '20'

      - name: Install and Unit Test
        run: |
          npm ci
          npm test -- --ci

      - name: Initialize CodeQL
        uses: github/codeql-action/init@v3
        with:
          languages: javascript
      - name: CodeQL Analyze
        uses: github/codeql-action/analyze@v3

      - name: Trivy FS (SCA/IaC)
        uses: aquasecurity/trivy-action@0.24.0
        with:
          scan-type: 'fs'
          severity: ${{ env.SEVERITY }}
          exit-code: '1'
          format: 'table'

      - name: Build Container
        run: |
          docker build -t $IMAGE .

      - name: Trivy Image
        uses: aquasecurity/trivy-action@0.24.0
        with:
          image-ref: ${{ env.IMAGE }}
          severity: ${{ env.SEVERITY }}
          exit-code: '1'
          format: 'table'

      - name: Generate SBOM (syft)
        uses: anchore/sbom-action@v0
        with:
          image: ${{ env.IMAGE }}
          format: spdx-json
          output-file: sbom.spdx.json

      - name: Push Image
        run: |
          echo "${{ secrets.GHCR_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin
          docker push $IMAGE

      - name: Cosign Sign (keyless)
        run: |
          cosign sign --yes $IMAGE

      - name: Run App (staging-like)
        run: |
          docker run -d -p 8080:8080 --name app $IMAGE
          sleep 5

      - name: OWASP ZAP Baseline
        uses: zaproxy/action-baseline@v0.10.0
        with:
          target: 'http://localhost:8080'
          cmd_options: '-a -m 3 -T 60'
        continue-on-error: true

      - name: Gate ZAP High/Critical
        run: |
          if grep -E "High|Critical" -i -n report_html.html; then
            echo "DAST high/critical found"
            exit 1
          fi

      - name: Upload Reports
        uses: actions/upload-artifact@v4
        with:
          name: security-reports
          path: |
            sbom.spdx.json
            *.sarif
            *.html

품질 게이트 기준은 SAST/SCA/DAST에서 High 이상이 나오면 실패 처리하는 것이다. 증분 최적화는 멀티스테이지 빌드 캐시와 변경 감지 기반 제한 스캔으로 하고, 도구 버전과 동작이 자주 바뀌므로 릴리스 노트를 확인하는 습관이 필요하다.

게이트를 얼마나 세게 걸 것인가

모범사례는 증분·병렬·캐시 전략으로 빌드·스캔 시간을 최소화하는 것, 오탐·중복 이슈를 억제하기 위한 기준선(baseline)과 티어링 정책을 운영하는 것, 정책-as-code로 예외 승인·만료·감사를 자동화하는 것이다. 하지만 트레이드오프는 그대로 남는다. 게이트를 강화하면 배포 속도가 떨어지므로 위험 점수 기반 차등 게이팅이 현실적이고, 스캔 범위를 넓히면 비용이 늘어나므로 변경 영향도 기반 스코프 축소·샘플링을 병행해야 한다. 도구가 다양해질수록 복잡도가 오르는데, 이건 중앙 규칙 저장소와 리포트 스키마 표준화로 완화하는 수밖에 없다.

DevTest / DevSecTest는 테스트·보안을 개발 초기에 내재화해 결함 유출을 최소화하고 리드타임을 줄이며 규제 대응력을 키우는 운영체계다. 결함 유출률은 3060% 감소 추정, 취약점 MTTR은 50% 이상 단축, High/Critical SLA 준수율은 90%+ 달성이 가능하고, 배포 리드타임은 2040% 단축된다고 보고된다. 성패는 표준 파이프라인·정책 코드화·데이터 관리·지표 운영을 얼마나 결합하느냐에 달려 있으며, 파일럿→템플릿화→조직 확산 순서로 위험도 기반 게이팅을 도입하는 게 속도와 안정성의 균형을 지키는 길이다.

DevSecTestShiftLeftSASTDASTSBOM