엄격 모드의 기능


CRA로 생성한 React 프로젝트에선 엄격 모드(Strict Mode)가 기본적으로 적용돼 있다. 엄격 모드는 어플리케이션의 잠재적인 문제를 알아내기 위해 리액트에서 제공하는 도구다. 개발 모드에서 함수 컴포넌트 렌더링 / API 호출 등이 중복해서 발생한다면 엄격 모드 때문에 그럴 가능성이 높다.

import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './pages/App';

const root = ReactDOM.createRoot(
  document.getElementById('root') as HTMLElement,
);

root.render(
  <React.StrictMode>
    {/* ... */}
  </React.StrictMode>,
);

엄격 모드는 아래 기능을 제공한다. 엄격 모드는 개발 환경에서만 적용되며 UI에 영향을 주지 않는다(렌더링 X).

함수 컴포넌트 바디, 상태 업데이트 함수, useState / useMemo / useReducer 인자에 넘김 함수 등을 2번씩 호출하는 것도 엄격 모드의 기능중 하나다. 사이드 이펙트를 찾을 수 있도록 의도적으로 2번씩 호출하는 것.



처음엔 사이드 이펙트를 찾기 위해 왜 2번씩 호출해야 하는지 의아했다. 오히려 로그가 더 복잡해져서 불편했다. 하지만 이 엄격 모드 덕분에 생각지 못한 문제를 발견한 뒤론 되려 유용하다고 생각한다. 잘 짜인 어플리케이션이라면 동일한 작업을 중복 수행하더라도 사이드 이펙트가 없어야 한다.

사이트 이펙트 사례


아래 글쓰기 기능을 담당하는 Compose.tsx 컴포넌트가 있다. 완료 버튼을 눌러 작성한 글을 제출하거나, 다른 페이지로 이동하면 Compose 컴포넌트는 언마운트돼야 한다. 컴포넌트를 언마운트할 때 입력창에 남아있는 텍스트를 모두 삭제하고(clearDraft) 리스트 화면으로 이동하는 작업을 수행하는 leavePage 함수를 호출한다.

const leavePage = useCallback(() => {
    dispatch(clearDraft()); // 입력창에 남아있는 텍스트 삭제
    navigate(siteUrl.community.list, { replace: true }); // 리스트 페이지로 이동
  }, [dispatch, navigate]);

const submitHandler = useCallback(async () => {
  try {
    await dispatch(submitDraft(draft)).unwrap(); // 작성한 글 제출
    leavePage() // 글 작성을 마쳐서 언마운트하는 case
		// ...
  } catch (e) {
    // ...
  }
}, [dispatch, draft, navigate]);

useEffect(() => {
  return () => {
    leavePage() // 뒤로가기 등 라우트 변경으로 언마운트하는 case
  };
}, [leavePage]);