pile·
AI / ML·무신사 테크무신사 테크·

LLM 비용 64% 절감, 캐시 히트율 98% 달성기

29CM(무신사 그룹)이 AWS Bedrock 기반 LLM 비용이 지속 증가하는 원인을 메트릭 가시성 확보부터 차근차근 파악하고, Prompt Caching 도입으로 전체 LLM 청구액의 64%를 절감한 과정을 다룬다. 문제는 AWS Bedrock 콘솔이 일별 합계만 보여주고 API별 토큰 분리를 지원하지 않는다는 점이었고, 직접 메트릭 파이프라인을 구축한 뒤에야 단일 속성 추출 API가 전체 토큰의 92%를 차지한다는 사실을 발견했다.

핵심 포인트
  • AWS Bedrock 콘솔은 API별 토큰 분리를 지원하지 않아 비용 원인 파악이 불가능했다 — 메트릭 가시성 확보가 첫 과제였다.
  • LangChain4j의 ChatModelListener로 API별 input/output/cache_read/cache_write 토큰을 Prometheus 메트릭으로 추적하는 파이프라인을 직접 구축했다.
  • 속성 추출 API 단독으로 전체 토큰의 92% 차지 — 15K 토큰짜리 시스템 프롬프트를 매 호출마다 변동 없이 재전송하는 구조가 원인이었다.
  • 프롬프트를 고정값(시스템 블록: 규칙·예시·JSON 스키마)과 변동값(유저 메시지 블록: 상품 데이터)으로 분리한 뒤 CachePointBlock(1시간 TTL)을 추가했다.
  • 적용 1주 후 캐시 히트율 98%, 전체 LLM 비용 64% 절감 달성 — AI 비용 시뮬레이션 예측과 실측 오차 1%p 이내였다.
상세 정리
  • 문제 발단: LLM 비용 증가 추이 관찰 → Bedrock 콘솔은 일별 토큰 합계만 표시, API별 분리 없음 → 원인 파악 불가, 최적화 시작점 결정 불가
  • 메트릭 파이프라인 설계: 서블릿 필터가 요청 경로를 ThreadLocal에 담아 태깅, ChatModelListener가 매 Bedrock 호출 완료 시 토큰 수·지연시간·에러를 llm_endpoint/llm_model/type 태그와 함께 Prometheus로 전송
  • 카디널리티 폭발 방지: allowlist에 등록된 경로만 태그로 남기고 나머지는 "other"로 버킷화
  • 비용 계산 분리: 코드가 아닌 Grafana 변수(토큰 단가)로 이동 — 단가 변경 시 재배포 불필요, Bedrock 콘솔 수치와 대조 가능
  • 원인 발견: 대시보드 가동 직후 속성 추출 API가 전체 92% 차지 확인 — 배치 작업(매일 오전 7시~오후 2시)이 상품 최대 100개(약 2K 토큰) + 15K 고정 시스템 프롬프트를 매 호출마다 반복 전송
  • AI 비용 시뮬레이션 활용: 코드베이스 호출 패턴 + Bedrock 가격표 + 실제 일일 토큰 분포를 LLM에 입력 → 옵션별 예상 절감율·우선순위·의존성 산출. 최종 금액 계산은 Grafana 실측치 × 단가로 결정론적 처리(LLM에 산술 위임 X)
  • 시뮬레이션 결론: Prompt Caching 1순위 — 정확도 영향 없음, 코드 변경 최소, 고빈도+동일 프롬프트 호출 패턴이 캐싱 가격 모델과 잘 맞음
  • 구현 전 준비: 프롬프트 내 고정값(규칙·예시·JSON 스키마)을 시스템 블록으로, 변동값(상품명·카테고리 ID)을 유저 메시지 블록으로 명시적 분리
  • Bedrock Converse API 적용: 시스템 프롬프트 블록 뒤에 CachePointBlock(type=DEFAULT, ttl=1시간) 추가 — prefix matching으로 K,V 캐시 저장, 히트마다 TTL 1시간 갱신, 히트 없을 때만 만료
  • LangChain4j 기여: 1시간 TTL 파라미터가 미지원이라 SDK 직접 호출로 우회, BedrockChatRequestParameters에 cacheTtl 추가하는 PR #4920 기여 후 main 머지 완료
  • 결과: 캐시 히트율 98%(사실상 전 호출이 캐시 히트), 전체 LLM 비용 64% 절감 — 시뮬레이션 예측 대비 실측 오차 1%p 이내로 가격 모델 신뢰도 검증됨
  • 추가 캐싱 패턴 정리: Tool 정의 캐싱, 대화 히스토리 캐싱, RAG 문서 캐싱, Cache Warming(병렬 발사 전 워밍 콜 1회 — Thomson Reuters Labs에서 히트율 한 자릿수 → 80%대), Relocation Trick(시스템 프롬프트 내 동적 값을 유저 메시지로 이동 — ProjectDiscovery에서 히트율 한 자릿수 → 70%대)
  • 안티패턴: 시스템 프롬프트에 타임스탬프·사용자 ID 삽입 시 매 호출마다 해시가 달라져 캐시 무효화 — 증상은 에러 없이 cache_read=0으로만 확인 가능
왜 읽나AWS Bedrock(또는 Claude API)으로 고빈도 반복 LLM 호출을 운영 중인 백엔드·ML 엔지니어에게 메트릭 가시성 확보부터 Prompt Caching 실전 적용까지 코드·수치·안티패턴을 모두 담은 레퍼런스.
무신사 테크
무신사 테크 블로그
원문은 여기서 이어서 읽을 수 있어요
원문 읽기
읽음 (0)

이 글과 비슷한

  1. AI / ML·AWS KoreaAWS Korea Tech·

    우리팀에 새롭게 입사한 Kiro Crew를 활용하여 업무 생산성 올리기

    Kiro Crew는 오픈소스 개인 AI 에이전트 워크스페이스로, 기존 AI 어시스턴트와 달리 로컬 또는 원격 머신에서 상시 동작하며 컨텍스트를 기억하고 스케줄 작업을 자율 실행한다. 이 글은 AWS EC2에 Kiro Crew를 배포하고 GitHub 이슈 자동 분류, PR 리뷰 자동화 등 실제 업무에 활용하는 방법을 다룬다.

    요약 이어보기
    #ai-agent#workflow-automation#aws-ec2+2
  2. AI / ML·한글과컴퓨터한글과컴퓨터·

    같은 LLM인데 왜 결과가 다를까? 답은 하네스에 있다.

    같은 LLM을 써도 결과가 천차만별인 이유는 모델이 아니라 하네스(harness) — 모델을 둘러싼 루프, 도구, 메모리, 컨텍스트 설계 — 때문이다. 이 글은 프롬프트 엔지니어링(무엇을 말하나) → 컨텍스트 엔지니어링(무엇을 보여주나) → 하네스 엔지니어링(어떤 환경에서 실행하나) 3계층을 구분하고, 각 레이어에서 무엇을 설계해야 좋은 에이전트를 만드는지 체계적으로 다룬다.

    요약 이어보기
    #prompt-engineering#agent-engineering#context-engineering+2