COST DECISION REPORT FINAL tokki · 게임 이벤트 로그레이크

로그레이크 비용 결정 — 실측 기반 재산정

기존 볼륨 앵커가 실측과 어긋나 예산을 다시 세웠다. 결론부터: 확정 설정으로 활성 1M DAU가 월 $488 — 순진 구현 대비 −93%, 원 예산 $1,350의 36%다.

§0 결론 · §1 비용 계산기 · §2 근거(실측 대사) · §3 확정 파라미터 · §4 절감 레버와 리스크 · §5 아키텍처 · §6 부록

§0 결론

무위험 설정 2개로 예산 성립
활성 1M DAU · 월 비용
$488
원 예산 $1,350의 36% · L1 on + 묶음 n=30
순진 구현 대비
−93%
$7,061 → $488
SQS 비중
17%
묶음 전 86% · 이제 Lambda가 최대 항목

확정 설정값

항목성격
볼륨 기준선명령어 실행 수플랫폼 원시 발화 아님 — 비명령 ~45% 제외 (D11)
콜당 레이크 이벤트 배수3확정
L1 DAU dedupon무위험 — 볼륨 −33%, 지표 정합성은 오히려 개선 (D7)
game_event_bundle_max (n)30수익 체감 지점 — 메시지 24KB(한도의 2.3%) (D10)
game_event_bundle_flush_ms200유일한 리스크 노브 — 유실 창 = 이 값. 인스턴스당 처리율 실측 후 조정(V-3)
평균 줄 크기≤1KB (목표 0.5KB)소급 불가 구현 전 확정 (D6)
레이크 raw 보존7일 (3~30 조정 가능)저장비 저렴 — 3→30일 폭 월 +$52 (D5)
ev / 활성DAU587L1 적용 기준 (D9)
Lambda 배치non-VPC데이터 전송 $0 · NAT(월 ~$87) 회피 — 근거는 §6

조치

지금 적용
  • L1 dedup 플래그 플립 (FR-4.1 Phase 3 우선순위 상향)
  • 묶음 n=30 · flush_ms=200
  • 와이어 포맷 events: [] 확정 — 소급 불가
  • 요청 합산 바이트 가드 (≤1,000,000 B)
조건부 유보
  • flush_ms 조정 — 인스턴스당 콜 처리율 실측 후 확정(V-3). 유실 창이 곧 이 값
  • 0.5KB 슬리밍 — $488→$354이나 소급 불가
하지 않음
  • 보존일 단축 — 절감이 미미(3일로도 −$9)한데 디버깅·재집계 창만 잃는다. 오히려 여유가 있으면 늘린다
  • 강화 이벤트 축약 — 절감 최대지만 지표 해상도 영구 상실. 최후 수단

표기 — 본 문서의 "발화"는 명령어 실행(게임 명령 호출)을 가리킨다. 플랫폼 원시 발화량(비명령 포함, ~1.8배)과 구분한다.

§1 비용 계산기

결론 검증 — 파라미터를 직접 조정

기본값은 §0 확정 설정(활성 1M DAU · 배수 3 · L1 on · n=30)이며 §0의 $488을 재현한다. 슬라이더·숫자입력·프리셋으로 각 파라미터의 민감도를 직접 확인할 수 있다.

로그 스케일 1천 ~ 1천만 · 아래에 직접 입력 가능
실측 15~25% — 고부하일 약 23% 가정 유효
구조 모델 15실측 평균 378 · 피크일 293 · 최대 568 (§0-C)
3 확정 — 실 구성 기준. v1.3의 "5×7=35" 서술은 오류로 확인됨
켜면 daily_active_user가 콜당 1회 → 유저·일당 1회로 붕괴. 실효 절감 ~33%
game_event_bundle_max기본 30(수익 체감 지점). 요청 합산 1 MiB 상한으로 자동 클램프
D6 게이트 ≤1,024B · 목표 512B
D5 — 기본 7일 · 최대 30일. 저장비가 저렴해 3→30일 증가분은 월 ~$52(+11%)뿐
재시도·DLQ·모니터링 여유 — 요청 비용이 명시 행으로 분리되어 기본 1.15×
⚠️ D6 게이트 초과 — 줄 크기가 1KB를 넘습니다. 스키마 슬리밍 필요.
활성 호출자 (RU)
DAU × RU%
일 호출 수
RU × 호출/일
일 로그 수
호출 × 로그/호출
일 raw 용량
로그 × 바이트
월 총 비용 (SQS 티어)
CW-경유였다면
바이트 감도
줄 크기 100B 감소당 월 절감
묶음(D10) 효과
묶음 미적용 대비
SQS 비중
항목산식월액

단가(Seoul, PRD 검증값): SQS $0.40/백만 req(10건 배치) · Lambda 앵커 $550/월@3억 ev/day 선형 · S3 $0.025/GB-월(압축 1/6) · Athena $5/TB(D-1+D-2 일 1회, Parquet 스캔 1/10) · CW 참고치 $0.76/GB ingest. SQS 수신·삭제와 S3 PUT까지 명시 행으로 분리 — 앵커(3억 ev/day·0.8KB)에서 소계 ≈ $1,140 × 마진 1.15 ≈ $1,310으로 PRD prod 앵커($1.3~1.5K)와 정합.

§2 근거

기존 볼륨 앵커의 무엇이 어긋났나

운영 지표 실측(단일 봇, 약 5개월)으로 기존 비용 모델의 가정을 대사했다. 아래는 절대 수치가 아니라 검증 결과와 방법론이다 — 원 데이터는 비공개.

가정 검증 — 6개 중 4개 반증

모델 요소기존 가정실측 판정
활성률DAU의 15~20%유효 — 실측도 15~25%
인당 명령어 수15콜수십 배 과소 — 게임 특성상 훨씬 높음
콜당 레이크 이벤트35 (5×7)서술 오류 — 실제 3
상한 앵커 단위"1M DAU" 기준정의 혼동 — 그 볼륨은 누적 이용자에 대응, 활성이 아니었음
명령 분포고르게 분포 → 선별 절감 불가반증 — 소수 명령이 볼륨 대부분 차지

볼륨 기준선 = 명령어 실행 수 D11

플랫폼 원시 발화량(잡담·오타 포함)과 실제 게임 명령 실행 사이에는 큰 차이가 있다(원시 발화가 명령 실행의 약 1.8배). 레이크 대상은 후자다.

§3 확정 파라미터

L1 dedup · 묶음 n

L1 DAU dedup — 실효 33.2%

키 설계가 판정 근거다: <bot>:user:{uid}:dau:{YYYY-MM-DD}(KST) — 유저·일당 1건이지 콜당 1건이 아니다. 그런데 daily_active_user콜마다 발행되므로, L1은 이 성분을 콜 수에서 유저 수로 붕괴시킨다.

구분산식활성 1M DAU/일
L1 미적용콜 × 38.8억
L1 적용콜 × 2 + 활성 유저 1건5.87억

기존 "비용 효과 ~3%"는 1/35에서 나온 값으로, 배수 오류의 파생값이다. 실제 배수가 3이므로 1/3이 맞다. L1은 정합성 도구가 아니라 2순위 비용 레버다.

묶음 n — 고정값이 아닌 런타임 노브

n은 "메시지 개수"가 아니라 "메시지 안의 이벤트 개수"다. 메시지 수는 AWS 하드 한도로 항상 10개다.

flowchart LR
    R["SendMessageBatch 요청 1회
합산 ≤ 1 MiB"] --> M["메시지 10개
(하드 한도, 조정 불가)"] M --> E["각 메시지 body에
이벤트 n개 — 조정 대상"] E --> T["요청당 총 이벤트 = 10 × n"]
한도 항목성격
요청당 메시지(entry) 수10하드 (TooManyEntriesInBatchRequest)
개별 메시지 크기1 MiB하드
요청 합산 페이로드1 MiB10개를 채우면 이쪽이 먼저 걸린다 (BatchRequestTooLong)

n_max = floor(1,000,000 / (10 × 줄크기)) — 0.5KB에서 200 · 0.8KB에서 125 · 1.0KB에서 100. 계산기의 최대(n_max) 버튼이 현재 줄 크기 기준으로 자동 계산한다.

n요청당 ev메시지 크기1M 활성SQS 비중
11024 KB$2,83786%
3302.4 KB$1,21767%
101008 KB$65037%
3030024 KB$48817%
1251,250100 KB$4265%

n=30이 수익 체감 지점이다 — 여기서 SQS가 17%로 떨어져 Lambda에 최대 항목 자리를 넘겨주고, n=125까지 올려도 $62밖에 더 못 줄인다. 메시지 크기는 24KB로 1 MiB 한도의 2.3%에 불과해 여유가 크다.

§4 절감 레버와 리스크

확정 설정으로 −93% · 잔여 레버는 대가가 크다
단계설정월액직전 대비
0순진 구현 (콜 단위 발행 · n=1 · L1 off)$7,061
1+ 요청 배칭 (10 entries/req)$4,230−40%
2+ L1 dedup on$2,837−33%
3+ 묶음 n=30  확정 기본값$488−83%
4+ 줄 크기 0.5KB$354−27%
5+ n=200 (0.5KB의 n_max)$285−19%
(보존 3↔30일 폭 / 강화 축약)±$61 / −$342±11% / −48%
레버절감리스크되돌리기
L1 dedup−33%없음 — 지표 정합성은 오히려 개선플래그 off
묶음 n=30−83%없음 — 버퍼는 이미 전제. 늘어나는 건 메시지 크기뿐(24KB)설정값
flush_ms = 200(구조적 필수)유실 창 200ms — 프로세스 강제 종료 시 버퍼 잔량. 기존 fire-and-forget 유실과 동일 계열설정값
줄 크기 0.5KB−27%소급 불가 — 삭제 필드 영구 복구 불가
보존일 (3~30)±11%저장비 저렴 — 단축 실익 없음, 여유 시 늘려 디버깅 창 확보삭제분 복구 불가
강화 축약−48%+소급 불가 + 지표 해상도 영구 상실

§5 아키텍처

신규 구축은 큐 1 + Lambda 1
flowchart TB
    subgraph BOTS["n개 봇 (수평 확장 — 파이프라인 무변경)"]
        B1["봇 A"]
        B2["봇 #2"]
        BN["봇 #n"]
    end
    LG["log_game_event() — 봇 중립 훅
payload 확정 직후 · 줄 크기 ≤1KB"] B1 --> LG B2 --> LG BN --> LG LG --> PUB["SQS 배치 발행 (기존 idiom 재사용)
events:[] × n · SendMessageBatch 10건"] PUB --> Q["SQS game-events 큐 (신규)
standard + DLQ"] Q --> LAM["소비자 Lambda (신규, Go/arm64)
flat-map → Parquet"] LAM --> LAKE["S3 레이크 (SSOT)
Parquet · Glue projection"] LAKE --> AGG["일별 집계 배치 KST 03:00
daily_* 영구 보존 · 실패 알람 필수"] AGG --> ADMIN["admin 대시보드"] LAKE -.->|"raw 7일 롤링 삭제"| DEL[("저장비 상수화")]

CW-경유가 요구하던 전용 Firehose·Dynamic Partitioning·normalizer·구독필터는 전부 불필요하다. bot_code는 파티션이 아니라 컬럼이라 봇 추가 시 DDL·Lambda 무변경.

§6 부록

결정 원장 · 단가 · 잔존 미결

결정 원장 (D1~D11)

#결정현재 상태
D1아키텍처단일 SQS 배치 티어 — CW-경유 폐기. qa가 prod 경로를 그대로 검증
D2발행·소비자기존 SQS 경로 재사용 + Go/arm64 Lambda(workers-go idiom 재사용, parquet-go)
D3소멸 리스크구독필터 한도·prod 로그레벨·이중 적재·whitelist 소급 불가 — CW 고유 리스크 4건 소멸
D4예산 재확정활성 1M DAU $488/월(L1+n=30). 앵커 단위는 활성 DAU
D5보존raw 7일 기본 · 3~30일 조정 가능(3→30일 월 +$52) + 집계 영구 · 집계 실패 알람 필수
D6스키마 게이트소급 불가 평균 줄 크기 ≤1KB, 목표 0.5KB
D7L1 dedup 격상실효 33.2% — 정합성 전용이 아니라 2순위 비용 레버
D8수용 트레이드오프Logs Insights 실시간 조회 상실(Athena 준실시간 보완) · 발행 유실은 기존 fire-and-forget과 동일 수준(DLQ + 레이크 대사)
D9계수 재확정587 ev/활성DAU(L1 적용) · 배수 3 · 콜/활성유저 293(피크)~378(평균)
D10묶음 n 노브game_event_bundle_max 기본 30 · flush_ms 기본 200 · 물리 상한 125(0.8KB) · 수익 체감 지점 30
D11볼륨 기준선 신규명령어 실행 수(플랫폼 원시 발화 아님)

단가 — ap-northeast-2 실조회 (AWS Price List API, 2026-07-20)

서비스과금 항목서울 실단가비고
SQSstandard 요청 (발행·수신·삭제 공통)$0.40 / 백만월 1,000억 req까지 Tier1 — 본 워크로드 전량 해당
Lambda요청 / 컴퓨트 (arm64)$0.20 / 백만
$0.0000133334 / GB-초
x86 대비 −20% — 채택 완료
S3PUT / Standard 저장$0.0045 / 1천
$0.025 / GB-월
첫 50TB 구간
Athena스캔$5.00 / TBParquet 컬럼 프루닝으로 실스캔 축소
데이터 전송egress (동일 리전 · non-VPC)$0전 구간 같은 리전 AWS 서비스 간 통신 — 인터넷·리전 경계 없음
CW Logsingest / 저장 (참고 — 기각 경로)$0.76 / GB
$0.0314 / GB-월
CW-경유가 4~5배 비싸 기각된 근거

감각치: 이벤트 100만 건당 약 $4.5(n=1 기준). Glue Data Catalog는 partition projection이라 크롤러·ETL Job 과금이 없어 $0.

데이터 전송 = $0 — "VPC 없이"가 절감 레버다

egress는 비용 모델에서 빠진 게 아니라 실제로 0이라 라인이 없다. 이 로그레이크 Lambda의 유일한 출력은 S3 PUT이고, 전 구간이 같은 리전(ap-northeast-2) AWS 서비스 간 통신이라 데이터 전송료가 발생하지 않는다. AWS는 동일 리전 S3 in-transfer(써 넣기)에 전송료를 부과하지 않으며, 과금은 인터넷 egress나 리전 경계 통과 시에만 일어난다 — 이 설계엔 둘 다 없다. 파이프라인의 유일한 종착지가 S3이므로 외부로 나가는 트래픽 자체가 존재하지 않는다.

구간방향데이터 전송 요금
봇(ECS) → SQSsend동일 리전 — $0
SQS → Lambdareceive동일 리전 — $0
Lambda → S3PUT동일 리전 S3 — $0
Athena → S3scan동일 리전 — $0

"VPC 없이"가 회피한 비용

Lambda를 VPC 밖에 두면 AWS 백본으로 S3 퍼블릭 엔드포인트에 바로 닿는다 — NAT 불필요, 전송료 0. 반대로 VPC 안에 넣었다면 S3 접근에 아래 둘 중 하나가 필요했다.

방식월 비용비고
NAT Gateway~$32.85 + $0.045/GB활성 1M DAU(압축 ~40GB/일 = 월 1.2TB)면 처리료만 월 ~$54 추가 + 고정비 $33
S3 Gateway VPC Endpoint$0게이트웨이형은 무료 — 단, VPC 구성·관리 부담은 남음

non-VPC 선택이 NAT 비용(월 ~$87)을 통째로 회피한다. Lambda 컴퓨트 라인($338)은 순수 GB-초라 전송 항목이 애초에 없다.

잔존 미결 — 구현 후 실측으로만 닫힘

#내용닫는 시점
V-1게임 이벤트 ÷ 명령어 실행 ≈ 3 검증 — 초과 시 훅이 명령 인식 이전으로 샌 것qa 적재 +1주
V-2외부 API 호출 실측과 산출 볼륨의 갭 — 명령어 외 발행 경로 존재 여부V-1과 동시
V-3flush_ms 확정 — 인스턴스당 콜 처리율 실측 후 200ms 적정성 판단(유실 창 = 이 값). 함께 n=30이 flush당 누적량을 1메시지로 덮는지 확인qa 부하 시험