React의 Strict Mode는 개발 단계에서 발생할 수 있는 잠재적인 문제를 미리 감지하고, 안정적인 코드를 작성할 수 있도록 도와주는 기능입니다. 하지만 개발자 입장에서 처음 경험하게 되는 “훅이 두 번 실행되는 현상”, “API가 중복 호출되는 문제” 등은 혼란을 유발할 수 있습니다. 본 글에서는 Strict Mode의 동작 원리부터 훅과 생명주기 메서드의 이중 실행 이유, 그리고 실무에서 발생할 수 있는 실제 문제와 면접 대응 전략까지 정리합니다. React 18 이후 업데이트된 동작 방식도 함께 반영하여 철저히 설명합니다.
Strict Mode란 무엇이며 왜 사용하는가
Strict Mode는 React가 제공하는 개발 전용 기능으로, 코드의 잠재적인 문제를 조기에 감지하고 경고해주는 역할을 합니다. 이 기능은 브라우저에 렌더링되는 결과에는 영향을 주지 않으며, 오직 개발 모드에서만 작동합니다. 컴포넌트 트리를 <React.StrictMode>로 감싸기만 하면 사용할 수 있습니다.
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
Strict Mode는 다음과 같은 문제를 감지하거나 예방하는 데 목적이 있습니다:
- 의도치 않은 부작용(side effects)
- 안정적이지 않은 생명주기 메서드 사용
- React API의 향후 사용 중단(deprecated) 예정 기능
- useEffect 내에서 의존성 누락 경고
특히 React 18 이후에는 **Concurrent Mode**를 위한 준비 단계로, 컴포넌트의 마운트/언마운트/마운트를 반복 실행하는 구조가 도입되었습니다. 이를 통해 React는 컴포넌트가 실제 환경에서도 안전하게 작동하는지 시뮬레이션할 수 있습니다. 이 반복 실행 구조가 바로 “훅이 두 번 실행된다”는 개발자들의 오해를 불러일으키는 주요 원인입니다.
Strict Mode는 실무에서 문제가 되는 동작을 유발하기보다는, 문제를 미리 파악하고 예방할 수 있도록 도와주는 보호장치입니다. 하지만 동작 원리를 제대로 이해하지 못한 상태에서 사용하면, 오히려 개발자 혼란을 가중시킬 수 있기 때문에 구조와 목적을 명확히 이해하는 것이 중요합니다.
개발모드에서 훅과 생명주기 메서드가 두 번 실행되는 이유
React Strict Mode의 가장 혼란스러운 특징 중 하나는 **개발 모드에서 특정 훅이나 클래스 컴포넌트의 생명주기 메서드가 두 번 실행된다는 점**입니다. 이는 “React가 버그를 감지하기 위해 의도적으로 적용한 정책”이며, 다음과 같은 함수들이 두 번 호출됩니다:
- 함수 컴포넌트 본문 (렌더링)
- useEffect() / useState()
- useMemo(), useCallback()
- 클래스 컴포넌트의 constructor, componentDidMount
React는 해당 컴포넌트가 마운트될 때 사이드 이펙트가 안정적으로 관리되는지를 확인하기 위해 **마운트 → 언마운트 → 마운트** 순으로 실행을 반복합니다. 예를 들어 다음과 같은 코드에서는 `useEffect` 내부 로직이 두 번 실행됩니다:
useEffect(() => {
console.log("API 요청 시작");
fetchData();
}, []);
이 코드는 개발 모드에서 Strict Mode가 활성화된 상태일 경우, 다음과 같은 순서로 동작합니다:
- 1차 마운트 → useEffect 실행 (fetchData 호출)
- 1차 언마운트 → cleanup 함수 실행
- 2차 마운트 → useEffect 재실행 (fetchData 또 호출됨)
이런 구조는 실제 프로덕션 빌드에서는 발생하지 않지만, **개발 중에는 동일 API가 두 번 호출되는 문제**로 이어질 수 있습니다. 이로 인해 다음과 같은 실무 문제가 발생할 수 있습니다:
- 서버에 중복된 요청이 전달되어 데이터 무결성 문제 발생
- POST 요청의 중복 → 중복 생성(create) 문제
- 로그인, 결제, 이메일 전송 등 민감한 동작이 반복 실행
이를 방지하기 위한 방법으로는 다음과 같은 전략이 있습니다:
- API 호출 로직을
useEffect
안에서 조건 분기 처리 - 비동기 요청에
ref
또는 상태 플래그를 사용하여 한 번만 실행되도록 제어 - React Query, SWR 같은 라이브러리의
dedupingInterval
사용 - useEffect 대신 사용자 정의 훅을 통해 실행 여부 컨트롤
Strict Mode는 이처럼 사이드 이펙트가 반복되어도 안정적으로 작동하도록 코드를 강제하기 때문에, 초기에 혼란을 겪더라도 실무에서는 장기적으로 큰 도움이 됩니다.
Strict Mode 관련 면접 질문과 실무 대응 전략
React Strict Mode는 면접에서도 자주 다뤄지는 주제입니다. 단순히 개념을 묻는 수준을 넘어, **실제 경험 기반의 문제 해결 능력**을 확인하는 질문이 많습니다. 실제로 출제되는 대표적인 질문은 다음과 같습니다:
- “Strict Mode에서 useEffect가 두 번 실행되는 이유는 무엇인가요?”
- “API 요청이 중복 발생할 수 있는 경우, 어떻게 방지하시나요?”
- “프로덕션과 개발 모드에서 컴포넌트 동작 차이를 설명해보세요.”
이러한 질문에는 React의 렌더링 정책, Concurrent Mode 대응, useEffect의 클린업 구조 등을 통합적으로 설명해야 좋은 인상을 줄 수 있습니다. 예를 들어 다음과 같은 답변이 효과적입니다:
“React Strict Mode는 사이드 이펙트의 안정성을 검증하기 위해 개발 모드에서 일부 훅을 두 번 실행합니다. 특히 useEffect는 마운트-언마운트-재마운트를 통해 메모리 누수나 부작용이 없는지 확인합니다. 그래서 API 요청은 중복 호출되지 않도록 ref 또는 조건 분기로 제어하며, 민감한 요청은 백엔드에서 중복 처리도 차단하는 설계를 병행합니다.”
실무에서는 다음과 같은 대응 전략도 중요합니다:
- 클라이언트 측 방어 로직 외에도 서버에 idempotency key 적용
- 비동기 요청에서 debounce, throttle 등 제어기법 적용
- 테스트 환경에서 Strict Mode를 조건부로 제거하고 결과 비교
Strict Mode는 React 18 이후로 더욱 중요해졌습니다. Suspense, Concurrent Features와의 연계를 고려하면, 앞으로도 더 다양한 방식으로 적용될 가능성이 높습니다. 따라서 지금부터라도 실무 코드와 개발 흐름에 이를 고려해 설계하고, 면접에서도 코드를 중심으로 풀어낼 수 있도록 연습하는 것이 좋습니다.
React Strict Mode는 초보 개발자에게는 혼란을, 숙련 개발자에게는 안정성을 제공하는 중요한 기능입니다. 개발 모드에서 훅이나 생명주기 메서드가 두 번 실행되는 것은 React가 버그 가능성을 조기에 확인하기 위한 의도된 구조이며, 실제 프로덕션에서는 발생하지 않습니다. 하지만 이 구조를 이해하지 못한 채 API를 호출하거나 외부 상태를 변경하면 실질적인 문제로 이어질 수 있으므로 주의가 필요합니다. 면접에서는 개념 설명을 넘어서 실무 경험과 해결 전략을 묻는 질문이 자주 등장하기 때문에, 본 글에서 설명한 원리와 대응법을 충분히 숙지해 두시기 바랍니다.