제가 개발하는 서비스에서는 다른 서비스들처럼 게시글에 좋아요를 할 수 있는 기능이 있는데요.
2024-04-23 19:42:47.427 INFO [reactor-http-nio-6] c.d.c.l.LoggingFilter: [9108d19a] HTTP PATCH /post/66409c40323215275afe86d2/like2024-04-23 19:42:47.438 INFO [nioEventLoopGroup-3-4] c.d.c.l.LoggingFilter: [9108d19a] HTTP 200 OK2024-04-23 19:42:47.565 INFO [reactor-http-nio-6] c.d.c.l.LoggingFilter: [4b42d217] HTTP PATCH /post/66409c40323215275afe86d2/like2024-04-23 19:42:47.570 INFO [nioEventLoopGroup-3-4] c.d.c.l.LoggingFilter: [4b42d217] HTTP 200 OK...
문제는 해당 기능에서 API 호출이 비정상적으로 많이 발생할 수 있는 가능성이 있다는 것입니다.
그래서 디바운싱(Debouncing)이라는 최적화 기법을 적용해 보기로 했습니다.
디바운싱
디바운싱이란 특정 함수가 연속으로 여러 번 호출되는 경우에 마지막 호출만 수행되도록 하는 최적화 기법 중 하나입니다.
호출이 되고 일정 시간이 지난 후 실제로 함수가 호출되며, 만약 일정 시간 안에 다시 함수가 호출이 되면 이전 호출이 취소되고 다시 일정 시간을 기다리는 방식으로 디바운싱을 구현할 수 있습니다.
위 예시는 검색 기능에 디바운싱을 적용한 예시인데요.
검색창 타이핑(Typing) 중에는 API 호출이 발생하지 않고 타이핑을 끝낸 후에 API 호출이 발생해 UI가 바뀌는 것을 확인할 수 있습니다.
React
React에서는 useEffect()를 통해 디바운싱을 쉽게 구현할 수 있습니다. useEffect()는 의존성 배열 내의 상태 변수가 바뀌었을 때, 콜백(Callback)을 호출하는 React Hook 중 하나입니다.
이때, useEffect()의 반환 값으로 설정된 콜백은 useEffect()의 다음 호출때 함께 호출됩니다.App.tsx
위 코드는 버튼을 클릭할 때마다 number가 1씩 증가하는 코드인데요. number를 증가시킬 때마다 이전 useEffect()에서의 onUnmounted()와 현재 useEffect()의 onMounted()가 함께 호출되는 것을 볼 수 있습니다.
이러한 점을 활용해 디바운싱을 구현할 수 있습니다.useDebouncing.ts
저는 디바운싱을 재사용할 수 있도록 커스텀 훅(Custom Hook)을 구현했습니다. useEffect()에서는 setTimeout()을 통해 delay 후에 실제 수행할 작업인 action()을 호출하는데, delay가 끝나기 전에 한 번 더 useEffect()가 호출되면 이전의 useEffect()에서의 setTimeout()이 clearTimeout()에 의해 취소됩니다.
이렇게 되면 delay 미만의 간격으로 연속 호출되는 useEffect()들에서 action()은 수행되지 않으며 마지막의 useEffect()에서의 action()만 수행되게 됩니다.
좋아요 기능 최적화
이제 실제로 좋아요 기능에 디바운싱을 적용해 최적화를 해보겠습니다.postReducer.ts
게시글의 좋아요 개수인 count 및 현재 유저의 좋아요 여부인 isLiked 등을 포함한 커스텀 훅을 구현했습니다. isLiked가 처음과 달라졌는지 여부를 확인하기 위해 initialIsLiked를 최초의 isLiked로 초기화 했습니다.
좋아요를 클릭하면 likeHandler에 의해 isLiked의 상태가 바뀌는데요.
이때, 호출되는 useDebouncing()에서 디바운싱을 통해 좋아요를 여러 번 클릭해도 마지막 좋아요만 API에 요청하게 됩니다.
최종적으로는 useDebouncing()에서 isLiked가 initialIsLiked와 다르다면 바뀐 좋아요 여부를 서버에 반영하고 Redux 스토어 내의 likedStudentIds를 갱신하게 됩니다.
2024-04-23 20:55:13.122 INFO [reactor-http-nio-5] c.d.c.l.LoggingFilter: [f8582d5c] HTTP PATCH /post/66409c40323215275afe86d2/like2024-04-23 20:55:13.135 INFO [nioEventLoopGroup-3-3] c.d.c.l.LoggingFilter: [f8582d5c] HTTP 200 OK
이전과 달리 많은 좋아요 요청에도 실제 API 호출은 한 번만 발생한 것을 확인할 수 있습니다.