From c8715aa000ab582e4f63923ccd1450ef9238aa7a Mon Sep 17 00:00:00 2001 From: Jaem <91131509+DarkChocoJaem@users.noreply.github.com> Date: Tue, 13 Jan 2026 21:38:35 +0900 Subject: [PATCH] Update removing-effect-dependencies.md --- .../learn/removing-effect-dependencies.md | 124 +++++++++--------- 1 file changed, 62 insertions(+), 62 deletions(-) diff --git a/src/content/learn/removing-effect-dependencies.md b/src/content/learn/removing-effect-dependencies.md index c72031050..148c1fadd 100644 --- a/src/content/learn/removing-effect-dependencies.md +++ b/src/content/learn/removing-effect-dependencies.md @@ -49,7 +49,7 @@ function ChatRoom({ roomId }) { const connection = createConnection(serverUrl, roomId); connection.connect(); return () => connection.disconnect(); - }, []); // <-- Fix the mistake here! + }, []); // <-- 여기서 실수를 수정하세요! return

Welcome to the {roomId} room!

; } @@ -77,7 +77,7 @@ export default function App() { ```js src/chat.js export function createConnection(serverUrl, roomId) { - // A real implementation would actually connect to the server + // 실제 구현에서는 서버에 연결됩니다 return { connect() { console.log('✅ Connecting to "' + roomId + '" room at ' + serverUrl + '...'); @@ -104,7 +104,7 @@ function ChatRoom({ roomId }) { const connection = createConnection(serverUrl, roomId); connection.connect(); return () => connection.disconnect(); - }, [roomId]); // ✅ All dependencies declared + }, [roomId]); // ✅ 모든 의존성 선언됨 // ... } ``` @@ -152,7 +152,7 @@ export default function App() { ```js src/chat.js export function createConnection(serverUrl, roomId) { - // A real implementation would actually connect to the server + // 실제 구현에서는 서버에 연결됩니다 return { connect() { console.log('✅ Connecting to "' + roomId + '" room at ' + serverUrl + '...'); @@ -178,12 +178,12 @@ Effect의 의존성을 "선택"할 수 없다는 점에 유의하세요. Effect ```js [[2, 3, "roomId"], [2, 5, "roomId"], [2, 8, "roomId"]] const serverUrl = 'https://localhost:1234'; -function ChatRoom({ roomId }) { // This is a reactive value +function ChatRoom({ roomId }) { // 이것은 반응형 값입니다 useEffect(() => { - const connection = createConnection(serverUrl, roomId); // This Effect reads that reactive value + const connection = createConnection(serverUrl, roomId); // 이 Effect는 해당 반응형 값을 읽습니다 connection.connect(); return () => connection.disconnect(); - }, [roomId]); // ✅ So you must specify that reactive value as a dependency of your Effect + }, [roomId]); // ✅ 따라서 해당 반응형 값을 Effect의 의존성으로 지정해야 합니다 // ... } ``` @@ -198,7 +198,7 @@ function ChatRoom({ roomId }) { const connection = createConnection(serverUrl, roomId); connection.connect(); return () => connection.disconnect(); - }, []); // 🔴 React Hook useEffect has a missing dependency: 'roomId' + }, []); // 🔴 React Hook useEffect의 의존성 'roomId'가 누락되었습니다. // ... } ``` @@ -209,14 +209,14 @@ function ChatRoom({ roomId }) { ```js {2,9} const serverUrl = 'https://localhost:1234'; -const roomId = 'music'; // Not a reactive value anymore +const roomId = 'music'; // 더 이상 반응형 값이 아닙니다 function ChatRoom() { useEffect(() => { const connection = createConnection(serverUrl, roomId); connection.connect(); return () => connection.disconnect(); - }, []); // ✅ All dependencies declared + }, []); // ✅ 모든 의존성 선언됨 // ... } ``` @@ -244,7 +244,7 @@ export default function ChatRoom() { ```js src/chat.js export function createConnection(serverUrl, roomId) { - // A real implementation would actually connect to the server + // 실제 구현에서는 서버에 연결됩니다 return { connect() { console.log('✅ Connecting to "' + roomId + '" room at ' + serverUrl + '...'); @@ -284,7 +284,7 @@ button { margin-left: 10px; } ```js {3-4} useEffect(() => { // ... - // 🔴 Avoid suppressing the linter like this: + // 🔴 이렇게 린터를 억제하지 마세요: // eslint-disable-next-line react-hooks/exhaustive-deps }, []); ``` @@ -380,7 +380,7 @@ function Form() { useEffect(() => { if (submitted) { - // 🔴 Avoid: Event-specific logic inside an Effect + // 🔴 피하세요: Effect 내부에 이벤트별 로직 post('/api/register'); showNotification('Successfully registered!'); } @@ -403,11 +403,11 @@ function Form() { useEffect(() => { if (submitted) { - // 🔴 Avoid: Event-specific logic inside an Effect + // 🔴 피하세요: Effect 내부에 이벤트별 로직 post('/api/register'); showNotification('Successfully registered!', theme); } - }, [submitted, theme]); // ✅ All dependencies declared + }, [submitted, theme]); // ✅ 모든 의존성 선언됨 function handleSubmit() { setSubmitted(true); @@ -426,7 +426,7 @@ function Form() { const theme = useContext(ThemeContext); function handleSubmit() { - // ✅ Good: Event-specific logic is called from event handlers + // ✅ 좋습니다: 이벤트별 로직은 이벤트 핸들러에서 호출됩니다 post('/api/register'); showNotification('Successfully registered!', theme); } @@ -460,7 +460,7 @@ function ShippingForm({ country }) { return () => { ignore = true; }; - }, [country]); // ✅ All dependencies declared + }, [country]); // ✅ 모든 의존성 선언됨 // ... ``` @@ -484,7 +484,7 @@ function ShippingForm({ country }) { setCities(json); } }); - // 🔴 Avoid: A single Effect synchronizes two independent processes + // 🔴 피하세요: 단일 Effect가 두 개의 독립적인 프로세스를 동기화함 if (city) { fetch(`/api/areas?city=${city}`) .then(response => response.json()) @@ -497,7 +497,7 @@ function ShippingForm({ country }) { return () => { ignore = true; }; - }, [country, city]); // ✅ All dependencies declared + }, [country, city]); // ✅ 모든 의존성 선언됨 // ... ``` @@ -527,7 +527,7 @@ function ShippingForm({ country }) { return () => { ignore = true; }; - }, [country]); // ✅ All dependencies declared + }, [country]); // ✅ 모든 의존성 선언됨 const [city, setCity] = useState(null); const [areas, setAreas] = useState(null); @@ -545,7 +545,7 @@ function ShippingForm({ country }) { ignore = true; }; } - }, [city]); // ✅ All dependencies declared + }, [city]); // ✅ 모든 의존성 선언됨 // ... ``` @@ -582,7 +582,7 @@ function ChatRoom({ roomId }) { setMessages([...messages, receivedMessage]); }); return () => connection.disconnect(); - }, [roomId, messages]); // ✅ All dependencies declared + }, [roomId, messages]); // ✅ 모든 의존성 선언됨 // ... ``` @@ -602,7 +602,7 @@ function ChatRoom({ roomId }) { setMessages(msgs => [...msgs, receivedMessage]); }); return () => connection.disconnect(); - }, [roomId]); // ✅ All dependencies declared + }, [roomId]); // ✅ 모든 의존성 선언됨 // ... ``` @@ -610,7 +610,7 @@ function ChatRoom({ roomId }) { ### 값의 변경에 '반응'하지 않고 값을 읽고 싶으신가요? {/*do-you-want-to-read-a-value-without-reacting-to-its-changes*/} -Suppose that you want to play a sound when the user receives a new message unless `isMuted` is `true`: +사용자가 새 메시지를 받을 때 `isMuted`가 `true`가 아니면 소리를 재생하고 싶다고 가정해 보세요. ```js {3,10-12} function ChatRoom({ roomId }) { @@ -646,7 +646,7 @@ function ChatRoom({ roomId }) { } }); return () => connection.disconnect(); - }, [roomId, isMuted]); // ✅ All dependencies declared + }, [roomId, isMuted]); // ✅ 모든 의존성 선언됨 // ... ``` @@ -675,7 +675,7 @@ function ChatRoom({ roomId }) { onMessage(receivedMessage); }); return () => connection.disconnect(); - }, [roomId]); // ✅ All dependencies declared + }, [roomId]); // ✅ 모든 의존성 선언됨 // ... ``` @@ -696,7 +696,7 @@ function ChatRoom({ roomId, onReceiveMessage }) { onReceiveMessage(receivedMessage); }); return () => connection.disconnect(); - }, [roomId, onReceiveMessage]); // ✅ All dependencies declared + }, [roomId, onReceiveMessage]); // ✅ 모든 의존성 선언됨 // ... ``` @@ -728,7 +728,7 @@ function ChatRoom({ roomId, onReceiveMessage }) { onMessage(receivedMessage); }); return () => connection.disconnect(); - }, [roomId]); // ✅ All dependencies declared + }, [roomId]); // ✅ 모든 의존성 선언됨 // ... ``` @@ -748,7 +748,7 @@ function Chat({ roomId, notificationCount }) { useEffect(() => { onVisit(roomId); - }, [roomId]); // ✅ All dependencies declared + }, [roomId]); // ✅ 모든 의존성 선언됨 // ... } ``` @@ -781,7 +781,7 @@ function ChatRoom({ roomId }) { const connection = createConnection(options); connection.connect(); return () => connection.disconnect(); - }, [options]); // ✅ All dependencies declared + }, [options]); // ✅ 모든 의존성 선언됨 // ... ``` @@ -798,7 +798,7 @@ const serverUrl = 'https://localhost:1234'; function ChatRoom({ roomId }) { const [message, setMessage] = useState(''); - // Temporarily disable the linter to demonstrate the problem + // 문제를 보여주기 위해 린터를 일시적으로 비활성화합니다. // eslint-disable-next-line react-hooks/exhaustive-deps const options = { serverUrl: serverUrl, @@ -843,7 +843,7 @@ export default function App() { ```js src/chat.js export function createConnection({ serverUrl, roomId }) { - // A real implementation would actually connect to the server + // 실제 구현에서는 서버에 연결됩니다 return { connect() { console.log('✅ Connecting to "' + roomId + '" room at ' + serverUrl + '...'); @@ -869,13 +869,13 @@ button { margin-left: 10px; } **이 문제는 객체와 함수에만 영향을 줍니다. 자바스크립트에서는 새로 생성된 객체와 함수가 다른 모든 객체와 구별되는 것으로 간주됩니다. 그 안의 내용이 동일할 수 있다는 것은 중요하지 않습니다!** ```js {7-8} -// During the first render +// 첫 번째 렌더링 중 const options1 = { serverUrl: 'https://localhost:1234', roomId: 'music' }; -// During the next render +// 다음 렌더링 중 const options2 = { serverUrl: 'https://localhost:1234', roomId: 'music' }; -// These are two different objects! +// 이 두 객체는 서로 다릅니다! console.log(Object.is(options1, options2)); // false ``` @@ -900,7 +900,7 @@ function ChatRoom() { const connection = createConnection(options); connection.connect(); return () => connection.disconnect(); - }, []); // ✅ All dependencies declared + }, []); // ✅ 모든 의존성 선언됨 // ... ``` @@ -924,7 +924,7 @@ function ChatRoom() { const connection = createConnection(options); connection.connect(); return () => connection.disconnect(); - }, []); // ✅ All dependencies declared + }, []); // ✅ 모든 의존성 선언됨 // ... ``` @@ -948,20 +948,20 @@ function ChatRoom({ roomId }) { const connection = createConnection(options); connection.connect(); return () => connection.disconnect(); - }, [roomId]); // ✅ All dependencies declared + }, [roomId]); // ✅ 모든 의존성 선언됨 // ... ``` 이제 `options`이 Effect 내부에서 선언되었으므로 더 이상 Effect의 의존성이 아닙니다. 대신 Effect에서 사용하는 유일한 반응형 값은 `roomId`입니다. `roomId`는 객체나 함수가 아니기 때문에 의도치 않게 달라지지 않을 것이라고 확신할 수 있습니다. 자바스크립트에서 숫자와 문자열은 그 내용에 따라 비교됩니다. ```js {7-8} -// During the first render +// 첫 번째 렌더링 중 const roomId1 = 'music'; -// During the next render +// 다음 렌더링 중 const roomId2 = 'music'; -// These two strings are the same! +// 이 두 문자열은 동일합니다! console.log(Object.is(roomId1, roomId2)); // true ``` @@ -1020,7 +1020,7 @@ export default function App() { ```js src/chat.js export function createConnection({ serverUrl, roomId }) { - // A real implementation would actually connect to the server + // 실제 구현에서는 서버에 연결됩니다 return { connect() { console.log('✅ Connecting to "' + roomId + '" room at ' + serverUrl + '...'); @@ -1061,7 +1061,7 @@ function ChatRoom({ roomId }) { const connection = createConnection(options); connection.connect(); return () => connection.disconnect(); - }, [roomId]); // ✅ All dependencies declared + }, [roomId]); // ✅ 모든 의존성 선언됨 // ... ``` @@ -1079,7 +1079,7 @@ function ChatRoom({ options }) { const connection = createConnection(options); connection.connect(); return () => connection.disconnect(); - }, [options]); // ✅ All dependencies declared + }, [options]); // ✅ 모든 의존성 선언됨 // ... ``` @@ -1109,7 +1109,7 @@ function ChatRoom({ options }) { }); connection.connect(); return () => connection.disconnect(); - }, [roomId, serverUrl]); // ✅ All dependencies declared + }, [roomId, serverUrl]); // ✅ 모든 의존성 선언됨 // ... ``` @@ -1145,7 +1145,7 @@ function ChatRoom({ getOptions }) { }); connection.connect(); return () => connection.disconnect(); - }, [roomId, serverUrl]); // ✅ All dependencies declared + }, [roomId, serverUrl]); // ✅ 모든 의존성 선언됨 // ... ``` @@ -1322,11 +1322,11 @@ export class FadeInAnimation { start(duration) { this.duration = duration; if (this.duration === 0) { - // Jump to end immediately + // 즉시 끝으로 이동 this.onProgress(1); } else { this.onProgress(0); - // Start animating + // 애니메이션 시작 this.startTime = performance.now(); this.frameId = requestAnimationFrame(() => this.onFrame()); } @@ -1336,7 +1336,7 @@ export class FadeInAnimation { const progress = Math.min(timePassed / this.duration, 1); this.onProgress(progress); if (progress < 1) { - // We still have more frames to paint + // 아직 더 그릴 프레임이 있습니다 this.frameId = requestAnimationFrame(() => this.onFrame()); } } @@ -1445,7 +1445,7 @@ export class FadeInAnimation { const progress = Math.min(timePassed / this.duration, 1); this.onProgress(progress); if (progress < 1) { - // We still have more frames to paint + // 아직 더 그릴 프레임이 있습니다 this.frameId = requestAnimationFrame(() => this.onFrame()); } } @@ -1547,7 +1547,7 @@ export default function ChatRoom({ options }) { ```js src/chat.js export function createConnection({ serverUrl, roomId }) { - // A real implementation would actually connect to the server + // 실제 구현에서는 서버에 연결됩니다 if (typeof serverUrl !== 'string') { throw Error('Expected serverUrl to be a string. Received: ' + serverUrl); } @@ -1645,7 +1645,7 @@ export default function ChatRoom({ options }) { ```js src/chat.js export function createConnection({ serverUrl, roomId }) { - // A real implementation would actually connect to the server + // 실제 구현에서는 서버에 연결됩니다 if (typeof serverUrl !== 'string') { throw Error('Expected serverUrl to be a string. Received: ' + serverUrl); } @@ -1736,7 +1736,7 @@ export default function ChatRoom({ roomId, serverUrl }) { ```js src/chat.js export function createConnection({ serverUrl, roomId }) { - // A real implementation would actually connect to the server + // 실제 구현에서는 서버에 연결됩니다 if (typeof serverUrl !== 'string') { throw Error('Expected serverUrl to be a string. Received: ' + serverUrl); } @@ -1886,7 +1886,7 @@ export default function ChatRoom({ roomId, createConnection, onMessage }) { ```js src/chat.js export function createEncryptedConnection({ serverUrl, roomId }) { - // A real implementation would actually connect to the server + // 실제 구현에서는 서버에 연결됩니다 if (typeof serverUrl !== 'string') { throw Error('Expected serverUrl to be a string. Received: ' + serverUrl); } @@ -1927,7 +1927,7 @@ export function createEncryptedConnection({ serverUrl, roomId }) { } export function createUnencryptedConnection({ serverUrl, roomId }) { - // A real implementation would actually connect to the server + // 실제 구현에서는 서버에 연결됩니다 if (typeof serverUrl !== 'string') { throw Error('Expected serverUrl to be a string. Received: ' + serverUrl); } @@ -2053,16 +2053,16 @@ export default function ChatRoom({ roomId, isEncrypted, onMessage }) { 이 두 가지 변경 사항 이후에는 Effect가 더 이상 함수 값에 의존하지 않습니다. ```js {1,8,10,21} -export default function ChatRoom({ roomId, isEncrypted, onMessage }) { // Reactive values - const onReceiveMessage = useEffectEvent(onMessage); // Not reactive +export default function ChatRoom({ roomId, isEncrypted, onMessage }) { // 반응형 값 + const onReceiveMessage = useEffectEvent(onMessage); // 비반응형 useEffect(() => { function createConnection() { const options = { serverUrl: 'https://localhost:1234', - roomId: roomId // Reading a reactive value + roomId: roomId // 반응형 값 읽기 }; - if (isEncrypted) { // Reading a reactive value + if (isEncrypted) { // 반응형 값 읽기 return createEncryptedConnection(options); } else { return createUnencryptedConnection(options); @@ -2073,7 +2073,7 @@ export default function ChatRoom({ roomId, isEncrypted, onMessage }) { // Reacti connection.on('message', (msg) => onReceiveMessage(msg)); connection.connect(); return () => connection.disconnect(); - }, [roomId, isEncrypted]); // ✅ All dependencies declared + }, [roomId, isEncrypted]); // ✅ 모든 의존성 선언됨 ``` 그 결과, 의미 있는 정보(`roomId` 또는 `isEncrypted`)가 변경될 때만 채팅이 다시 연결됩니다. @@ -2186,7 +2186,7 @@ export default function ChatRoom({ roomId, isEncrypted, onMessage }) { ```js src/chat.js export function createEncryptedConnection({ serverUrl, roomId }) { - // A real implementation would actually connect to the server + // 실제 구현에서는 서버에 연결됩니다 if (typeof serverUrl !== 'string') { throw Error('Expected serverUrl to be a string. Received: ' + serverUrl); } @@ -2227,7 +2227,7 @@ export function createEncryptedConnection({ serverUrl, roomId }) { } export function createUnencryptedConnection({ serverUrl, roomId }) { - // A real implementation would actually connect to the server + // 실제 구현에서는 서버에 연결됩니다 if (typeof serverUrl !== 'string') { throw Error('Expected serverUrl to be a string. Received: ' + serverUrl); }