오픈 15분 전, CMS가 안된다고 했다

Yeshin Lee
4 min readJan 5, 2024

--

TL;DR

  • api를 호출하는 범위는 최대한 좁게 걸자.
  • 해당 엔드 포인트의 목적이 무엇인지 분명하게 파악하고 그에 맞는 최적의 방법을 고민해보자.

사내 고객센터는 10시에 열리는데, 오픈 15분 전인 9시 45분에 CMS가 전체적으로 느리고 안되는 것 같다는 글이 올라왔다.

이전에도 비슷한 상황이 있었는데, 캐시를 삭제하고 재로그인하면 해결됐던 방법이 이번에는 먹히지 않았다. 이 때까지만 해도 뭐가 문제일까 싶었는데..

주변 동료가 찾아보더니 DB에 과부하가 걸린 것 같다고 했다. 좀 이따 Latency가 튄 것을 확인하면서 전 날 진행했던 릴리즈에 문제가 있는 것 같다고 했다.

어, 그건 내가 짠 코드인데?

어제 릴리즈한, 내가 구현한 기능은 두 가지였다.

  1. 카테고리 내에 존재하는 쿠폰의 개수를 반환하는 GET api
  2. 카테고리를 삭제하는 버튼을 클릭할 때, 1번의 반환값(쿠폰 개수)을 화면에 보여주기

Datadog에서 전 날 릴리즈한 시점부터 현재 시간까지의 로그를 확인해보았다.

역시나 어제 릴리즈한 코드에 문제가 있었다. Total time으로 정렬했을 때, 내가 짠 코드의 총 소요 시간은 4분 중반대에 P95 latency가 3.97s, 거의 4초가 걸렸다.

P95란?

좀 더 자세하게 보기 위해 해당 엔드포인트를 클릭했다.

latency가 튀는 것뿐만 아니라 request 횟수가 지나치게 늘어났다. 오른쪽 아래 ‘% of Time spent’ 그래프를 보면, 오전 9시 30분쯤 api-mysql 폭이 갑자기 상승한 걸 볼 수 있다.

Request 횟수가 증가함에 따라 latency 튀면서 CMS 전반에 영향을 미친 것이다.

어느 정도 파악을 했으니 코드를 보자

  1. request 횟수가 지나치게 많다.
  • 카테고리 아이디를 클릭하면 카테고리의 상세 정보와 수정, 삭제하는 기능이 담겨있는 팝오버가 열린다.
  • 팝오버 내 삭제 버튼을 클릭하면, 카테고리 내에 존재하는 쿠폰의 개수를 보여준다.
  • 해당 api는 카테고리 모달을 누를 때마다 호출되어 비정상적인 request가 많았다. 즉, 중복 요청이 발생한 것이다.

2. 쿠폰의 개수를 세는 방법

어디가 문제인지 고쳐야지?

사실 이 문제는 빠르게 해결해야했기 때문에, 해당 프로젝트 오너 분이 수정하시고 릴리즈하셨다.

그렇다고 이대로 지나칠 수는 없지.

  1. 엔드포인트를 호출하는 조건을 수정하자.
  • 기존 코드에서 enabled에 걸린 조건은 ‘카테고리 아이디를 클릭했을 때, 즉 팝오버가 열릴 때’였다.
  • 카테고리를 누를 때마다가 아닌 카테고리 삭제 버튼을 눌렀을 때 해당 엔드포인트를 호출한다.
useQuery(
couponCategoryKey.couponCount(currentCouponCategoryId),
() => fetchCouponCategoryCouponCount(currentCouponCategoryId),
{
enabled: isDeletePopoverOpen,
},
)

2. findAll – length 대신 count 함수를 사용하자.

const couponCount = await Coupon.count({
attributes: [‘id’],
where: {
couponCategoryId: req.params.couponCategoryId,
},
})

return couponCount

에러 원인을 찾는건 보물 찾기같다

--

--