클라우드 도커 스펙 - 100-hours-a-week/16-Hot6-wiki GitHub Wiki

Docker 기반 AI 생성 API 스펙 산정 계획서

테스트 설계

POST https://dev-backend.onthe-top.com/api/v1/ai-images
Content-Type: multipart/form-data
Authorization: Bearer <token>

요청 body:

{
  "prompt": "미니멀하고 화이톤의 셋업",
  "beforeImagePath": <파일>
}

K6 부하 스크립트:

import http from 'k6/http';
import { check } from 'k6';

export let options = {
  vus: 5,
  duration: '1s',
};

const image = open('./test.png', 'b');

export default function () {
  const formData = {
    prompt: '미니멀하고 화이톤의 셋업',
    beforeImagePath: http.file(image, 'test.png', 'image/png'),
  };
  const headers = {
    Authorization: 'Bearer <token>',
  };

  let res = http.post('https://dev-backend.onthe-top.com/api/v1/ai-images', formData, { headers });

  check(res, {
   '200 OK': (r) => r.status === 200,
  });
}

           

테스트 시나리오

목표

  • 다양한 동시 사용자 수 (VU)에 따른 Spring Boot + FastAPI 기반 AI 이미지 생성 API의 부하 응답 평가
  • 각 케이스에서 응답 시간, 실패율, CPU/MEM 사용률 수집
  • Docker 컨테이너 리소스 제한 (--cpus, --memory) 조정하며 적절한 스펙을 도출

⠀Scouter Java Agent 미사용(버전이슈) → 대체 전략

  • Scouter Host Agent + docker stats + k6 지표 조합으로 측정

접근 방식 - 리소스 기반 산정

1. “목표 기반 설계” (이상적인 방식)

  • N1명의 동시 사용자가 N2초 이내 응답을 받을 수 있어야 함 -> 그걸 만족하는 도커 스펙을 검색.
  • 이런 방식은 트래픽 예측 + SLA 기반으로 스펙을 결정
  • 보통 규모 있는 서비스실제 사용량이 확보된 상태에서 가능

⠀문제점: 초기에 트래픽이 없으면 "목표" 자체가 불확실

2. “리소스 기반 산정” (선택한 방식)

  • N1코어 / N2GB 컨테이너에서 VU N3명을 버틸 수 있어야함 → 이것을 baseline으로 삼아 산정.
  • 지금처럼 예산, 인프라, 실험 인원이 정해진 상황에서는 이 방식이 더 현실적
  • 일단 리소스를 고정한 상태에서 “얼마나 감당 가능한가”를 테스트함
  • 이후 결과를 기준으로 “이 스펙으로 최대 얼마까지 가능한지”를 추정
방식 설명 주로 쓰이는 상황
목표 기반 (Top-down) 목표 트래픽을 기준으로 스펙을 맞춤 실서비스, 예산 확보된 환경
리소스 기반 (Bottom-up) 정해진 스펙에서 감당 가능한 범위 측정 PoC, 초기 실험, 클라우드 견적 추정 등

계획 결론:

리소스 기반 추정으로, “1코어 / 1GB 스펙에서 최대 몇 명의 동시 접속자가 가능하고, 이때 성능은 어떤가”를 실측 → 이걸 기반으로 운영 스펙, Auto Scaling 기준, 예산 계획 등을 역산

현재 조건 요약:

  • 주요 부하 지점: /api/v1/ai-images (Spring Boot + FastAPI 연동)
  • Scouter Java Agent 사용 불가 → 대신 docker stats + 리눅스 모니터링 도구로 리소스 수집
  • 목표: 도커 CPU/메모리 스펙 산정

단계별 테스트 계획

1단계: 기준 컨테이너 스펙 정의

  • 테스트 대상 컨테이너 초기값:
### --cpus="1.0" --memory="1024m"
  • 이후 단계별로 리소스 제한을 증가시키며 부하에 따른 변화 관찰

2단계: 시나리오 유형별 테스트 정의

시나리오 설명 목적
S1 로그인/게시물 등 단순 API 백엔드 기본 부하 확인
S2 이미지 없이 prompt만 전송 AI 서버 FastAPI 처리만 측정
S3 이미지 포함 요청 (현재 코드) 전체 시스템 부하 측정 (실전 조건)
S4 1명이 반복 요청 반복 부하에서의 리소스 누수/누적 확인
실제 K6 코드는 S3에 해당 → 이걸 기준으로 부하 세기 조절

3단계: 부하 조건별 테스트 설계

Test ID VU (동시 접속자) Duration 설명
T1 10 30s 워밍업 / 기본 동작 확인
T2 50 30s 평균 트래픽 대응 테스트
T3 100 60s 피크 트래픽 조건
T4 200 60s 시스템 한계/병목 분석
각 T1~T4는 S3 시나리오로 반복 실행

4단계: 측정 항목 및 도구

측정 항목 도구 설명
평균 응답시간, 성공률 k6 summary + check() 부하에 따른 성능 변화
오류 비율, 코드 분포 K6 + 백엔드 로그 4xx/5xx 분포 분석
CPU/메모리 사용량 docker stats, top, htop 백엔드/AI 각각 측정
GC/내부 로깅 Spring Boot 로그 Java의 GC 병목 여부 등
Nginx 오류 nginx error.log FastAPI 앞단 Reverse Proxy 분석 시 사용

테스트 결과 및 추산

테스트 결과

테스트 VU Duration 평균 응답 시간 최대 응답 시간 CPU 사용률 메모리 사용률 평균 TPS 비고
T1 5 30s 316.42ms 703.94ms 99.9% 약 40% 30.1 CPU 100%, 과부하
T2 3 30s 93.07ms 360.07ms 99.6% 약 40% 30.3 거의 포화
T3 2 30s 58.72ms 140.62ms 91.7% 약 38% 30.2 안정적 기준선 후보

테스트 결과 요약

항목 결론
테스트 환경 VM: e2-medium (2 vCPU, 4GB RAM)
포화 지점 VU 3에서 CPU 99.6% → VM의 최대 성능 근접
안정적 한계 VU 2에서 응답 빠르고 CPU 91.7% → 안정선으로 적절
TPS 기준 약 30 TPS 가능 (AI 생성 API 기준)

최종 추산 방법 정리

"VU 수가 주어졌을 때, 그걸 감당할 수 있는 컨테이너 스펙 (vCPU, Memory)을 정확히 추산"

  • 2 vCPU → VU 2에서 CPU 91.7%, TPS 30 (안정적으로 감당) 단순 역산 (1 VU당 필요한 자원 추정)
  • vCPU ≒ 1 VU당 1 vCPU / 2 (즉, 0.5 vCPU)
  • Memory ≒ 약 750MB/VU (메모리 사용량은 거의 일정함) 
* 2 vCPU 머신에서 동시 사용자 2명(VU 2) 부하를 걸었을 때 CPU 사용률이 **91.7%**였고, TPS 30 정도로 안정적으로 처리됨.

vCPU ≒ 1 VU당 1 vCPU / 2 (즉, 0.5 vCPU) 2 vCPU 머신에서 2 VU를 처리했지만, 1 VU가 차지한 vCPU는 2 vCPU ÷ 2 VU = 1 vCPU per VU가 아니라, CPU 사용률이 91.7%였으므로 완전한 2 vCPU를 다 쓴 건 아니기 때문에 여유를 둬서 "1 VU ≒ -0.5 vCPU"로 잡음 즉, VU 1명을 감당하는 데 약 0.5 vCPU가 필요하다고 추정.

Memory ≒ 약 750MB/VU (메모리 사용량은 거의 일정함) 테스트 도중 메모리 사용량을 모니터링해보니, VU 수가 늘어나도 메모리는 거의 선형적으로 증가함. 즉, VU 1명당 약 750MB 정도 메모리를 쓰는 것으로 판단

  • 방법 1
총 메모리 = VU × 750MB

최소 스펙

항목 추정 값
vCPU 약 0.5 vCPU / 1 VU
Memory 약 750MB / 1 VU

ex)이걸 바탕으로 만약 VU 수가 10명이라면 최소 스펙은 → 5 vCPU, 7.5GB RAM 정도 필요하다고 추산

  • 방법 2
         ≈ 700MB + (VU × 250MB)
항목 추정 값
vCPU 약 0.5 vCPU / 1 VU
Memory 약 700MB + 250MB × VU

ex)VU 1명 → 0.5 vCPU, 700MB + 250MB = 950MB → 1GB ex)VU 3명 → 1.5 vCPU, 700MB + (3×250) = 1.45GB → 2GB 정도

           

최종 정리

VU(가상의 동시 사용자)별 도커 스펙 산정표

  • (VU당 메모리) 계산시
VU 수 vCPU 권장 스펙 Memory 권장 스펙 TPS 기대치 비고
1 0.5 vCPU 768MB ~15 TPS 최소 스펙, 단일 요청 대응 가능
2 1.0 vCPU 1.5GB ~30 TPS 가장 이상적인 안정 기준선
3 1.5 vCPU 2.0GB ~35 TPS 고부하 상황 대비
4 2.0 vCPU 2.5GB ~40 TPS 여유 있게 운영
5 2.5 vCPU 3.0GB ~45 TPS CPU 포화 위험성 고려 필요
6 이상 3.0+ vCPU 3.5GB+ 50+ TPS 수평 확장 고려 권장
  • (기본 메모리) + (VU당 메모리) 계산시
VU 수 vCPU 권장 스펙 Memory 권장 스펙 TPS 기대치 비고
1 0.5 vCPU 1.0GB ~15 TPS 기본 단위
2 1.0 vCPU 1.2GB ~30 TPS 안정 운영
3 1.5 vCPU 1.5~1.6GB ~35 TPS GC 여유 필요
4 2.0 vCPU 1.7~1.8GB ~40 TPS 여유 있는 운영
5 2.5 vCPU 2.0~2.1GB ~45 TPS 피크 부하
6 이상 3.0+ vCPU 2.3GB+ 50+ TPS scale-out 권장

서울 리전 기준 월간 비용 추정

Google Cloud 가격 계산기

머신 스펙 시간당 요금 (서울) 월 비용 (서울, 720시간 기준)
0.5 vCPU / 0.75GB $0.0138 $9.94
1 vCPU / 1.5GB $0.0276 $19.87
2 vCPU / 3GB $0.0552 $39.74

비용 대비 TPS 분석 (GCP 기준)

Google Cloud 가격 계산기

스펙 서울 시간당 비용 TPS TPS당 비용 (서울)
0.5 vCPU / 768MB $0.0138 ~15 $0.00092
1.0 vCPU / 1.5GB $0.0276 ~30 $0.00092
1.5 vCPU / 2.0GB $0.0414 ~35 $0.00118
2.0 vCPU / 2.5GB $0.0552 ~40 $0.00138

1 vCPU / 1.5GB가 가장 효율적 (TPS당 비용이 가장 낮고, 안정성도 우수)

상황별 스펙

  • (VU당 메모리) 계산시
상황 추천 도커 스펙 이유
일반 운영 (Stable) 1 vCPU / 1.5GB 비용 효율 + 안정성 균형
고성능 고객 대응용 2 vCPU / 2.5GB 요청량 많은 유저 대응
이벤트/버즈 대응 (단기) 3 vCPU / 3.5GB+ 단기간 과부하 견딤
장기 확장성 고려 VU 2 기준으로 수평 확장 컨테이너 다수 배포 (scale-out)
  • (기본 메모리) + (VU당 메모리) 계산시
상황 추천 도커 스펙 이유
일반 운영 (Stable) 1 vCPU / 1.2~1.5GB 비용 효율 + 안정성 균형
고성능 고객 대응용 2 vCPU / 1.8~2.5GB 요청량 많은 유저 대응
이벤트 대응 (단기) 3 vCPU / 2.5~3.5GB 피크 대응 여유
장기 확장 고려 VU 2 기준으로 수평 확장 컨테이너 다수로 scale-out
⚠️ **GitHub.com Fallback** ⚠️