pile·
백엔드·트렌비트렌비·

트렌비 리뷰 서비스의 성능 개선기

트렌비 리뷰 서비스가 DB 커넥션 풀 고갈과 API 타임아웃 알럿을 잡고 p90 응답 속도를 200~250ms에서 30~40ms로 줄인 기록이다. 다섯 가지 개선을 순서대로 짚으며 각 단계에서 응답 속도가 얼마나 내려갔는지 수치를 붙였다. 문제 유형이 서로 달라 대응 수단도 각각 다르다.

핵심 포인트
  • 목표는 응답 속도 100ms 이하와 알럿 해소 두 가지였고 최종적으로 30~40ms까지 내려갔다.
  • 주문 ID마다 외부 서비스를 호출하던 n번 호출을 목록을 받는 API 하나로 합쳐 100ms 수준이 됐다.
  • 애초에 그 데이터를 리뷰 작성 시점에 함께 받아 자체 보관하도록 바꿔 외부 호출을 없애자 30~40ms가 됐다.
  • 트랜잭션 안에서 외부 API 호출과 DB 접근이 함께 있어 커넥션을 쥔 채 대기하다 풀이 고갈됐다.
  • TransactionTemplate으로 DB 구간만 트랜잭션에 넣어 분리하자 고갈이 사라졌다.
  • 불안정한 외부 서비스는 Redis 캐시를 앞에 두고, 인덱스가 빠져 600ms 걸리던 조회 쿼리는 인덱스 추가로 해결했다.
상세 정리
  • 문제 상황: 서비스 런칭 후 사용자와 트래픽이 늘며 DB 커넥션 풀 고갈과 API 타임아웃 알럿이 반복해서 떴다. 보통 5분 내로 안정화되지만 반복돼 사용자 경험을 해쳤다.
  • 기준 설정: 0.1초 이내면 즉각적인 응답으로 인식된다는 자료를 근거로, p90 200~250ms인 현재 상태는 즉각적이지 않다고 판단했다.
  • 개선 1 문제: 주문 ID 목록을 순회하며 주문 서비스를 ID마다 호출하고 있었다. 한 번에 1~2ms인 통신 비용이 보통 10건이면 10~20ms가 된다.
  • 개선 1 조치: 주문 서비스에 여러 ID를 받는 API를 만들고 리뷰 서비스는 한 번만 호출하도록 바꿔 p90이 100ms 수준이 됐다.
  • 개선 2 질문: 그 호출로 무엇을 받아오는지 확인해보니 주문 ID에 매핑된 구매 옵션 데이터뿐이었다.
  • 개선 2 조치: 리뷰가 작성될 때 구매 옵션이 파라미터로 함께 들어오므로 그때 리뷰 도메인에 저장해두면 된다고 보고 외부 의존을 끊었다. p90이 30~40ms가 됐다.
  • 개선 3 증상: 트래픽이 몰릴 때 트랜잭션용 EntityManager를 열 수 없다는 에러가 대량으로 났고 같은 시간대 커넥션 풀 메트릭이 튀었다.
  • 개선 3 원인: 트랜잭션이 걸린 하나의 메서드 안에서 외부 API 호출과 내부 DB 접근이 함께 수행되고 있었다. 트랜잭션은 시작 시 커넥션을 가져와 끝날 때 반납하는데, 외부 호출이 지연되면 커넥션을 쥔 채 대기하게 된다.
  • 개선 3 근거: 하나의 트랜잭션 안에 DB I/O와 다른 I/O가 섞이는 것은 나쁜 신호이며 우선 분리하라는 가이드를 인용한다.
  • 개선 3 조치: 외부 호출을 트랜잭션 밖으로 빼고 DB 접근 구간만 TransactionTemplate으로 감싸 범위를 명확히 했다. 이후 트래픽이 늘어도 고갈이 발생하지 않았다.
  • 개선 4 문제: 중고 상품 데이터를 위해 상품 서비스를 계속 호출하는데 그쪽에서 타임아웃이 나면 리뷰 서비스도 같이 타임아웃을 내 프론트까지 영향을 줬다.
  • 개선 4 판단: 필요한 상품 데이터가 거의 동일하고 자주 바뀌지 않으므로 캐시가 적합하다고 봤다.
  • 개선 4 결과: Redis 캐시 레이어를 두고 호출을 최소화하자 상품 서비스 응답 속도에서 보이던 스파이크가 거의 사라졌다.
  • 개선 5 발견: 핀포인트로 요청 구성과 구간별 응답 속도를 보다가 간단한 역할의 API가 예상보다 느린 경우를 찾았다.
  • 개선 5 원인: 주문 상품에 이미 리뷰가 있는지 확인하는 단순 조회가 약 600ms 걸리고 있었는데 해당 컬럼에 인덱스가 빠져 있었다.
  • 개선 5 조치: 그 컬럼에 인덱스를 추가해 간단히 해결했다.
  • 최종 상태: p90 응답 속도가 30~40ms 수준에서 안정적으로 유지되고 커넥션 풀 고갈로 인한 알럿은 더 이상 발생하지 않는다.
왜 읽나마이크로서비스 간 호출이 많은 API가 느리고 커넥션 풀 알럿까지 뜬다면, 호출 합치기와 의존 제거, 트랜잭션 분리, 캐시, 인덱스라는 다섯 갈래를 순서대로 점검할 수 있다.
트렌비
트렌비 블로그
원문은 여기서 이어서 읽을 수 있어요
원문 읽기
읽음 (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