<StrictMode>
<StrictMode>๋ฅผ ํตํด ๊ฐ๋ฐ ์ค์ ์ปดํฌ๋ํธ์์ ์ผ๋ฐ์ ์ธ ๋ฒ๊ทธ๋ฅผ ๋น ๋ฅด๊ฒ ์ฐพ์ ์ ์๋๋ก ํฉ๋๋ค.
<StrictMode>
<App />
</StrictMode>- ๋ ํผ๋ฐ์ค
- ์ฌ์ฉ๋ฒ
- ์ ์ฒด ์ฑ์ ๋ํด Strict Mode ํ์ฑํ
- ์ฑ์ ์ผ๋ถ๋ถ์์ Strict Mode ํ์ฑํ
- ๊ฐ๋ฐ ์ค ์ด์ค ๋ ๋๋ง์ผ๋ก ๋ฐ๊ฒฌํ ๋ฒ๊ทธ ์์
- ๊ฐ๋ฐ ํ๊ฒฝ์์ Effect๋ฅผ ๋ค์ ์คํํ์ฌ ๋ฐ๊ฒฌ๋ ๋ฒ๊ทธ ์์
- ๊ฐ๋ฐ ํ๊ฒฝ์์ ref ์ฝ๋ฐฑ์ ๋ค์ ์คํํ์ฌ ๋ฐ๊ฒฌ๋ ๋ฒ๊ทธ ์์
- Fixing deprecation warnings enabled by Strict Mode
๋ ํผ๋ฐ์ค
<StrictMode>
์ปดํฌ๋ํธ ํธ๋ฆฌ ๋ด๋ถ์์ ์ถ๊ฐ์ ์ธ ๊ฐ๋ฐ ๋์ ๋ฐ ๊ฒฝ๊ณ ๋ฅผ ํ์ฑํํ๊ธฐ ์ํด StrictMode๋ฅผ ์ฌ์ฉํ์ธ์.
import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';
const root = createRoot(document.getElementById('root'));
root.render(
<StrictMode>
<App />
</StrictMode>
);์๋ ์์๋ฅผ ์ฐธ๊ณ ํ์ธ์.
Strict Mode๋ ๋ค์๊ณผ ๊ฐ์ ๊ฐ๋ฐ ์ ์ฉ ๋์์ ํ์ฑํํฉ๋๋ค.
- ์ปดํฌ๋ํธ๊ฐ ์์ํ์ง ์์ ๋ ๋๋ง์ผ๋ก ์ธํ ๋ฒ๊ทธ๋ฅผ ์ฐพ๊ธฐ ์ํด ์ถ๊ฐ๋ก ๋ค์ ๋ ๋๋งํฉ๋๋ค.
- ์ปดํฌ๋ํธ๊ฐ Effect ํด๋ฆฐ์ ์ด ๋๋ฝ๋์ด ๋ฐ์ํ ๋ฒ๊ทธ๋ฅผ ์ฐพ๊ธฐ ์ํด Effect๋ฅผ ๋ค์ ์คํํฉ๋๋ค.
- ์ปดํฌ๋ํธ๊ฐ Ref ํด๋ฆฐ์ ์ด ๋๋ฝ๋์ด ๋ฐ์ํ ๋ฒ๊ทธ๋ฅผ ์ฐพ๊ธฐ ์ํด Ref ์ฝ๋ฐฑ์ ๋ค์ ์คํํฉ๋๋ค.
- ์ปดํฌ๋ํธ๊ฐ ๋ ์ด์ ์ฌ์ฉ๋์ง ์๋ API๋ฅผ ์ฌ์ฉํ๋์ง ํ์ธํฉ๋๋ค.
Props
StrictMode๋ Props๋ฅผ ๋ฐ์ง ์์ต๋๋ค.
์ฃผ์ ์ฌํญ
<StrictMode>๋ก ๋ํ๋ ํธ๋ฆฌ ๋ด์์ Strict Mode๋ฅผ ํด์ ํ ์ ์๋ ๋ฐฉ๋ฒ์ ์์ต๋๋ค. ์ด๋ฅผ ํตํด<StrictMode>๋ด๋ถ์ ๋ชจ๋ ์ปดํฌ๋ํธ๊ฐ ๊ฒ์ฌ๋์์์ ํ์ ํ ์ ์์ต๋๋ค. ์ ํ์ ๊ฐ๋ฐํ๋ ๋ ํ์ด ๊ฒ์ฌ๊ฐ ๊ฐ์น ์๋์ง์ ๋ํด ์๊ฒฌ์ด ๊ฐ๋ฆฌ๋ ๊ฒฝ์ฐ, ํฉ์์ ๋๋ฌํ๊ฑฐ๋<StrictMode>๋ฅผ ํธ๋ฆฌ์์ ํ๋จ์ผ๋ก ์ฎ๊ฒจ์ผ ํฉ๋๋ค.
์ฌ์ฉ๋ฒ
์ ์ฒด ์ฑ์ ๋ํด Strict Mode ํ์ฑํ
Strict Mode๋ <StrictMode> ์ปดํฌ๋ํธ ๋ด๋ถ์ ๋ชจ๋ ์ปดํฌ๋ํธ ํธ๋ฆฌ์ ๋ํด ์ถ๊ฐ์ ์ธ ๊ฐ๋ฐ ์ ์ฉ ๊ฒ์ฌ๋ฅผ ํ์ฑํํฉ๋๋ค. ์ด๋ฌํ ๊ฒ์ฌ๋ ๊ฐ๋ฐ ํ๋ก์ธ์ค ์ด๊ธฐ์ ์ปดํฌ๋ํธ์์ ์ผ๋ฐ์ ์ธ ๋ฒ๊ทธ๋ฅผ ์ฐพ๋ ๋ฐ ๋์์ด ๋ฉ๋๋ค.
์ ์ฒด ์ฑ์ ๋ํ Strict Mode๋ฅผ ํ์ฑํํ๋ ค๋ฉด ๋ ๋๋งํ ๋ ๋ฃจํธ ์ปดํฌ๋ํธ๋ฅผ <StrictMode>๋ก ๋ํํ์ธ์.
import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';
const root = createRoot(document.getElementById('root'));
root.render(
<StrictMode>
<App />
</StrictMode>
);์ ์ฒด ์ฑ์ (ํนํ ์๋ก ์์ฑ๋ ์ฑ์ ๊ฒฝ์ฐ) Strict Mode๋ก ๋ํํ๋ ๊ฒ์ ๊ถ์ฅํฉ๋๋ค. createRoot๋ฅผ ํธ์ถํ๋ ํ๋ ์์ํฌ๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ, Strict Mode๋ฅผ ํ์ฑํํ๋ ๋ฐฉ๋ฒ์ ๋ํ ๋ฌธ์๋ฅผ ํ์ธํ์ธ์.
Strict Mode ๊ฒ์ฌ๋ ๊ฐ๋ฐ ํ๊ฒฝ์์๋ง ์คํ๋์ง๋ง, ์ด๋ฏธ ์ฝ๋์ ์กด์ฌํ๋ ๋ฒ๊ทธ๋ฅผ ์ฐพ์๋ด๋ ๋ฐ ๋์์ ์ค๋๋ค. ์ด๋ฌํ ๋ฒ๊ทธ๋ ์ค์ ์ด์ ํ๊ฒฝ์์ ์ฌํํ๊ธฐ ๊น๋ค๋ก์ธ ์ ์์ต๋๋ค. Strict Mode๋ฅผ ์ฌ์ฉํ๋ฉด ์ฌ์ฉ์๊ฐ ๋ณด๊ณ ํ๊ธฐ ์ ์ ๋ฒ๊ทธ๋ฅผ ์์ ํ ์ ์์ต๋๋ค.
์ฑ์ ์ผ๋ถ๋ถ์์ Strict Mode ํ์ฑํ
์ ํ๋ฆฌ์ผ์ด์ ์ ์ด๋ค ๋ถ๋ถ์์๋ผ๋ Strict Mode๋ฅผ ํ์ฑํํ ์ ์์ต๋๋ค.
import { StrictMode } from 'react';
function App() {
return (
<>
<Header />
<StrictMode>
<main>
<Sidebar />
<Content />
</main>
</StrictMode>
<Footer />
</>
);
}์ด ์์์์ Header์ Footer ์ปดํฌ๋ํธ์์๋ Strict Mode ๊ฒ์ฌ๊ฐ ์คํ๋์ง ์์ต๋๋ค. ๊ทธ๋ฌ๋ Sidebar์ Content, ๊ทธ๋ฆฌ๊ณ ๊ทธ ์์ ์ปดํฌ๋ํธ๋ ๊น์ด์ ์๊ด์์ด ๊ฒ์ฌ๊ฐ ์คํ๋ฉ๋๋ค.
๊ฐ๋ฐ ์ค ์ด์ค ๋ ๋๋ง์ผ๋ก ๋ฐ๊ฒฌํ ๋ฒ๊ทธ ์์
React๋ ์์ฑํ๋ ๋ชจ๋ ์ปดํฌ๋ํธ๊ฐ ์์ ํจ์๋ผ๊ณ ๊ฐ์ ํฉ๋๋ค. ์ด๊ฒ์ React ์ปดํฌ๋ํธ๋ ํญ์ ๋์ผํ ์ ๋ ฅ(Props, State, Context)์ ๋ํด ๋์ผํ JSX๋ฅผ ๋ฐํํด์ผ ํ๋ค๋ ๊ฒ์ ์๋ฏธํฉ๋๋ค.
์ด ๊ท์น์ ์๋ฐํ๋ ์ปดํฌ๋ํธ๋ ์๊ธฐ์น ์๊ฒ ๋์ํ๋ฉฐ ๋ฒ๊ทธ๋ฅผ ์ผ์ผํต๋๋ค. Strict Mode๋ ์ค์๋ก ์์ฑ๋ ์์ํ์ง ์์ ์ฝ๋๋ฅผ ์ฐพ์๋ด๊ธฐ ์ํด ๋ช ๊ฐ์ง ํจ์(์์ ํจ์์ฌ์ผ ํ๋ ๊ฒ๋ง)๋ฅผ ๊ฐ๋ฐ ํ๊ฒฝ์์ ๋ ๋ฒ ํธ์ถํฉ๋๋ค. ์ด์๋ ๋ค์์ด ํฌํจ๋ฉ๋๋ค.
- ์ปดํฌ๋ํธ ํจ์ ๋ณธ๋ฌธ. (๋จ, ์ต์์ ๋ก์ง๋ง ํด๋นํ๋ฉฐ, ์ด๋ฒคํธ ํธ๋ค๋ฌ ๋ด๋ถ์ ์ฝ๋๋ ํฌํจํ์ง ์์.)
useState,setํจ์,useMemo, ๋๋useReducer์ ์ ๋ฌํ ํจ์.constructor,render,shouldComponentUpdate์ ๊ฐ์ ์ผ๋ถ ํด๋์ค ์ปดํฌ๋ํธ ๋ฉ์๋. (์ ์ฒด ๋ชฉ๋ก ๋ณด๊ธฐ)
ํจ์๊ฐ ์์ํ ๊ฒฝ์ฐ ๋ ๋ฒ ์คํํ์ฌ๋ ๋์์ด ๋ณ๊ฒฝ๋์ง ์์ต๋๋ค. ์์ ํจ์๋ ํญ์ ๊ฐ์ ๊ฒฐ๊ณผ๋ฅผ ์์ฑํ๊ธฐ ๋๋ฌธ์ ๋๋ค. ๊ทธ๋ฌ๋ ํจ์๊ฐ ์์ํ์ง ์๋ค๋ฉด (์: ๋ฐ์ ๋ฐ์ดํฐ๋ฅผ ๋ณ๊ฒฝํ๋ ํจ์) ๋ ๋ฒ ์คํํ๋ฉด ๋ณดํต ์์์ฑ ์ ์์ต๋๋ค. (์ด๊ฒ์ด ๋ฐ๋ก ํจ์๊ฐ ์์ํ์ง ์๋ค๋ ๊ฒ์ ์๋ฏธํฉ๋๋ค!) ์ด๋ ๋ฒ๊ทธ๋ฅผ ์กฐ๊ธฐ์ ๋ฐ๊ฒฌํ๊ณ ์์ ํ๋ ๋ฐ ๋์์ด ๋ฉ๋๋ค.
๋ค์์ Strict Mode์ ์ด์ค ๋ ๋๋ง์ด ์ด๋ป๊ฒ ๋ฒ๊ทธ๋ฅผ ์กฐ๊ธฐ์ ๋ฐ๊ฒฌํ๋ ๋ฐ ๋์์ด ๋๋์ง ๋ณด์ฌ์ฃผ๋ ์์์ ๋๋ค.
StoryTray ์ปดํฌ๋ํธ๋ stories ๋ฐฐ์ด์ ๋ฐ์ ๋ง์ง๋ง์ โ์ด์ผ๊ธฐ ๋ง๋ค๊ธฐโ ํญ๋ชฉ์ ์ถ๊ฐํฉ๋๋ค.
export default function StoryTray({ stories }) { const items = stories; items.push({ id: 'create', label: '์ด์ผ๊ธฐ ๋ง๋ค๊ธฐ' }); return ( <ul> {items.map(story => ( <li key={story.id}> {story.label} </li> ))} </ul> ); }
์ ์ฝ๋์๋ ์ค์๊ฐ ์์ต๋๋ค. ํ์ง๋ง ์ด๊ธฐ ์ถ๋ ฅ์ด ์ฌ๋ฐ๋ฅด๊ฒ ๋ํ๋๊ธฐ ๋๋ฌธ์ ๋์น๊ธฐ ์ฝ์ต๋๋ค.
This mistake will become more noticeable if the StoryTray component re-renders multiple times. For example, letโs make the StoryTray re-render with a different background color whenever you hover over it:
import { useState } from 'react'; export default function StoryTray({ stories }) { const [isHover, setIsHover] = useState(false); const items = stories; items.push({ id: 'create', label: '์ด์ผ๊ธฐ ๋ง๋ค๊ธฐ' }); return ( <ul onPointerEnter={() => setIsHover(true)} onPointerLeave={() => setIsHover(false)} style={{ backgroundColor: isHover ? '#ddd' : '#fff' }} > {items.map(story => ( <li key={story.id}> {story.label} </li> ))} </ul> ); }
StoryTray ์ปดํฌ๋ํธ ์๋ก ๋ง์ฐ์ค๋ฅผ ๊ฐ์ ธ๊ฐ ๋๋ง๋ค โ์ด์ผ๊ธฐ ๋ง๋ค๊ธฐโ๊ฐ ๋ชฉ๋ก์ ๋ค์ ์ถ๊ฐ๋๋ ๊ฒ์ ํ์ธํ ์ ์์ต๋๋ค. ์ด ์ฝ๋์ ์๋๋ ๋ง์ง๋ง์ ํ ๋ฒ ์ถ๊ฐํ๋ ๊ฒ์ด์์ต๋๋ค. ํ์ง๋ง StoryTray๋ ์ํ์ stories ๋ฐฐ์ด์ ์ง์ ์์ ํฉ๋๋ค. StoryTray๋ ๋ ๋๋งํ ๋๋ง๋ค ๊ฐ์ ๋ฐฐ์ด์ ๋์ โ์ด์ผ๊ธฐ ๋ง๋ค๊ธฐโ๋ฅผ ๋ค์ ์ถ๊ฐํฉ๋๋ค. ์ฆ, StoryTray๋ ์์ ํจ์๊ฐ ์๋๋ฏ๋ก ์ฌ๋ฌ ๋ฒ ์คํํ๋ฉด ๋ค๋ฅธ ๊ฒฐ๊ณผ๊ฐ ์์ฑ๋ฉ๋๋ค.
์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ๋ฐฐ์ด์ ์ฌ๋ณธ์ ๋ง๋ ๋ค์ ์๋ณธ์ด ์๋ ์ฌ๋ณธ์ ์์ ํ ์ ์์ต๋๋ค.
export default function StoryTray({ stories }) {
const items = stories.slice(); // ๋ฐฐ์ด ๋ณต์
// โ
Good: ์๋ก์ด ๋ฐฐ์ด์ ์ถ๊ฐ
items.push({ id: 'create', label: '์ด์ผ๊ธฐ ๋ง๋ค๊ธฐ' });์ด๋ ๊ฒ ํ๋ฉด StoryTray ํจ์๋ฅผ ์์ํ๊ฒ ๋ง๋ค ์ ์์ต๋๋ค. ํจ์๊ฐ ํธ์ถ๋ ๋๋ง๋ค ๋ฐฐ์ด์ ์ฌ๋ณธ๋ง ์์ ํ๊ณ , ์ธ๋ถ ๊ฐ์ฒด๋ ๋ณ์์๋ ์ํฅ์ ๋ฏธ์น์ง ์์ต๋๋ค. ์ด๋ ๊ฒ ํ๋ฉด ๋ฒ๊ทธ๋ฅผ ํด๊ฒฐํ ์ ์์ง๋ง, ์ปดํฌ๋ํธ๋ฅผ ์ฌ๋ฌ๋ฒ ๋ค์ ๋ ๋๋งํ๋๋ก ๋ง๋ค์ด์ผ ๋น๋ก์ ์ปดํฌ๋ํธ์ ๋์์ ๋ฌธ์ ๊ฐ ์๋ค๋ ๊ฒ์ด ๋ช
ํํด์ก์ต๋๋ค.
์๋ ์์์์๋ ๋ฒ๊ทธ๊ฐ ๋ช
ํํ์ง ์์์ต๋๋ค. ์ด์ ์๋ (๋ฒ๊ทธ๊ฐ ์๋) ์ฝ๋๋ฅผ <StrictMode>๋ก ๋ํํด ๋ณด๊ฒ ์ต๋๋ค.
export default function StoryTray({ stories }) { const items = stories; items.push({ id: 'create', label: '์ด์ผ๊ธฐ ๋ง๋ค๊ธฐ' }); return ( <ul> {items.map(story => ( <li key={story.id}> {story.label} </li> ))} </ul> ); }
Strict Mode์์๋ ํญ์ ๋ ๋๋ง ํจ์๋ฅผ ๋ ๋ฒ ํธ์ถํ๋ฏ๋ก ์ค์๋ฅผ ๋ฐ๋ก ํ์ธํ ์ ์์ต๋๋ค. (โ์ด์ผ๊ธฐ ๋ง๋ค๊ธฐโ๊ฐ ๋ ๋ฒ ๋ํ๋จ.) ๋ฐ๋ผ์ ํ๋ก์ธ์ค ์ด๊ธฐ์ ์ด๋ฌํ ์ค์๋ฅผ ๋ฐ๊ฒฌํ ์ ์์ต๋๋ค. ์ปดํฌ๋ํธ๊ฐ Strict Mode์์ ๋ ๋๋ง๋๋๋ก ์์ ํ๋ฉด ์ด์ ์ ํธ๋ฒ ๊ธฐ๋ฅ๊ณผ ๊ฐ์ด ํฅํ ๋ฐ์ํ ์ ์๋ ๋ง์ ํ๋ก๋์ ๋ฒ๊ทธ๋ ์์ ํ ์ ์์ต๋๋ค.
import { useState } from 'react'; export default function StoryTray({ stories }) { const [isHover, setIsHover] = useState(false); const items = stories.slice(); // ๋ฐฐ์ด ๋ณต์ items.push({ id: 'create', label: '์ด์ผ๊ธฐ ๋ง๋ค๊ธฐ' }); return ( <ul onPointerEnter={() => setIsHover(true)} onPointerLeave={() => setIsHover(false)} style={{ backgroundColor: isHover ? '#ddd' : '#fff' }} > {items.map(story => ( <li key={story.id}> {story.label} </li> ))} </ul> ); }
Strict Mode๊ฐ ์์ผ๋ฉด ๋ฆฌ๋ ๋๋ง์ ๋ ์ถ๊ฐํ๊ธฐ ์ ๊น์ง๋ ๋ฒ๊ทธ๋ฅผ ๋์น๊ธฐ ์ฌ์ ์ต๋๋ค. Strict Mode๋ฅผ ์ฌ์ฉํ๋ฉด ๋์ผํ ๋ฒ๊ทธ๊ฐ ์ฆ์ ๋ํ๋ฉ๋๋ค. Strict Mode๋ ๋ฒ๊ทธ๋ฅผ ํ์ด๋ ์ฌ์ฉ์์๊ฒ ํธ์ํ๊ธฐ ์ ์ ๋ฐ๊ฒฌํ ์ ์๋๋ก ๋์์ค๋๋ค.
์ปดํฌ๋ํธ๋ฅผ ์์ํ๊ฒ ์ ์งํ๋ ๋ฐฉ๋ฒ์ ๋ํด ์์ธํ ์์๋ณด์ธ์.
๊ฐ๋ฐ ํ๊ฒฝ์์ Effect๋ฅผ ๋ค์ ์คํํ์ฌ ๋ฐ๊ฒฌ๋ ๋ฒ๊ทธ ์์
Strict Mode๋ Effect์ ๋ฒ๊ทธ๋ฅผ ์ฐพ๋ ๋ฐ๋ ๋์์ด ๋ ์ ์์ต๋๋ค.
๋ชจ๋ Effect์๋ ๋ช ๊ฐ์ง ์ ์ ์ฝ๋๊ฐ ์๊ณ ์ด์ฉ๋ฉด ํด๋ฆฐ์ ์ฝ๋๊ฐ ์์ ์ ์์ต๋๋ค. ์ผ๋ฐ์ ์ผ๋ก React๋ ์ปดํฌ๋ํธ๊ฐ ๋ง์ดํธ(ํ๋ฉด์ ์ถ๊ฐ)๋ ๋ ์ ์ ์ ํธ์ถํ๊ณ ์ปดํฌ๋ํธ๊ฐ ๋ง์ดํธ ํด์ (ํ๋ฉด์์ ์ ๊ฑฐ)๋ ๋ ํด๋ฆฐ์ ์ ํธ์ถํฉ๋๋ค. ๊ทธ๋ฐ ๋ค์ React๋ ๋ง์ง๋ง ๋ ๋๋ง ์ดํ๋ก๋ถํฐ ์์กด์ฑ์ด ๋ณ๊ฒฝ๋ ๊ฒฝ์ฐ ํด๋ฆฐ์ ๊ณผ ์ ์ ์ ๋ค์ ํธ์ถํฉ๋๋ค.
Strict Mode๊ฐ ์ผ์ ธ ์์ผ๋ฉด React๋ ๋ชจ๋ Effect์ ๋ํด ๊ฐ๋ฐ ํ๊ฒฝ์์ ํ ๋ฒ ๋ ์ ์ +ํด๋ฆฐ์ ์ฌ์ดํด์ ์คํํฉ๋๋ค. ์์ธ๋ก ๋๊ปด์ง ์๋ ์์ง๋ง ์๋์ผ๋ก ํ์ ํ๊ธฐ ์ด๋ ค์ด ๋ฏธ๋ฌํ ๋ฒ๊ทธ๋ฅผ ๋๋ฌ๋ด๋ ๋ฐ ๋์์ด ๋ฉ๋๋ค.
๋ค์์ Strict Mode์์ Effect๋ฅผ ๋ค์ ์คํํ๋ ๊ฒ์ด ๋ฒ๊ทธ๋ฅผ ์กฐ๊ธฐ์ ๋ฐ๊ฒฌํ๋ ๋ฐ ์ด๋ป๊ฒ ๋์์ด ๋๋์ง ๋ณด์ฌ์ฃผ๋ ์์์ ๋๋ค.
์ปดํฌ๋ํธ๋ฅผ ์ฑํ ์ ์ฐ๊ฒฐํ๋ ์ด ์์๋ฅผ ์ดํด๋ด ์๋ค.
import { createRoot } from 'react-dom/client'; import './styles.css'; import App from './App'; const root = createRoot(document.getElementById("root")); root.render(<App />);
์ด ์ฝ๋์๋ ๋ฌธ์ ๊ฐ ์์ง๋ง ์ฆ์ ํ์ ํ๊ธฐ ์ด๋ ค์ธ ์ ์์ต๋๋ค.
๋ฌธ์ ๋ฅผ ๋ ๋ช
ํํ๊ฒ ๋๋ฌ๋ด๊ธฐ ์ํด ๊ธฐ๋ฅ์ ๊ตฌํํด ๋ณด๊ฒ ์ต๋๋ค. ์๋ ์์์์๋ roomId๊ฐ ํ๋์ฝ๋ฉ๋์ด ์์ง ์์ต๋๋ค. ๋์ ์ฌ์ฉ์๊ฐ ์ฐ๊ฒฐํ๋ ค๋ roomId๋ฅผ ๋๋กญ๋ค์ด์์ ์ ํํ ์ ์์ต๋๋ค. โ๋ํ ์ด๊ธฐโ์ ํด๋ฆญํ ๋ค์ ๋ค๋ฅธ ๋ํ๋ฐฉ์ ํ๋์ฉ ์ ํํฉ๋๋ค. ์ฝ์์์ ํ์ฑํ๋ ์ฐ๊ฒฐ ์๋ฅผ ์ถ์ ํฉ๋๋ค.
import { createRoot } from 'react-dom/client'; import './styles.css'; import App from './App'; const root = createRoot(document.getElementById("root")); root.render(<App />);
์ด๋ฆฐ ์ฐ๊ฒฐ ์๊ฐ ํญ์ ๊ณ์ ์ฆ๊ฐํ๋ ๊ฒ์ ์ ์ ์์ต๋๋ค. ์ค์ ์ฑ์์๋ ์ฑ๋ฅ ๋ฐ ๋คํธ์ํฌ ๋ฌธ์ ๊ฐ ๋ฐ์ํ ์ ์์ต๋๋ค. ๋ฌธ์ ๋ Effect์ ํด๋ฆฐ์ ํจ์๊ฐ ๋๋ฝ๋์๋ค๋ ๊ฒ์ ๋๋ค.
useEffect(() => {
const connection = createConnection(serverUrl, roomId);
connection.connect();
return () => connection.disconnect();
}, [roomId]);์ด์ Effect๊ฐ ์์ฒด์ ์ผ๋ก โํด๋ฆฐ์ โํ๊ณ ์ค๋๋ ์ฐ๊ฒฐ์ ํ๊ดดํ๋ฏ๋ก ๋์๊ฐ ํด๊ฒฐ๋์์ต๋๋ค. ๊ทธ๋ฌ๋ ๋ ๋ง์ ๊ธฐ๋ฅ(์ ํ ์์)์ ์ถ๊ฐํ๊ธฐ ์ ๊น์ง๋ ๋ฌธ์ ๊ฐ ๋๋ฌ๋์ง ์์์์ ์ ์ ์์ต๋๋ค.
์๋ ์์์์๋ ๋ฒ๊ทธ๊ฐ ๋ช
ํํ์ง ์์์ต๋๋ค. ์ด์ ์๋ (๋ฒ๊ทธ๊ฐ ์๋) ์ฝ๋๋ฅผ <StrictMode>๋ก ๋ํํด ๋ณด๊ฒ ์ต๋๋ค.
import { StrictMode } from 'react'; import { createRoot } from 'react-dom/client'; import './styles.css'; import App from './App'; const root = createRoot(document.getElementById("root")); root.render( <StrictMode> <App /> </StrictMode> );
Strict Mode๋ฅผ ์ฌ์ฉํ๋ฉด ๋ฌธ์ ๊ฐ ์์์ ์ฆ์ ์ ์ ์์ต๋๋ค(ํ์ฑํ๋ ์ฐ๊ฒฐ ์๊ฐ 2๊ฐ๋ก ์ฆ๊ฐํจ). Strict Mode๋ ๋ชจ๋ Effect์ ๋ํด ์ถ๊ฐ ์ ์ +ํด๋ฆฐ์ ์ฌ์ดํด์ ์คํํฉ๋๋ค. ์ด Effect์๋ ํด๋ฆฐ์ ๋ก์ง์ด ์์ผ๋ฏ๋ก ์ถ๊ฐ ์ฐ๊ฒฐ์ ์์ฑํ์ง๋ง ํ๊ดดํ์ง๋ ์์ต๋๋ค. ์ด๊ฒ์ ํด๋ฆฐ์ ํจ์๊ฐ ๋๋ฝ๋์๋ค๋ ํํธ์ ๋๋ค.
Strict Mode๋ฅผ ์ฌ์ฉํ๋ฉด ์ด๋ฌํ ์ค์๋ฅผ ํ๋ก์ธ์ค ์ด๊ธฐ์ ๋ฐ๊ฒฌํ ์ ์์ต๋๋ค. Strict Mode์์ ํด๋ฆฐ์ ํจ์๋ฅผ ์ถ๊ฐํ์ฌ Effect๋ฅผ ์์ ํ๋ฉด ์ด์ ์ ์ ํ ์์์ ๊ฐ์ด ํฅํ ํ๋ก๋์ ์์ ๋ฐ์ํ ์ ์๋ ๋ง์ ๋ฒ๊ทธ ๋ํ ์์ ํฉ๋๋ค.
import { StrictMode } from 'react'; import { createRoot } from 'react-dom/client'; import './styles.css'; import App from './App'; const root = createRoot(document.getElementById("root")); root.render( <StrictMode> <App /> </StrictMode> );
์ฝ์์ ํ์ฑํ๋ ์ฐ๊ฒฐ ์๊ฐ ๋ ์ด์ ์ฆ๊ฐํ์ง ์๋ ๊ฒ์ ํ์ธํ ์ ์์ต๋๋ค.
Strict Mode๊ฐ ์์ผ๋ฉด Effect๋ฅผ ํด๋ฆฐ์ ํด์ผ ํ๋ค๋ ์ฌ์ค์ ๋์น๊ธฐ ์ฌ์ ์ต๋๋ค. ๊ฐ๋ฐ ํ๊ฒฝ์์ Effect์ ๋ํด ์ ์ ๋์ ์ ์ โ ํด๋ฆฐ์ โ ์ ์ ์ ์คํํ๋ฉด Strict Mode์์ ๋๋ฝ๋ ํด๋ฆฐ์ ๋ก์ง์ด ๋ ๋์ ๋๊ฒ ๋ฉ๋๋ค.
Effect ํด๋ฆฐ์ ์ ๊ตฌํํ๋ ๋ฐฉ๋ฒ์ ๋ํด ์์ธํ ์์๋ณด์ธ์.
๊ฐ๋ฐ ํ๊ฒฝ์์ ref ์ฝ๋ฐฑ์ ๋ค์ ์คํํ์ฌ ๋ฐ๊ฒฌ๋ ๋ฒ๊ทธ ์์
Strict Mode๋ callbacks refs์ ๋ฒ๊ทธ๋ฅผ ์ฐพ๋ ๋ฐ๋ ๋์์ด ๋ฉ๋๋ค.
๋ชจ๋ ์ฝ๋ฐฑ ref์๋ ๋ช ๊ฐ์ง ์
์
์ฝ๋๊ฐ ์๊ณ ์ด์ฉ๋ฉด ํด๋ฆฐ์
์ฝ๋๊ฐ ์์ ์ ์์ต๋๋ค. ์ผ๋ฐ์ ์ผ๋ก React๋ ์๋ฆฌ๋จผํธ๊ฐ ์์ฑ(DOM์ ์ถ๊ฐ)๋ ๋ ์
์
์ฝ๋๋ฅผ ์คํํ๊ณ , ์๋ฆฌ๋จผํธ๊ฐ ์ ๊ฑฐ(DOM์์ ์ญ์ )๋ ๋ ์
์
์ฝ๋๋ฅผ ์คํํฉ๋๋ค.
Strict Mode๊ฐ ์ผ์ ธ ์์ผ๋ฉด React๋ ๋ชจ๋ ์ฝ๋ฐฑ ref์ ๋ํด ๊ฐ๋ฐ ํ๊ฒฝ์์ ํ ๋ฒ ๋ ์
์
+ํด๋ฆฐ์
์ฌ์ดํด์ ์คํํฉ๋๋ค. ์ด์ธ๋ก ๋๊ปด์ง ์๋ ์์ง๋ง, ์๋์ผ๋ก ํ์
ํ๊ธฐ ์ด๋ ค์ด ๋ฏธ๋ฌํ ๋ฒ๊ทธ๋ฅผ ๋๋ฌ๋ด๋ ๋ฐ ๋์์ด ๋ฉ๋๋ค.
๋ค์ ์์๋ฅผ ์ดํด๋ด ์๋ค. ์ด ์์๋ ๋๋ฌผ์ ์ ํํ ํ ๋ชฉ๋ก ์ค ํ๋๋ก ์คํฌ๋กค ํ ์ ์๊ฒ ํด์ค๋๋ค. โcatsโ์์ โdogsโ๋ก ์ ํํ ๋ ์ฝ์ ๋ก๊ทธ๋ฅผ ๋ณด๋ฉด ๋ชฉ๋ก์ ์๋ ๋๋ฌผ์ ์๊ฐ ๊ณ์ ์ฆ๊ฐํ๊ณ , โScroll toโ ๋ฒํผ์ด ๋์ํ์ง ์๊ฒ ๋๋ ์ ์ ํ์ธํ ์ ์์ต๋๋ค.
import { useRef, useState } from "react"; export default function CatFriends() { const itemsRef = useRef([]); const [catList, setCatList] = useState(setupCatList); const [cat, setCat] = useState('neo'); function scrollToCat(index) { const list = itemsRef.current; const {node} = list[index]; node.scrollIntoView({ behavior: "smooth", block: "nearest", inline: "center", }); } const cats = catList.filter(c => c.type === cat) return ( <> <nav> <button onClick={() => setCat('neo')}>Neo</button> <button onClick={() => setCat('millie')}>Millie</button> </nav> <hr /> <nav> <span>Scroll to:</span>{cats.map((cat, index) => ( <button key={cat.src} onClick={() => scrollToCat(index)}> {index} </button> ))} </nav> <div> <ul> {cats.map((cat) => ( <li key={cat.src} ref={(node) => { const list = itemsRef.current; const item = {cat: cat, node}; list.push(item); console.log(`โ Adding cat to the map. Total cats: ${list.length}`); if (list.length > 10) { console.log('โ Too many cats in the list!'); } return () => { // ๐ฉ No cleanup, this is a bug! } }} > <img src={cat.src} /> </li> ))} </ul> </div> </> ); } function setupCatList() { const catList = []; for (let i = 0; i < 10; i++) { catList.push({type: 'neo', src: "https://placecats.com/neo/320/240?" + i}); } for (let i = 0; i < 10; i++) { catList.push({type: 'millie', src: "https://placecats.com/millie/320/240?" + i}); } return catList; }
์ด๊ฒ์ ํ๋ก๋์ ๋ฒ๊ทธ์ ๋๋ค! ref ์ฝ๋ฐฑ์ด ํด๋ฆฐ์ ๊ณผ์ ์์ ๋๋ฌผ ๋ชฉ๋ก์ ์ ๊ฑฐํ์ง ์์ผ๋ฏ๋ก ๋๋ฌผ ๋ชฉ๋ก์ด ๊ณ์ ์ฆ๊ฐํฉ๋๋ค. ์ด๋ ๋ฉ๋ชจ๋ฆฌ ๋์๋ฅผ ์ผ์ผ์ผ ์ค์ ์ฑ์์ ์ฑ๋ฅ ๋ฌธ์ ๋ฅผ ์ ๋ฐํ ์ ์์ผ๋ฉฐ, ์ฑ์ ๋์์ ๋ง๊ฐ๋จ๋ฆฝ๋๋ค.
๋ฌธ์ ๋ ref ์ฝ๋ฐฑ์ด ์ค์ค๋ก ํด๋ฆฐ์ ์ ํ์ง ์๋ ์ ์ ๋๋ค.
<li
ref={node => {
const list = itemsRef.current;
const item = {animal, node};
list.push(item);
return () => {
// ๐ฉ No cleanup, this is a bug!
}
}}
</li>์ด์ ์๋ณธ (๋ฒ๊ทธ๊ฐ ์๋) ์ฝ๋๋ฅผ <StrictMode>๋ก ๊ฐ์ธ๋ด
์๋ค.
import { useRef, useState } from "react"; export default function CatFriends() { const itemsRef = useRef([]); const [catList, setCatList] = useState(setupCatList); const [cat, setCat] = useState('neo'); function scrollToCat(index) { const list = itemsRef.current; const {node} = list[index]; node.scrollIntoView({ behavior: "smooth", block: "nearest", inline: "center", }); } const cats = catList.filter(c => c.type === cat) return ( <> <nav> <button onClick={() => setCat('neo')}>Neo</button> <button onClick={() => setCat('millie')}>Millie</button> </nav> <hr /> <nav> <span>Scroll to:</span>{cats.map((cat, index) => ( <button key={cat.src} onClick={() => scrollToCat(index)}> {index} </button> ))} </nav> <div> <ul> {cats.map((cat) => ( <li key={cat.src} ref={(node) => { const list = itemsRef.current; const item = {cat: cat, node}; list.push(item); console.log(`โ Adding cat to the map. Total cats: ${list.length}`); if (list.length > 10) { console.log('โ Too many cats in the list!'); } return () => { // ๐ฉ No cleanup, this is a bug! } }} > <img src={cat.src} /> </li> ))} </ul> </div> </> ); } function setupCatList() { const catList = []; for (let i = 0; i < 10; i++) { catList.push({type: 'neo', src: "https://placecats.com/neo/320/240?" + i}); } for (let i = 0; i < 10; i++) { catList.push({type: 'millie', src: "https://placecats.com/millie/320/240?" + i}); } return catList; }
Strict Mode๋ฅผ ์ฌ์ฉํ๋ฉด ๋ฌธ์ ๋ฅผ ์ฆ์ ์ฐพ์ ์ ์์ต๋๋ค. Strict Mode๋ ๋ชจ๋ ์ฝ๋ฐฑ ref์ ๋ํด ์ถ๊ฐ์ ์ธ ์ ์ +ํด๋ฆฐ์ ์ฌ์ดํด์ ์คํ ์คํํฉ๋๋ค. ์ด ์ฝ๋ฐฑ ref์๋ ํด๋ฆฐ์ ๋ก์ง์ด ์๊ธฐ ๋๋ฌธ์ ref๋ฅผ ์ถ๊ฐ๋ง ํ๊ณ ์ ๊ฑฐํ์ง ์์ต๋๋ค. ์ด๋ ํด๋ฆฐ์ ํจ์๊ฐ ๋๋ฝ๋์๋ค๋ ํํธ์ ๋๋ค.
Strict Mode๋ฅผ ํตํด ์ฝ๋ฐฑ ref์์ ๋ฐ์ํ๋ ์ค์๋ฅผ ์กฐ๊ธฐ์ ๋ฐ๊ฒฌํ ์ ์์ต๋๋ค. Strict Mode์์ ํด๋ฆฐ์ ํจ์๋ฅผ ์ถ๊ฐํด ์ฝ๋ฐฑ์ ์์ ํ๋ฉด, ์ด์ ์ ๋ฐ์ํ๋ โScroll toโ ๋ฒ๊ทธ์ ๊ฐ์ ๋ง์ ์ ์ฌ์ ์ธ ํ๋ก๋์ ๋ฒ๊ทธ๋ ํจ๊ป ํด๊ฒฐํ ์ ์์ต๋๋ค.
import { useRef, useState } from "react"; export default function CatFriends() { const itemsRef = useRef([]); const [catList, setCatList] = useState(setupCatList); const [cat, setCat] = useState('neo'); function scrollToCat(index) { const list = itemsRef.current; const {node} = list[index]; node.scrollIntoView({ behavior: "smooth", block: "nearest", inline: "center", }); } const cats = catList.filter(c => c.type === cat) return ( <> <nav> <button onClick={() => setCat('neo')}>Neo</button> <button onClick={() => setCat('millie')}>Millie</button> </nav> <hr /> <nav> <span>Scroll to:</span>{cats.map((cat, index) => ( <button key={cat.src} onClick={() => scrollToCat(index)}> {index} </button> ))} </nav> <div> <ul> {cats.map((cat) => ( <li key={cat.src} ref={(node) => { const list = itemsRef.current; const item = {cat: cat, node}; list.push(item); console.log(`โ Adding cat to the map. Total cats: ${list.length}`); if (list.length > 10) { console.log('โ Too many cats in the list!'); } return () => { list.splice(list.indexOf(item), 1); console.log(`โ Removing cat from the map. Total cats: ${itemsRef.current.length}`); } }} > <img src={cat.src} /> </li> ))} </ul> </div> </> ); } function setupCatList() { const catList = []; for (let i = 0; i < 10; i++) { catList.push({type: 'neo', src: "https://placecats.com/neo/320/240?" + i}); } for (let i = 0; i < 10; i++) { catList.push({type: 'millie', src: "https://placecats.com/millie/320/240?" + i}); } return catList; }
์ด์ StrictMode์์ ์ด๊ธฐ ๋ง์ดํธ ์, ref ์ฝ๋ฐฑ์ด ๋ชจ๋ ์ ์ ๋๊ณ , ํด๋ฆฐ์ ํ, ๋ค์ ์ ์ ๋ฉ๋๋ค.
...
โ
๋๋ฌผ์ ๋ชฉ๋ก์ ์ถ๊ฐํ๋ ์ค. ์ด ๋๋ฌผ ์: 10
...
โ ๋ชฉ๋ก์์ ๋๋ฌผ์ ์ ๊ฑฐํฉ๋๋ค. ์ด ๋๋ฌผ ์: 0
...
โ
๋๋ฌผ์ ๋ชฉ๋ก์ ์ถ๊ฐํ๋ ์ค. ์ด ๋๋ฌผ ์: 10์ด๊ฒ์ด ์์๋ ๊ฒฐ๊ณผ์ ๋๋ค. Strict Mode๋ ref ์ฝ๋ฐฑ์ด ์ฌ๋ฐ๋ฅด๊ฒ ํด๋ฆฐ์ ๋์๋์ง ํ์ธํด ์ฃผ๊ธฐ ๋๋ฌธ์ ํฌ๊ธฐ๊ฐ ์์๋ ์์ ์ด๊ณผํ์ง ์์ต๋๋ค. ์์ ํ์๋ ๋ฉ๋ชจ๋ฆฌ ๋์๊ฐ ๋ฐ์ํ์ง ์์ผ๋ฉฐ, ๋ชจ๋ ๊ธฐ๋ฅ์ด ์์๋๋ก ์๋ํฉ๋๋ค.
Strict Mode ์์ด๋ ๊ณ ์ฅ ๋ ๊ธฐ๋ฅ์ ์์์ฐจ๋ฆด ๋๊น์ง ์ฌ๊ธฐ์ ๊ธฐ ํด๋ฆญํด์ผ ํ๋ฏ๋ก ๋ฒ๊ทธ๋ฅผ ๋์น๊ธฐ ์ฝ์ต๋๋ค. Strict Mode๋ ๋ฒ๊ทธ๋ฅผ ์ฆ์ ๋๋ฌ๋๋๋ก ํ์ฌ ํ๋ก๋์ ์ ๋ฐฐํฌํ๊ธฐ ์ ์ ๋ฌธ์ ๋ฅผ ๋ฐ๊ฒฌํ ์ ์์ต๋๋ค.
Fixing deprecation warnings enabled by Strict Mode
React๋ <StrictMode> ํธ๋ฆฌ ๋ด๋ถ์ ์ปดํฌ๋ํธ๊ฐ ๋ ์ด์ ์ฌ์ฉ๋์ง ์๋ ๋ค์ API ์ค ํ๋๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ ๊ฒฝ๊ณ ๋ฅผ ํ์ํฉ๋๋ค.
UNSAFE_componentWillMount์ ๊ฐ์UNSAFE_ํด๋์ค ์๋ช ์ฃผ๊ธฐ ๋ฉ์๋. ๋์ ํ์ธํ๊ธฐ.
์ด๋ฌํ API๋ ์ฃผ๋ก ์ด์ ํด๋์ค ์ปดํฌ๋ํธ์์ ์ฌ์ฉ๋๋ฏ๋ก ์ต์ ์ฑ์์๋ ๊ฑฐ์ ๋ํ๋์ง ์์ต๋๋ค.