목차
- 1. 왜 Trivy 성능 최적화가 필요한가
- 2. Trivy가 느려지는 구간을 먼저 이해해보죠
- 3. 실전 구현 1: DB 캐시와 캐시 디렉터리부터 잡습니다
- 4. 실전 구현 2: 필요한 스캐너만 돌리고 스캔 범위를 줄입니다
- 5. 실전 구현 3: 서버 모드로 중복 작업을 줄입니다
- 6. ⚠️ 실제로 자주 만나는 문제와 트러블슈팅
- 6-1. 캐시를 붙였는데도 체감이 없다
- 6-2. secret 스캔 때문에 예상보다 오래 걸린다
- 6-3. 같은 베이스 이미지를 계속 스캔한다
- 6-4. 네트워크가 느린 날만 유독 전체 시간이 튄다
- 7. 결과 검증: 빨라졌는지 어떻게 확인할까
- 8. 정리: 상황별 추천 전략과 다음 단계
- 9. 자주 묻는 질문
- Q1. Trivy 성능 최적화는 캐시만 잘 써도 충분한가요?
- Q2. 모든 CI 단계에서 secret 스캔을 돌려야 할까요?
- Q3. 서버 모드는 언제 고려하면 좋을까요?
[보안] Trivy 성능 최적화로 대규모 컨테이너 스캔 가속하기
대규모 컨테이너 환경을 운영하다 보면 Trivy 성능 최적화가 생각보다 빨리 중요한 과제가 됩니다. 처음에는 이미지 하나, 둘 스캔할 때는 괜찮거든요. 근데 마이크로서비스가 늘고, CI/CD 파이프라인마다 이미지 스캔이 붙기 시작하면 갑자기 빌드 시간이 확 늘어납니다. 저도 홈랩이랑 실무 환경에서 비슷한 상황을 꽤 겪었는데요. 처음엔 “보안 검사니까 원래 느린가 보다” 하고 넘겼다가, 나중엔 배포 병목이 되더라고요. 특히 컨테이너 보안 정책과 이미지 스캔을 체계적으로 관리하려다 보니, 취약점 관리의 효율성까지 함께 챙겨야 하는 팀들이라면 이 부분을 그냥 두면 안 됩니다.
오늘은 제가 직접 적용하면서 효과를 봤던 방향 위주로, Trivy를 더 빠르게 돌리는 방법을 정리해보겠습니다. 핵심은 무작정 옵션을 많이 붙이는 게 아니라, 어디서 시간이 쓰이는지 구간을 나눠서 보는 것입니다. 데이터베이스(DB) 다운로드, 레이어 분석, 불필요한 스캐너 실행, CI/CD 캐시 미활용, 중복 스캔. 보통 여기서 시간 대부분이 나갑니다.
대규모 컨테이너 환경에서 Trivy 스캔이 어디서 느려지는지 한눈에 보여주는 개요 이미지입니다.
1. 왜 Trivy 성능 최적화가 필요한가
쉽게 말해 Trivy는 취약점 데이터베이스를 내려받고, 이미지 레이어를 분석하고, 패키지 정보를 대조해서 취약점을 찾는 도구입니다. 이 과정 자체는 합리적이죠. 문제는 서비스 수가 많아질수록 같은 작업을 너무 자주 반복한다는 데 있더라고요.
- 같은 베이스 이미지를 여러 서비스가 반복 스캔
- CI/CD 러너(runner, 빌드 실행기)가 매번 새로 떠서 캐시가 없음
- 필요 없는 스캐너까지 같이 실행
- 모든 브랜치에서 동일한 깊이로 검사
저도 처음엔 각 저장소마다 Trivy를 독립 실행하게 해뒀었는데, 실제로 써보니까 DB 다운로드와 캐시 미스(cache miss) 때문에 시간이 꽤 날아가더라고요. 특히 ephemeral runner(에페메럴 러너, 작업 후 사라지는 실행 환경) 쓰는 곳에서는 더 체감이 큽니다.
2. Trivy가 느려지는 구간을 먼저 이해해보죠
여기서 중요한 포인트가 있습니다. Trivy를 빠르게 만들려면 먼저 느린 구간을 분리해서 봐야 하더라고요. 보통 아래 네 가지입니다.
- DB 준비 시간: 취약점 데이터베이스를 매번 새로 가져오면 느립니다.
- 이미지 분석 시간: 레이어가 많거나 패키지 종류가 다양하면 분석 시간이 늘어납니다.
- 스캐너 범위: vuln(취약점), secret(시크릿), config(설정)까지 한 번에 다 돌리면 당연히 무거워집니다.
- 중복 실행: 같은 이미지를 브랜치마다, 잡(job)마다 반복 스캔하면 비효율이 크더라고요.
그래서 제가 권하는 접근은 이렇습니다. “DB 캐시 최적화 → 스캔 범위 축소 → 실행 구조 개선 → 서버 모드 검토” 순서로 보시면 됩니다. 이 순서가 좋은 이유는, 앞 단계일수록 적용 난이도 대비 체감 효과가 큰 경우가 많기 때문입니다.
3. 실전 구현 1: DB 캐시와 캐시 디렉터리부터 잡습니다
Trivy 성능 최적화에서 제일 먼저 손볼 건 캐시입니다. 이건 진짜 기본인데, 의외로 놓치는 팀이 많아요. 러너가 매번 깨끗한 상태로 시작하면 Trivy 입장에서는 매번 처음부터 다시 해야 하거든요.
제가 직접 해보니 가장 단순하고 효과적인 방법은 캐시 디렉터리(cache directory)를 고정하고, CI 캐시와 연결하는 거더라고요.
export TRIVY_CACHE_DIR=.trivycache
trivy image --cache-dir .trivycache my-registry.example.com/sample-app:latest
파이프라인에서는 보통 이 디렉터리를 캐시 대상으로 잡습니다. 예를 들면 이런 식이죠.
steps:
- name: Restore Trivy cache
uses: actions/cache@v4
with:
path: .trivycache
key: trivy-cache-${{ runner.os }}-${{ hashFiles('**/Dockerfile') }}
restore-keys: |
trivy-cache-${{ runner.os }}-
- name: Scan image
run: |
export TRIVY_CACHE_DIR=.trivycache
trivy image --cache-dir .trivycache my-image:latest
여기서 팁 하나 더 있습니다. 빌드 잡과 스캔 잡을 분리했다면, 스캔 직전에 DB를 미리 받아두는 방식도 꽤 유용하더라고요.
trivy image --download-db-only
trivy image my-image:latest
이렇게 해두면 네트워크 상태가 애매한 환경에서 시간 분산이 되더라고요. “왜 어떤 날은 빠르고 어떤 날은 느리지?” 싶은 분들, 사실 DB 다운로드 타이밍 영향이 큽니다.
4. 실전 구현 2: 필요한 스캐너만 돌리고 스캔 범위를 줄입니다
Trivy는 기능이 많은 만큼, 아무 생각 없이 다 켜면 무거워집니다. 물론 보안 관점에서는 이것저것 다 보고 싶죠. 저도 처음엔 그랬습니다. 근데 CI/CD 전체 시간을 생각하면 목적별 분리가 필요하더라고요.
예를 들어 PR 단계에서는 취약점(vulnerability, 취약성) 위주로 빠르게 보고, 야간 배치나 메인 브랜치에서는 secret(시크릿, 노출된 비밀정보)나 config(설정 검사)까지 확장하는 식입니다.
trivy image \
--scanners vuln \
--severity HIGH,CRITICAL \
--ignore-unfixed \
my-image:latest
이렇게 하면 노이즈가 꽤 줄어듭니다. 특히 취약점 관리를 실무에서 운영할 때 당장 조치 가능한 항목 위주로 보는 데 도움이 되더라고요.
또 하나 많이 쓰는 방법이 skip 옵션입니다. 파일 시스템(fs, 파일 시스템) 스캔이나 저장소(repo, 리포지토리) 스캔에서는 불필요한 디렉터리를 건너뛰는 것만으로도 시간이 줄 수 있습니다.
trivy fs \
--skip-dirs node_modules \
--skip-dirs vendor \
--skip-files '*.log' \
.
물론 무턱대고 제외하면 안 돼요. 여기서 중요한 포인트! 실제 배포 산출물에 포함되는 경로인지 먼저 확인해야 합니다. 예전에 제가 빌드 컨텍스트(build context)를 제대로 안 보고 디렉터리 제외했다가, 필요한 패키지 경로까지 날려서 결과가 이상하게 나온 적이 있었어요. 삽질 좀 했습니다 ㅎㅎ

CI 파이프라인에서 Trivy 캐시, 스캐너 범위, 스캔 경로를 어떻게 나누는지 설명하는 구성 이미지입니다.
5. 실전 구현 3: 서버 모드로 중복 작업을 줄입니다
이미지가 많고 팀이 여러 파이프라인에서 Trivy를 동시에 쓰는 환경이라면, server mode(서버 모드)도 검토할 만하더라고요. 이 방식은 공용 Trivy 서버가 DB와 캐시를 들고 있고, 클라이언트가 거기로 요청을 보내는 구조입니다. 제가 실제로 여러 서비스 이미지를 반복 검사하던 환경에서 이 구조를 써보니까, 매번 러너마다 준비 작업을 다시 하는 비용이 줄어서 운영이 한결 편해졌어요.
trivy server --listen 0.0.0.0:4954
trivy image --server http://trivy-server.internal:4954 my-image:latest
이 구조의 장점은 명확합니다.
- DB와 캐시를 중앙에서 관리 가능
- 여러 CI/CD 잡이 같은 준비 상태를 재활용
- 에페메럴 러너 환경에서도 일관된 속도 확보
다만 모든 환경에 정답은 아닙니다. 소규모 팀이나 저장소 수가 적은 경우에는 오히려 운영 포인트만 늘어날 수 있거든요. 그래서 저는 보통 아래 기준으로 판단합니다.
| 환경 | 추천 방식 | 이유 |
|---|---|---|
| 소규모 단일 저장소 | 로컬 캐시 중심 | 구성이 단순하고 관리가 쉽습니다 |
| 여러 서비스가 있는 CI/CD | 공용 캐시 + 잡 분리 | 중복 다운로드를 줄이기 좋습니다 |
| 대규모 멀티 프로젝트 | Trivy 서버 모드 | 중앙 캐시 재사용 효과가 큽니다 |
6. ⚠️ 실제로 자주 만나는 문제와 트러블슈팅
이 섹션은 정말 중요해요. 문서만 보면 다 쉬워 보이는데, 실제 운영에서는 예상 밖의 병목이 꼭 나옵니다. 제가 겪었던 것과 많이 상담받았던 케이스를 정리해보겠습니다.
6-1. 캐시를 붙였는데도 체감이 없다
대부분은 캐시 경로가 매 실행마다 달라지거나, 러너가 캐시 복원을 제대로 못 하고 있는 경우였어요. CI 로그에서 실제로 캐시 restore가 성공했는지 꼭 보셔야 합니다. 경로만 같다고 끝이 아니더라고요.
6-2. secret 스캔 때문에 예상보다 오래 걸린다
이건 자주 있습니다. secret 스캔은 용도가 분명하지만, 모든 PR 단계에서 항상 필요한 건 아닐 수 있어요. 빠른 피드백이 우선인 구간과 정밀 검사가 필요한 구간을 분리해보세요.
6-3. 같은 베이스 이미지를 계속 스캔한다
이 경우는 이미지 계층(layer) 구조를 먼저 보셔야 합니다. 베이스 이미지가 공통이라면 변경 없는 브랜치에서 풀스캔을 반복하는 구조가 맞는지 점검해보는 게 좋아요. 실제로 써보니까 애플리케이션 변경이 거의 없는데도 이미지만 다시 빌드해서 전체 스캔하는 경우가 많았거든요.
6-4. 네트워크가 느린 날만 유독 전체 시간이 튄다
DB 다운로드와 외부 레지스트리 접근 시간이 흔들리면 전체 결과도 흔들린답니다. 이럴 때는 사전 DB 준비, 사내 레지스트리 미러, 스캔 전용 실행 구간 분리가 도움이 돼요.
- 캐시가 복원되는지 로그로 확인
- 스캐너 범위를 목적별로 나눌 것
- 불필요한 디렉터리 제외는 실제 배포 경로 기준으로 검토
- 중앙 캐시가 필요할 정도인지 운영 복잡도와 함께 판단
7. 결과 검증: 빨라졌는지 어떻게 확인할까
최적화는 느낌으로 하면 안 돼요. “조금 빨라진 것 같아요”는 운영에서 별 의미가 없거든요. 최소한 아래 정도는 비교해보시는 걸 권합니다.
- DB 다운로드 포함/미포함 전체 소요 시간
- PR 스캔과 메인 브랜치 스캔의 평균 실행 시간
- 이미지 크기별 스캔 편차
- 동시 실행 시 대기 시간 증가 여부
예를 들어 간단하게는 CI 로그에서 전후 시간을 모아 비교할 수 있어요. 더 여유가 있으면 잡 실행 시간 추이를 대시보드로 모아보세요. 이거 진짜 편하더라고요. 어느 날 갑자기 느려졌을 때 원인 찾는 속도가 달라집니다.
time trivy image --cache-dir .trivycache my-image:latest
결과를 볼 때는 단순 평균보다 최악의 경우(worst case)도 같이 보셔야 합니다. 실무에서는 평소 2분이어도 가끔 9분 튀는 게 더 문제거든요. 특히 배포 직전 파이프라인에서 그러면 팀 전체가 멈춘 느낌이 납니다.

Trivy 최적화 적용 전후의 스캔 시간, 캐시 적중률, 병목 감소를 시각화한 결과 이미지입니다.
8. 정리: 상황별 추천 전략과 다음 단계
지금까지 내용을 정리하면, Trivy 성능 최적화는 거창한 튜닝보다 기본기에서 시작돼요. 캐시를 제대로 쓰고, 필요한 스캐너만 돌리고, 중복 작업을 줄이는 것. 이 세 가지만 해도 체감 차이가 꽤 큽니다. 제가 직접 해보니 특히 CI/CD에서 빌드 대기열이 긴 팀일수록 효과가 빨리 보였어요.
상황별로 간단히 추천하면 이렇습니다.
| 상황 | 우선 적용할 것 | 비고 |
|---|---|---|
| 러너가 매번 새로 생성됨 | 캐시 디렉터리 고정 + CI 캐시 복원 | 가장 먼저 볼 포인트입니다 |
| PR이 너무 느림 | severity, scanners 범위 축소 | 빠른 피드백용 정책 분리 |
| 서비스 수가 많음 | 공용 캐시 또는 서버 모드 | 중복 작업 절감 효과가 큽니다 |
| 노이즈가 많음 | ignore-unfixed와 정책 재정비 | 속도와 운영 피로를 함께 줄입니다 |
혹시 지금 Trivy를 돌리고 있는데 “느리긴 한데 어디서부터 손대야 할지 모르겠다” 싶으시면, 오늘 글 기준으로는 1) 캐시 확인, 2) 스캐너 범위 분리, 3) 중복 스캔 구조 점검 이 세 가지부터 해보시면 돼요. 이 순서가 실패 확률도 낮고, 결과 확인도 쉽습니다.
다음 글에서는 CI/CD 파이프라인에서 이미지 스캔 정책을 단계별로 분리하는 방법도 다뤄볼 예정입니다. 이전 글에서 다뤘던 레지스트리 구조 설계와 함께 보시면 훨씬 이해가 쉬우실 거예요.

Trivy 성능 최적화 핵심 포인트를 빠르게 복습할 수 있도록 정리한 요약 인포그래픽입니다.
9. 자주 묻는 질문
Q1. Trivy 성능 최적화는 캐시만 잘 써도 충분한가요?
아닙니다. 캐시는 시작점이에요. 대규모 환경에서는 스캔 범위 조정과 중복 실행 구조 개선까지 같이 봐야 합니다.
Q2. 모든 CI 단계에서 secret 스캔을 돌려야 할까요?
반드시 그럴 필요는 없어요. 보안 요구사항에 따라 다르지만, 빠른 피드백이 중요한 구간과 정밀 검사가 필요한 구간을 나누는 편이 현실적입니다.
Q3. 서버 모드는 언제 고려하면 좋을까요?
여러 프로젝트가 동일한 취약점 데이터와 캐시를 반복해서 쓰는 환경이라면 검토 가치가 크더라고요. 반대로 작은 팀이라면 운영 복잡도가 더 클 수도 있습니다.
결국 핵심은 하나입니다. 보안을 포기하지 않으면서도 배포 속도를 지키는 구조를 만드는 것. 이 균형을 맞추는 게 인프라 엔지니어 일의 재미이기도 하죠.
![[보안] Trivy 성능 최적화로 대규모 컨테이너 스캔 가속하기](https://blog.pswq.net/wp-content/uploads/2026/08/trivy-performance-optimization-container-scan-strategy-thumbnail.jpg)