벤치마크 테스트 & 리포팅 가이드
코드 변경이 성능에 미치는 영향을 정량적으로 측정하고, 이전 버전과 비교하여 성능 회귀를 방지하는 방법을 안내합니다.
📋 개요
Caffeine은 두 가지 벤치마크 도구를 제공합니다:
| 도구 | 목적 | 측정 대상 | 실행 시간 |
|---|---|---|---|
| BenchmarkDotNet | 마이크로벤치마크 | 함수 단위 실행 시간, 메모리 할당, GC 수집 | 3-10분 |
| BenchmarkRunner | 부하 테스트 | 시스템 전체 처리량(RPS), 단계별 확장성 | 1-30분 (설정에 따라) |
🎯 이 가이드에서 배울 것
- BenchmarkDotNet으로 코드 성능 측정하기
- Admin UI에서 결과 조회하기
- 이전 버전과 성능 비교하기
- 부하 테스트로 시스템 한계 확인하기
- 성능 리포트 읽는 법
Caffeine CLI 설치
cafe 명령어를 사용하려면 CLI를 먼저 설치하세요:
dotnet tool install -g NEXCODE.Caffeine.Cli
cafe --version
이미 설치된 경우 업데이트: dotnet tool update -g NEXCODE.Caffeine.Cli
🚀 Part 1: BenchmarkDotNet (마이크로벤치마크)
Step 1: 벤치마크 실행
Release 모드 필수
벤치마크는 반드시 Release 모드로 실행하세요. Debug 모드에서는 최적화가 비활성화되어 결과가 부정확합니다.
cafe benchmark run
실행하면 콘솔에 진행 상황이 표시됩니다:
// * Running: AlarmEvaluationBenchmark *
// * Results *
| Method | Mean | Error | StdDev | Allocated |
|--------------- |------------:|----------:|----------:|----------:|
| EvaluateSingle | 45.23 ns | 0.89 ns | 0.83 ns | 0 B |
| EvaluateBatch | 312.45 ns | 6.12 ns | 5.43 ns | 64 B |
Step 2: 벤치마크 카테고리
| 카테고리 | 측정 대상 | 핵심 지표 |
|---|---|---|
| AlarmEvaluation | 알람 평가 로직 | 단일/배치 처리 시간 |
| ProcessedValue | 태그 값 처리 | 값 생성 + 변환 시간 |
| IngestionMetrics | 데이터 수집 메트릭 | 메트릭 기록 오버헤드 |
| TagStore | 태그 저장소 읽기/쓰기 | 조회/갱신 레이턴시 |
| TagDispatch | 태그 디스패치 | 구독자 알림 시간 |
| Serialization | 직렬화/역직렬화 | JSON/Protobuf 변환 속도 |
| ObservablePipeline | Rx 파이프라인 | 스트림 처리 처리량 |
| Encryption | 암호화 | AES 암복호화 속도 |
Step 3: 결과 확인 (Admin UI)
- Admin이 실행 중인지 확인합니다 (
cafe setup status로 확인) - 브라우저에서 http://localhost:5233/benchmark/results 접속

다른 벤치마크 결과 보기
드롭다운에서 다른 실행을 선택하면 해당 벤치마크 결과로 전환됩니다:

결과 화면 구성:
- 상단: 벤치마크 실행 목록 (날짜, 시나리오 수, 총 시간)
- 중단: 개별 메서드 성능 테이블
- 하단: 카테고리별 평균 시간 차트
결과 테이블 읽는 법
| 열 | 의미 | 좋은 값 |
|---|---|---|
| Mean | 평균 실행 시간 | 낮을수록 좋음 |
| Error | 측정 오차 범위 | Mean의 5% 이내 |
| Allocated | 메모리 할당량 | 0 B가 이상적 |
| Gen0 | GC Generation 0 수집 횟수 | 0이 이상적 |
단위 읽기
- ns (나노초) = 0.000000001초 → 매우 빠름
- μs (마이크로초) = 0.000001초 → 빠름
- ms (밀리초) = 0.001초 → 보통
- s (초) → 느림, 최적화 필요
📊 Part 2: 성능 비교 분석
Step 1: Baseline 생성
코드 변경 전에 벤치마크를 실행하여 기준선을 만듭니다:
# 1. 현재 코드로 벤치마크 실행 (Baseline)
cafe benchmark run
Step 2: 코드 변경 후 재실행
# 2. 코드 수정 후 벤치마크 재실행 (Current)
cafe benchmark run
Step 3: 비교 페이지에서 분석
브라우저에서 http://localhost:5233/benchmark/compare 접속:
- Baseline 드롭다운에서 변경 전 실행 선택
- Current 드롭다운에서 변경 후 실행 선택
- 비교 버튼 클릭

비교 결과 판정 기준
| 상태 | 기호 | 기준 | 의미 |
|---|---|---|---|
| 개선 | ▼ | Change < -5% | 5% 이상 빨라짐 |
| 유지 | — | -5% ≤ Change ≤ 10% | 의미 있는 변화 없음 |
| 회귀 | ▲ | Change > 10% | 10% 이상 느려짐, 확인 필요 |
회귀 발견 시
Change가 10%를 초과하면 성능 회귀입니다:
- 해당 메서드의 코드 변경 내역 확인
- 불필요한 메모리 할당이 추가되었는지 확인
- 알고리즘 복잡도가 증가했는지 확인
- 수정 후 벤치마크 재실행하여 검증
⚡ Part 3: 부하 테스트 (BenchmarkRunner)
시스템 전체의 처리량 한계를 확인하는 방법입니다. RPS를 단계적으로 증가시키며 언제 병목이 발생하는지 확인합니다.
워크플로우
Admin UI에서 부하 테스트 실행
- http://localhost:5233/simulation 접속
- 아래 파라미터 설정:
| 파라미터 | 초보자 권장 | 스트레스 테스트 |
|---|---|---|
| 초기 RPS | 1,000 | 5,000 |
| 최대 RPS | 5,000 | 50,000 |
| 단계 증가 | 1,000 | 5,000 |
| 단계 지속 시간 | 10초 | 30초 |
| 프로세스 수 | 1 | 4 |
- 시작 클릭
결과 해석
부하 테스트가 완료되면 각 단계의 실제 RPS를 확인합니다:
Step 1: Target 1,000 RPS → Actual 998 RPS ✅ 정상
Step 2: Target 2,000 RPS → Actual 1,985 RPS ✅ 정상
Step 3: Target 3,000 RPS → Actual 2,870 RPS ⚠️ 약간 부족 (96%)
Step 4: Target 4,000 RPS → Actual 3,200 RPS ❌ 병목 (80%)
Step 5: Target 5,000 RPS → Actual 3,150 RPS ❌ 포화 (63%)
해석: 이 시스템은 약 3,000 RPS에서 병목이 시작됩니다. 3,000 RPS 이상의 처리량이 필요하면 스케일 아웃(프로세스 증가) 또는 인프라 튜닝이 필요합니다.
🔧 Part 4: 벤치마크 결과 관리
결과 파일 위치
벤치마크 결과는 JSON 파일로 자동 저장됩니다:
benchmarks/results/
├── a1b2c3d4_2026-03-23_143022.json
├── e5f6g7h8_2026-03-22_091500.json
└── ...
결과 파일 구조
{
"id": "a1b2c3d4",
"timestamp": "2026-03-23T14:30:22Z",
"environment": {
"os": "macOS 15.3",
"cpu": "Apple M2 Pro",
"dotnetVersion": "10.0.0",
"machineName": "dev-mac"
},
"results": [
{
"category": "AlarmEvaluation",
"method": "EvaluateSingle",
"meanNs": 45.23,
"errorNs": 0.89,
"allocatedBytes": 0,
"gen0Collections": 0
}
]
}
CLI로 결과 관리
# 모든 결과 목록 조회
curl http://localhost:5233/api/benchmark/results
# 특정 결과 상세 조회
curl http://localhost:5233/api/benchmark/results/{id}
# 두 결과 비교
curl "http://localhost:5233/api/benchmark/compare?baseline={id1}¤t={id2}"
# 오래된 결과 삭제
curl -X DELETE http://localhost:5233/api/benchmark/results/{id}
🧪 Part 5: 일상적인 성능 관리 워크플로우
PR 전 성능 체크 (권장)
- 코드 변경 전:
cafe benchmark run - 코드 변경 후: 동일 명령 재실행
- Admin UI에서 비교: http://localhost:5233/benchmark/compare
- 회귀 없으면 PR 생성, 있으면 수정 후 재측정
성능 기준 (참고)
| 카테고리 | 기대 성능 | 경고 기준 |
|---|---|---|
| 알람 평가 (단일) | < 100ns | > 500ns |
| 태그 조회 | < 50ns | > 200ns |
| 직렬화 (JSON) | < 1μs | > 10μs |
| Rx 파이프라인 | < 500ns | > 2μs |
| 메모리 할당 | 0 B 목표 | > 1KB |
📚 참고 자료
- 시뮬레이션 환경 구성 가이드 — 시뮬레이터 설정 방법
- BenchmarkDotNet 공식 문서 — 벤치마크 프레임워크
- 배포 가이드 — Docker 환경 구성