본문 바로가기

Next

Strict Mode와 useEffect의 반복 실행 이슈 정리

Next.js로 개발을 하다가 이상한 현상을 하나 발견했다. 분명히 컴포넌트가 한 번만 마운트될 거라 생각했는데, 콘솔에 로그가 세 번이나 찍힌 것이다.

 

상황

다음은 테스트로 작성했던 코드다.

const q1 = useTestDataQuery(1, { enabled: false });
const q2 = useTestDataQuery(2, { enabled: false });

useEffect(() => {
  // onMount -> 추후 q1 대신 GET 호출 예정
  q1.refetch();

  return () => {
    // onUnmount -> 추후 q2 대신 POST 호출 예정
    q2.refetch();
  };
}, []);

 

단순히 마운트될 때 1번, 언마운트될 때 1번만 호출될 거라 예상했지만, 개발 모드 콘솔에는 아래처럼 로그 찍혔다.

[React Mount] q1.refetch() 실행
[React Unmount] q2.refetch() 실행
[React Re-mount] q1.refetch() 실행

 

즉, 컴포넌트가 한 번만 마운트되는 것이 아니라 마운트 → 언마운트 → 리마운트되는 동작이 발생한 것이다.

 

왜 이렇게 된 걸까?

이 현상은 React의 버그가 아니라 React 18부터 추가된 Strict Mode 동작 때문이다. React 18부터는 개발 모드에서 Strict Mode가 effect가 여러 번 실행되고 정리되는 상황을 일부러 시뮬레이션해서, 컴포넌트가 향후 Reusable State 기능(상태 보존 리마운트)에 대비할 수 있도록 도와주는 역할을 하고 있다. (이 동작은 개발 모드(Development Mode) 에서만 발생한다.)

 

왜 이렇게 하냐면!

 

React 팀은 앞으로 나올 Reusable State (상태 재사용) 기능을 대비하고 있다. 이 기능은 컴포넌트를 완전히 파괴하지 않고 상태를 유지한 채로 다시 마운트할 수 있게 만드는 기능이다.

예를 들어 탭 전환이나 Suspense 로딩 전환 시 기존 상태를 그대로 유지한 채 컴포넌트를 복구하는 구조다.

이를 제대로 지원하려면 모든 useEffect가 “깨끗하게 정리(cleanup)”되고 다시 실행되더라도 부작용이 없어야 한다. 그래서 React는 개발 모드에서 의도적으로 마운트/언마운트를 두 번 반복하며 문제가 없는지 테스트한다.

 

Next.js에서는 기본적으로 활성화되어 있다

Next.js의 next.config.js에는 기본적으로 다음 설정이 들어가 있다. 그래서 Next.js로 개발하면 React의 Strict Mode 시뮬레이션이 항상 동작한다.

module.exports = {
  reactStrictMode: true,
};

 

이 옵션을 false로 설정하면, 로그는 한번만 찍히지만 React가 제공하는 조기 버그 감지 기능을 잃게 된다. production 모드로 실행했을 때는 정상 동작하기 때문에, 문제라고 생각했던 부분의 원인을 알고 개발을 진행하면 될 것 같다.

'Next' 카테고리의 다른 글

mutateAsync 도입기  (0) 2025.11.14
Next.js 프로젝트 구조, src/app으로 써야 할까?  (0) 2025.10.19
Loading.jsx와 Suspense fallback의 차이  (0) 2025.07.01
bodySizeLimit 설정  (0) 2025.06.16