클라우드 과부하 - 100-hours-a-week/16-Hot6-wiki GitHub Wiki

특가 출시 기준 부하 테스트 시나리오

1. 목적

  • Spring Boot 앱을 Docker 컨테이너에 배포할 때, 실제 예상 부하를 기준으로 --cpus, --memory 값을 최적화합니다.
  • 자원 낭비는 줄이고, 서비스 장애 없이 동시접속을 견디도록 구성합니다.
  • 이후 Blue-Green 배포 및 GitHub Actions CD 파이프라인과 통합 가능하게 합니다.

2. 대상 앱 정보

  • 프레임워크: Spring Boot
  • 실행 환경: Docker container
  • 엔드포인트 예시:
    • GET backend.onthe-top.com/api/~
    • POST backend.onthe-top.com/api/~

3. 테스트 시나리오 구성 (특가 이벤트 기준)

시나리오 가정

  • 오전 10시 특가 이벤트 오픈
  • 동시접속자: 최대 1,000명
  • 사용자당 평균 3~5 API 요청
  • 트래픽은 오픈 직후 3분간 집중됨

⠀요청량 예측 (RPS 기준) ——> 향후 측정하고 싶은 엔드포인트에 맞게 변경.

API RPS 비고
GET backend.onthe-top.com/api/~ 1000
GET backend.onthe-top.com/api/~{id} 600
POST backend.onthe-top.com/api/~/ 300

4. 무제한 컨테이너로 먼저 실행

docker run -d --name springapp-unlimited -p 8080:8080 springapp:latest
  • Docker에 리소스 제한 없이 먼저 실행합니다.

5-1 부하테스트 도구 선택

wrk vs k6 비교 요약

항목 wrk k6
언어 기반 C (고성능) JavaScript (테스트 시나리오 스크립트 기반)
특징 - 초당 수천~수만 RPS 가능- 매우 빠름 - 복잡한 시나리오 구성 가능- 사용자 흐름 표현
사용 목적 단순하고 빠른 부하 테스트 (GET/POST 반복 등) 실제 사용자 행동 기반 시나리오 시뮬레이션
사용 방식 커맨드라인에서 직접 실행 JavaScript 스크립트 작성 후 실행
UI / 대시보드 없음 (CLI 출력만) 기본 CLI + Grafana 연동 가능
Docker 적합성 아주 좋음 (경량, CLI 기반) 좋음 (컨테이너화 가능 + CI/CD 통합 유리)
학습 난이도 매우 쉬움 약간 학습 필요 (JS 문법, 구조 이해)
라이선스 오픈소스 (MIT) 오픈소스 (AGPLv3), Cloud 버전은 유료 옵션 있음

사용 상황 정리

상황 추천 도구
초당 수천 건 이상의 GET 요청 테스트 wrk
"로그인 → 상품 조회 → 구매" 시나리오 테스트 k6
CI/CD 파이프라인에 부하 테스트 포함시키기 k6
리소스 소모 적은 빠른 부하 확인 wrk

사용 예시

wrk

wrk -t12 -c1000 -d30s backend.onthe-top.com:8080/api/~
  • 12개 스레드, 1000개 연결로 30초간 테스트합니다.

k6

# script.js
import http from 'k6/http';

export default function () {
  http.get('backend.onthe-top.com:8080/api');
}
k6 run --vus 500 --duration 1m script.js
  • 500명의 가상 사용자가 1분간 시뮬레이션합니다.

결론

  • 빠르고 단순한 테스트 → wrk
  • 사용자 시나리오 기반 정밀 테스트 + CI/CD 통합 → k6

둘 다 사용하는 게 이상적이지만, wrk은 스펙 산정용이지만 k6은 사용자 시나리오 검증 및 자동화 기반용으로 사용하기 때문에 실제 유저 행동 흐름을 반영한 정밀 테스트 + 확장성 + 자동화에 유리함으로, 비중을 높게 가져가는게 좋다고 생각했습ㄴ디ㅏ. 비중은 k6 (70%) + wrk 보조(30%).



5-2. 부하 테스트 도구 실행

현재 구조에서 부하 테스트는 프론트가 아닌 "백엔드 내부 네트워크 또는 내부 서버"에서 직접 실행해야 합니다. 부하 테스트는 백엔드에 직접 요청을 많이 보내는 것이기 때문에, React/S3를 거치면 오히려 부하가 분산되고 테스트 목적과 맞지 않습니다. 게다가 S3 정적 사이트는 부하를 만들 수 없고, 브라우저는 대량 요청이 불가합니다.

올바른 테스트 위치 - (백엔드가 실행되는 서버 안)

Wrk 사용 (고성능 GET 요청)

wrk -t12 -c1000 -d180s backend.onthe-top.com:8080/api/~

k6 예시 시나리오 기반으로

 // script.js
 import http from 'k6/http';
 import { sleep } from 'k6';

 export let options = {
   stages: [
     { duration: '30s', target: 500 },
     { duration: '30s', target: 1000 },
    { duration: '1m', target: 2000 },
    { duration: '1m', target: 500 },
   ],
 };

 export default function () {
   http.get('http://localhost:8080/엔드포인트');
   sleep(1);
 }
k6 run script.js

6. 리소스 사용량 측정

docker stats springapp-unlimited

또는:

  • htop 또는 top
  • Prometheus + Grafana
  • APM 도구 (Elastic APM)

⠀기록 예시:

자원 최대 사용량
CPU 1.9 vCPU
메모리 1.6 GB
평균 응답시간 250ms
오류율 0.5%

7. Docker 제한 스펙 계산

→ JVM이 GC로 메모리를 많이 쓰기 때문에 메모리는 여유 있게, CPU는 측정값 + 20% 정도

docker run -d --name springapp-limited \
   --cpus="2" \
   --memory="2g" \
   -p 8081:8080 \
   springapp:latest
  • 포트 8081로 제한된 컨테이너 실행 (Blue-Green 구조 가능)

8. 다시 동일 시나리오로 테스트

http.get(“backend.onthe-top.com/api/엔드포인트”);

→ 성능이 여전히 양호한지 확인

지표 무제한 컨테이너 제한 컨테이너 비고
평균 응답시간 250ms 270ms OK (소폭 증가)
오류율 0.5% 0.5% OK
CPU 1.9 vCPU 1.95 vCPU OK
메모리 1.6 GB 1.9 GB OK

9. 스펙 확정 및 반영

  • 확정된 스펙 → Dockerfile / docker-compose / Helm chart 등에 반영합니다.
  • 예:
 docker-compose.yml 일부
services:
  app:
    image: springapp:latest
    deploy:
      resources:
        limits:
          cpus: "2.0"
          memory: "2g"

10. Blue-Green 배포 활용

  • 기존 컨테이너(Blue: 8080) → 새 버전 컨테이너(Green: 8081)
  • 동일 부하 시나리오로 성능을 비교합니다.
  • 문제가 없으면 Green을 Live로 전환합니다.

Blue-Green 배포에서 포트 기반 컨테이너 전환 설명

  • Blue: 현재 운영 중인 안정된 버전 (예: 포트 8080)
  • Green: 새로 배포한 테스트용 버전 (예: 포트 8081)
  • 두 버전을 동시에 실행하고,
  • 트래픽만 전환하여 배포/롤백을 빠르게 수행

동작 방식

  • 테스트 완료 후 문제가 없으면:
    • 트래픽을 8081로 전환 → Green이 운영 버전이 됨
  • 문제가 생기면:
    • 8081 컨테이너만 종료 → Blue 그대로 유지

목적

  • 무중단 배포 가능
  • 실시간 버전 비교 / 테스트
  • 즉시 롤백 가능 (컨테이너만 내리면 끝)

실제 Docker 명령어 예시

# 운영 버전 (Blue)

docker run -d --name springapp-v1 -p 8080:8080 springapp:1.0

# 새 버전 (Green)

docker run -d --name springapp-v2 -p 8081:8080 springapp:2.0

트래픽 전환 방법

  • 수동 전환:
    • Nginx 설정에서 proxy_pass 대상 포트만 8080 → 8081로 변경
  • 자동화 전환:
    • Load Balancer나 GitHub Actions, ArgoCD 등을 통해 자동 스위치

11-1. APM 도구 도입 이유

APM이 필요한 이유

“특가 출시 상황”을 가정해 부하 테스트 중 /api의 엔드포인트에 수백~수천 RPS가 요청됩니다. Docker 리소스 스펙을 정하기 위해 병목 지점, 과부하 구간 분석이 필요합니다.

일반 부하 테스트 도구 APM 도구
응답시간, 실패율, CPU/Mem만 보여줌 왜 느려졌는지, 어디서 느려졌는지까지 보여줌

wrk와 apm 비교

wrk 결과:

  • /purchase 응답시간이 600ms → 1200ms로 증가함
  • CPU는 70%, 메모리는 여유 있음

⠀왜 느려졌는지 wrk만으론 알 수 없습니다.

APM을 보면:

  • /purchase 트랜잭션에서:
    • DB insert에 800ms 소요됨
    • Redis Cache miss 발생
    • 특정 메서드에서 N+1 쿼리 발생
    • GC가 빈번하게 발생함

병목 원인을 코드/쿼리/GC 레벨에서 정확히 확인할 수 있습니다.

목적 설명
병목 위치 파악 컨트롤러? 서비스? 쿼리? GC? 어디에서 지연이 생기는지 확인
부하 분산 설계 기반 확보 특정 API나 쿼리에 집중되는 트래픽 분석 가능
Docker 스펙 최적화 보조 CPU 사용이 높은 이유 → GC 때문인지? 코어 부족인지?
장애 시 빠른 원인 추적 응답 지연, 500 오류 발생 시 빠르게 구간 파악
Blue/Green 비교 v1 vs v2 트랜잭션 구조 차이 시각화 가능

11-2. APM 도구 선정.

APM 도구 목록

도구 유형 Spring Boot 지원 Docker 친화성 SaaS 여부
Elastic APM 오픈소스 강력 (공식 지원) 매우 좋음 자체 운영
Datadog APM SaaS 자동 계측 가능 좋음 구독형
New Relic SaaS 좋음 좋음 구독형
Sentry (Perf) SaaS/오픈소스 성능 계측 한정 가볍게 가능 (프리 티어 있음)

세부 비교

항목 Elastic APM Datadog APM New Relic Sentry Performance
Spring Boot 연동 매우 쉬움 (apm-agent-attach) 아주 쉬움 (에이전트 자동설정) 쉬움 오류 추적은 뛰어남, 성능은 한정적
대시보드 Kibana로 자유롭게 시각화 매우 직관적 (UI 우수) 보기 편함 기본적인 퍼포먼스 UI
분석 수준 트랜잭션/쿼리/GC까지 가능 전체 스택 추적, 로그/메트릭 통합 전체 분산 트레이스 경량 추적에 적합
Docker 연동 에이전트 + 호스트 내 서버 Agent 컨테이너 있음 에이전트 설치 SDK 기반
보안 격리 내부망 구축 가능 SaaS 전송 (VPC 피어링 가능) SaaS 전송 SaaS 전송
비용 무료 (자체 운영시) 유료 (프리 티어 제한적) 유료 (가격 비슷) 무료 플랜 있음
CD 통합 (GitHub Actions 등) 가능 가능 (태깅/배포 추적 자동) 가능 가능 (릴리즈 추적 위주)

현재 조건에 가장 적합한 도구 : Elastic APM

선정 이유:

  • Spring Boot + Docker 조합에서 가장 강력한 오픈소스 APM입니다.
  • 자체 서버(Docker 또는 EC2)에 APM 서버 + Kibana 올려서 내부망만으로 구성이 가능합니다.
  • GC, SQL 쿼리, HTTP 응답, Exception 모두 추적할 수 있습니다.
  • 자체 구축임으로 비용이 없습니다.
  • 이후 GitHub Actions 배포 시 릴리즈 추적이 가능합니다.

11-2. APM 도구 추가비교

상황 맞춤형 비교표

항목 Scouter Elastic APM
목적 빠른 성능 확인, 병목 추적 정교한 모니터링, 분석, 시각화
설치 난이도 매우 쉬움 (agent 붙이기만 하면 됨) APM Server + Kibana 구성 필요
계측 범위 JVM 전용 (메서드, SQL, GC 등) JVM 포함, 다중 언어 + 쿼리 + 에러 추적
대시보드/시각화 기본 Web UI 제공 Kibana 기반 고급 시각화 지원
Docker 친화성 Docker로 구성 가능, 약간의 설정 필요 Docker-Compose로 공식 구성 가능
내부망 설치 가능 (온프레미스 100%) 가능 (Elastic Stack 자체 호스팅 시)
커스터마이징 낮음 (정해진 UI) 높음 (Kibana 시각화 자유로움)
분석 깊이 가볍고 빠르지만 분석은 얕음 요청 트레이스, DB 쿼리, 에러 등 상세 분석
비용 무료 무료 (자체 운영시)
상황 추천 APM 이유
빠르게 설치하고 성능 보기, JVM 앱만 있음 Scouter 가볍고 쉽고 빠름. 부하 테스트에 적합
장기적으로 운영/분석/확장까지 고려 Elastic APM 시각화, 대시보드, SQL/GC/분산 추적까지 가능

단기 성능 확인 / 테스트 위주Scouter 운영 환경 전반 / CI-CD 통합 / 시각화 기반 분석까지 고려하면 Elastic APM

Scouter가 더 적합한 경우

당장 Docker 환경에서 부하 테스트 결과를 빠르게 확인하고, 팀에서 JVM(Spring Boot) 앱만 운영하고, ELK 구성 없이도 APM 기능이 필요한 경우에 적합합니다.

Elastic APM이 더 적합한 경우

운영 환경까지 포함해서 정식 도입할 APM을 고민 중이고, Prometheus, Grafana, Kibana 같은 시각화/분석 통합을 고려하고 있고, SQL 쿼리/GC/에러/배포 추적까지 한 화면에서 보고 싶고, 향후 Python, Node.js, 또는 프론트엔드까지도 같이 계측하고 싶은 경우에 더 적합합니다.

최종 판단

목적 추천
부하 테스트와 성능 확인 (단기) Scouter
운영 환경 통합/지속 분석 (장기) Elastic APM

Elastic APM만 써도 사실 충분하긴 하만 Scouter부터 빠르게 써보고, 나중에 Elastic APM으로 확장하는 전략도 좋다고 생각합니다.