📌 관련 Epic
Part of #204
📋 기능 설명
Lambda 환경에서 **SOPT 홈페이지의 실제 트래픽 패턴(간헐적 접속)**을 시뮬레이션하여,
Caffeine 로컬 캐시의 효과가 사실상 사라지는 것을 정량적으로 증명한다.
측정 환경
- 인프라: AWS Lambda + API Gateway (
https://org-api-dev.sopt.org)
- 캐시: Caffeine (In-Memory) — EC2와 동일 코드
핵심 가설
Lambda 인스턴스는 일정 시간(약 5~15분) 비활성 상태가 지속되면 소멸된다.
SOPT 홈페이지는 대부분의 시간에 트래픽이 없고, 간헐적으로 접속이 발생하는 패턴이다.
따라서 사용자가 접속할 때마다 새 인스턴스가 생성되어 캐시가 비어있고,
매번 Playground API를 다시 호출해야 한다.
즉, 연속 트래픽에서는 캐시가 작동하지만, 실제 사용 패턴에서는 캐시 효과가 거의 없다.
EC2와의 근본적 차이
|
EC2 |
Lambda |
| 인스턴스 수명 |
서버가 켜져 있는 동안 영구 |
비활성 5~15분 후 소멸 |
| 캐시 수명 |
프로세스 재시작 전까지 유지 (TTL 24시간) |
인스턴스와 함께 소멸 |
| 간헐적 트래픽 |
캐시 그대로 유지 → 히트 |
인스턴스 소멸 → 새 인스턴스 → 미스 |
🎯 왜 필요한가요?
이슈 #4에서 연속 부하 테스트로 측정한 Lambda 결과(P50 75ms, 안정적)는
Lambda가 잘 작동하는 최상의 시나리오일 뿐이다.
실제 SOPT 홈페이지 트래픽 패턴에서 Lambda + 로컬 캐시가 효과를 잃는다는 걸 증명해야
Redis 외부 캐시 도입의 필요성이 설득력을 갖는다.
💡 제안하는 해결 방법
1. 간헐적 트래픽 시뮬레이션 스크립트
일정 간격으로 API를 호출하여, 각 호출이 Cold Start인지 Warm인지를 기록한다.
파일: k6/load-test-interval.js
import http from 'k6/http';
import { check, sleep } from 'k6';
import { Trend, Counter } from 'k6/metrics';
// 커스텀 메트릭
const responseLatency = new Trend('interval_latency', true);
const coldCount = new Counter('cold_count'); // 응답 > 임계값 → 캐시 미스로 추정
const warmCount = new Counter('warm_count'); // 응답 < 임계값 → 캐시 히트로 추정
// Cold/Warm 판별 임계값 (ms)
// EC2 캐시 히트 시 P95가 8.46ms, 캐시 미스 시 P50이 2.65s
// Lambda에서 캐시 히트 시 ~80ms, 미스 시 훨씬 느릴 것으로 예상
const COLD_THRESHOLD_MS = 500;
export const options = {
scenarios: {
interval_test: {
executor: 'per-vu-iterations',
vus: 1,
iterations: 10, // 10회 반복
},
},
};
const BASE_URL = __ENV.BASE_URL || 'https://org-api-dev.sopt.org';
const CTX_PATH = __ENV.CTX_PATH !== undefined ? __ENV.CTX_PATH : '/v2';
const PROJECTS_URL = `${BASE_URL}${CTX_PATH}/projects`;
// 호출 간격 (초) — Lambda 인스턴스 소멸을 유도
// 5분 = 300초, 10분 = 600초, 15분 = 900초
const INTERVAL_SECONDS = parseInt(__ENV.INTERVAL || '600');
export function setup() {
console.log('========================================');
console.log('Interval Traffic Simulation');
console.log(`Target URL: ${PROJECTS_URL}`);
console.log(`Interval: ${INTERVAL_SECONDS}s (${INTERVAL_SECONDS / 60}min)`);
console.log(`Iterations: ${options.scenarios.interval_test.iterations}`);
console.log(`Cold threshold: ${COLD_THRESHOLD_MS}ms`);
console.log('========================================');
return { projectsUrl: PROJECTS_URL };
}
export default function (data) {
const iteration = __ITER;
// API 호출
const res = http.get(data.projectsUrl, {
timeout: '30s',
});
check(res, {
'status is 200': (r) => r.status === 200,
});
const duration = res.timings.duration;
responseLatency.add(duration);
// Cold/Warm 판별
const isCold = duration > COLD_THRESHOLD_MS;
if (isCold) {
coldCount.add(1);
} else {
warmCount.add(1);
}
const label = isCold ? '🥶 COLD (cache miss)' : '🔥 WARM (cache hit)';
console.log(
`[${iteration + 1}/10] ${label} — ${duration.toFixed(0)}ms (status: ${res.status})`
);
// 마지막 반복이 아니면 간격 대기
if (iteration < options.scenarios.interval_test.iterations - 1) {
console.log(`⏳ Waiting ${INTERVAL_SECONDS}s for Lambda instance to cool down...`);
sleep(INTERVAL_SECONDS);
}
}
export function teardown(data) {
console.log('========================================');
console.log('Interval test completed.');
console.log(`Target: ${data.projectsUrl}`);
console.log('========================================');
}
2. 실행 방법
# 10분 간격, 10회 반복 (총 약 90분 소요)
k6 run \
--env BASE_URL=https://org-api-dev.sopt.org \
--env CTX_PATH=/v2 \
--env INTERVAL=600 \
k6/load-test-interval.js
# 5분 간격으로 더 빠르게 테스트 (총 약 45분 소요)
k6 run \
--env BASE_URL=https://org-api-dev.sopt.org \
--env CTX_PATH=/v2 \
--env INTERVAL=300 \
k6/load-test-interval.js
3. 예상 결과
[1/10] 🥶 COLD (cache miss) — 3200ms (status: 200) ← 새 인스턴스, 캐시 없음
⏳ Waiting 600s for Lambda instance to cool down...
[2/10] 🥶 COLD (cache miss) — 2800ms (status: 200) ← 인스턴스 소멸 후 재생성
⏳ Waiting 600s for Lambda instance to cool down...
[3/10] 🥶 COLD (cache miss) — 3100ms (status: 200) ← 매번 반복
...
[10/10] 🥶 COLD (cache miss) — 2900ms (status: 200)
10회 중 대부분이 COLD로 찍히면 → 간헐적 트래픽에서 캐시 히트율 ≈ 0% 증명
4. EC2 대조군 (같은 스크립트로 EC2 테스트)
# EC2에서 동일한 간격 테스트
k6 run \
--env BASE_URL=http://localhost:8080 \
--env CTX_PATH=/v2 \
--env INTERVAL=600 \
k6/load-test-interval.js
EC2에서는 10회 모두 WARM으로 찍힐 것 → 동일 조건에서 캐시 효과의 차이를 명확히 대비
5. 결과 기록
## 시나리오 ④ 측정 결과 (Lambda, Caffeine 로컬 캐시 — 간헐적 트래픽)
### 테스트 조건
- 호출 간격: 10분 (600초)
- 반복 횟수: 10회
- Cold 판별 임계값: 500ms
### 호출별 결과
| # | 응답시간 | 판별 | 비고 |
|---|---|---|---|
| 1 | ___ms | COLD / WARM | |
| 2 | ___ms | COLD / WARM | |
| ... | | | |
| 10 | ___ms | COLD / WARM | |
### 요약
- Cold 횟수: ___/10 (___%)
- Warm 횟수: ___/10 (___%)
- 평균 응답시간: ___ms
### ② EC2 Caffeine 대비 비교 (핵심!)
| 지표 | ② EC2 + Caffeine (간헐적) | ④ Lambda + Caffeine (간헐적) |
|---|---|---|
| Cold 비율 | 0/10 (0%) | ___/10 (___%) |
| 평균 응답시간 | ~4ms (캐시 히트) | ___ms |
| 캐시 실효성 | ✅ 트래픽 무관 유지 | ❌ 간헐적 트래픽에서 무효화 |
6. 보충: 연속 트래픽 측정 결과 (이미 완료)
이슈 코멘트에 아래도 함께 기록하여, "연속 vs 간헐적" 두 패턴의 차이를 보여준다:
### 참고: 연속 트래픽에서의 Lambda 결과 (초당 30 요청, 2분)
| 지표 | 값 |
|---|---|
| P50 | 75.65ms |
| P95 | 83.18ms |
| RPS | 28.3 |
→ 연속 트래픽에서는 Lambda도 캐시가 잘 작동함
→ 하지만 SOPT 홈페이지의 실제 패턴은 간헐적 트래픽이므로, 이 결과는 실사용과 괴리가 있음
✅ 완료 조건 (Definition of Done)
🔗 참고 자료
💬 추가 논의사항
- Lambda 인스턴스 소멸 시간은 AWS가 내부적으로 관리하므로 정확한 시간을 보장할 수 없음. 5분/10분/15분 간격으로 각각 테스트하여 소멸 임계점을 파악하면 더 좋음
- CloudWatch의
ConcurrentExecutions 메트릭으로 인스턴스 생성/소멸 패턴도 확인 가능
- Cold 판별 임계값(500ms)은 실제 테스트 후 조정 가능 — EC2 캐시 미스(2.65s)와 Lambda 캐시 히트(~80ms) 사이 적절한 값으로 설정
- SOPT 홈페이지의 실제 트래픽 패턴(Google Analytics 등)을 함께 제시하면 포트폴리오 설득력이 더 높아짐
📌 관련 Epic
Part of #204
📋 기능 설명
Lambda 환경에서 **SOPT 홈페이지의 실제 트래픽 패턴(간헐적 접속)**을 시뮬레이션하여,
Caffeine 로컬 캐시의 효과가 사실상 사라지는 것을 정량적으로 증명한다.
측정 환경
https://org-api-dev.sopt.org)핵심 가설
EC2와의 근본적 차이
🎯 왜 필요한가요?
이슈 #4에서 연속 부하 테스트로 측정한 Lambda 결과(P50 75ms, 안정적)는
Lambda가 잘 작동하는 최상의 시나리오일 뿐이다.
실제 SOPT 홈페이지 트래픽 패턴에서 Lambda + 로컬 캐시가 효과를 잃는다는 걸 증명해야
Redis 외부 캐시 도입의 필요성이 설득력을 갖는다.
💡 제안하는 해결 방법
1. 간헐적 트래픽 시뮬레이션 스크립트
일정 간격으로 API를 호출하여, 각 호출이 Cold Start인지 Warm인지를 기록한다.
파일:
k6/load-test-interval.js2. 실행 방법
3. 예상 결과
4. EC2 대조군 (같은 스크립트로 EC2 테스트)
# EC2에서 동일한 간격 테스트 k6 run \ --env BASE_URL=http://localhost:8080 \ --env CTX_PATH=/v2 \ --env INTERVAL=600 \ k6/load-test-interval.jsEC2에서는 10회 모두 WARM으로 찍힐 것 → 동일 조건에서 캐시 효과의 차이를 명확히 대비
5. 결과 기록
6. 보충: 연속 트래픽 측정 결과 (이미 완료)
이슈 코멘트에 아래도 함께 기록하여, "연속 vs 간헐적" 두 패턴의 차이를 보여준다:
✅ 완료 조건 (Definition of Done)
k6/load-test-interval.js스크립트 작성 완료🔗 참고 자료
https://org-api-dev.sopt.org💬 추가 논의사항
ConcurrentExecutions메트릭으로 인스턴스 생성/소멸 패턴도 확인 가능