본문 바로가기

React.js

[React] 서버와 통신하며 임시저장 기능 구현하기

저는 영상 자막 편집에 대해 임시저장을 하는 기능을 구현했습니다. 그때 발생한 이슈에 대해 공유하려고 합니다.

 

이 전에 사용했던 코드

이전에는 setInterval 사용한 방식이었습니다.

//useEffect (30초마다 임시 저장)

useEffect(() => {
  const interval = setInterval(saveTemporary, 10000); // 10초마다 호출
  return () => clearInterval(interval); // 페이지 나갈 때 정리
  // eslint-disable-next-line react-hooks/exhaustive-deps
}, [inputText, testImageTextIdx, saveTemporary]);

 

이 부분은 10초마다 saveTemporary 함수를 호출하여 임시 저장을 자동으로 실행하는 코드입니다. setInterval을 사용해 일정 간격으로 함수를 호출하고, 페이지를 벗어날 때(return 부분에서) clearInterval을 호출하여 메모리 누수나 불필요한 동작을 방지합니다.

 

// useEffect (쿼리 제거 및 interval 정리)

useEffect(() => {
  const interval = setInterval(saveTemporary, 30000); // 30초마다 호출
  console.log("페이지 들어올때 테스트 clearInterval");

  return () => {
    queryClient.removeQueries({
      queryKey: ["GET", "test"],
    }); // 뒤로가기 했을 때 쿼리 제거
    clearInterval(interval); // interval 제거
  };
  // eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

 

두 번째 useEffect는 페이지에 진입할 때마다 30초마다 saveTemporary 함수를 호출하고, 뒤로 가거나 페이지를 떠날 때 쿼리를 제거하고 setInterval을 정리하는 로직입니다. 이 코드는 적절하게 쿼리 데이터를 관리하면서, 일정 간격마다 자동 저장을 진행합니다.

문제점

이전 코드에서는 setInterval이 두 번 사용되며, 각기 다른 주기로 작동했습니다. 이러한 구조는 반복적인 설정과 해제 과정에서 혼란을 초래하고, 불필요하게 중복된 코드를 생성했습니다. 또한, setInterval과 관련된 코드를 여러 곳에서 관리하는 것은 복잡성을 높이고 유지보수에 어려움을 줄 수 있습니다. 따라서 useEffect를 두 번 이상 선언했던 코드에 대한 리팩토링이 필요하다고 생각하게 되었습니다. 이에 따라 서치하던 중 useInterval을 발견하고 프로젝트에 적용하기로 하였습니다.

 

이후 도입한 코드

import { useInterval } from "usehooks-ts";

useInterval(() => {
  saveMutate(
    {
      //서버에 보내는 데이터
    },
    {
      onSuccess: () => {},
    }
  );
}, 30000); // 30초마다 자동으로 저장

 

useInterval을 도입한 이유

  1. 코드 간소화: useInterval 훅을 사용하면 setInterval의 반복 설정과 해제 과정을 useEffect 내부에서 관리할 필요가 없어집니다. 이전 코드에서는 두 개의 useEffect에서 중복된 setInterval 로직이 있었지만, useInterval을 사용하면 한 줄로 간단하게 자동 저장을 구현할 수 있습니다. 이는 코드 가독성을 크게 향상시킵니다.
  2. 반복 설정 문제 해결: 이전 코드에서는 10초, 30초 간격으로 setInterval을 두 번 사용했으나, useInterval을 사용하면 하나의 간격으로 일정하게 동작하게 됩니다. 이로 인해 중복 호출 문제나 불필요한 호출이 방지됩니다.
  3. 자동화된 정리: useInterval 훅은 setInterval과 달리 컴포넌트가 언마운트될 때 자동으로 clearInterval을 처리합니다. 이를 통해 메모리 누수나 정리 문제를 쉽게 해결할 수 있습니다. 더 이상 별도로 clearInterval을 호출하지 않아도 되기 때문에, 관리가 간편해집니다.

useInterval을 도입한 이유는 주기적으로 임시 저장 기능을 더 간결하게 관리하고, 복잡한 setInterval 관리 로직을 줄여 코드 가독성 및 유지보수성을 향상시키기 위함입니다. 또한, useInterval을 통해 자동으로 정리 작업을 처리할 수 있어 메모리 누수 및 불필요한 반복 설정을 방지할 수 있었습니다.

 

느낀 점

이번 기능 구현을 통해 코드의 복잡성을 줄이고 가독성을 높이는 것이 얼마나 중요한지를 깨달았습니다. useInterval을 도입한 결과, 코드가 간결해지고 유지보수가 쉬워졌으며, 사용자가 편리하게 임시 저장 기능을 활용할 수 있도록 개선되었습니다. 현재 저희 프로젝트에서 사용자가 급격하게 늘어나지 않았지만, 만약 사용자가 점점 증가할 경우에 대한 고민을 하게 되었습니다. 데이터 저장 기능이 여러 사용자에 의해 동시에 실행될 경우, 서버에 부하가 가해지고 성능 저하가 발생할 수 있습니다.

 

이러한 이유로, 저희는 프로젝트 중간에 서버 인프라에 로드 밸런서를 추가하여 요청을 여러 서버에 분산시키기로 결정했습니다. 이를 통해 특정 서버에 부하가 집중되는 것을 방지하고 전체적인 서버 성능을 향상시킬 수 있습니다. 클라우드 서비스 제공업체의 로드 밸런싱 기능을 활용하면 수평 확장이 용이해지고, 사용자 수에 따라 서버를 추가하거나 줄일 수 있는 유연성을 제공받을 수 있습니다.