pile·
백엔드·버즈빌버즈빌·

피크 타임 Pod 245개를 100여개로 — DynamoDB SDK v2 전환으로 Go 서버 CPU 절반 줄이기

버즈빌 Supply 그룹이 저녁 피크 타임마다 Pod가 245개로 치솟는 문제를 Pyroscope 프로파일링으로 추적해 DynamoDB wrapper 라이브러리 내부의 AWS SDK v1 unmarshal이 CPU 병목임을 밝히고, guregu/dynamo v2 전환으로 요청당 CPU를 59% 줄이고 월 비용을 약 4,000달러 절감한 사례다.

핵심 포인트
  • Pyroscope flame graph에서 guregu/dynamo가 전체 CPU의 절반 가까이를 차지했으며, 원인은 내부 AWS SDK v1의 reflection 기반 JSON unmarshal이었다.
  • AWS SDK v2는 타입별로 struct를 나눈 union 형태와 생성된 serializer를 사용해 reflection 비용이 대폭 감소한다.
  • 코드 변경은 import 경로 교체 수준으로 단순했으나 효과는 극적이었다.
  • 요청당 CPU -59%, 피크 타임 Pod 245개→109개(-55.3%), 일 비용 약 400달러→250달러 수준으로 절감.
  • 핵심 교훈: 문제 인식과 원인 파악은 여전히 엔지니어링이 필요한 영역이다.
상세 정리
  • 배경: Supply 그룹 Go 앱이 저녁 피크마다 Pod 200여 개 이상으로 확장. 시간당 7천만 건 처리량이 원인으로 의심됐으나 Pyroscope로 확인하니 DynamoDB 클라이언트가 진짜 원인이었다.
  • Pyroscope 발견: flame graph에서 guregu/dynamo가 CPU의 절반 가까이 점유. 네트워크 I/O나 DynamoDB latency·throttling은 관측되지 않았다.
  • 원인 파악: guregu/dynamo v1은 HTTP 요청·응답 파싱을 AWS SDK v1에 위임. SDK v1의 reflection 기반 JSON unmarshal 비용이 wrapper로 집계된 것.
  • AWS SDK v1 구조: AttributeValue를 하나의 큰 struct에 모든 타입을 포인터 필드로 포함. 값 읽을 때마다 어떤 필드가 채워졌는지 reflection으로 확인하는 비용이 반복된다.
  • AWS SDK v2 구조: 타입별로 struct를 분리한 union 형태(AttributeValueMemberS/N/M 등). switch문 기반 타입 분기로 reflection 없이 처리하며, 서비스 모델 기반 생성된 serializer를 사용한다.
  • 코드 변경: import 경로를 github.com/guregu/dynamo에서 github.com/guregu/dynamo/v2로 교체, AllWithContext를 All(ctx)로 변경, 초기화는 v2 DynamoDB 클라이언트로 교체. 카나리 배포로 점진 적용.
  • 즉시 효과(배포 전후 30분 비교): Pyroscope CPU 샘플 18h→7h(-61%), 요청당 CPU 2.149ms→0.876ms(-59.2%), AWS SDK v1 JSON unmarshal 비중 46.97%→2.55%.
  • 장기 효과(4일 비교): CPU avg -46.6%, p95 -44.4%, HPA desired p95 245→109개(-55.3%). 요일 통제 비교에서도 Pod 217개→96개, CPU 401.1→203.7 cores 확인.
  • 비용 절감: 일 비용 400달러대→250달러 수준, 월 기준 약 3,500~4,500달러 절감.
왜 읽나Go 서버의 DynamoDB CPU·비용이 예상보다 높은 팀, 프로파일링 기반 병목 추적부터 라이브러리 교체 의사결정까지 전 과정을 따라가고 싶은 백엔드·인프라 엔지니어에게 실전 레퍼런스다.
버즈빌
버즈빌 블로그
원문은 여기서 이어서 읽을 수 있어요
원문 읽기
읽음 (0)

이 글과 비슷한

  1. 백엔드·twilio-engTwilio Engineering·

    Programmable Messaging에서 Verify API로 마이그레이션하기

    Twilio의 Programmable Messaging API로 자체 OTP 솔루션을 운영하던 서비스가 Verify API로 전환하는 방법을 코드 예시와 함께 설명한다. Verify는 OTP 전송·검증을 위한 전용 API로, 전화번호 구매, 토큰 생성, DB 저장·만료 관리를 내부에서 처리해 개발자가 직접 구현할 코드를 크게 줄인다.

    요약 이어보기
    #authentication#twilio#sms+2
  2. 백엔드·포스타입포스타입·

    포스타입이 개인화 추천을 하는 방법 2부

    포스타입 백엔드 엔지니어가 벡터 기반 개인화 추천 시스템을 실제 운영하며 맞닥뜨린 성능 장애와 용량 문제를 해결한 과정을 담은 2부다. 수백만 개의 벡터 KNN 검색이 피크 시간대에 전체 Elasticsearch 검색 성능을 흔드는 문제부터 클러스터 OOM 사태까지, 쿼리 최적화와 인프라 분리 두 가지 경로로 근본 해결에 이른다.

    요약 이어보기
    #elasticsearch#vector-search#recommendation-system+2
  3. 백엔드·포스타입포스타입·

    포스타입이 개인화 추천을 하는 방법 1부

    포스타입이 태그 기반 추천의 한계를 극복하고 벡터 임베딩 기반 개인화 추천 시스템을 구축한 과정을 담은 1부다. 유사한 콘텐츠가 다른 용어를 쓰거나 동일한 태그가 전혀 다른 톤의 콘텐츠를 가리키는 문제를 임베딩 벡터로 해결하고, OpenSearch의 HNSW ANN 검색으로 수백만 벡터를 실시간 검색하는 시스템을 구축해 구매율 15% 향상을 달성했다.

    요약 이어보기
    #opensearch#vector-search#recommendation-system+2