From 9534dc7accffdb02054f284c93e187f177dcbb9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=A3=A8=EB=B0=80LuMir?= Date: Wed, 27 May 2026 19:41:33 +0900 Subject: [PATCH 1/2] docs: fix typos --- .../learn/lifecycle-of-reactive-effects.md | 2 +- .../learn/removing-effect-dependencies.md | 48 +++++++++---------- src/content/reference/react/useEffect.md | 2 +- src/content/reference/react/useRef.md | 10 ++-- .../reference/react/useSyncExternalStore.md | 46 +++++++++--------- 5 files changed, 54 insertions(+), 54 deletions(-) diff --git a/src/content/learn/lifecycle-of-reactive-effects.md b/src/content/learn/lifecycle-of-reactive-effects.md index a54ce29b2..0a1d9ff78 100644 --- a/src/content/learn/lifecycle-of-reactive-effects.md +++ b/src/content/learn/lifecycle-of-reactive-effects.md @@ -753,7 +753,7 @@ function ChatRoom() { useEffect(() => { // ... // ๐Ÿ”ด ์ด๋Ÿฐ ์‹์œผ๋กœ ๋ฆฐํŠธ๋ฅผ ์–ต๋ˆ„๋ฅด์ง€ ๋งˆ์„ธ์š”. - // eslint-ignore-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line react-hooks/exhaustive-deps }, []); ``` diff --git a/src/content/learn/removing-effect-dependencies.md b/src/content/learn/removing-effect-dependencies.md index 2a8ce4a0c..b2c4cb5a9 100644 --- a/src/content/learn/removing-effect-dependencies.md +++ b/src/content/learn/removing-effect-dependencies.md @@ -18,7 +18,7 @@ Effect๋ฅผ ์ž‘์„ฑํ•˜๋ฉด ๋ฆฐํ„ฐ๋Š” Effect์˜ ์˜์กด์„ฑ ๋ชฉ๋ก์— Effect๊ฐ€ ์ฝ๋Š” -## ์˜์กด์„ฑ์€ ์ฝ”๋“œ์™€ ์ผ์น˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. {/*dependencies-should-match-the-code*/} +## ์˜์กด์„ฑ์€ ์ฝ”๋“œ์™€ ์ผ์น˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค {/*dependencies-should-match-the-code*/} Effect๋ฅผ ์ž‘์„ฑํ•  ๋•Œ๋Š” ๋จผ์ € Effect๊ฐ€ ์ˆ˜ํ–‰ํ•˜๊ธฐ๋ฅผ ์›ํ•˜๋Š” ์ž‘์—…์„ [์‹œ์ž‘ํ•˜๊ณ  ์ค‘์ง€](/learn/lifecycle-of-reactive-effects#the-lifecycle-of-an-effect)ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค. @@ -96,7 +96,7 @@ button { margin-left: 10px; } -๋ฆฐํ„ฐ์— ํ‘œ์‹œ๋œ ๋‚ด์šฉ์— ๋”ฐ๋ผ ์ฑ„์šฐ์„ธ์š”: +๋ฆฐํ„ฐ์— ํ‘œ์‹œ๋œ ๋‚ด์šฉ์— ๋”ฐ๋ผ ์ฑ„์šฐ์„ธ์š”. ```js {6} function ChatRoom({ roomId }) { @@ -205,7 +205,7 @@ function ChatRoom({ roomId }) { ๊ทธ๋ฆฌ๊ณ  ๋ฆฐํ„ฐ๊ฐ€ ๋งž์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค! `roomId`๋Š” ์‹œ๊ฐ„์ด ์ง€๋‚จ์— ๋”ฐ๋ผ ๋ณ€๊ฒฝ๋  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ์ฝ”๋“œ์— ๋ฒ„๊ทธ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -**์˜์กด์„ฑ์„ ์ œ๊ฑฐํ•˜๋ ค๋ฉด ํ•ด๋‹น ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์˜์กด์„ฑ์ด ๋  *ํ•„์š”๊ฐ€ ์—†๋‹ค๋Š” ๊ฒƒ*์„ ๋ฆฐํ„ฐ์— "์ฆ๋ช…"ํ•˜์„ธ์š”.** ์˜ˆ๋ฅผ ๋“ค์–ด `roomId`๋ฅผ ์ปดํฌ๋„ŒํŠธ ๋ฐ–์œผ๋กœ ์ด๋™์‹œ์ผœ์„œ ๋ฐ˜์‘ํ˜•๊ฐ’์ด ์•„๋‹ˆ๊ณ  ์žฌ๋ Œ๋”๋ง ์‹œ์—๋„ ๋ณ€๊ฒฝ๋˜์ง€ ์•Š์Œ์„ ์ฆ๋ช…ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +**์˜์กด์„ฑ์„ ์ œ๊ฑฐํ•˜๋ ค๋ฉด ํ•ด๋‹น ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์˜์กด์„ฑ์ด ๋  *ํ•„์š”๊ฐ€ ์—†๋‹ค๋Š” ๊ฒƒ*์„ ๋ฆฐํ„ฐ์— "์ฆ๋ช…"ํ•˜์„ธ์š”.** ์˜ˆ๋ฅผ ๋“ค์–ด `roomId`๋ฅผ ์ปดํฌ๋„ŒํŠธ ๋ฐ–์œผ๋กœ ์ด๋™์‹œ์ผœ์„œ ๋ฐ˜์‘ํ˜• ๊ฐ’์ด ์•„๋‹ˆ๊ณ  ์žฌ๋ Œ๋”๋ง ์‹œ์—๋„ ๋ณ€๊ฒฝ๋˜์ง€ ์•Š์Œ์„ ์ฆ๋ช…ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ```js {2,9} const serverUrl = 'https://localhost:1234'; @@ -265,7 +265,7 @@ button { margin-left: 10px; } ์ด๊ฒƒ์ด [๋นˆ(`[]`) ์˜์กด์„ฑ ๋ชฉ๋ก](/learn/lifecycle-of-reactive-effects#what-an-effect-with-empty-dependencies-means)์„ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋Š” ์ด์œ ์ž…๋‹ˆ๋‹ค. Effect๋Š” ๋” ์ด์ƒ ๋ฐ˜์‘ํ˜• ๊ฐ’์— ์˜์กดํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ ์ปดํฌ๋„ŒํŠธ์˜ props๋‚˜ State๊ฐ€ ๋ณ€๊ฒฝ๋  ๋•Œ Effect๋ฅผ ๋‹ค์‹œ ์‹คํ–‰ํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. -### ์˜์กด์„ฑ์„ ๋ณ€๊ฒฝํ•˜๋ ค๋ฉด ์ฝ”๋“œ๋ฅผ ๋ณ€๊ฒฝํ•˜์„ธ์š”. {/*to-change-the-dependencies-change-the-code*/} +### ์˜์กด์„ฑ์„ ๋ณ€๊ฒฝํ•˜๋ ค๋ฉด ์ฝ”๋“œ๋ฅผ ๋ณ€๊ฒฝํ•˜์„ธ์š” {/*to-change-the-dependencies-change-the-code*/} ์ž‘์—… ํ๋ฆ„์—์„œ ํŒจํ„ด์„ ๋ฐœ๊ฒฌํ–ˆ์„ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. @@ -284,7 +284,7 @@ button { margin-left: 10px; } ```js {3-4} useEffect(() => { // ... - // ๐Ÿ”ด ์ด๋ ‡๊ฒŒ ๋ฆฐํ„ฐ๋ฅผ ์–ต์ œํ•˜์ง€ ๋งˆ์„ธ์š”: + // ๐Ÿ”ด ์ด๋ ‡๊ฒŒ ๋ฆฐํ„ฐ๋ฅผ ์–ต์ œํ•˜์ง€ ๋งˆ์„ธ์š”. // eslint-disable-next-line react-hooks/exhaustive-deps }, []); ``` @@ -328,7 +328,7 @@ export default function Timer() {

- Every second, increment by: + Every second, increment by. @@ -350,7 +350,7 @@ button { margin: 10px; } "๋งˆ์šดํŠธํ•  ๋•Œ๋งŒ" Effect๋ฅผ ์‹คํ–‰ํ•˜๊ณ  ์‹ถ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด ๋ด…์‹œ๋‹ค. [๋นˆ(`[]`) ์˜์กด์„ฑ](/learn/lifecycle-of-reactive-effects#what-an-effect-with-empty-dependencies-means)์ด ๊ทธ๋ ‡๊ฒŒ ํ•œ๋‹ค๋Š” ๊ฒƒ์„ ์ฝ์—ˆ์œผ๋ฏ€๋กœ ๋ฆฐํ„ฐ๋ฅผ ๋ฌด์‹œํ•˜๊ณ  `[]` ์˜์กด์„ฑ์„ ๊ฐ•์ œ๋กœ ์ง€์ •ํ•˜๊ธฐ๋กœ ๊ฒฐ์ •ํ–ˆ์Šต๋‹ˆ๋‹ค. -์ด ์นด์šดํ„ฐ๋Š” ๋‘ ๊ฐœ์˜ ๋ฒ„ํŠผ์œผ๋กœ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋Š” ์–‘๋งŒํผ ๋งค์ดˆ๋งˆ๋‹ค ์ฆ๊ฐ€ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ด Effect๊ฐ€ ์•„๋ฌด ๊ฒƒ๋„ ์˜์กดํ•˜์ง€ ์•Š๋Š”๋‹ค๊ณ  React์— "๊ฑฐ์ง“๋ง"์„ ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์—, React๋Š” ์ดˆ๊ธฐ ๋ Œ๋”๋ง์—์„œ ๊ณ„์† `onTick` ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. [์ด ๋ Œ๋”๋ง์—์„œ](/learn/state-as-a-snapshot#rendering-takes-a-snapshot-in-time) `count`๋Š” `0`์ด์—ˆ๊ณ  `increment`๋Š” `1`์ด์—ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์ด ๋ Œ๋”๋ง์˜ `onTick`์€ ํ•ญ์ƒ ๋งค์ดˆ๋งˆ๋‹ค `setCount(0 + 1)`๋ฅผ ํ˜ธ์ถœํ•˜๊ณ  ํ•ญ์ƒ `1`์ด ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค. ์ด์™€ ๊ฐ™์€ ๋ฒ„๊ทธ๋Š” ์—ฌ๋Ÿฌ ์ปดํฌ๋„ŒํŠธ์— ๋ถ„์‚ฐ๋˜์–ด ์žˆ์„ ๋•Œ ์ˆ˜์ •ํ•˜๊ธฐ๊ฐ€ ๋” ์–ด๋ ต์Šต๋‹ˆ๋‹ค. +์ด ์นด์šดํ„ฐ๋Š” ๋‘ ๊ฐœ์˜ ๋ฒ„ํŠผ์œผ๋กœ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋Š” ์–‘๋งŒํผ ๋งค์ดˆ๋งˆ๋‹ค ์ฆ๊ฐ€ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ด Effect๊ฐ€ ์–ด๋–ค ๊ฒƒ์—๋„ ์˜์กดํ•˜์ง€ ์•Š๋Š”๋‹ค๊ณ  React์— "๊ฑฐ์ง“๋ง"์„ ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์—, React๋Š” ์ดˆ๊ธฐ ๋ Œ๋”๋ง์—์„œ ๊ณ„์† `onTick` ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. [์ด ๋ Œ๋”๋ง์—์„œ](/learn/state-as-a-snapshot#rendering-takes-a-snapshot-in-time) `count`๋Š” `0`์ด์—ˆ๊ณ  `increment`๋Š” `1`์ด์—ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์ด ๋ Œ๋”๋ง์˜ `onTick`์€ ํ•ญ์ƒ ๋งค์ดˆ๋งˆ๋‹ค `setCount(0 + 1)`๋ฅผ ํ˜ธ์ถœํ•˜๊ณ  ํ•ญ์ƒ `1`์ด ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค. ์ด์™€ ๊ฐ™์€ ๋ฒ„๊ทธ๋Š” ์—ฌ๋Ÿฌ ์ปดํฌ๋„ŒํŠธ์— ๋ถ„์‚ฐ๋˜์–ด ์žˆ์„ ๋•Œ ์ˆ˜์ •ํ•˜๊ธฐ๊ฐ€ ๋” ์–ด๋ ต์Šต๋‹ˆ๋‹ค. ๋ฆฐํ„ฐ๋ฅผ ๋ฌด์‹œํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค ๋” ์ข‹์€ ํ•ด๊ฒฐ์ฑ…์€ ํ•ญ์ƒ ์žˆ์Šต๋‹ˆ๋‹ค! ์ด ์ฝ”๋“œ๋ฅผ ์ˆ˜์ •ํ•˜๋ ค๋ฉด ์˜์กด์„ฑ ๋ชฉ๋ก์— `onTick`์„ ์ถ”๊ฐ€ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. (interval์„ ํ•œ ๋ฒˆ๋งŒ ์„ค์ •ํ•˜๋ ค๋ฉด [`onTick`์„ Effect ์ด๋ฒคํŠธ๋กœ ๋งŒ๋“œ์„ธ์š”.](/learn/separating-events-from-effects#reading-latest-props-and-state-with-effect-events)) @@ -360,7 +360,7 @@ button { margin: 10px; } ## ๋ถˆํ•„์š”ํ•œ ์˜์กด์„ฑ ์ œ๊ฑฐํ•˜๊ธฐ {/*removing-unnecessary-dependencies*/} -์ฝ”๋“œ๋ฅผ ๋ฐ˜์˜ํ•˜๊ธฐ ์œ„ํ•ด Effect์˜ ์˜์กด์„ฑ์„ ์กฐ์ •ํ•  ๋•Œ๋งˆ๋‹ค ์˜์กด์„ฑ ๋ชฉ๋ก์„ ์‚ดํŽด๋ณด์‹ญ์‹œ์˜ค. ์ด๋Ÿฌํ•œ ์˜์กด์„ฑ ์ค‘ ํ•˜๋‚˜๋ผ๋„ ๋ณ€๊ฒฝ๋˜๋ฉด Effect๊ฐ€ ๋‹ค์‹œ ์‹คํ–‰๋˜๋Š” ๊ฒƒ์ด ํ•ฉ๋ฆฌ์ ์ผ๊นŒ์š”? ๊ฐ€๋” ๋Œ€๋‹ต์€ "์•„๋‹ˆ์˜ค"์ž…๋‹ˆ๋‹ค. +์ฝ”๋“œ๋ฅผ ๋ฐ˜์˜ํ•˜๊ธฐ ์œ„ํ•ด Effect์˜ ์˜์กด์„ฑ์„ ์กฐ์ •ํ•  ๋•Œ๋งˆ๋‹ค ์˜์กด์„ฑ ๋ชฉ๋ก์„ ์‚ดํŽด๋ณด์„ธ์š”. ์ด๋Ÿฌํ•œ ์˜์กด์„ฑ ์ค‘ ํ•˜๋‚˜๋ผ๋„ ๋ณ€๊ฒฝ๋˜๋ฉด Effect๊ฐ€ ๋‹ค์‹œ ์‹คํ–‰๋˜๋Š” ๊ฒƒ์ด ํ•ฉ๋ฆฌ์ ์ผ๊นŒ์š”? ๊ฐ€๋” ๋Œ€๋‹ต์€ "์•„๋‹ˆ์˜ค"์ž…๋‹ˆ๋‹ค. * ๋‹ค๋ฅธ ์กฐ๊ฑด์—์„œ Effect์˜ *๋‹ค๋ฅธ ๋ถ€๋ถ„*์„ ๋‹ค์‹œ ์‹คํ–‰ํ•˜๊ณ  ์‹ถ์„ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. * ์ผ๋ถ€ ์˜์กด์„ฑ์˜ ๋ณ€๊ฒฝ์— "๋ฐ˜์‘"ํ•˜์ง€ ์•Š๊ณ  "์ตœ์‹  ๊ฐ’"๋งŒ ์ฝ๊ณ  ์‹ถ์„ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. @@ -370,7 +370,7 @@ button { margin: 10px; } ### ์ด ์ฝ”๋“œ๋ฅผ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋กœ ์˜ฎ๊ฒจ์•ผ ํ•˜๋‚˜์š”? {/*should-this-code-move-to-an-event-handler*/} -๊ฐ€์žฅ ๋จผ์ € ๊ณ ๋ คํ•ด์•ผ ํ•  ๊ฒƒ์€ ์ด ์ฝ”๋“œ๊ฐ€ Effect ๋˜์–ด์•ผ ํ•˜๋Š”์ง€ ์—ฌ๋ถ€์ž…๋‹ˆ๋‹ค. +๊ฐ€์žฅ ๋จผ์ € ๊ณ ๋ คํ•ด์•ผ ํ•  ๊ฒƒ์€ ์ด ์ฝ”๋“œ๊ฐ€ Effect์—ฌ์•ผ ํ•˜๋Š”์ง€ ์—ฌ๋ถ€์ž…๋‹ˆ๋‹ค. ํผ์„ ์ƒ์ƒํ•ด ๋ด…์‹œ๋‹ค. ์ œ์ถœํ•  ๋•Œ `submitted` State ๋ณ€์ˆ˜๋ฅผ `true`๋กœ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค. POST ์š”์ฒญ์„ ๋ณด๋‚ด๊ณ  ์•Œ๋ฆผ์„ ํ‘œ์‹œํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด ๋กœ์ง์€ `submitted`๊ฐ€ `true`๊ฐ€ ๋  ๋•Œ "๋ฐ˜์‘"ํ•˜๋Š” Effect ์•ˆ์— ๋„ฃ์—ˆ์Šต๋‹ˆ๋‹ค. @@ -394,7 +394,7 @@ function Form() { } ``` -๋‚˜์ค‘์— ํ˜„์žฌ ํ…Œ๋งˆ์— ๋”ฐ๋ผ ์•Œ๋ฆผ ๋ฉ”์‹œ์ง€์˜ ์Šคํƒ€์ผ์„ ์ง€์ •ํ•˜๊ณ  ์‹ถ์œผ๋ฏ€๋กœ ํ˜„์žฌ ํ…Œ๋งˆ๋ฅผ ์ฝ์Šต๋‹ˆ๋‹ค. `theme`๋Š” ์ปดํฌ๋„ŒํŠธ ๋ณธ๋ฌธ์—์„œ ์„ ์–ธ๋˜์—ˆ๊ธฐ๋•Œ๋ฌธ์— ์ด๋Š” ๋ฐ˜์‘ํ˜• ๊ฐ’์ด๋ฏ€๋กœ ์˜์กด์„ฑ์œผ๋กœ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค. +๋‚˜์ค‘์— ํ˜„์žฌ ํ…Œ๋งˆ์— ๋”ฐ๋ผ ์•Œ๋ฆผ ๋ฉ”์‹œ์ง€์˜ ์Šคํƒ€์ผ์„ ์ง€์ •ํ•˜๊ณ  ์‹ถ์œผ๋ฏ€๋กœ ํ˜„์žฌ ํ…Œ๋งˆ๋ฅผ ์ฝ์Šต๋‹ˆ๋‹ค. `theme`๋Š” ์ปดํฌ๋„ŒํŠธ ๋ณธ๋ฌธ์—์„œ ์„ ์–ธ๋˜์—ˆ๊ธฐ ๋•Œ๋ฌธ์— ์ด๋Š” ๋ฐ˜์‘ํ˜• ๊ฐ’์ด๋ฏ€๋กœ ์˜์กด์„ฑ์œผ๋กœ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค. ```js {3,9,11} function Form() { @@ -437,7 +437,7 @@ function Form() { ์ด์ œ ์ฝ”๋“œ๊ฐ€ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ์— ์žˆ๊ณ , ์ด๋Š” ๋ฐ˜์‘ํ˜• ์ฝ”๋“œ๊ฐ€ ์•„๋‹ˆ๋ฏ€๋กœ ์‚ฌ์šฉ์ž๊ฐ€ ํผ์„ ์ œ์ถœํ•  ๋•Œ๋งŒ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค. [์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ์™€ Effect ์ค‘์—์„œ ์„ ํƒํ•˜๋Š” ๋ฐฉ๋ฒ•](/learn/separating-events-from-effects#reactive-values-and-reactive-logic)๊ณผ [๋ถˆํ•„์š”ํ•œ Effect๋ฅผ ์‚ญ์ œํ•˜๋Š” ๋ฐฉ๋ฒ•](/learn/you-might-not-need-an-effect)์— ๋Œ€ํ•ด ์ž์„ธํžˆ ์•Œ์•„๋ณด์„ธ์š”. -### Effect ๊ฐ€ ๊ด€๋ จ ์—†๋Š” ์—ฌ๋Ÿฌ ๊ฐ€์ง€ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋‚˜์š”? {/*is-your-effect-doing-several-unrelated-things*/} +### Effect๊ฐ€ ๊ด€๋ จ ์—†๋Š” ์—ฌ๋Ÿฌ ๊ฐ€์ง€ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋‚˜์š”? {/*is-your-effect-doing-several-unrelated-things*/} ๋‹ค์Œ์œผ๋กœ ์Šค์Šค๋กœ์—๊ฒŒ ๋ฌผ์–ด๋ด์•ผ ํ•  ์งˆ๋ฌธ์€ Effect๊ฐ€ ์„œ๋กœ ๊ด€๋ จ์ด ์—†๋Š” ์—ฌ๋Ÿฌ ๊ฐ€์ง€ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๊ณ  ์žˆ๋Š”์ง€ ์—ฌ๋ถ€์ž…๋‹ˆ๋‹ค. @@ -552,7 +552,7 @@ function ShippingForm({ country }) { ์ด์ œ ์ฒซ ๋ฒˆ์งธ Effect๋Š” `country`๊ฐ€ ๋ณ€๊ฒฝ๋  ๋•Œ๋งŒ ๋‹ค์‹œ ์‹คํ–‰๋˜๊ณ , ๋‘ ๋ฒˆ์งธ Effect๋Š” `city`๊ฐ€ ๋ณ€๊ฒฝ๋  ๋•Œ ๋‹ค์‹œ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค. ๋ชฉ์ ์— ๋”ฐ๋ผ ๋ถ„๋ฆฌํ–ˆ์œผ๋‹ˆ, ์„œ๋กœ ๋‹ค๋ฅธ ๋‘ ๊ฐ€์ง€๊ฐ€ ๋‘ ๊ฐœ์˜ ๊ฐœ๋ณ„ Effect์— ์˜ํ•ด ๋™๊ธฐํ™”๋ฉ๋‹ˆ๋‹ค. ๋‘ ๊ฐœ์˜ ๊ฐœ๋ณ„ Effect์—๋Š” ๋‘ ๊ฐœ์˜ ๊ฐœ๋ณ„ ์˜์กด์„ฑ ๋ชฉ๋ก์ด ์žˆ์œผ๋ฏ€๋กœ ์˜๋„์น˜ ์•Š๊ฒŒ ์„œ๋กœ๋ฅผ ํŠธ๋ฆฌ๊ฑฐํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. -์ตœ์ข… ์ฝ”๋“œ๋Š” ์›๋ณธ๋ณด๋‹ค ๊ธธ์ง€๋งŒ Effect๋ฅผ ๋ถ„ํ• ํ•˜๋Š” ๊ฒƒ์ด ์—ฌ์ „ํžˆ ์ •ํ™•ํ•ฉ๋‹ˆ๋‹ค. [๊ฐ Effect๋Š” ๋…๋ฆฝ์ ์ธ ๋™๊ธฐํ™” ํ”„๋กœ์„ธ์Šค๋ฅผ ๋‚˜ํƒ€๋‚ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.](/learn/lifecycle-of-reactive-effects#each-effect-represents-a-separate-synchronization-process) ์ด ์˜ˆ์‹œ์—์„œ๋Š” ํ•œ Effect๋ฅผ ์‚ญ์ œํ•ด๋„ ๋‹ค๋ฅธ Effect์˜ ๋กœ์ง์ด ๊นจ์ง€์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ฆ‰, *์„œ๋กœ ๋‹ค๋ฅธ ๊ฒƒ์„ ๋™๊ธฐํ™”*ํ•˜๋ฏ€๋กœ ๋ถ„ํ• ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. [์ค‘๋ณต์ด ๊ฑฑ์ •๋œ๋‹ค๋ฉด ๋ฐ˜๋ณต๋˜๋Š” ๋กœ์ง์„ ์ปค์Šคํ…€ ํ›…์œผ๋กœ ์ถ”์ถœ](/learn/reusing-logic-with-custom-hooks#when-to-use-custom-hooks)ํ•˜์—ฌ ์ด ์ฝ”๋“œ๋ฅผ ๊ฐœ์„ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +์ตœ์ข… ์ฝ”๋“œ๋Š” ์›๋ณธ๋ณด๋‹ค ๊ธธ์ง€๋งŒ Effect๋ฅผ ๋ถ„ํ• ํ•˜๋Š” ๊ฒƒ์ด ์—ฌ์ „ํžˆ ์ •ํ™•ํ•ฉ๋‹ˆ๋‹ค. [๊ฐ Effect๋Š” ๋…๋ฆฝ์ ์ธ ๋™๊ธฐํ™” ํ”„๋กœ์„ธ์Šค๋ฅผ ๋‚˜ํƒ€๋‚ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.](/learn/lifecycle-of-reactive-effects#each-effect-represents-a-separate-synchronization-process) ์ด ์˜ˆ์‹œ์—์„œ๋Š” ํ•œ Effect๋ฅผ ์‚ญ์ œํ•ด๋„ ๋‹ค๋ฅธ Effect์˜ ๋กœ์ง์ด ๊นจ์ง€์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ฆ‰, *์„œ๋กœ ๋‹ค๋ฅธ ๊ฒƒ์„ ๋™๊ธฐํ™”*ํ•˜๋ฏ€๋กœ ๋ถ„ํ• ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. [์ค‘๋ณต์ด ๊ฑฑ์ •๋œ๋‹ค๋ฉด ๋ฐ˜๋ณต๋˜๋Š” ๋กœ์ง์„ ์ปค์Šคํ…€ Hook์œผ๋กœ ์ถ”์ถœ](/learn/reusing-logic-with-custom-hooks#when-to-use-custom-hooks)ํ•˜์—ฌ ์ด ์ฝ”๋“œ๋ฅผ ๊ฐœ์„ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ### ๋‹ค์Œ State๋ฅผ ๊ณ„์‚ฐํ•˜๊ธฐ ์œ„ํ•ด ์–ด๋–ค State๋ฅผ ์ฝ๊ณ  ์žˆ๋‚˜์š”? {/*are-you-reading-some-state-to-calculate-the-next-state*/} @@ -590,7 +590,7 @@ function ChatRoom({ roomId }) { ๋ฉ”์‹œ์ง€๋ฅผ ์ˆ˜์‹ ํ•  ๋•Œ๋งˆ๋‹ค `setMessages()`๋Š” ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์ˆ˜์‹ ๋œ ๋ฉ”์‹œ์ง€๋ฅผ ํฌํ•จํ•˜๋Š” ์ƒˆ `messages` ๋ฐฐ์—ด๋กœ ์žฌ๋ Œ๋”๋งํ•˜๋„๋ก ํ•ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ด Effect๋Š” ์ด์ œ `messages`์— ๋”ฐ๋ผ ๋‹ฌ๋ผ์ง€๋ฏ€๋กœ Effect๋„ ๋‹ค์‹œ ๋™๊ธฐํ™”๋ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์ƒˆ ๋ฉ”์‹œ์ง€๊ฐ€ ์˜ฌ ๋•Œ๋งˆ๋‹ค ์ฑ„ํŒ…์ด ๋‹ค์‹œ ์—ฐ๊ฒฐ๋ฉ๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž๊ฐ€ ์›ํ•˜์ง€ ์•Š์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค! -์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋ ค๋ฉด Effect ๋‚ด์—์„œ `messages`๋ฅผ ์ฝ์ง€ ๋งˆ์„ธ์š”. ๋Œ€์‹  [์—…๋ฐ์ดํ„ฐ ํ•จ์ˆ˜](/reference/react/useState#updating-state-based-on-the-previous-state)๋ฅผ `setMessages`์— ์ „๋‹ฌํ•˜์„ธ์š”: +์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋ ค๋ฉด Effect ๋‚ด์—์„œ `messages`๋ฅผ ์ฝ์ง€ ๋งˆ์„ธ์š”. ๋Œ€์‹  [์—…๋ฐ์ดํ„ฐ ํ•จ์ˆ˜](/reference/react/useState#updating-state-based-on-the-previous-state)๋ฅผ `setMessages`์— ์ „๋‹ฌํ•˜์„ธ์š”. ```js {7,10} function ChatRoom({ roomId }) { @@ -652,7 +652,7 @@ function ChatRoom({ roomId }) { ๋ฌธ์ œ๋Š” (์‚ฌ์šฉ์ž๊ฐ€ `isMuted` ํ† ๊ธ€์„ ๋ˆ„๋ฅด๋Š” ๋“ฑ) `isMuted`๊ฐ€ ๋ณ€๊ฒฝ๋  ๋•Œ๋งˆ๋‹ค Effect๊ฐ€ ๋‹ค์‹œ ๋™๊ธฐํ™”๋˜๊ณ  ์ฑ„ํŒ…์— ๋‹ค์‹œ ์—ฐ๊ฒฐ๋œ๋‹ค๋Š” ์ ์ž…๋‹ˆ๋‹ค. ์ด๋Š” ๋ฐ”๋žŒ์งํ•œ ์‚ฌ์šฉ์ž ๊ฒฝํ—˜์ด ์•„๋‹™๋‹ˆ๋‹ค! (์ด ์˜ˆ์‹œ์—์„œ๋Š” ๋ฆฐํ„ฐ๋ฅผ ๋น„ํ™œ์„ฑํ™”ํ•ด๋„ ์ž‘๋™ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ทธ๋ ‡๊ฒŒ ํ•˜๋ฉด `isMuted`๊ฐ€ ์ด์ „ ๊ฐ’์œผ๋กœ '๊ณ ์ฐฉ'๋ฉ๋‹ˆ๋‹ค.) -์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋ ค๋ฉด Effect์—์„œ ๋ฐ˜์‘ํ•ด์„œ๋Š” ์•ˆ ๋˜๋Š” ๋กœ์ง์„ ์ถ”์ถœํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด Effect๊ฐ€ `isMuted`์˜ ๋ณ€๊ฒฝ์— "๋ฐ˜์‘"ํ•˜์ง€ ์•Š๊ธฐ๋ฅผ ์›ํ•ฉ๋‹ˆ๋‹ค. [์ด ๋น„๋ฐ˜์‘ ๋กœ์ง์„ Effect ์ด๋ฒคํŠธ๋กœ ์˜ฎ๊ธฐ๋ฉด ๋ฉ๋‹ˆ๋‹ค](/learn/separating-events-from-effects#declaring-an-effect-event): +์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋ ค๋ฉด Effect์—์„œ ๋ฐ˜์‘ํ•ด์„œ๋Š” ์•ˆ ๋˜๋Š” ๋กœ์ง์„ ์ถ”์ถœํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด Effect๊ฐ€ `isMuted`์˜ ๋ณ€๊ฒฝ์— "๋ฐ˜์‘"ํ•˜์ง€ ์•Š๊ธฐ๋ฅผ ์›ํ•ฉ๋‹ˆ๋‹ค. [์ด ๋น„๋ฐ˜์‘ ๋กœ์ง์„ Effect ์ด๋ฒคํŠธ๋กœ ์˜ฎ๊ธฐ๋ฉด ๋ฉ๋‹ˆ๋‹ค](/learn/separating-events-from-effects#declaring-an-effect-event). ```js {1,7-12,18,21} import { useState, useEffect, useEffectEvent } from 'react'; @@ -711,7 +711,7 @@ function ChatRoom({ roomId, onReceiveMessage }) { /> ``` -`onReceiveMessage`๋Š” ์˜์กด์„ฑ์ด๋ฏ€๋กœ ๋ถ€๋ชจ๊ฐ€ ์žฌ๋ Œ๋”๋งํ•  ๋•Œ๋งˆ๋‹ค Effect๊ฐ€ ๋‹ค์‹œ ๋™๊ธฐํ™”๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋ฉด ์ฑ„ํŒ…์— ๋‹ค์‹œ ์—ฐ๊ฒฐ๋ฉ๋‹ˆ๋‹ค. ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋ ค๋ฉด ํ˜ธ์ถœ์„ Effect ์ด๋ฒคํŠธ๋กœ ๊ฐ์‹ธ์„ธ์š”: +`onReceiveMessage`๋Š” ์˜์กด์„ฑ์ด๋ฏ€๋กœ ๋ถ€๋ชจ๊ฐ€ ์žฌ๋ Œ๋”๋งํ•  ๋•Œ๋งˆ๋‹ค Effect๊ฐ€ ๋‹ค์‹œ ๋™๊ธฐํ™”๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋ฉด ์ฑ„ํŒ…์— ๋‹ค์‹œ ์—ฐ๊ฒฐ๋ฉ๋‹ˆ๋‹ค. ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋ ค๋ฉด ํ˜ธ์ถœ์„ Effect ์ด๋ฒคํŠธ๋กœ ๊ฐ์‹ธ์„ธ์š”. ```js {4-6,12,15} function ChatRoom({ roomId, onReceiveMessage }) { @@ -785,7 +785,7 @@ function ChatRoom({ roomId }) { // ... ``` -์˜์กด์„ฑ์œผ๋กœ ์„ ์–ธํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค! ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์˜ˆ๋ฅผ ๋“ค์–ด `roomId`๊ฐ€ ๋ณ€๊ฒฝ๋˜๋ฉด Effect๊ฐ€ ์ƒˆ `options`์œผ๋กœ ์ฑ„ํŒ…์— ๋‹ค์‹œ ์—ฐ๊ฒฐ๋ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์œ„ ์ฝ”๋“œ์—๋„ ๋ฌธ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ํ™•์ธํ•˜๋ ค๋ฉด ์•„๋ž˜ ์ƒŒ๋“œ๋ฐ•์Šค์˜ ์ธํ’‹์— ํƒ€์ดํ•‘ํ•˜๊ณ  ์ฝ˜์†”์—์„œ ์–ด๋–ค ์ผ์ด ๋ฐœ์ƒํ•˜๋Š”์ง€ ์‚ดํŽด๋ณด์„ธ์š”: +์˜์กด์„ฑ์œผ๋กœ ์„ ์–ธํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค! ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์˜ˆ๋ฅผ ๋“ค์–ด `roomId`๊ฐ€ ๋ณ€๊ฒฝ๋˜๋ฉด Effect๊ฐ€ ์ƒˆ `options`์œผ๋กœ ์ฑ„ํŒ…์— ๋‹ค์‹œ ์—ฐ๊ฒฐ๋ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์œ„ ์ฝ”๋“œ์—๋„ ๋ฌธ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ํ™•์ธํ•˜๋ ค๋ฉด ์•„๋ž˜ ์ƒŒ๋“œ๋ฐ•์Šค์˜ ์ธํ’‹์— ํƒ€์ดํ•‘ํ•˜๊ณ  ์ฝ˜์†”์—์„œ ์–ด๋–ค ์ผ์ด ๋ฐœ์ƒํ•˜๋Š”์ง€ ์‚ดํŽด๋ณด์„ธ์š”. @@ -1095,7 +1095,7 @@ function ChatRoom({ options }) { /> ``` -์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์žฌ๋ Œ๋”๋งํ•  ๋•Œ๋งˆ๋‹ค Effect๊ฐ€ ๋‹ค์‹œ ์—ฐ๊ฒฐ๋ฉ๋‹ˆ๋‹ค. ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋ ค๋ฉด Effect ์™ธ๋ถ€์˜ ๊ฐ์ฒด์—์„œ ์ •๋ณด๋ฅผ ์ฝ๊ณ  ๊ฐ์ฒด ๋ฐ ํ•จ์ˆ˜ ์˜์กด์„ฑ์„ ํ”ผํ•˜์‹ญ์‹œ์˜ค: +์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์žฌ๋ Œ๋”๋งํ•  ๋•Œ๋งˆ๋‹ค Effect๊ฐ€ ๋‹ค์‹œ ์—ฐ๊ฒฐ๋ฉ๋‹ˆ๋‹ค. ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋ ค๋ฉด Effect ์™ธ๋ถ€์˜ ๊ฐ์ฒด์—์„œ ์ •๋ณด๋ฅผ ์ฝ๊ณ  ๊ฐ์ฒด ๋ฐ ํ•จ์ˆ˜ ์˜์กด์„ฑ์„ ํ”ผํ•˜์„ธ์š”. ```js {4,7-8,12} function ChatRoom({ options }) { @@ -1115,7 +1115,7 @@ function ChatRoom({ options }) { ๋กœ์ง์€ ์•ฝ๊ฐ„ ๋ฐ˜๋ณต์ ์ž…๋‹ˆ๋‹ค (Effect ์™ธ๋ถ€์˜ ๊ฐ์ฒด์—์„œ ์ผ๋ถ€ ๊ฐ’์„ ์ฝ์€ ๋‹ค์Œ Effect ๋‚ด๋ถ€์— ๋™์ผํ•œ ๊ฐ’์„ ๊ฐ€์ง„ ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค). ํ•˜์ง€๋งŒ Effect๊ฐ€ ์‹ค์ œ๋กœ ์–ด๋–ค ์ •๋ณด์— ์˜์กดํ•˜๋Š”์ง€ ๋งค์šฐ ๋ช…ํ™•ํ•˜๊ฒŒ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ์— ์˜ํ•ด ์˜๋„์น˜ ์•Š๊ฒŒ ๊ฐ์ฒด๊ฐ€ ๋‹ค์‹œ ์ƒ์„ฑ๋œ ๊ฒฝ์šฐ ์ฑ„ํŒ…์ด ๋‹ค์‹œ ์—ฐ๊ฒฐ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ `options.roomId` ๋˜๋Š” `options.serverUrl`์ด ์‹ค์ œ๋กœ ๋‹ค๋ฅธ ๊ฒฝ์šฐ ์ฑ„ํŒ…์ด ๋‹ค์‹œ ์—ฐ๊ฒฐ๋ฉ๋‹ˆ๋‹ค. -#### ํ•จ์ˆ˜์—์„œ ์›์‹œ๊ฐ’ ๊ณ„์‚ฐ {/*calculate-primitive-values-from-functions*/} +#### ํ•จ์ˆ˜์—์„œ ์›์‹œ ๊ฐ’ ๊ณ„์‚ฐ {/*calculate-primitive-values-from-functions*/} ํ•จ์ˆ˜์— ๋Œ€ํ•ด์„œ๋„ ๋™์ผํ•œ ์ ‘๊ทผ ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ํ•จ์ˆ˜๋ฅผ ์ „๋‹ฌํ•œ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. @@ -1206,7 +1206,7 @@ export default function Timer() { -Effect ๋‚ด๋ถ€์—์„œ `count` State๋ฅผ `count + 1`๋กœ ์—…๋ฐ์ดํŠธํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด Effect๊ฐ€ ํ‹ฑํ•  ๋•Œ๋งˆ๋‹ค ๋ณ€๊ฒฝ๋˜๋Š” `count`์— ์˜์กดํ•˜๊ฒŒ๋˜๋ฏ€๋กœ ๋งค ํ‹ฑ๋งˆ๋‹ค ์ธํ„ฐ๋ฒŒ์ด ๋‹ค์‹œ ๋งŒ๋“ค์–ด์ง‘๋‹ˆ๋‹ค. +Effect ๋‚ด๋ถ€์—์„œ `count` State๋ฅผ `count + 1`๋กœ ์—…๋ฐ์ดํŠธํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด Effect๊ฐ€ ํ‹ฑํ•  ๋•Œ๋งˆ๋‹ค ๋ณ€๊ฒฝ๋˜๋Š” `count`์— ์˜์กดํ•˜๊ฒŒ ๋˜๋ฏ€๋กœ ๋งค ํ‹ฑ๋งˆ๋‹ค ์ธํ„ฐ๋ฒŒ์ด ๋‹ค์‹œ ๋งŒ๋“ค์–ด์ง‘๋‹ˆ๋‹ค. ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋ ค๋ฉด [์—…๋ฐ์ดํ„ฐ ํ•จ์ˆ˜](/reference/react/useState#updating-state-based-on-the-previous-state)๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ `setCount(count + 1)` ๋Œ€์‹  `setCount(c => c + 1)`๋ฅผ ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค. @@ -1242,7 +1242,7 @@ Effect ๋‚ด๋ถ€์—์„œ `count`๋ฅผ ์ฝ๋Š” ๋Œ€์‹  `c => c + 1` ๋ช…๋ น์–ด("์ด ์ˆซ์ž #### ์• ๋‹ˆ๋ฉ”์ด์…˜์„ ๋‹ค์‹œ ์ด‰๋ฐœํ•˜๋Š” ํ˜„์ƒ ๊ณ ์น˜๊ธฐ {/*fix-a-retriggering-animation*/} -์ด ์˜ˆ์‹œ์—์„œ๋Š” "Show"๋ฅผ ๋ˆ„๋ฅด๋ฉด ํ™˜์˜ ๋ฉ”์‹œ์ง€๊ฐ€ ํŽ˜์ด๋“œ์ธ ํ•ฉ๋‹ˆ๋‹ค. ์• ๋‹ˆ๋ฉ”์ด์…˜์€ 1์ดˆ ์ •๋„ ๊ฑธ๋ฆฝ๋‹ˆ๋‹ค."Remove"๋ฅผ ๋ˆ„๋ฅด๋ฉด ํ™˜์˜ ๋ฉ”์‹œ์ง€๊ฐ€ ์ฆ‰์‹œ ์‚ฌ๋ผ์ง‘๋‹ˆ๋‹ค. ํŽ˜์ด๋“œ์ธ ์• ๋‹ˆ๋ฉ”์ด์…˜์˜ ๋กœ์ง์€ `animation.js` ํŒŒ์ผ์—์„œ ์ผ๋ฐ˜ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์• ๋‹ˆ๋ฉ”์ด์…˜ ๋ฃจํ”„๋กœ ๊ตฌํ˜„๋ฉ๋‹ˆ๋‹ค. ์ด ๋กœ์ง์„ ๋ณ€๊ฒฝํ•  ํ•„์š”๋Š” ์—†์Šต๋‹ˆ๋‹ค. ์„œ๋“œํŒŒํ‹ฐ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋กœ ์ฒ˜๋ฆฌํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. Effect๋Š” DOM ๋…ธ๋“œ์— ๋Œ€ํ•œ `FadeInAnimation` ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•œ ๋‹ค์Œ `start(duration)` ๋˜๋Š” `stop()`์„ ํ˜ธ์ถœํ•˜์—ฌ ์• ๋‹ˆ๋ฉ”์ด์…˜์„ ์ œ์–ดํ•ฉ๋‹ˆ๋‹ค. `duration`์€ ์Šฌ๋ผ์ด๋”๋กœ ์ œ์–ดํ•ฉ๋‹ˆ๋‹ค. ์Šฌ๋ผ์ด๋”๋ฅผ ์กฐ์ •ํ•˜์—ฌ ์• ๋‹ˆ๋ฉ”์ด์…˜์ด ์–ด๋–ป๊ฒŒ ๋ณ€ํ•˜๋Š”์ง€ ํ™•์ธํ•˜์„ธ์š”. +์ด ์˜ˆ์‹œ์—์„œ๋Š” "Show"๋ฅผ ๋ˆ„๋ฅด๋ฉด ํ™˜์˜ ๋ฉ”์‹œ์ง€๊ฐ€ ํŽ˜์ด๋“œ์ธํ•ฉ๋‹ˆ๋‹ค. ์• ๋‹ˆ๋ฉ”์ด์…˜์€ 1์ดˆ ์ •๋„ ๊ฑธ๋ฆฝ๋‹ˆ๋‹ค. "Remove"๋ฅผ ๋ˆ„๋ฅด๋ฉด ํ™˜์˜ ๋ฉ”์‹œ์ง€๊ฐ€ ์ฆ‰์‹œ ์‚ฌ๋ผ์ง‘๋‹ˆ๋‹ค. ํŽ˜์ด๋“œ์ธ ์• ๋‹ˆ๋ฉ”์ด์…˜์˜ ๋กœ์ง์€ `animation.js` ํŒŒ์ผ์—์„œ ์ผ๋ฐ˜ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์• ๋‹ˆ๋ฉ”์ด์…˜ ๋ฃจํ”„๋กœ ๊ตฌํ˜„๋ฉ๋‹ˆ๋‹ค. ์ด ๋กœ์ง์„ ๋ณ€๊ฒฝํ•  ํ•„์š”๋Š” ์—†์Šต๋‹ˆ๋‹ค. ์„œ๋“œ ํŒŒํ‹ฐ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋กœ ์ฒ˜๋ฆฌํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. Effect๋Š” DOM ๋…ธ๋“œ์— ๋Œ€ํ•œ `FadeInAnimation` ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•œ ๋‹ค์Œ `start(duration)` ๋˜๋Š” `stop()`์„ ํ˜ธ์ถœํ•˜์—ฌ ์• ๋‹ˆ๋ฉ”์ด์…˜์„ ์ œ์–ดํ•ฉ๋‹ˆ๋‹ค. `duration`์€ ์Šฌ๋ผ์ด๋”๋กœ ์ œ์–ดํ•ฉ๋‹ˆ๋‹ค. ์Šฌ๋ผ์ด๋”๋ฅผ ์กฐ์ •ํ•˜์—ฌ ์• ๋‹ˆ๋ฉ”์ด์…˜์ด ์–ด๋–ป๊ฒŒ ๋ณ€ํ•˜๋Š”์ง€ ํ™•์ธํ•˜์„ธ์š”. ์ด ์ฝ”๋“œ๋Š” ์ด๋ฏธ ์ž‘๋™ํ•˜์ง€๋งŒ ๋ณ€๊ฒฝํ•˜๊ณ  ์‹ถ์€ ๋ถ€๋ถ„์ด ์žˆ์Šต๋‹ˆ๋‹ค. ํ˜„์žฌ `duration` State ๋ณ€์ˆ˜๋ฅผ ์ œ์–ดํ•˜๋Š” ์Šฌ๋ผ์ด๋”๋ฅผ ์›€์ง์ด๋ฉด ์• ๋‹ˆ๋ฉ”์ด์…˜์ด ๋‹ค์‹œ ์ด‰๋ฐœ๋ฉ๋‹ˆ๋‹ค. Effect๊ฐ€ `duration` ๋ณ€์ˆ˜์— "๋ฐ˜์‘"ํ•˜์ง€ ์•Š๋„๋ก ๋™์ž‘์„ ๋ณ€๊ฒฝํ•˜์„ธ์š”. "Show"๋ฅผ ๋ˆ„๋ฅด๋ฉด Effect๋Š” ์Šฌ๋ผ์ด๋”์˜ ํ˜„์žฌ `duration`์„ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์Šฌ๋ผ์ด๋”๋ฅผ ์›€์ง์ด๋Š” ๊ฒƒ๋งŒ์œผ๋กœ ์• ๋‹ˆ๋ฉ”์ด์…˜์ด ๋‹ค์‹œ ์ด‰๋ฐœ๋˜์–ด์„œ๋Š” ์•ˆ ๋ฉ๋‹ˆ๋‹ค. @@ -1476,7 +1476,7 @@ html, body { min-height: 300px; } ์ด ์˜ˆ์‹œ์—์„œ๋Š” 'Toggle theme'์„ ๋ˆ„๋ฅผ ๋•Œ๋งˆ๋‹ค ์ฑ„ํŒ…์ด ๋‹ค์‹œ ์—ฐ๊ฒฐ๋ฉ๋‹ˆ๋‹ค. ์™œ ์ด๋Ÿฐ ์ผ์ด ๋ฐœ์ƒํ•˜๋‚˜์š”? ์„œ๋ฒ„ URL์„ ํŽธ์ง‘ํ•˜๊ฑฐ๋‚˜ ๋‹ค๋ฅธ ์ฑ„ํŒ…๋ฐฉ์„ ์„ ํƒํ•  ๋•Œ๋งŒ ์ฑ„ํŒ…์ด ๋‹ค์‹œ ์—ฐ๊ฒฐ๋˜๋„๋ก ์‹ค์ˆ˜๋ฅผ ์ˆ˜์ •ํ•˜์„ธ์š”. -`chat.js`๋ฅผ ์™ธ๋ถ€ ์„œ๋“œํŒŒํ‹ฐ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋กœ ์ทจ๊ธ‰ํ•˜์—ฌ API๋ฅผ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•ด ์ฐธ์กฐํ•  ์ˆ˜๋Š” ์žˆ์ง€๋งŒ ํŽธ์ง‘ํ•ด์„œ๋Š” ์•ˆ ๋ฉ๋‹ˆ๋‹ค. +`chat.js`๋ฅผ ์™ธ๋ถ€ ์„œ๋“œ ํŒŒํ‹ฐ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋กœ ์ทจ๊ธ‰ํ•˜์—ฌ API๋ฅผ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•ด ์ฐธ์กฐํ•  ์ˆ˜๋Š” ์žˆ์ง€๋งŒ ํŽธ์ง‘ํ•ด์„œ๋Š” ์•ˆ ๋ฉ๋‹ˆ๋‹ค. @@ -1576,7 +1576,7 @@ label, button { display: block; margin-bottom: 5px; } Effect๊ฐ€ `options` ๊ฐ์ฒด์— ์˜์กดํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋‹ค์‹œ ์‹คํ–‰๋˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฐ์ฒด๋Š” ์˜๋„์น˜ ์•Š๊ฒŒ ๋‹ค์‹œ ์ƒ์„ฑ๋  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ๊ฐ€๋Šฅํ•˜๋ฉด Effect์˜ ์˜์กด์„ฑ ์š”์†Œ๋กœ ์ง€์ •ํ•˜์ง€ ์•Š๋„๋ก ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. -๊ฐ€์žฅ ๋œ ๊ณต๊ฒฉ์ ์ธ ์ˆ˜์ • ๋ฐฉ๋ฒ•์€ Effect ์™ธ๋ถ€์—์„œ `roomId`์™€ `serverUrl`์„ ์ฝ์€ ๋‹ค์Œ Effect๊ฐ€ ์ด๋Ÿฌํ•œ ๊ธฐ๋ณธ ๊ฐ’์— ์˜์กดํ•˜๋„๋ก ๋งŒ๋“œ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค(์˜๋„์น˜ ์•Š๊ฒŒ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์—†์Œ). Effect ๋‚ด๋ถ€์—์„œ, ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ์ด๋ฅผ `createConnection`์— ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค. +๊ฐ€์žฅ ๋œ ๊ณต๊ฒฉ์ ์ธ ์ˆ˜์ • ๋ฐฉ๋ฒ•์€ Effect ์™ธ๋ถ€์—์„œ `roomId`์™€ `serverUrl`์„ ์ฝ์€ ๋‹ค์Œ Effect๊ฐ€ ์ด๋Ÿฌํ•œ ์›์‹œ ๊ฐ’์— ์˜์กดํ•˜๋„๋ก ๋งŒ๋“œ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค(์˜๋„์น˜ ์•Š๊ฒŒ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์—†์Œ). Effect ๋‚ด๋ถ€์—์„œ, ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ์ด๋ฅผ `createConnection`์— ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค. @@ -1994,7 +1994,7 @@ label, button { display: block; margin-bottom: 5px; } -์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ์˜ฌ๋ฐ”๋ฅธ ๋ฐฉ๋ฒ•์€ ์—ฌ๋Ÿฌ ๊ฐ€์ง€๊ฐ€ ์žˆ๋Š”๋ฐ, ๊ทธ ์ค‘ ํ•œ ๊ฐ€์ง€ ํ•ด๊ฒฐ์ฑ…์„ ์†Œ๊ฐœํ•ฉ๋‹ˆ๋‹ค. +์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ์˜ฌ๋ฐ”๋ฅธ ๋ฐฉ๋ฒ•์€ ์—ฌ๋Ÿฌ ๊ฐ€์ง€๊ฐ€ ์žˆ๋Š”๋ฐ, ๊ทธ์ค‘ ํ•œ ๊ฐ€์ง€ ํ•ด๊ฒฐ์ฑ…์„ ์†Œ๊ฐœํ•ฉ๋‹ˆ๋‹ค. ์›๋ž˜ ์˜ˆ์‹œ์—์„œ๋Š” ํ…Œ๋งˆ๋ฅผ ๋ณ€๊ฒฝํ•˜๋ฉด ๋‹ค๋ฅธ `onMessage` ๋ฐ `createConnection` ํ•จ์ˆ˜๊ฐ€ ์ƒ์„ฑ๋˜์–ด ์ „๋‹ฌ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. Effect๊ฐ€ ์ด๋Ÿฌํ•œ ํ•จ์ˆ˜์— ์˜์กดํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ํ…Œ๋งˆ๋ฅผ ์ „ํ™˜ํ•  ๋•Œ๋งˆ๋‹ค ์ฑ„ํŒ…์ด ๋‹ค์‹œ ์—ฐ๊ฒฐ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. @@ -2012,7 +2012,7 @@ export default function ChatRoom({ roomId, createConnection, onMessage }) { `onMessage` props์™€ ๋‹ฌ๋ฆฌ `onReceiveMessage` Effect ์ด๋ฒคํŠธ๋Š” ๋ฐ˜์‘ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— Effect์˜ ์˜์กด์„ฑ์ด ๋  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ `onMessage`๋ฅผ ๋ณ€๊ฒฝํ•ด๋„ ์ฑ„ํŒ…์ด ๋‹ค์‹œ ์—ฐ๊ฒฐ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. -๋ฐ˜์‘ํ˜•์ด์–ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— `createConnection`์œผ๋กœ๋Š” ๋™์ผํ•œ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž๊ฐ€ ์•”ํ˜ธํ™” ์—ฐ๊ฒฐ๊ณผ ๋น„์•”ํ˜ธํ™” ์—ฐ๊ฒฐ ์‚ฌ์ด๋ฅผ ์ „ํ™˜ํ•˜๊ฑฐ๋‚˜ ์‚ฌ์šฉ์ž๊ฐ€ ํ˜„์žฌ ๋ฐฉ์„ ์ „ํ™˜ํ•˜๋ฉด Effect๊ฐ€ ๋‹ค์‹œ ์ด‰๋ฐœ๋˜๊ธฐ๋ฅผ ์›ํ•ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ `createConnection`์€ ํ•จ์ˆ˜์ด๊ธฐ ๋•Œ๋ฌธ์— ์ด ํ•จ์ˆ˜๊ฐ€ ์ฝ๋Š” ์ •๋ณด๊ฐ€ ์‹ค์ œ๋กœ ๋ณ€๊ฒฝ๋˜์—ˆ๋Š”์ง€ ์—ฌ๋ถ€๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋ ค๋ฉด `App` ์ปดํฌ๋„ŒํŠธ์—์„œ `createConnection`์„ ์ „๋‹ฌํ•˜๋Š” ๋Œ€์‹  ์›์‹œ๊ฐ’์ธ `roomId` ๋ฐ `isEncrypted`๋ฅผ ์ „๋‹ฌํ•˜์„ธ์š”: +๋ฐ˜์‘ํ˜•์ด์–ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— `createConnection`์œผ๋กœ๋Š” ๋™์ผํ•œ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž๊ฐ€ ์•”ํ˜ธํ™” ์—ฐ๊ฒฐ๊ณผ ๋น„์•”ํ˜ธํ™” ์—ฐ๊ฒฐ ์‚ฌ์ด๋ฅผ ์ „ํ™˜ํ•˜๊ฑฐ๋‚˜ ์‚ฌ์šฉ์ž๊ฐ€ ํ˜„์žฌ ๋ฐฉ์„ ์ „ํ™˜ํ•˜๋ฉด Effect๊ฐ€ ๋‹ค์‹œ ์ด‰๋ฐœ๋˜๊ธฐ๋ฅผ ์›ํ•ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ `createConnection`์€ ํ•จ์ˆ˜์ด๊ธฐ ๋•Œ๋ฌธ์— ์ด ํ•จ์ˆ˜๊ฐ€ ์ฝ๋Š” ์ •๋ณด๊ฐ€ ์‹ค์ œ๋กœ ๋ณ€๊ฒฝ๋˜์—ˆ๋Š”์ง€ ์—ฌ๋ถ€๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋ ค๋ฉด `App` ์ปดํฌ๋„ŒํŠธ์—์„œ `createConnection`์„ ์ „๋‹ฌํ•˜๋Š” ๋Œ€์‹  ์›์‹œ ๊ฐ’์ธ `roomId` ๋ฐ `isEncrypted`๋ฅผ ์ „๋‹ฌํ•˜์„ธ์š”. ```js {2-3} { // ... // ๐Ÿ”ด Avoid suppressing the linter like this: - // eslint-ignore-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line react-hooks/exhaustive-deps }, []); ``` diff --git a/src/content/reference/react/useRef.md b/src/content/reference/react/useRef.md index c44c2bff7..29018df7f 100644 --- a/src/content/reference/react/useRef.md +++ b/src/content/reference/react/useRef.md @@ -512,9 +512,9 @@ function Video() { -#### `useRef`๋ฅผ ์ดˆ๊ธฐํ™”ํ•  ๋•Œ null ๊ฒ€์‚ฌ๋ฅผ ํ”ผํ•˜๋Š” ๋ฐฉ๋ฒ• {/*how-to-avoid-null-checks-when-initializing-use-ref-later*/} +#### `useRef`๋ฅผ ์ดˆ๊ธฐํ™”ํ•  ๋•Œ `null` ๊ฒ€์‚ฌ๋ฅผ ํ”ผํ•˜๋Š” ๋ฐฉ๋ฒ• {/*how-to-avoid-null-checks-when-initializing-use-ref-later*/} -ํƒ€์ž… ๊ฒ€์‚ฌ๊ธฐ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด์„œ ํ•ญ์ƒ `null`์„ ๊ฒ€์‚ฌํ•˜๊ณ  ์‹ถ์ง€ ์•Š๋‹ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํŒจํ„ด์„ ๋Œ€์‹  ์‚ฌ์šฉํ•ด ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: +ํƒ€์ž… ๊ฒ€์‚ฌ๊ธฐ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด์„œ ํ•ญ์ƒ `null`์„ ๊ฒ€์‚ฌํ•˜๊ณ  ์‹ถ์ง€ ์•Š๋‹ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํŒจํ„ด์„ ๋Œ€์‹  ์‚ฌ์šฉํ•ด ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ```js function Video() { @@ -542,7 +542,7 @@ function Video() { ### ์ปค์Šคํ…€ ์ปดํฌ๋„ŒํŠธ์— ๋Œ€ํ•œ ref๋ฅผ ์–ป์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค {/*i-cant-get-a-ref-to-a-custom-component*/} -์ปดํฌ๋„ŒํŠธ์— `ref`๋ฅผ ์ „๋‹ฌํ•˜๊ณ ์ž ๋‹ค์Œ๊ณผ ๊ฐ™์ด ํ•˜๋ฉด: +์ปดํฌ๋„ŒํŠธ์— `ref`๋ฅผ ์ „๋‹ฌํ•˜๊ณ ์ž ๋‹ค์Œ๊ณผ ๊ฐ™์ด ํ•˜๋ฉด ```js const inputRef = useRef(null); @@ -550,7 +550,7 @@ const inputRef = useRef(null); return ; ``` -๋‹ค์Œ๊ณผ ๊ฐ™์€ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค: +๋‹ค์Œ๊ณผ ๊ฐ™์€ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. @@ -560,7 +560,7 @@ TypeError: Cannot read properties of null ๊ธฐ๋ณธ์ ์œผ๋กœ ์ปดํฌ๋„ŒํŠธ๋Š” ๋‚ด๋ถ€์˜ DOM ๋…ธ๋“œ์— ๋Œ€ํ•œ ref๋ฅผ ์™ธ๋ถ€๋กœ ๋…ธ์ถœํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. -์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋ ค๋ฉด ref๋ฅผ ๊ฐ€์ ธ์˜ค๊ณ ์ž ํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ฐพ์œผ์„ธ์š”: +์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋ ค๋ฉด ref๋ฅผ ๊ฐ€์ ธ์˜ค๊ณ ์ž ํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ฐพ์œผ์„ธ์š”. ```js export default function MyInput({ value, onChange }) { diff --git a/src/content/reference/react/useSyncExternalStore.md b/src/content/reference/react/useSyncExternalStore.md index 05dd7e921..96e87a42d 100644 --- a/src/content/reference/react/useSyncExternalStore.md +++ b/src/content/reference/react/useSyncExternalStore.md @@ -40,11 +40,11 @@ store์— ์žˆ๋Š” ๋ฐ์ดํ„ฐ์˜ ์Šค๋ƒ…์ƒท์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ๋‘ ๊ฐœ์˜ ํ•จ์ˆ˜๋ฅผ #### ๋งค๊ฐœ๋ณ€์ˆ˜ {/*parameters*/} -* `subscribe`: ํ•˜๋‚˜์˜ `callback` ์ธ์ˆ˜๋ฅผ ๋ฐ›์•„ store์— ๊ตฌ๋…ํ•˜๋Š” ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค. store๊ฐ€ ๋ณ€๊ฒฝ๋  ๋•Œ, ์ œ๊ณต๋œ `callback`์ด ํ˜ธ์ถœ๋˜์–ด React๊ฐ€ `getSnapshot`์„ ๋‹ค์‹œ ํ˜ธ์ถœํ•˜๊ณ  (ํ•„์š”ํ•œ ๊ฒฝ์šฐ) ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋‹ค์‹œ ๋ Œ๋”๋งํ•˜๋„๋ก ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. `subscribe` ํ•จ์ˆ˜๋Š” ๊ตฌ๋…์„ ์ •๋ฆฌํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. +* `subscribe`: ํ•˜๋‚˜์˜ `callback` ์ธ์ˆ˜๋ฅผ ๋ฐ›์•„ store๋ฅผ ๊ตฌ๋…ํ•˜๋Š” ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค. store๊ฐ€ ๋ณ€๊ฒฝ๋  ๋•Œ, ์ œ๊ณต๋œ `callback`์ด ํ˜ธ์ถœ๋˜์–ด React๊ฐ€ `getSnapshot`์„ ๋‹ค์‹œ ํ˜ธ์ถœํ•˜๊ณ  (ํ•„์š”ํ•œ ๊ฒฝ์šฐ) ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋‹ค์‹œ ๋ Œ๋”๋งํ•˜๋„๋ก ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. `subscribe` ํ•จ์ˆ˜๋Š” ๊ตฌ๋…์„ ์ •๋ฆฌํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. * `getSnapshot`: ์ปดํฌ๋„ŒํŠธ์— ํ•„์š”ํ•œ store ๋ฐ์ดํ„ฐ์˜ ์Šค๋ƒ…์ƒท์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค. store๊ฐ€ ๋ณ€๊ฒฝ๋˜์ง€ ์•Š์€ ์ƒํƒœ์—์„œ `getSnapshot`์„ ๋ฐ˜๋ณต์ ์œผ๋กœ ํ˜ธ์ถœํ•˜๋ฉด ๋™์ผํ•œ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ €์žฅ์†Œ๊ฐ€ ๋ณ€๊ฒฝ๋˜์–ด ๋ฐ˜ํ™˜๋œ ๊ฐ’์ด ๋‹ค๋ฅด๋ฉด ([`Object.is`](https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Object/is)์™€ ๋น„๊ตํ•˜์—ฌ) React๋Š” ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ฆฌ๋ Œ๋”๋งํ•ฉ๋‹ˆ๋‹ค. -* `getServerSnapshot`**(์„ ํƒ์‚ฌํ•ญ)**: store์— ์žˆ๋Š” ๋ฐ์ดํ„ฐ์˜ ์ดˆ๊ธฐ ์Šค๋ƒ…์ƒท์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค. ์„œ๋ฒ„ ๋ Œ๋”๋ง ๋„์ค‘๊ณผ ํด๋ผ์ด์–ธํŠธ์—์„œ ์„œ๋ฒ„ ๋ Œ๋”๋ง ๋œ ์ฝ˜ํ…์ธ ์˜ ํ•˜์ด๋“œ๋ ˆ์ด์…˜ ์ค‘์—๋งŒ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ์„œ๋ฒ„ ์Šค๋ƒ…์ƒท์€ ํด๋ผ์ด์–ธํŠธ์™€ ์„œ๋ฒ„ ๊ฐ„์— ๋™์ผํ•ด์•ผ ํ•˜๋ฉฐ ์ผ๋ฐ˜์ ์œผ๋กœ ์ง๋ ฌํ™”๋˜์–ด ์„œ๋ฒ„์—์„œ ํด๋ผ์ด์–ธํŠธ๋กœ ์ „๋‹ฌ๋ฉ๋‹ˆ๋‹ค. ์ด ํ•จ์ˆ˜๊ฐ€ ์ œ๊ณต๋˜์ง€ ์•Š์œผ๋ฉด ์„œ๋ฒ„์—์„œ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ Œ๋”๋งํ•  ๋•Œ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. +* `getServerSnapshot`**(์„ ํƒ์‚ฌํ•ญ)**: store์— ์žˆ๋Š” ๋ฐ์ดํ„ฐ์˜ ์ดˆ๊ธฐ ์Šค๋ƒ…์ƒท์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค. ์„œ๋ฒ„ ๋ Œ๋”๋ง ๋„์ค‘๊ณผ ํด๋ผ์ด์–ธํŠธ์—์„œ ์„œ๋ฒ„ ๋ Œ๋”๋ง๋œ ์ฝ˜ํ…์ธ ์˜ ํ•˜์ด๋“œ๋ ˆ์ด์…˜ ์ค‘์—๋งŒ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ์„œ๋ฒ„ ์Šค๋ƒ…์ƒท์€ ํด๋ผ์ด์–ธํŠธ์™€ ์„œ๋ฒ„ ๊ฐ„์— ๋™์ผํ•ด์•ผ ํ•˜๋ฉฐ ์ผ๋ฐ˜์ ์œผ๋กœ ์ง๋ ฌํ™”๋˜์–ด ์„œ๋ฒ„์—์„œ ํด๋ผ์ด์–ธํŠธ๋กœ ์ „๋‹ฌ๋ฉ๋‹ˆ๋‹ค. ์ด ํ•จ์ˆ˜๊ฐ€ ์ œ๊ณต๋˜์ง€ ์•Š์œผ๋ฉด ์„œ๋ฒ„์—์„œ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ Œ๋”๋งํ•  ๋•Œ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. #### ๋ฐ˜ํ™˜๊ฐ’ {/*returns*/} @@ -52,13 +52,13 @@ store์— ์žˆ๋Š” ๋ฐ์ดํ„ฐ์˜ ์Šค๋ƒ…์ƒท์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ๋‘ ๊ฐœ์˜ ํ•จ์ˆ˜๋ฅผ #### ์ฃผ์˜ ์‚ฌํ•ญ {/*caveats*/} -* `getSnapshot`์ด ๋ฐ˜ํ™˜ํ•˜๋Š” store ์Šค๋ƒ…์ƒท์€ ๋ถˆ๋ณ€์ด์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ๋ณธ ์Šคํ† ์–ด์— ๋ณ€๊ฒฝ ๊ฐ€๋Šฅํ•œ ๋ฐ์ดํ„ฐ๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ ๋ฐ์ดํ„ฐ๊ฐ€ ๋ณ€๊ฒฝ๋œ ๊ฒฝ์šฐ ๋ณ€๊ฒฝ ๋ถˆ๊ฐ€๋Šฅํ•œ ์ƒˆ ์Šค๋ƒ…์ƒท์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ์บ์‹œ ๋œ ๋งˆ์ง€๋ง‰ ์Šค๋ƒ…์ƒท์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. +* `getSnapshot`์ด ๋ฐ˜ํ™˜ํ•˜๋Š” store ์Šค๋ƒ…์ƒท์€ ๋ถˆ๋ณ€์ด์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ๋ณธ ์Šคํ† ์–ด์— ๋ณ€๊ฒฝ ๊ฐ€๋Šฅํ•œ ๋ฐ์ดํ„ฐ๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ ๋ฐ์ดํ„ฐ๊ฐ€ ๋ณ€๊ฒฝ๋˜์—ˆ์„ ๋•Œ ๋ณ€๊ฒฝ ๋ถˆ๊ฐ€๋Šฅํ•œ ์ƒˆ ์Šค๋ƒ…์ƒท์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ์บ์‹œ๋œ ๋งˆ์ง€๋ง‰ ์Šค๋ƒ…์ƒท์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. -* ๋ฆฌ๋ Œ๋”๋งํ•˜๋Š” ๋™์•ˆ ๋‹ค๋ฅธ `subscribe` ํ•จ์ˆ˜๊ฐ€ ์ „๋‹ฌ๋˜๋ฉด React๋Š” ์ƒˆ๋กœ ์ „๋‹ฌ๋œ `subscribe` ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ €์žฅ์†Œ๋ฅผ ๋‹ค์‹œ ๊ตฌ๋…ํ•ฉ๋‹ˆ๋‹ค. ์ปดํฌ๋„ŒํŠธ ์™ธ๋ถ€์—์„œ `subscribe` ๋ฅผ ์„ ์–ธํ•˜๋ฉด ์ด๋ฅผ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +* ๋ฆฌ๋ Œ๋”๋งํ•˜๋Š” ๋™์•ˆ ๋‹ค๋ฅธ `subscribe` ํ•จ์ˆ˜๊ฐ€ ์ „๋‹ฌ๋˜๋ฉด React๋Š” ์ƒˆ๋กœ ์ „๋‹ฌ๋œ `subscribe` ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ €์žฅ์†Œ๋ฅผ ๋‹ค์‹œ ๊ตฌ๋…ํ•ฉ๋‹ˆ๋‹ค. ์ปดํฌ๋„ŒํŠธ ์™ธ๋ถ€์—์„œ `subscribe`๋ฅผ ์„ ์–ธํ•˜๋ฉด ์ด๋ฅผ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. * [non-blocking transition ์—…๋ฐ์ดํŠธ](/reference/react/useTransition) ์ค‘์— ์Šคํ† ์–ด๊ฐ€ ๋ณ€๊ฒฝ๋˜๋ฉด, React๋Š” ํ•ด๋‹น ์—…๋ฐ์ดํŠธ๋ฅผ blocking์œผ๋กœ ์ˆ˜ํ–‰ํ•˜๋„๋ก ๋˜๋Œ์•„๊ฐ‘๋‹ˆ๋‹ค. ๊ตฌ์ฒด์ ์œผ๋กœ, ๋ชจ๋“  Transition ์—…๋ฐ์ดํŠธ์— ๋Œ€ํ•ด React๋Š” DOM์— ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ์ ์šฉํ•˜๊ธฐ ์ง์ „์— `getSnapshot`์„ ํ•œ ๋ฒˆ ๋” ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค. ์ฒ˜์Œ ํ˜ธ์ถœํ–ˆ์„ ๋•Œ์™€ ๋‹ค๋ฅธ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•˜๋ฉด, React๋Š” ์ฒ˜์Œ๋ถ€ํ„ฐ ๋‹ค์‹œ ์—…๋ฐ์ดํŠธ๋ฅผ ์‹œ์ž‘ํ•˜๊ณ , ์ด๋ฒˆ์—๋Š” blocking ์—…๋ฐ์ดํŠธ๋ฅผ ์ ์šฉํ•˜์—ฌ ํ™”๋ฉด์˜ ๋ชจ๋“  ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๊ฐ™์€ ์Šคํ† ์–ด ๋ฒ„์ „์„ ๋ฐ˜์˜ํ•˜๋„๋ก ํ•ฉ๋‹ˆ๋‹ค. -* `useSyncExternalStore`๊ฐ€ ๋ฐ˜ํ™˜ํ•œ ์Šคํ† ์–ด ๊ฐ’์„ ๊ธฐ๋ฐ˜์œผ๋กœ ๋ Œ๋”๋ง์„ _์ผ์‹œ ์ค‘๋‹จ_ ํ•˜๋Š” ๊ฒƒ์€ ๊ถŒ์žฅํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ทธ ์ด์œ ๋Š” ์™ธ๋ถ€ ์Šคํ† ์–ด์— ๋Œ€ํ•œ ๋ณ€ํ˜•์„ [non-blocking transition ์—…๋ฐ์ดํŠธ](/reference/react/useTransition)๋กœ ํ‘œ์‹œํ•  ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์—, ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด [`Suspense` fallback](/reference/react/Suspense)์„ ํŠธ๋ฆฌ๊ฑฐํ•ด์„œ, ํ™”๋ฉด์—์„œ ๋กœ๋”ฉ ์Šคํ”ผ๋„ˆ๋กœ ๋Œ€์ฒดํ•˜์—ฌ, ์ผ๋ฐ˜์ ์œผ๋กœ UX๊ฐ€ ์ข‹์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. +* `useSyncExternalStore`๊ฐ€ ๋ฐ˜ํ™˜ํ•œ ์Šคํ† ์–ด ๊ฐ’์„ ๊ธฐ๋ฐ˜์œผ๋กœ ๋ Œ๋”๋ง์„ ์ผ์‹œ ์ค‘๋‹จํ•˜๋Š” ๊ฒƒ์€ ๊ถŒ์žฅํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ทธ ์ด์œ ๋Š” ์™ธ๋ถ€ ์Šคํ† ์–ด์— ๋Œ€ํ•œ ๋ณ€๊ฒฝ์„ [non-blocking transition ์—…๋ฐ์ดํŠธ](/reference/react/useTransition)๋กœ ํ‘œ์‹œํ•  ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์—, ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด [`Suspense` fallback](/reference/react/Suspense)์„ ํŠธ๋ฆฌ๊ฑฐํ•ด์„œ ํ™”๋ฉด์˜ ๋‚ด์šฉ์„ ๋กœ๋”ฉ ์Šคํ”ผ๋„ˆ๋กœ ๋Œ€์ฒดํ•  ์ˆ˜ ์žˆ๊ณ , ์ผ๋ฐ˜์ ์œผ๋กœ UX๊ฐ€ ์ข‹์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ๋‹ค์Œ์€ ๊ถŒ์žฅ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. @@ -69,7 +69,7 @@ store์— ์žˆ๋Š” ๋ฐ์ดํ„ฐ์˜ ์Šค๋ƒ…์ƒท์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ๋‘ ๊ฐœ์˜ ํ•จ์ˆ˜๋ฅผ const selectedProductId = useSyncExternalStore(...); // โŒ `selectedProductId`์— ์ข…์†๋œ Promise๋กœ `use`๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๊ฒƒ - const data = use(fetchItem(selectedProductId)) + const data = use(fetchItem(selectedProductId)); // โŒ `selectedProductId`๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ์ง€์—ฐ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์กฐ๊ฑด๋ถ€๋กœ ๋ Œ๋”๋งํ•˜๋Š” ๊ฒƒ return selectedProductId != null ? : ; @@ -84,7 +84,7 @@ store์— ์žˆ๋Š” ๋ฐ์ดํ„ฐ์˜ ์Šค๋ƒ…์ƒท์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ๋‘ ๊ฐœ์˜ ํ•จ์ˆ˜๋ฅผ ๋Œ€๋ถ€๋ถ„์˜ React ์ปดํฌ๋„ŒํŠธ๋Š” [props](/learn/passing-props-to-a-component), [state](/reference/react/useState), ๊ทธ๋ฆฌ๊ณ  [context](/reference/react/useContext)์—์„œ๋งŒ ๋ฐ์ดํ„ฐ๋ฅผ ์ฝ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๋•Œ๋กœ๋Š” ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์‹œ๊ฐ„์ด ์ง€๋‚จ์— ๋”ฐ๋ผ ๋ณ€๊ฒฝ๋˜๋Š” React ์™ธ๋ถ€์˜ ์ผ๋ถ€ ์ €์žฅ์†Œ์—์„œ ์ผ๋ถ€ ๋ฐ์ดํ„ฐ๋ฅผ ์ฝ์–ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ๋‹ค์Œ์ด ํฌํ•จ๋ฉ๋‹ˆ๋‹ค. -* React ์™ธ๋ถ€์— state๋ฅผ ๋ณด๊ด€ํ•˜๋Š” ์„œ๋“œํŒŒํ‹ฐ ์ƒํƒœ ๊ด€๋ฆฌ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ. +* React ์™ธ๋ถ€์— state๋ฅผ ๋ณด๊ด€ํ•˜๋Š” ์„œ๋“œ ํŒŒํ‹ฐ ์ƒํƒœ ๊ด€๋ฆฌ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ. * ๋ณ€๊ฒฝ ๊ฐ€๋Šฅํ•œ ๊ฐ’์„ ๋…ธ์ถœํ•˜๋Š” ๋ธŒ๋ผ์šฐ์ € API์™€ ๊ทธ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ๊ตฌ๋…ํ•˜๋Š” ์ด๋ฒคํŠธ. ์™ธ๋ถ€ ๋ฐ์ดํ„ฐ ์ €์žฅ์†Œ์—์„œ ๊ฐ’์„ ์ฝ์œผ๋ ค๋ฉด ์ปดํฌ๋„ŒํŠธ์˜ ์ตœ์ƒ์œ„ ๋ ˆ๋ฒจ์—์„œ `useSyncExternalStore`๋ฅผ ํ˜ธ์ถœํ•˜์„ธ์š”. @@ -101,12 +101,12 @@ function TodosApp() { store์— ์žˆ๋Š” ๋ฐ์ดํ„ฐ์˜ snapshot์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ๋‘ ๊ฐœ์˜ ํ•จ์ˆ˜๋ฅผ ์ธ์ˆ˜๋กœ ์ „๋‹ฌํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. -1. `subscribe` ํ•จ์ˆ˜๋Š” store์— ๊ตฌ๋…ํ•˜๊ณ  ๊ตฌ๋…์„ ์ทจ์†Œํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. +1. `subscribe` ํ•จ์ˆ˜๋Š” store๋ฅผ ๊ตฌ๋…ํ•˜๊ณ  ๊ตฌ๋…์„ ์ทจ์†Œํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. 2. `getSnapshot` ํ•จ์ˆ˜๋Š” store์—์„œ ๋ฐ์ดํ„ฐ์˜ ์Šค๋ƒ…์ƒท์„ ์ฝ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. -React๋Š” ์ด ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•ด ์ปดํฌ๋„ŒํŠธ๋ฅผ store์— ๊ตฌ๋…ํ•œ ์ƒํƒœ๋กœ ์œ ์ง€ํ•˜๊ณ  ๋ณ€๊ฒฝ ์‚ฌํ•ญ์ด ์žˆ์„ ๋•Œ ๋ฆฌ๋ Œ๋”๋งํ•ฉ๋‹ˆ๋‹ค. +React๋Š” ์ด ํ•จ์ˆ˜๋“ค์„ ์‚ฌ์šฉํ•ด ์ปดํฌ๋„ŒํŠธ๊ฐ€ store๋ฅผ ๊ตฌ๋…ํ•œ ์ƒํƒœ๋ฅผ ์œ ์ง€ํ•˜๊ฒŒ ํ•˜๊ณ  ๋ณ€๊ฒฝ ์‚ฌํ•ญ์ด ์žˆ์„ ๋•Œ ๋ฆฌ๋ Œ๋”๋งํ•ฉ๋‹ˆ๋‹ค. -์˜ˆ๋ฅผ ๋“ค์–ด ์•„๋ž˜ ์ƒŒ๋“œ๋ฐ•์Šค์—์„œ `todosStore`๋Š” React ์™ธ๋ถ€์— ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๋Š” ์™ธ๋ถ€ store๋กœ ๊ตฌํ˜„๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. `TodosApp`์ปดํฌ๋„ŒํŠธ๋Š” `useSyncExternalStore` Hook์œผ๋กœ ํ•ด๋‹น ์™ธ๋ถ€ store์— ์—ฐ๊ฒฐํ•ฉ๋‹ˆ๋‹ค. +์˜ˆ๋ฅผ ๋“ค์–ด ์•„๋ž˜ ์ƒŒ๋“œ๋ฐ•์Šค์—์„œ `todosStore`๋Š” React ์™ธ๋ถ€์— ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๋Š” ์™ธ๋ถ€ store๋กœ ๊ตฌํ˜„๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. `TodosApp` ์ปดํฌ๋„ŒํŠธ๋Š” `useSyncExternalStore` Hook์œผ๋กœ ํ•ด๋‹น ์™ธ๋ถ€ store์— ์—ฐ๊ฒฐํ•ฉ๋‹ˆ๋‹ค. @@ -131,7 +131,7 @@ export default function TodosApp() { ``` ```js src/todoStore.js -// ์ด๊ฒƒ์€ third-party store์˜ ์˜ˆ์‹œ์ž…๋‹ˆ๋‹ค +// ์ด๊ฒƒ์€ ์„œ๋“œ ํŒŒํ‹ฐ store์˜ ์˜ˆ์‹œ์ž…๋‹ˆ๋‹ค // ํ•ด๋‹น store๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ React์™€ ํ†ตํ•ฉํ•  ํ•„์š”๊ฐ€ ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. // ์•ฑ์ด React๋กœ ์™„์ „ํžˆ ๋นŒ๋“œ๋œ ๊ฒฝ์šฐ, @@ -143,7 +143,7 @@ let listeners = []; export const todosStore = { addTodo() { - todos = [...todos, { id: nextId++, text: 'Todo #' + nextId }] + todos = [...todos, { id: nextId++, text: 'Todo #' + nextId }]; emitChange(); }, subscribe(listener) { @@ -176,7 +176,7 @@ function emitChange() { ### ๋ธŒ๋ผ์šฐ์ € API ๊ตฌ๋… {/*subscribing-to-a-browser-api*/} -`useSyncExternalStore`๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๋˜ ๋‹ค๋ฅธ ์ด์œ ๋Š” ์‹œ๊ฐ„์ด ์ง€๋‚จ์— ๋”ฐ๋ผ ๋ณ€๊ฒฝ๋˜๋Š” ๋ธŒ๋ผ์šฐ์ €์— ๋…ธ์ถœ๋˜๋Š” ์ผ๋ถ€ ๊ฐ’์„ ๊ตฌ๋…ํ•˜๋ ค๋Š” ๊ฒฝ์šฐ์ž…๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ์ปดํฌ๋„ŒํŠธ์— ๋„คํŠธ์›Œํฌ ์—ฐ๊ฒฐ์ด ํ™œ์„ฑํ™”๋˜์–ด ์žˆ๋Š”์ง€ ์—ฌ๋ถ€๋ฅผ ํ‘œ์‹œํ•˜๊ณ  ์‹ถ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ๋ธŒ๋ผ์šฐ์ €๋Š” [`navigator.onLine`.](https://developer.mozilla.org/en-US/docs/Web/API/Navigator/onLine)์ด๋ผ๋Š” ์†์„ฑ์„ ํ†ตํ•ด ์ด ์ •๋ณด๋ฅผ ๋…ธ์ถœํ•ฉ๋‹ˆ๋‹ค. +`useSyncExternalStore`๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๋˜ ๋‹ค๋ฅธ ์ด์œ ๋Š” ์‹œ๊ฐ„์ด ์ง€๋‚จ์— ๋”ฐ๋ผ ๋ณ€๊ฒฝ๋˜๋Š” ๋ธŒ๋ผ์šฐ์ €์— ๋…ธ์ถœ๋˜๋Š” ์ผ๋ถ€ ๊ฐ’์„ ๊ตฌ๋…ํ•˜๋ ค๋Š” ๊ฒฝ์šฐ์ž…๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ์ปดํฌ๋„ŒํŠธ์— ๋„คํŠธ์›Œํฌ ์—ฐ๊ฒฐ์ด ํ™œ์„ฑํ™”๋˜์–ด ์žˆ๋Š”์ง€ ์—ฌ๋ถ€๋ฅผ ํ‘œ์‹œํ•˜๊ณ  ์‹ถ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ๋ธŒ๋ผ์šฐ์ €๋Š” [`navigator.onLine`](https://developer.mozilla.org/en-US/docs/Web/API/Navigator/onLine)์ด๋ผ๋Š” ์†์„ฑ์„ ํ†ตํ•ด ์ด ์ •๋ณด๋ฅผ ๋…ธ์ถœํ•ฉ๋‹ˆ๋‹ค. ์ด ๊ฐ’์€ ์‹œ๊ฐ„์ด ์ง€๋‚จ์— ๋”ฐ๋ผ React๊ฐ€ ์•Œ์ง€ ๋ชปํ•˜๋Š” ์‚ฌ์ด์— ๋ณ€๊ฒฝ๋  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ `useSyncExternalStore`๋กœ ๊ฐ’์„ ์ฝ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. @@ -197,7 +197,7 @@ function getSnapshot() { } ``` -๋‹ค์Œ์œผ๋กœ `subscribe` ํ•จ์ˆ˜๋ฅผ ๊ตฌํ˜„ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด `navigator.onLine`์ด ๋ณ€๊ฒฝ๋˜๋ฉด ๋ธŒ๋ผ์šฐ์ €๋Š” `window` ๊ฐ์ฒด์—์„œ [`online`](https://developer.mozilla.org/en-US/docs/Web/API/Window/online_event) ๋ฐ [`offline`](https://developer.mozilla.org/en-US/docs/Web/API/Window/offline_event) ์ด๋ฒคํŠธ๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค. `callback` ์ธ์ˆ˜๋ฅผ ํ•ด๋‹น ์ด๋ฒคํŠธ์— ๊ตฌ๋…ํ•œ ๋‹ค์Œ ๊ตฌ๋…์„ ์ •๋ฆฌํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. +๋‹ค์Œ์œผ๋กœ `subscribe` ํ•จ์ˆ˜๋ฅผ ๊ตฌํ˜„ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด `navigator.onLine`์ด ๋ณ€๊ฒฝ๋˜๋ฉด ๋ธŒ๋ผ์šฐ์ €๋Š” `window` ๊ฐ์ฒด์—์„œ [`online`](https://developer.mozilla.org/en-US/docs/Web/API/Window/online_event) ๋ฐ [`offline`](https://developer.mozilla.org/en-US/docs/Web/API/Window/offline_event) ์ด๋ฒคํŠธ๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค. `callback` ์ธ์ˆ˜๋ฅผ ํ•ด๋‹น ์ด๋ฒคํŠธ์— ๋“ฑ๋กํ•œ ๋‹ค์Œ ๊ตฌ๋…์„ ์ •๋ฆฌํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ```js function subscribe(callback) { @@ -240,11 +240,11 @@ function subscribe(callback) { --- -### custom Hook์œผ๋กœ ๋กœ์ง ์ถ”์ถœํ•˜๊ธฐ {/*extracting-the-logic-to-a-custom-hook*/} +### ์ปค์Šคํ…€ Hook์œผ๋กœ ๋กœ์ง ์ถ”์ถœํ•˜๊ธฐ {/*extracting-the-logic-to-a-custom-hook*/} -์ผ๋ฐ˜์ ์œผ๋กœ ์ปดํฌ๋„ŒํŠธ์—์„œ ์ง์ ‘ `useSyncExternalStore`๋ฅผ ์ž‘์„ฑํ•˜์ง€๋Š” ์•Š์Šต๋‹ˆ๋‹ค. ๋Œ€์‹  ์ผ๋ฐ˜์ ์œผ๋กœ custom Hook์—์„œ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์„œ๋กœ ๋‹ค๋ฅธ ์ปดํฌ๋„ŒํŠธ์—์„œ ๋™์ผํ•œ ์™ธ๋ถ€ ์ €์žฅ์†Œ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +์ผ๋ฐ˜์ ์œผ๋กœ ์ปดํฌ๋„ŒํŠธ์—์„œ ์ง์ ‘ `useSyncExternalStore`๋ฅผ ์ž‘์„ฑํ•˜์ง€๋Š” ์•Š์Šต๋‹ˆ๋‹ค. ๋Œ€์‹  ์ปค์Šคํ…€ Hook์—์„œ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์„œ๋กœ ๋‹ค๋ฅธ ์ปดํฌ๋„ŒํŠธ์—์„œ ๋™์ผํ•œ ์™ธ๋ถ€ ์ €์žฅ์†Œ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -์˜ˆ๋ฅผ ๋“ค์–ด ์ด custom `useOnlineStatus` Hook์€ ๋„คํŠธ์›Œํฌ๊ฐ€ ์˜จ๋ผ์ธ ์ƒํƒœ์ธ์ง€ ์—ฌ๋ถ€๋ฅผ ์ถ”์ ํ•ฉ๋‹ˆ๋‹ค. +์˜ˆ๋ฅผ ๋“ค์–ด ์ด ์ปค์Šคํ…€ `useOnlineStatus` Hook์€ ๋„คํŠธ์›Œํฌ๊ฐ€ ์˜จ๋ผ์ธ ์ƒํƒœ์ธ์ง€ ์—ฌ๋ถ€๋ฅผ ์ถ”์ ํ•ฉ๋‹ˆ๋‹ค. ```js {3,6} import { useSyncExternalStore } from 'react'; @@ -358,13 +358,13 @@ function subscribe(callback) { `getServerSnapshot` ํ•จ์ˆ˜๋Š” `getSnapshot`๊ณผ ์œ ์‚ฌํ•˜์ง€๋งŒ ๋‘ ๊ฐ€์ง€ ์ƒํ™ฉ์—์„œ๋งŒ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค. - HTML์„ ์ƒ์„ฑํ•  ๋•Œ ์„œ๋ฒ„์—์„œ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค. -- [hydration](/reference/react-dom/client/hydrateRoot) ์ค‘ ์ฆ‰ React๊ฐ€ ์„œ๋ฒ„ HTML์„ ๊ฐ€์ ธ์™€์„œ ์ธํ„ฐ๋ž™ํ‹ฐ๋ธŒํ•˜๊ฒŒ ๋งŒ๋“ค ๋•Œ ํด๋ผ์ด์–ธํŠธ์—์„œ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค. +- [hydration](/reference/react-dom/client/hydrateRoot) ์ค‘, ์ฆ‰ React๊ฐ€ ์„œ๋ฒ„ HTML์„ ๊ฐ€์ ธ์™€์„œ ์ธํ„ฐ๋ž™ํ‹ฐ๋ธŒํ•˜๊ฒŒ ๋งŒ๋“ค ๋•Œ ํด๋ผ์ด์–ธํŠธ์—์„œ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ์•ฑ์ด ์ƒํ˜ธ์ž‘์šฉํ•˜๊ธฐ ์ „์— ์‚ฌ์šฉ๋  ์ดˆ๊ธฐ ์Šค๋ƒ…์ƒท ๊ฐ’์„ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์„œ๋ฒ„ ๋ Œ๋”๋ง์— ์˜๋ฏธ ์žˆ๋Š” ์ดˆ๊ธฐ๊ฐ’์ด ์—†๋‹ค๋ฉด [์ปดํฌ๋„ŒํŠธ๊ฐ€ ํด๋ผ์ด์–ธํŠธ์—์„œ๋งŒ ๋ Œ๋”๋ง๋˜๋„๋ก ๊ฐ•์ œ ์„ค์ •](/reference/react/Suspense#providing-a-fallback-for-server-errors-and-client-only-content)ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -`getServerSnapshot`์ด ์ดˆ๊ธฐ ํด๋ผ์ด์–ธํŠธ ๋ Œ๋”๋ง์—์„œ ์„œ๋ฒ„์—์„œ ๋ฐ˜ํ™˜ํ•œ ๊ฒƒ๊ณผ ๋™์ผํ•œ ์ •ํ™•ํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š”์ง€ ํ™•์ธํ•˜์„ธ์š”. ์˜ˆ๋ฅผ ๋“ค์–ด `getServerSnapshot`์ด ์„œ๋ฒ„์—์„œ ๋ฏธ๋ฆฌ ์ฑ„์›Œ์ง„ store ์ฝ˜ํ…์ธ ๋ฅผ ๋ฐ˜ํ™˜ํ•œ ๊ฒฝ์šฐ ์ด ์ฝ˜ํ…์ธ ๋ฅผ ํด๋ผ์ด์–ธํŠธ๋กœ ์ „์†กํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ์ˆ˜ํ–‰ํ•˜๋Š” ์ผ๋ฐ˜์ ์ธ ๋ฐฉ๋ฒ• ์ค‘ ํ•˜๋‚˜๋Š” ์„œ๋ฒ„ ๋ Œ๋”๋ง ์ค‘์— `window.MY_STORE_DATA`์™€ ๊ฐ™์€ ๊ธ€๋กœ๋ฒŒ์„ ์„ค์ •ํ•˜๋Š” `