일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
- 리액트네이티브
- JavaScript
- mock service worker
- 동기
- react server component
- 최적화
- Basic
- next.js
- react-query
- Cache
- CSS-in-JS
- 쓰레드
- vanilla-extract
- thread
- amplify
- Concurrent Mode
- front-end mocking
- 자바스크립트
- 리액트
- mockoon
- sprinkles
- Babel
- 기본
- 컴포넌트
- 아키텍처
- MSW
- 기초
- next hydration
- 리액트쿼리
- react-native
- Critical Rendering Path
- async
- 캐쉬
- styled-component
- 비동기
- link
- 개발자
- SWC
- React
- 목킹
- Today
- Total
Don’t worry about failures
React StrictMode에 대해 본문
React Strict Mode는 애플리케이션 내에서 개발 시 발견된 잠재적인 문제를 감지하고 경고를 출력하는 도구이다.
*StrictMode는 development 환경에서만 동작한다.
StrictMode가 제공해주는 기능에 대해 확인해보자.
1. 버그를 잡기위해 렌더링을 두번한다.
리액트의 컴포넌트는 순수함수이어야한다. 순수함수가 아닐 경우에는 예측 불가한 상황이나 오류가 생겨날 우려가 있기 때문에 순수함수를 지켜줘야한다.
이를 위해 StrictMode에서는 두번의 렌더링을 통해서 동일한 값이 나오는지 비교하고 그렇지 않으면 경고를 해준다.
이에 대한 예제를 봐보자. 해당 예제는 공식문서에서 가져온 것이다.
//App.js
import { useState } from 'react';
import StoryTray from './StoryTray.js';
let initialStories = [
{id: 0, label: "Ankit's Story" },
{id: 1, label: "Taylor's Story" },
];
export default function App() {
let [stories, setStories] = useState(initialStories)
return (
<div
style={{
width: '100%',
height: '100%',
textAlign: 'center',
}}
>
<StoryTray stories={stories} />
</div>
);
}
//StoryTray.js
export default function StoryTray({ stories }) {
const items = stories;
items.push({ id: 'create', label: 'Create Story' });
return (
<ul>
{items.map(story => (
<li key={story.id}>
{story.label}
</li>
))}
</ul>
);
}


예제는 단순하다. list를 props로 넘기고 StoryTray 컴포넌트 안에서 props를 값을 할당하고 push를 통해 값을 추가하고 뿌려준다.
근데 결과가 이상하다. create Story가 두개가 생긴다. 이는 React.StrictMode로 인한 것으로 2번의 렌더링을 하기 때문에다.
근데 왜 두번 렌더링된다고해서 목록이 하나 더 생기나?
리액트의 불변성이 지켜지지 않았기 때문이다.
const item = stories; 이 부분은 스택에 새로운 영역에 똑같은 주소를 가진 값만 복사될 뿐 실제 힙영역의 값이 복사되는 것이 아니다.
이에 따라 첫 렌더링때
{id: 'create', label: 'Create Story'}
push되고 두번째 렌더링 또 같은 배열에 같은 값이 push가 되기 때문에 발생 되는 것이다.
또 다른 예시를 봐보자.
import { useState } from 'react';
export default function StoryTray({ stories }) {
const [isHover, setIsHover] = useState(false);
const items = stories;
items.push({ id: 'create', label: 'Create Story' });
return (
<ul
onPointerEnter={() => setIsHover(true)}
onPointerLeave={() => setIsHover(false)}
style={{
backgroundColor: isHover ? '#ddd' : '#fff'
}}
>
{items.map(story => (
<li key={story.id}>
{story.label}
</li>
))}
</ul>
);
}
이 예시는 item에 hover를 하면서 해당 컴포넌트가 리렌더링되도록 하는 예시이다.
코드와 의도와는 상관없었이 렌더링되면서 계속해서 list가 추가되는 결과값을 얻을 수 있다.

이를 해결하고자 하려면 어떻게 해야할까?
불변성을 지켜주면된다. slice()의 경우 새로운 list를 리턴해주기 때문에 이를 활용하면 하나의 해결책이 될 수 있다.
const items = stories.slice(); // Clone the array
items.push({ id: 'create', label: 'Create Story' });
위의 예제와 같이 StrictMode에서는 2번의 렌더링을 통해서 리액트가 불필요한 렌더링 오류를 잡아줄 수 있다.
2. useEffect의 사이클이 한번 더 돈다.
이 또한 잠재적 버그를 잡고자 StrictMode에서 하는 행위 중 하나이다. 예제를 봐보자.
// App.js
import { useState, useEffect } from 'react';
import { createConnection } from './chat.js';
const serverUrl = 'https://localhost:1234';
const roomId = 'general';
export default function ChatRoom() {
useEffect(() => {
const connection = createConnection(serverUrl, roomId);
connection.connect();
}, []);
return <h1>Welcome to the {roomId} room!</h1>;
}
// Chat.js
let connections = 0;
export function createConnection(serverUrl, roomId) {
// A real implementation would actually connect to the server
return {
connect() {
console.log('✅ Connecting to "' + roomId + '" room at ' + serverUrl + '...');
connections++;
console.log('Active connections: ' + connections);
},
disconnect() {
console.log('❌ Disconnected from "' + roomId + '" room at ' + serverUrl);
connections--;
console.log('Active connections: ' + connections);
}
};
}


결과는 위와 같다. Acive connect이 2번찍히는 결과값을 볼 수 있다.
물론 여기서 StrictMode를 off한다면 1번만 찍힌다.
이와 더불어 StrictMode에서는
- 문자열 ref사용에 대한 경고, createRef 사용권장
- 권장되지 않는 findDOMNode 사용 경고
- 레거시 contextAPI 검사
를 검사해주며 개발환경에서 strict하게 개발하도록 하게 해준다.
참고:
'React' 카테고리의 다른 글
전역 상태관리에 대해 (0) | 2024.03.25 |
---|---|
Hydrate에 대해 (0) | 2024.03.22 |
useTransition에 대해 (0) | 2024.03.16 |
concurrent mode에 대해 (0) | 2024.03.15 |
React Big list state 관리 이슈 (0) | 2022.11.25 |