DevSecOps는 개발 속도와 운영 안정성을 유지하면서도 보안을 기본 품질 요소로 내재화하려는 접근 방식이다.
이 개념이 등장하기 이전의 보안은 대부분 개발이 완료된 이후 별도의 점검 단계에서 수행되었고, 그 결과 보안은 종종 일정 지연의 원인이 되거나 형식적인 절차로 전락하곤 했다.
DevSecOps에서의 테스팅은 이러한 문제를 해결하기 위해, 보안을 개발 생명주기 전반에 걸쳐 지속적으로 검증하는 활동으로 정의된다.
DevSecOps 환경에서의 테스팅은 단일 도구나 특정 테스트 기법을 의미하지 않는다. 오히려 각 단계의 특성에 맞는 테스트 관점을 정의하고, 이를 자동화된 파이프라인 안에 녹여 반복적으로 수행하는 것이 핵심이다.
이 글에서는 요구사항 단계부터 운영 단계까지, DevSecOps 라이프사이클 전반에서 보안 테스팅이 어떻게 이루어져야 하는지를 단계별로 자세히 살펴본다.
○ 요구사항 단계에서의 보안 테스팅 관점
DevSecOps에서 보안 테스팅은 코드를 작성하기 훨씬 이전 단계부터 시작된다. 요구사항 단계에서의 테스팅은 일반적인 의미의 테스트 실행이라기보다는, “이 시스템이 어떤 보안 위험을 내포하고 있는가”를 검증하는 활동에 가깝다. 이 단계의 핵심은 보안 요구사항이 누락되지 않았는지를 확인하는 것이다.
예를 들어, 사용자 인증이 필요한 시스템임에도 불구하고 인증 방식이나 권한 분리 기준이 명확히 정의되지 않았다면, 이는 구현 이전에 발견되어야 할 보안 결함이다. 요구사항 단계에서의 테스팅은 이러한 모호함을 제거하는 역할을 한다. 데이터 분류 기준, 암호화 필요 여부, 외부 연동 시 인증 방식과 같은 항목을 체크리스트 형태로 검증하는 것이 대표적인 방법이다.
또한 위협 모델링은 이 단계에서 매우 중요한 테스팅 기법이다. STRIDE나 공격 시나리오 기반 분석을 활용해 “이 기능이 악용된다면 어떤 일이 발생할 수 있는가”를 미리 검토한다.
예를 들어 파일 업로드 기능이 있다면, 단순히 기능 구현 가능 여부를 확인하는 것이 아니라 악성 파일 업로드, 경로 조작, 대용량 업로드로 인한 서비스 거부 가능성까지 함께 검토한다.
이러한 검증 결과는 이후 단계에서 수행할 보안 테스트의 기준점이 된다.
○ 설계 단계에서의 보안 테스팅 관점
설계 단계에서의 보안 테스팅은 아키텍처 수준의 검증에 초점을 둔다.
이 단계에서는 개별 코드의 취약점보다는 시스템 구성과 흐름 자체가 공격에 얼마나 취약한지를 검토한다. 즉, “이 구조가 안전한가”를 테스트하는 단계라고 볼 수 있다.
예를 들어 마이크로서비스 아키텍처를 사용하는 경우, 서비스 간 통신이 모두 내부 네트워크라는 이유만으로 무 인증 상태로 설계되는 경우가 있다.
설계 단계의 보안 테스팅에서는 이러한 가정을 검증하고, 서비스 간 인증과 권한 검증이 필요한지 여부를 확인한다.
또 데이터베이스와 애플리케이션 서버가 동일한 네트워크에 존재하는 경우, 네트워크 분리가 필요한지도 함께 검토한다.
이 단계에서의 테스팅 방법으로는 아키텍처 다이어그램 리뷰, 보안 설계 체크리스트, 설계 기반 공격 시나리오 검증 등이 있다.
최근에는 IaC (Infrastructure as Code)를 활용해 인프라 설계를 코드로 관리하는 경우가 많아졌는데, 이 경우 보안 정책을 코드 수준에서 자동 검증하는 방식도 효과적인 테스팅 방법이 된다.
○ 개발 단계에서의 보안 테스팅 관점
개발 단계는 DevSecOps 보안 테스팅이 가장 활발하게 수행되는 구간이다. 이 단계의 목표는 취약한 코드가 빌드 단계로 넘어가기 전에 최대한 제거하는 것이다. 이를 위해 자동화된 정적 분석과 의존성 검증이 핵심 역할을 한다.
정적 애플리케이션 보안 테스트는 소스 코드를 실행하지 않고 분석하여 취약한 패턴을 탐지한다. 예를 들어 사용자 입력 값을 검증하지 않고 데이터베이스 쿼리에 직접 사용하는 코드가 있다면, 이는 SQL 인젝션 가능성이 있는 코드로 탐지된다.
이러한 테스트는 개발자가 코드를 커밋하거나 Pull Request를 생성하는 시점에 자동으로 수행되며, 결과는 개발자가 즉시 확인할 수 있어야 한다.
또한 현대 애플리케이션은 수많은 오픈소스 라이브러리에 의존하고 있기 때문에, 소프트웨어 구성 분석 테스트가 필수적이다.
예를 들어 특정 라이브러리 버전에 원격 코드 실행 취약점이 존재한다면, 해당 라이브러리를 사용하는 모든 서비스는 잠재적인 공격 대상이 된다. DevSecOps 환경에서는 이러한 테스트 결과를 단순 경고로 끝내지 않고, 위험도가 높은 경우 빌드를 실패 시키는 정책을 적용하기도 한다.
이 단계에서 중요한 테스팅 관점은 “보안 테스트가 개발자의 생산성을 방해하지 않도록 설계되어야 한다”는 점이다. 결과는 명확하고 구체적이어야 하며, 수정 방법까지 함께 제시되는 것이 이상적이다.
○ 빌드 및 패키지 단계에서의 보안 테스팅 관점
코드가 빌드 되어 실행 가능한 산출물이 되는 단계에서도 중요한 보안 테스트가 수행된다. 특히 컨테이너 기반 환경에서는 이미지 자체가 하나의 공격 표면이 되기 때문에, 빌드 산출물에 대한 테스팅이 필수적이다.
이 단계의 대표적인 테스트는 컨테이너 이미지 스캔이다. 이미지에 포함된 운영체제 패키지와 라이브러리를 분석해 알려진 취약점이 있는지를 확인하고, 불필요한 도구나 서비스가 포함되어 있지는 않은지를 검증한다.
예를 들어 디버깅용 도구나 테스트용 계정이 포함된 이미지가 운영 환경에 배포되는 것은 명백한 보안 위험이다.
또한 빌드 과정에서 생성되는 설정 파일에 민감한 정보가 포함되어 있는지도 중요한 테스트 대상이다.
환경 변수나 설정 파일에 평문 비밀번호나 API 키가 포함되어 있다면, 이는 배포 이전에 반드시 제거되어야 한다.
이러한 검증은 CI 파이프라인에서 자동으로 수행되어야 하며, 기준을 충족하지 못할 경우 배포를 차단하는 역할을 한다.
○ 배포 전 테스트 환경에서의 보안 테스팅 관점
배포 전 단계에서는 실행 환경을 기준으로 한 보안 테스팅이 중요해진다. 이 단계에서는 동적 애플리케이션 보안 테스트를 통해 실제 공격 시나리오를 모의 실행한다. 정적 분석으로는 발견하기 어려운 인증 우회나 세션 관리 취약점, 비정상 입력 처리 문제 등을 검증할 수 있다.
예를 들어 로그인 기능이 정상적으로 동작하더라도, 비밀번호 재설정 과정에서 인증 검증이 충분하지 않다면 계정 탈취로 이어질 수 있다.
이러한 문제는 실제 요청 흐름을 기반으로 테스트해야만 발견할 수 있다. DevSecOps 환경에서는 이러한 테스트를 스테이징 환경에 자동으로 실행해, 운영 배포 이전에 위험 요소를 제거한다.
또한 이 단계에서는 API 보안 테스트도 중요한 비중을 차지한다. 인증 토큰 없이 접근 가능한 API가 있는지, 권한이 없는 사용자가 민감한 데이터를 조회할 수 있는지 등을 테스트하는 것이 대표적인 예다.
○ 운영 단계에서의 보안 테스팅 관점
DevSecOps에서 테스팅은 운영 단계에서도 계속된다. 운영 단계의 보안 테스팅은 “지금 이 순간에도 시스템이 안전한가” 를 검증하는 활동이다. 이는 침입 탐지나 로그 분석과 같은 운영 보안 활동과 밀접하게 연결된다.
운영 환경에서는 이상 행위 탐지를 통해 정상적인 사용자 행동 패턴과 다른 접근을 식별한다. 예를 들어 평소 접근하지 않던 관리 기능에 갑작스럽게 접근하거나, 짧은 시간 내 대량의 요청이 발생하는 경우 이는 보안 사고의 전조일 수 있다.
이러한 이벤트를 분석하고 대응하는 과정 자체가 운영 단계의 보안 테스팅이라고 볼 수 있다.
또한 카나리 배포나 점진적 배포 전략을 활용하면, 새로운 기능이나 변경 사항이 보안에 미치는 영향을 제한된 범위에서 검증할 수 있다. 이는 보안 사고 발생 시 피해 범위를 최소화하는 데에도 큰 도움이 된다.
○ DevSecOps 테스팅의 핵심 정리
DevSecOps에서의 테스팅은 단순히 보안 도구를 많이 사용하는 것이 아니라, 각 단계에서 “무엇을 검증해야 하는가”를 명확히 정의하고 이를 자동화하는 데 있다.
요구사항 단계에서는 보안 요구사항과 위협을 검증하고, 개발 단계에서는 코드와 의존성을 테스트하며, 운영 단계에서는 실제 환경에서 보안 통제가 잘 작동하는지를 지속적으로 확인한다.
이러한 흐름이 정착되면 보안은 더 이상 개발의 마지막 단계에서 급하게 처리해야 할 과제가 아니라, 품질을 구성하는 자연스러운 요소가 된다.
DevSecOps 테스팅의 궁극적인 목적은 모든 취약점을 제거하는 것이 아니라, 변화하는 환경 속에서도 지속적으로 위험을 관리할 수 있는 체계를 만드는 데 있다.
○ 실제 CI/CD 파이프라인 기준 DevSecOps 보안 테스트 흐름 예시
DevSecOps에서 보안 테스팅은 단일 테스트 단계로 존재하지 않는다. 실제 CI/CD 파이프라인에서는 코드가 작성되고, 빌드 되고, 배포되고, 운영되는 전 과정에 걸쳐 서로 다른 목적의 보안 테스트가 자연스럽게 연결된다.
중요한 점은 각 테스트가 독립적으로 동작하는 것이 아니라, 이전 단계의 결과를 다음 단계의 판단 기준으로 사용한다는 점이다.
아래에서는 개발자가 코드를 커밋하는 시점부터 운영 환경에 배포된 이후까지, 하나의 흐름으로 이어지는 보안 테스트 파이프라인을 단계별로 살펴본다.
① 개발자 로컬 환경: 사전 보안 테스트 (Pre-commit 단계)
실제 CI/CD 파이프라인에 코드가 올라가기 전, 가장 앞단에서 수행되는 테스트는 개발자 로컬 환경에서의 사전 검증이다. 이 단계는 공식적인 CI 단계는 아니지만, DevSecOps 관점에서는 매우 중요한 첫 번째 방어선이다.
개발자는 코드를 작성한 후 커밋을 하기 전에 간단한 정적 분석이나 보안 규칙 검사를 수행한다.
예를 들어 하드코딩된 비밀번호나 API 키가 코드에 포함되어 있는지, 명백한 보안 규칙 위반이 있는지를 빠르게 확인한다. 이러한 테스트는 커밋 훅(pre-commit hook)을 통해 자동으로 실행되기도 한다.
이 단계의 테스팅 관점은 “CI에서 실패할 코드를 미리 걸러내는 것”이다. 즉, 보안 테스트를 개발자의 책임으로 일부 이전시키는 Shift Left의 가장 극단적인 형태라고 볼 수 있다.
② 코드 커밋 및 Pull Request 생성: 정적 코드 보안 테스트
개발자가 코드를 원격 저장소에 푸시 하고 Pull Request를 생성하면, CI 파이프라인이 본격적으로 동작하기 시작한다. 이 시점에서 가장 먼저 수행되는 보안 테스트는 정적 애플리케이션 보안 테스트다.
정적 분석 도구는 소스 코드를 분석해 SQL 인젝션, XSS, 인증 우회 가능성이 있는 코드 패턴을 탐지한다. 예를 들어 사용자 입력 값을 검증하지 않고 데이터베이스 쿼리에 사용하는 코드가 발견되면, 이는 즉시 보안 이슈로 표시된다.
이 단계에서 중요한 점은 테스트 결과가 Pull Request 리뷰 과정에 자연스럽게 포함되어야 한다는 것이다. 보안 이슈는 별도의 문서나 리포트가 아니라, 일반 코드 리뷰 코멘트처럼 표시되어 개발자가 즉시 수정할 수 있어야 한다. 이로써 보안 테스트는 개발 프로세스의 일부가 된다.
③ 의존성 분석 단계: 오픈소스 및 라이브러리 보안 테스트
정적 코드 분석과 함께 또는 그 직후에 수행되는 테스트는 소프트웨어 구성 분석이다. 현대 애플리케이션은 대부분 외부 라이브러리에 의존하고 있기 때문에, 코드 자체보다 라이브러리 취약점이 더 큰 위험이 되는 경우도 많다.
CI 파이프라인에서는 프로젝트에 포함된 라이브러리 목록과 버전을 분석해, 이미 알려진 취약점이 있는지를 자동으로 검사한다. 예를 들어 특정 버전의 암호화 라이브러리에 치명적인 취약점이 존재한다면, 해당 라이브러리를 사용하는 모든 서비스는 즉시 위험 상태가 된다.
이 단계에서의 테스팅 관점은 “우리 코드가 아니라 우리가 가져다 쓴 코드도 테스트 대상이다”라는 인식을 조직에 정착시키는 것이다. 실제로 많은 보안 사고가 이 단계에서 걸러질 수 있다.
④ 빌드 단계: 빌드 무결성 및 시크릿 노출 테스트
코드와 의존성 검증을 통과하면, CI 파이프라인은 빌드 단계로 넘어간다. 이 단계에서는 실행 가능한 산출물이 생성되는데, DevSecOps 관점에서는 이 산출물 자체가 하나의 테스트 대상이 된다.
빌드 과정에서는 설정 파일이나 환경 변수에 민감한 정보가 포함되어 있는지를 검사한다. 예를 들어 데이터베이스 비밀번호가 설정 파일에 평문으로 포함되어 있다면, 이는 즉시 실패 처리되어야 한다.
또한 빌드 산출물이 의도하지 않은 디버그 옵션이나 테스트 설정을 포함하고 있지 않은지도 검증 대상이 된다.
이 단계의 보안 테스트는 “빌드가 성공했다고 해서 안전한 것은 아니다”라는 메시지를 조직에 전달하는 역할을 한다.
⑤ 컨테이너 이미지 생성: 이미지 보안 스캔
컨테이너 기반 환경에서는 빌드 이후 컨테이너 이미지가 생성된다. 이 시점에서 수행되는 보안 테스트는 이미지 스캔이다. 이미지 내부에 포함된 운영체제 패키지, 라이브러리, 실행 파일을 분석해 알려진 취약점이 있는지를 확인한다.
예를 들어 사용하지 않는 패키지나 기본 계정이 이미지에 포함되어 있다면, 이는 불필요한 공격 표면을 제공하는 요소가 된다. 이미지 스캔 결과는 취약점의 심각도에 따라 빌드 실패 또는 경고로 처리될 수 있다.
이 단계에서의 테스팅 관점은 애플리케이션 코드 뿐 아니라, 실행 환경 자체도 테스트 대상이라는 점을 명확히 하는 것이다.
⑥ 테스트 환경 배포: 동적 보안 테스트
이미지가 생성되고 나면, 애플리케이션은 테스트 또는 스테이징 환경에 배포된다. 이 단계에서 수행되는 핵심 보안 테스트는 동적 애플리케이션 보안 테스트다.
동적 테스트는 실제 실행 중인 애플리케이션에 대해 공격 시나리오를 모의 실행한다. 인증 없이 접근 가능한 API가 있는지, 권한이 없는 사용자가 민감한 데이터를 조회할 수 있는지, 입력 값 검증이 제대로 이루어지는지를 실제 요청 흐름을 기준으로 검증한다.
이 단계에서 발견되는 보안 이슈는 대부분 운영 환경에서도 그대로 발생할 가능성이 높기 때문에, 배포 전 마지막 방어선 역할을 한다.
⑦ 운영 배포 이후: 런타임 보안 테스트와 모니터링
운영 환경에 배포된 이후에도 보안 테스팅은 끝나지 않는다. 이 단계에서는 런타임 보안과 모니터링이 테스팅의 역할을 수행한다.
운영 환경에서는 정상적인 사용자 행동 패턴과 다른 접근을 탐지하고, 이상 징후를 분석한다.
예를 들어 특정 API에 대해 비정상적으로 많은 요청이 발생하거나, 관리자 기능에 대한 접근 시도가 증가하는 경우 이는 보안 사고 가능성을 의미한다.
이러한 이벤트를 분석하고 대응하는 과정은 “운영 환경에서의 지속적인 보안 테스트”라고 볼 수 있다. 실제 환경에서 보안 통제가 의도한 대로 작동하는지를 검증하는 단계이기 때문이다.
⑧ 전체 CI/CD 보안 테스트 흐름 요약
실제 CI/CD 파이프라인에서의 DevSecOps 보안 테스트 흐름은 다음과 같이 정리할 수 있다.
개발자 로컬에서 기본적인 보안 규칙을 검증하고, 코드 커밋 시 정적 분석과 의존성 테스트를 수행한다.
빌드 단계에서는 산출물의 무결성과 시크릿 노출 여부를 확인하고, 컨테이너 이미지 단계에서는 실행 환경의 취약점을 점검한다.
이후 테스트 환경에서 동적 테스트를 수행한 뒤 운영 환경에서는 지속적인 모니터링을 통해 보안 상태를 검증한다.
이러한 흐름이 정착되면 보안 테스트는 특정 시점의 이벤트가 아니라, CI/CD 파이프라인 자체의 기본 동작이 된다.
지금까지 DevSecOps에서의 단계별 보안 테스트 관점과 CI/CD 파이프라인을 기준으로 한 테스트 흐름을 간략히 살펴보았다.
주목해야 할 점은 보안이 더 이상 선택적인 기술 요소가 아니라, 전 세계적으로 특히 유럽을 중심으로 강력한 법적 요건과 준수 이행을 동반한 필수 요소로 자리 잡고 있다는 사실이다.
이는 단순히 보안 테스트를 추가적으로 수행하는 수준을 넘어, 개발·운영·품질 관리 전반의 프로세스에 보안을 내재화하고 보안 중심의 프로세스 흐름으로 전환해야 한다는 요구로 이어지고 있다.
이러한 변화는 조직 내부의 개발 및 운영 방식뿐만 아니라, 시험과 인증 체계 전반에도 영향을 미치고 있으며, 앞으로는 보안을 고려하지 않은 품질 활동 자체가 의미를 잃게 될 가능성도 크다.
따라서 우리 역시 이러한 흐름을 명확히 인식하고, 조직 차원의 보안 관점과 더불어 시험 및 인증 단계에서의 보안 관점을 놓치지 않는 전략적인 대응이 필요하다.