<StrictMode>๋Š” ๊ฐœ๋ฐœ ์ค‘์— ์ปดํฌ๋„ŒํŠธ์—์„œ ์ผ๋ฐ˜์ ์ธ ๋ฒ„๊ทธ๋ฅผ ๋น ๋ฅด๊ฒŒ ์ฐพ์„ ์ˆ˜ ์žˆ๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.

<StrictMode>
<App />
</StrictMode>

๋ ˆํผ๋Ÿฐ์Šค

<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๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ฐœ๋ฐœ ์ „์šฉ ๋™์ž‘์„ ํ™œ์„ฑํ™”ํ•ฉ๋‹ˆ๋‹ค.

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 ํ™œ์„ฑํ™”

์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์–ด๋–ค ๋ถ€๋ถ„์—์„œ๋ผ๋„ 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๋Š” ์‹ค์ˆ˜๋กœ ์ž‘์„ฑ๋œ ์ˆœ์ˆ˜ํ•˜์ง€ ์•Š์€ ์ฝ”๋“œ๋ฅผ ์ฐพ์•„๋‚ด๊ธฐ ์œ„ํ•ด ๋ช‡ ๊ฐ€์ง€ ํ•จ์ˆ˜(์ˆœ์ˆ˜ ํ•จ์ˆ˜์—ฌ์•ผ ํ•˜๋Š” ๊ฒƒ๋งŒ)๋ฅผ ๊ฐœ๋ฐœ ํ™˜๊ฒฝ์—์„œ ๋‘ ๋ฒˆ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค. ์ด์—๋Š” ๋‹ค์Œ์ด ํฌํ•จ๋ฉ๋‹ˆ๋‹ค.

ํ•จ์ˆ˜๊ฐ€ ์ˆœ์ˆ˜ํ•œ ๊ฒฝ์šฐ ๋‘ ๋ฒˆ ์‹คํ–‰ํ•˜์—ฌ๋„ ๋™์ž‘์ด ๋ณ€๊ฒฝ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ˆœ์ˆ˜ ํ•จ์ˆ˜๋Š” ํ•ญ์ƒ ๊ฐ™์€ ๊ฒฐ๊ณผ๋ฅผ ์ƒ์„ฑํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ํ•จ์ˆ˜๊ฐ€ ์ˆœ์ˆ˜ํ•˜์ง€ ์•Š๋‹ค๋ฉด (์˜ˆ: ๋ฐ›์€ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณ€๊ฒฝํ•˜๋Š” ํ•จ์ˆ˜) ๋‘ ๋ฒˆ ์‹คํ–‰ํ•˜๋ฉด ๋ณดํ†ต ์•Œ์•„์ฑŒ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. (์ด๊ฒƒ์ด ์ˆœ์ˆ˜ํ•˜์ง€ ์•Š์€ ์ด์œ ์ž…๋‹ˆ๋‹ค!) ์ด๋Š” ๋ฒ„๊ทธ๋ฅผ ์กฐ๊ธฐ์— ๋ฐœ๊ฒฌํ•˜๊ณ  ์ˆ˜์ •ํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋ฉ๋‹ˆ๋‹ค.

๋‹ค์Œ์€ 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>
  );
}

์œ„ ์ฝ”๋“œ์—๋Š” ์‹ค์ˆ˜๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ดˆ๊ธฐ ์ถœ๋ ฅ์ด ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ๋‚˜ํƒ€๋‚˜๊ธฐ ๋•Œ๋ฌธ์— ๋†“์น˜๊ธฐ ์‰ฝ์Šต๋‹ˆ๋‹ค.

์ด ์‹ค์ˆ˜๋Š” StoryTray ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์—ฌ๋Ÿฌ ๋ฒˆ ๋‹ค์‹œ ๋ Œ๋”๋งํ•˜๋ฉด ๋” ๋ˆˆ์— ๋„๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด StoryTray์— ๋งˆ์šฐ์Šค๋ฅผ ์˜ฌ๋ ค๋†“์„ ๋•Œ๋งˆ๋‹ค ๋‹ค๋ฅธ ๋ฐฐ๊ฒฝ์ƒ‰์œผ๋กœ ๋‹ค์‹œ ๋ Œ๋”๋งํ•˜๋„๋ก ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

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๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋ฒ„๊ทธ๋ฅผ ํŒ€๊ณผ ์‚ฌ์šฉ์ž์—๊ฒŒ ํ‘ธ์‹œํ•˜๊ธฐ ์ „์— ๋ฐœ๊ฒฌํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋ฉ๋‹ˆ๋‹ค.

์ปดํฌ๋„ŒํŠธ๋ฅผ ์ˆœ์ˆ˜ํ•˜๊ฒŒ ์œ ์ง€ํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ์ž์„ธํžˆ ์•Œ์•„๋ณด์„ธ์š”.

์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค!

React DevTools๊ฐ€ ์„ค์น˜๋˜์–ด ์žˆ๋‹ค๋ฉด, ๋‘ ๋ฒˆ์งธ ๋ Œ๋”๋ง ํ˜ธ์ถœ ์ค‘ console.log ํ˜ธ์ถœ์ด ์•ฝ๊ฐ„ ํ๋ฆฌ๊ฒŒ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค. React ๊ฐœ๋ฐœ์ž ๋„๊ตฌ๋Š” ์ด๋ฅผ ์™„์ „ํžˆ ์–ต์ œํ•˜๋Š” ์„ค์ •(๊ธฐ๋ณธ๊ฐ’์€ ๊บผ์ง)๋„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.


๊ฐœ๋ฐœ ํ™˜๊ฒฝ์—์„œ Effect๋ฅผ ๋‹ค์‹œ ์‹คํ–‰ํ•˜์—ฌ ๋ฐœ๊ฒฌ๋œ ๋ฒ„๊ทธ ์ˆ˜์ •

Strict Mode๋Š” Effects์˜ ๋ฒ„๊ทธ๋ฅผ ์ฐพ๋Š” ๋ฐ๋„ ๋„์›€์ด ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ชจ๋“  Effect์—๋Š” ๋ช‡ ๊ฐ€์ง€ ์…‹์—… ์ฝ”๋“œ๊ฐ€ ์žˆ๊ณ  ์–ด์ฉŒ๋ฉด ํด๋ฆฐ์—… ์ฝ”๋“œ๊ฐ€ ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ผ๋ฐ˜์ ์œผ๋กœ React๋Š” ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋งˆ์šดํŠธ(ํ™”๋ฉด์— ์ถ”๊ฐ€)๋  ๋•Œ ์…‹์—…์„ ํ˜ธ์ถœํ•˜๊ณ  ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋งˆ์šดํŠธ ํ•ด์ œ(ํ™”๋ฉด์—์„œ ์ œ๊ฑฐ)๋  ๋•Œ ํด๋ฆฐ์—…์„ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ React๋Š” ๋งˆ์ง€๋ง‰ ๋ Œ๋”๋ง ์ดํ›„๋กœ๋ถ€ํ„ฐ ์˜์กด์„ฑ์ด ๋ณ€๊ฒฝ๋œ ๊ฒฝ์šฐ ํด๋ฆฐ์—…๊ณผ ์…‹์—…์„ ๋‹ค์‹œ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค.

Strict Mode๊ฐ€ ์ผœ์ ธ ์žˆ์œผ๋ฉด React๋Š” ๋ชจ๋“  Effect์— ๋Œ€ํ•ด ๊ฐœ๋ฐœ ํ™˜๊ฒฝ์—์„œ ํ•œ ๋ฒˆ ๋” ์…‹์—…+ํด๋ฆฐ์—… ์‚ฌ์ดํด์„ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค. ์˜์™ธ๋กœ ๋Š๊ปด์งˆ ์ˆ˜๋„ ์žˆ์ง€๋งŒ ์ˆ˜๋™์œผ๋กœ ํŒŒ์•…ํ•˜๊ธฐ ์–ด๋ ค์šด ๋ฏธ๋ฌ˜ํ•œ ๋ฒ„๊ทธ๋ฅผ ๋“œ๋Ÿฌ๋‚ด๋Š” ๋ฐ ๋„์›€์ด ๋ฉ๋‹ˆ๋‹ค.

๋‹ค์Œ์€ Strict Mode์—์„œ Effects๋ฅผ ๋‹ค์‹œ ์‹คํ–‰ํ•˜๋Š” ๊ฒƒ์ด ๋ฒ„๊ทธ๋ฅผ ์กฐ๊ธฐ์— ๋ฐœ๊ฒฌํ•˜๋Š” ๋ฐ ์–ด๋–ป๊ฒŒ ๋„์›€์ด ๋˜๋Š”์ง€ ๋ณด์—ฌ์ฃผ๋Š” ์˜ˆ์‹œ์ž…๋‹ˆ๋‹ค.

์ปดํฌ๋„ŒํŠธ๋ฅผ ์ฑ„ํŒ…์— ์—ฐ๊ฒฐํ•˜๋Š” ์ด ์˜ˆ์‹œ๋ฅผ ์‚ดํŽด๋ด…์‹œ๋‹ค.

import { useState, useEffect } from 'react';
import { createConnection } from './chat.js';

const serverUrl = 'https://localhost:1234';
const roomId = '์ผ๋ฐ˜';

export default function ChatRoom() {
  useEffect(() => {
    const connection = createConnection(serverUrl, roomId);
    connection.connect();
  }, []);
  return <h1>{roomId} ๋ฐฉ์— ์˜ค์‹  ๊ฒƒ์„ ํ™˜์˜ํ•ฉ๋‹ˆ๋‹ค!</h1>;
}

์ด ์ฝ”๋“œ์—๋Š” ๋ฌธ์ œ๊ฐ€ ์žˆ์ง€๋งŒ ์ฆ‰์‹œ ํŒŒ์•…ํ•˜๊ธฐ ์–ด๋ ค์šธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ฌธ์ œ๋ฅผ ๋” ๋ช…ํ™•ํ•˜๊ฒŒ ๋“œ๋Ÿฌ๋‚ด๊ธฐ ์œ„ํ•ด ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ์•„๋ž˜ ์˜ˆ์‹œ์—์„œ๋Š” roomId๊ฐ€ ํ•˜๋“œ์ฝ”๋”ฉ๋˜์–ด ์žˆ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋Œ€์‹  ์‚ฌ์šฉ์ž๊ฐ€ ์—ฐ๊ฒฐํ•˜๋ ค๋Š” roomId๋ฅผ ๋“œ๋กญ๋‹ค์šด์—์„œ ์„ ํƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. โ€œ๋Œ€ํ™” ์—ด๊ธฐโ€์„ ํด๋ฆญํ•œ ๋‹ค์Œ ๋‹ค๋ฅธ ๋Œ€ํ™”๋ฐฉ์„ ํ•˜๋‚˜์”ฉ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค. ์ฝ˜์†”์—์„œ ํ™œ์„ฑํ™”๋œ ์—ฐ๊ฒฐ ์ˆ˜๋ฅผ ์ถ”์ ํ•ฉ๋‹ˆ๋‹ค.

import { useState, useEffect } from 'react';
import { createConnection } from './chat.js';

const serverUrl = 'https://localhost:1234';

function ChatRoom({ roomId }) {
  useEffect(() => {
    const connection = createConnection(serverUrl, roomId);
    connection.connect();
  }, [roomId]);

  return <h1>{roomId} ๋ฐฉ์— ์˜ค์‹  ๊ฒƒ์„ ํ™˜์˜ํ•ฉ๋‹ˆ๋‹ค!</h1>;
}

export default function App() {
  const [roomId, setRoomId] = useState('์ผ๋ฐ˜');
  const [show, setShow] = useState(false);
  return (
    <>
      <label>
        ๋Œ€ํ™”๋ฐฉ ์„ ํƒํ•˜๊ธฐ:{' '}
        <select
          value={roomId}
          onChange={e => setRoomId(e.target.value)}
        >
          <option value="์ผ๋ฐ˜">์ผ๋ฐ˜</option>
          <option value="์—ฌํ–‰">์—ฌํ–‰</option>
          <option value="์Œ์•…">์Œ์•…</option>
        </select>
      </label>
      <button onClick={() => setShow(!show)}>
        {show ? '๋Œ€ํ™” ๋‹ซ๊ธฐ' : '๋Œ€ํ™” ์—ด๊ธฐ'}
      </button>
      {show && <hr />}
      {show && <ChatRoom roomId={roomId} />}
    </>
  );
}

์—ด๋ฆฐ ์—ฐ๊ฒฐ ์ˆ˜๊ฐ€ ํ•ญ์ƒ ๊ณ„์† ์ฆ๊ฐ€ํ•˜๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์‹ค์ œ ์•ฑ์—์„œ๋Š” ์„ฑ๋Šฅ ๋ฐ ๋„คํŠธ์›Œํฌ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฌธ์ œ๋Š” Effect์— ํด๋ฆฐ์—… ํ•จ์ˆ˜๊ฐ€ ๋ˆ„๋ฝ๋˜์—ˆ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

useEffect(() => {
const connection = createConnection(serverUrl, roomId);
connection.connect();
return () => connection.disconnect();
}, [roomId]);

์ด์ œ Effect๊ฐ€ ์ž์ฒด์ ์œผ๋กœ โ€œํด๋ฆฐ์—…โ€ํ•˜๊ณ  ์˜ค๋ž˜๋œ ์—ฐ๊ฒฐ์„ ํŒŒ๊ดดํ•˜๋ฏ€๋กœ ๋ˆ„์ˆ˜๊ฐ€ ํ•ด๊ฒฐ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๋” ๋งŽ์€ ๊ธฐ๋Šฅ(์„ ํƒ ์ƒ์ž)์„ ์ถ”๊ฐ€ํ•˜๊ธฐ ์ „๊นŒ์ง€๋Š” ๋ฌธ์ œ๊ฐ€ ๋“œ๋Ÿฌ๋‚˜์ง€ ์•Š์•˜์Œ์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์›๋ž˜ ์˜ˆ์‹œ์—์„œ๋Š” ๋ฒ„๊ทธ๊ฐ€ ๋ช…ํ™•ํ•˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. ์ด์ œ ์›๋ž˜ (๋ฒ„๊ทธ๊ฐ€ ์žˆ๋Š”) ์ฝ”๋“œ๋ฅผ <StrictMode>๋กœ ๋ž˜ํ•‘ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

import { useState, useEffect } from 'react';
import { createConnection } from './chat.js';

const serverUrl = 'https://localhost:1234';
const roomId = '์ผ๋ฐ˜';

export default function ChatRoom() {
  useEffect(() => {
    const connection = createConnection(serverUrl, roomId);
    connection.connect();
  }, []);
  return <h1>{roomId} ๋ฐฉ์— ์˜ค์‹  ๊ฒƒ์„ ํ™˜์˜ํ•ฉ๋‹ˆ๋‹ค!</h1>;
}

Strict Mode๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋ฌธ์ œ๊ฐ€ ์žˆ์Œ์„ ์ฆ‰์‹œ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(ํ™œ์„ฑํ™”๋œ ์—ฐ๊ฒฐ ์ˆ˜๊ฐ€ 2๊ฐœ๋กœ ์ฆ๊ฐ€ํ•จ). Strict Mode๋Š” ๋ชจ๋“  Effect์— ๋Œ€ํ•ด ์ถ”๊ฐ€ ์…‹์—…+ํด๋ฆฐ์—… ์‚ฌ์ดํด์„ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค. ์ด Effect์—๋Š” ํด๋ฆฐ์—… ๋กœ์ง์ด ์—†์œผ๋ฏ€๋กœ ์ถ”๊ฐ€ ์—ฐ๊ฒฐ์„ ์ƒ์„ฑํ•˜์ง€๋งŒ ํŒŒ๊ดดํ•˜์ง€๋Š” ์•Š์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ํด๋ฆฐ์—… ํ•จ์ˆ˜๊ฐ€ ๋ˆ„๋ฝ๋˜์—ˆ๋‹ค๋Š” ํžŒํŠธ์ž…๋‹ˆ๋‹ค.

Strict Mode๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ด๋Ÿฌํ•œ ์‹ค์ˆ˜๋ฅผ ํ”„๋กœ์„ธ์Šค ์ดˆ๊ธฐ์— ๋ฐœ๊ฒฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. Strict Mode์—์„œ ํด๋ฆฐ์—… ํ•จ์ˆ˜๋ฅผ ์ถ”๊ฐ€ํ•˜์—ฌ Effect๋ฅผ ์ˆ˜์ •ํ•˜๋ฉด ์ด์ „์˜ ์„ ํƒ ์ƒ์ž์™€ ๊ฐ™์ด ํ–ฅํ›„ ํ”„๋กœ๋•์…˜์—์„œ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ๋งŽ์€ ๋ฒ„๊ทธ ๋˜ํ•œ ์ˆ˜์ •ํ•ฉ๋‹ˆ๋‹ค.

import { useState, useEffect } from 'react';
import { createConnection } from './chat.js';

const serverUrl = 'https://localhost:1234';

function ChatRoom({ roomId }) {
  useEffect(() => {
    const connection = createConnection(serverUrl, roomId);
    connection.connect();
    return () => connection.disconnect();
  }, [roomId]);

  return <h1>{roomId} ๋ฐฉ์— ์˜ค์‹  ๊ฒƒ์„ ํ™˜์˜ํ•ฉ๋‹ˆ๋‹ค!</h1>;
}

export default function App() {
  const [roomId, setRoomId] = useState('์ผ๋ฐ˜');
  const [show, setShow] = useState(false);
  return (
    <>
      <label>
        ๋Œ€ํ™”๋ฐฉ ์„ ํƒํ•˜๊ธฐ:{' '}
        <select
          value={roomId}
          onChange={e => setRoomId(e.target.value)}
        >
          <option value="์ผ๋ฐ˜">์ผ๋ฐ˜</option>
          <option value="์—ฌํ–‰">์—ฌํ–‰</option>
          <option value="์Œ์•…">์Œ์•…</option>
        </select>
      </label>
      <button onClick={() => setShow(!show)}>
        {show ? '๋Œ€ํ™” ๋‹ซ๊ธฐ' : '๋Œ€ํ™” ์—ด๊ธฐ'}
      </button>
      {show && <hr />}
      {show && <ChatRoom roomId={roomId} />}
    </>
  );
}

์ฝ˜์†”์˜ ํ™œ์„ฑํ™”๋œ ์—ฐ๊ฒฐ ์ˆ˜๊ฐ€ ๋” ์ด์ƒ ์ฆ๊ฐ€ํ•˜์ง€ ์•Š๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Strict Mode๊ฐ€ ์—†์œผ๋ฉด Effect๋ฅผ ํด๋ฆฐ์—…ํ•ด์•ผ ํ•œ๋‹ค๋Š” ์‚ฌ์‹ค์„ ๋†“์น˜๊ธฐ ์‰ฌ์› ์Šต๋‹ˆ๋‹ค. ๊ฐœ๋ฐœ ํ™˜๊ฒฝ์—์„œ Effect์— ๋Œ€ํ•ด ์…‹์—… ๋Œ€์‹  ์…‹์—… โ†’ ํด๋ฆฐ์—… โ†’ ์…‹์—…์„ ์‹คํ–‰ํ•˜๋ฉด Strict Mode์—์„œ ๋ˆ„๋ฝ๋œ ํด๋ฆฐ์—… ๋กœ์ง์ด ๋” ๋ˆˆ์— ๋„๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

Effect ํด๋ฆฐ์—…์„ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ์ž์„ธํžˆ ์•Œ์•„๋ณด์„ธ์š”.


Strict Mode์— ์˜ํ•ด ํ™œ์„ฑํ™”๋œ ์‚ฌ์šฉ ์ค‘๋‹จ ๊ฒฝ๊ณ  ์ˆ˜์ •

React๋Š” <StrictMode> ํŠธ๋ฆฌ ๋‚ด๋ถ€์˜ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋” ์ด์ƒ ์‚ฌ์šฉ๋˜์ง€ ์•Š๋Š” ๋‹ค์Œ API ์ค‘ ํ•˜๋‚˜๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ ๊ฒฝ๊ณ ๋ฅผ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค.

์ด๋Ÿฌํ•œ API๋Š” ์ฃผ๋กœ ์ด์ „ ํด๋ž˜์Šค ์ปดํฌ๋„ŒํŠธ์—์„œ ์‚ฌ์šฉ๋˜๋ฏ€๋กœ ์ตœ์‹  ์•ฑ์—์„œ๋Š” ๊ฑฐ์˜ ๋‚˜ํƒ€๋‚˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.