From afdcbf7e3a6b27613b9f017e1e9957a1c6add304 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=A3=A8=EB=B0=80LuMir?= Date: Sat, 16 May 2026 11:44:50 +0900 Subject: [PATCH] docs: fix typos --- src/components/PageHeading.tsx | 6 ++--- .../learn/choosing-the-state-structure.md | 2 +- src/content/learn/creating-a-react-app.md | 8 +++--- src/content/learn/describing-the-ui.md | 2 +- src/content/learn/escape-hatches.md | 2 +- .../extracting-state-logic-into-a-reducer.md | 10 +++---- src/content/learn/keeping-components-pure.md | 8 +++--- .../learn/manipulating-the-dom-with-refs.md | 4 +-- .../learn/passing-props-to-a-component.md | 2 +- .../learn/preserving-and-resetting-state.md | 4 +-- .../react-compiler/incremental-adoption.md | 2 +- .../learn/reacting-to-input-with-state.md | 2 +- .../learn/referencing-values-with-refs.md | 4 +-- .../learn/removing-effect-dependencies.md | 2 +- src/content/learn/render-and-commit.md | 12 ++++----- src/content/learn/rendering-lists.md | 2 +- src/content/learn/responding-to-events.md | 4 +-- .../learn/reusing-logic-with-custom-hooks.md | 2 +- .../learn/separating-events-from-effects.md | 2 +- .../learn/sharing-state-between-components.md | 4 +-- .../learn/start-a-new-react-project.md | 4 +-- src/content/learn/state-as-a-snapshot.md | 2 +- .../learn/synchronizing-with-effects.md | 26 +++++++++---------- src/content/learn/thinking-in-react.md | 2 +- src/content/learn/tutorial-tic-tac-toe.md | 8 +++--- src/content/learn/updating-arrays-in-state.md | 12 ++++----- .../learn/updating-objects-in-state.md | 12 ++++----- .../learn/you-might-not-need-an-effect.md | 4 +-- src/content/learn/your-first-component.md | 20 +++++++------- 29 files changed, 87 insertions(+), 87 deletions(-) diff --git a/src/components/PageHeading.tsx b/src/components/PageHeading.tsx index ba4b413a0..3cfb6337d 100644 --- a/src/components/PageHeading.tsx +++ b/src/components/PageHeading.tsx @@ -65,11 +65,11 @@ function CopyAsMarkdownButton() { diff --git a/src/content/learn/choosing-the-state-structure.md b/src/content/learn/choosing-the-state-structure.md index 05763485e..781bea400 100644 --- a/src/content/learn/choosing-the-state-structure.md +++ b/src/content/learn/choosing-the-state-structure.md @@ -160,7 +160,7 @@ function sendMessage(text) { 이 코드는 작동하긴 하지만, "불가능한" state를 허용합니다. 예를 들어 `setIsSent`와 `setIsSending`을 함께 호출하는 것을 잊어버린 경우, `isSending`과 `isSent`가 동시에 `true`인 상황에 처할 수 있습니다. 컴포넌트가 복잡할수록 무슨 일이 일어났는지 이해하기가 어렵습니다. -**`isSending`과 `isSent`는 동시에 `true`가 되어서는 안되기 때문에, 이 두 변수를** `'typing'`(초깃값), `'sending'`, `'sent'` **세 가지 유효한 상태 중 하나를 가질 수 있는 `status` state 변수로 대체하는 것이 좋습니다.** +**`isSending`과 `isSent`는 동시에 `true`가 되어서는 안 되기 때문에, 이 두 변수를** `'typing'`(초깃값), `'sending'`, `'sent'` **세 가지 유효한 상태 중 하나를 가질 수 있는 `status` state 변수로 대체하는 것이 좋습니다.** diff --git a/src/content/learn/creating-a-react-app.md b/src/content/learn/creating-a-react-app.md index e80cb3a2c..d4090ee7e 100644 --- a/src/content/learn/creating-a-react-app.md +++ b/src/content/learn/creating-a-react-app.md @@ -32,7 +32,7 @@ React로 새로운 앱이나 웹사이트를 구축하려면 프레임워크부 npx create-next-app@latest -Next.js는 [Vercel](https://vercel.com/)에서 유지 관리합니다. [Next.js 앱을 빌드](https://nextjs.org/docs/app/building-your-application/deploying)해서 Node.js, 도커 컨테이너, 서버리스 호스팅, 혹은 자체 서버에 배포할 수 있습니다. Next.js는 또한 서버가 필요없는 [정적 내보내기](https://nextjs.org/docs/app/building-your-application/deploying/static-exports)도 지원합니다. +Next.js는 [Vercel](https://vercel.com/)에서 유지 관리합니다. [Next.js 앱을 빌드](https://nextjs.org/docs/app/building-your-application/deploying)해서 Node.js, 도커 컨테이너, 서버리스 호스팅, 혹은 자체 서버에 배포할 수 있습니다. Next.js는 또한 서버가 필요 없는 [정적 내보내기](https://nextjs.org/docs/app/building-your-application/deploying/static-exports)도 지원합니다. ### React Router (v7) {/*react-router-v7*/} @@ -48,7 +48,7 @@ React Router는 [Shopify](https://www.shopify.com)에서 유지 관리합니다. ### Expo (네이티브 앱용) {/*expo*/} -**[Expo](https://expo.dev/)는 네이티브 UI를 사용하여 안드로이드, iOS, 웹을 위한 범용앱을 만들 수 있는 React 프레임워크입니다.** 네이티브 부분을 쉽게 사용할 수 있게 해주는 [React Native SDK](https://reactnative.dev/)를 제공합니다. 새로운 Expo 프로젝트를 생성하려면 다음 명령을 사용하세요. +**[Expo](https://expo.dev/)는 네이티브 UI를 사용하여 안드로이드, iOS, 웹을 위한 범용 앱을 만들 수 있는 React 프레임워크입니다.** 네이티브 부분을 쉽게 사용할 수 있게 해주는 [React Native SDK](https://reactnative.dev/)를 제공합니다. 새로운 Expo 프로젝트를 생성하려면 다음 명령을 사용하세요. npx create-expo-app@latest @@ -56,7 +56,7 @@ npx create-expo-app@latest Expo를 처음 사용하는 경우, [Expo 자습서](https://docs.expo.dev/tutorial/introduction/)를 참조하세요. -Expo는 [Expo (the company)](https://expo.dev/about)에서 유지 관리합니다. Expo로 앱을 빌드하는 것은 무료이고 구글이나 애플 스토어에 제한없이 제출할 수 있습니다. Expo는 추가적으로 옵트인 유료 클라우드 서비스를 제공합니다. +Expo는 [Expo (the company)](https://expo.dev/about)에서 유지 관리합니다. Expo로 앱을 빌드하는 것은 무료이고 구글이나 애플 스토어에 제한 없이 제출할 수 있습니다. Expo는 추가적으로 옵트인 유료 클라우드 서비스를 제공합니다. ## 다른 프레임워크 {/*other-frameworks*/} @@ -64,7 +64,7 @@ Expo는 [Expo (the company)](https://expo.dev/about)에서 유지 관리합니 풀스택 React 비전을 향해 나아가고 있는 또 다른 떠오르는 프레임워크가 있습니다. - [TanStack Start (Beta)](https://tanstack.com/): TanStack Start는 TanStack Router를 기반으로 하는 풀스택 React 프레임워크입니다. Nitro나 Vite와 같이 전체 문서 SSR, 스트리밍, 서버 함수, 번들링과 많은 유용한 도구를 제공합니다. -- [RedwoodJS](https://redwoodjs.com/): Redwood는 쉽게 풀스택 웹 애플리케이션을 만들 수 있도록 사전탑재된 패키지와 구성을 가진 풀스택 React 프레임워크입니다. +- [RedwoodJS](https://redwoodjs.com/): Redwood는 쉽게 풀스택 웹 애플리케이션을 만들 수 있도록 사전 탑재된 패키지와 구성을 가진 풀스택 React 프레임워크입니다. diff --git a/src/content/learn/describing-the-ui.md b/src/content/learn/describing-the-ui.md index 94098dbf4..82820712b 100644 --- a/src/content/learn/describing-the-ui.md +++ b/src/content/learn/describing-the-ui.md @@ -538,7 +538,7 @@ React 렌더 트리 예시 트리의 상단에 위치한 컴포넌트와 루트 컴포넌트 근처의 컴포넌트를 최상위 컴포넌트라고 합니다. 자식 컴포넌트가 없는 컴포넌트를 리프 컴포넌트라고 합니다. 이 컴포넌트 분류는 앱의 데이터 흐름과 성능을 이해하는 데 유용합니다. -자바스크립트 모듈 간의 관계를 모델링하는 것은 앱을 이해하는데 유용한 또 다른 방법입니다. 이를 모듈 의존성 트리라고 정의합니다. +자바스크립트 모듈 간의 관계를 모델링하는 것은 앱을 이해하는 데 유용한 또 다른 방법입니다. 이를 모듈 의존성 트리라고 정의합니다. diff --git a/src/content/learn/escape-hatches.md b/src/content/learn/escape-hatches.md index 89eff6a73..3dfbf91d8 100644 --- a/src/content/learn/escape-hatches.md +++ b/src/content/learn/escape-hatches.md @@ -746,7 +746,7 @@ Effect 재실행을 줄이는 방법을 배우려면 [Effect의 의존 ## 커스텀 Hook으로 로직 재사용하기 {/*reusing-logic-with-custom-hooks*/} -React는 `useState`, `useContext`, 그리고 `useEffect`같은 Hook들이 내장되어 있습니다. 때로는 데이터를 가져오거나 사용자가 온라인 상태인지 여부를 추적하거나 대화방에 연결하는 등 조금 더 구체적인 목적을 가진 Hook이 존재하길 바랄 수도 있습니다. 이를 위해 애플리케이션의 필요에 따라 자신만의 Hook을 만들 수 있습니다. +React는 `useState`, `useContext`, 그리고 `useEffect` 같은 Hook들이 내장되어 있습니다. 때로는 데이터를 가져오거나 사용자가 온라인 상태인지 여부를 추적하거나 대화방에 연결하는 등 조금 더 구체적인 목적을 가진 Hook이 존재하길 바랄 수도 있습니다. 이를 위해 애플리케이션의 필요에 따라 자신만의 Hook을 만들 수 있습니다. 이번 예시에서는 `usePointerPosition` 커스텀 Hook은 커서 위치를 추적하는 반면 `useDelayedValue` 커스텀 Hook은 전달한 값보다 특정 밀리초만큼 "지연"된 값을 반환합니다. 샌드박스 미리보기 영역 위로 커서를 이동하면 커서를 따라 움직이는 점의 흔적을 확인할 수 있습니다. diff --git a/src/content/learn/extracting-state-logic-into-a-reducer.md b/src/content/learn/extracting-state-logic-into-a-reducer.md index 1bdb26a4e..65e80b71f 100644 --- a/src/content/learn/extracting-state-logic-into-a-reducer.md +++ b/src/content/learn/extracting-state-logic-into-a-reducer.md @@ -292,7 +292,7 @@ function yourReducer(state, action) { React는 Reducer에서 반환한 값을 State에 설정합니다. -이 예시에서 이벤트 핸들러에 구현 되어있는 State 설정과 관련 로직을 Reducer 함수로 옮기기 위해서 다음과 같이 해보겠습니다. +이 예시에서 이벤트 핸들러에 구현되어 있는 State 설정과 관련 로직을 Reducer 함수로 옮기기 위해서 다음과 같이 해보겠습니다. 1. 첫 번째 인자에 현재 State (`tasks`) 선언하기. 2. 두 번째 인자에 `action` 객체 선언하기. @@ -884,13 +884,13 @@ Reducer가 좋은 점만 있는 것은 아닙니다! 아래에서 `useState`와 Reducer를 작성할 때, 다음과 같은 두 가지 팁을 명심하세요. -- **Reducer는 반드시 순수해야 합니다.** [State 업데이트 함수](/learn/queueing-a-series-of-state-updates)와 비슷하게, Reducer는 렌더링 중에 실행됩니다! (Action은 다음 렌더링까지 대기합니다.) 이것은 Reducer는 [반드시 순수](/learn/keeping-components-pure)해야한다는 걸 의미합니다. 즉, 입력 값이 같다면 결과 값도 항상 같아야 합니다. 요청을 보내거나 timeout을 스케쥴링하거나 사이드 이펙트(컴포넌트 외부에 영향을 미치는 작업)를 수행해서는 안 됩니다. Reducer는 [객체](/learn/updating-objects-in-state)와 [배열](/learn/updating-arrays-in-state)을 변경하지 않고 업데이트해야 합니다. +- **Reducer는 반드시 순수해야 합니다.** [State 업데이트 함수](/learn/queueing-a-series-of-state-updates)와 비슷하게, Reducer는 렌더링 중에 실행됩니다! (Action은 다음 렌더링까지 대기합니다.) 이것은 Reducer는 [반드시 순수](/learn/keeping-components-pure)해야 한다는 걸 의미합니다. 즉, 입력 값이 같다면 결과 값도 항상 같아야 합니다. 요청을 보내거나 timeout을 스케줄링하거나 사이드 이펙트(컴포넌트 외부에 영향을 미치는 작업)를 수행해서는 안 됩니다. Reducer는 [객체](/learn/updating-objects-in-state)와 [배열](/learn/updating-arrays-in-state)을 변경하지 않고 업데이트해야 합니다. - **각 Action은 데이터 안에서 여러 변경들이 있더라도 하나의 사용자 상호작용을 설명해야 합니다.** 예를 들어, 사용자가 Reducer가 관리하는 5개의 필드가 있는 양식에서 '재설정'을 누른 경우, 5개의 개별 `set_field` Action보다는 하나의 `reset_form` Action을 전송하는 것이 더 합리적입니다. 모든 Action을 Reducer에 기록하면 어떤 상호작용이나 응답이 어떤 순서로 일어났는지 재구성할 수 있을 만큼 로그가 명확해야 합니다. 이는 디버깅에 도움이 됩니다! ## Immer로 간결한 Reducer 작성하기 {/*writing-concise-reducers-with-immer*/} -일반적인 State에서 [객체](/learn/updating-objects-in-state#write-concise-update-logic-with-immer)와 [배열](/learn/updating-arrays-in-state#write-concise-update-logic-with-immer)을 업데이트 하는 것처럼, Immer 라이브러리를 사용하면 Reducer를 더 간결하게 작성할 수 있습니다. 이 라이브러리에서 제공하는 [`useImmerReducer`](https://github.com/immerjs/use-immer#useimmerreducer)를 사용하여 `push` 또는 `arr[i] =` 로 값을 할당하므로써 State를 변경해보겠습니다. +일반적인 State에서 [객체](/learn/updating-objects-in-state#write-concise-update-logic-with-immer)와 [배열](/learn/updating-arrays-in-state#write-concise-update-logic-with-immer)을 업데이트하는 것처럼, Immer 라이브러리를 사용하면 Reducer를 더 간결하게 작성할 수 있습니다. 이 라이브러리에서 제공하는 [`useImmerReducer`](https://github.com/immerjs/use-immer#useimmerreducer)를 사용하여 `push` 또는 `arr[i] =`로 값을 할당함으로써 State를 변경해보겠습니다. @@ -1115,7 +1115,7 @@ Reducer는 순수해야 하기 때문에, 이 안에서는 State를 변경할 현재 `ContactList.js`와 `Chat.js`의 이벤트 핸들러 안에는 `// TODO` 주석이 있습니다. 이 때문에 input에 값을 입력해도 동작하지 않고 탭 버튼을 클릭해도 선택된 수신인을 변경할 수 없습니다. -`// TODO` 주석이 있는 부분을 지우고 상황에 맞는 Action을 `dispatch`하는 코드를 작성해보세요. Action에 대한 힌트를 얻고 싶다면 `messengerReducer.js`에 구현된 reducer를 확인해보세요. 이 reducer는 이미 작성되어있기 때문에 변경할 필요가 없습니다. 여러분은 `ContactList.js`와 `Chat.js`에 Action을 담아 전달하는 코드를 작성하기만 하면 됩니다. +`// TODO` 주석이 있는 부분을 지우고 상황에 맞는 Action을 `dispatch`하는 코드를 작성해보세요. Action에 대한 힌트를 얻고 싶다면 `messengerReducer.js`에 구현된 reducer를 확인해보세요. 이 reducer는 이미 작성되어 있기 때문에 변경할 필요가 없습니다. 여러분은 `ContactList.js`와 `Chat.js`에 Action을 담아 전달하는 코드를 작성하기만 하면 됩니다. @@ -1948,7 +1948,7 @@ textarea { #### 탭 전환 시, input 입력 값 복원하기 {/*restore-input-values-when-switching-between-tabs*/} -이 예시에서 선택된 수신자를 바꾸기 위해 탭 버튼을 누르면 message를 입력받는 input 필드의 텍스트 값이 항상 지워지도록 되어있습니다. +이 예시에서 선택된 수신자를 바꾸기 위해 탭 버튼을 누르면 message를 입력받는 input 필드의 텍스트 값이 항상 지워지도록 되어 있습니다. ```js case 'changed_selection': { diff --git a/src/content/learn/keeping-components-pure.md b/src/content/learn/keeping-components-pure.md index 2a683a025..2e97617f6 100644 --- a/src/content/learn/keeping-components-pure.md +++ b/src/content/learn/keeping-components-pure.md @@ -143,7 +143,7 @@ export default function TeaSet() { 이제 컴포넌트가 `guest` prop에만 의존해 JSX를 반환하므로 순수해졌습니다. -일반적으로 컴포넌트가 특정 순서대로 렌더링될 것이라고 기대하면 안됩니다. y = 2xy = 5x보다 먼저 계산하든 나중에 계산하든 상관없습니다. 두 수식은 서로 독립적으로 결과를 도출하기 때문입니다. 마찬가지로 각 컴포넌트는 "자기 자신만 생각"해야 합니다. 렌더링 도중에 다른 컴포넌트와 영향을 주고받거나, 의존해서는 안됩니다. 렌더링은 마치 학교 시험과 같습니다. 각 컴포넌트는 자신의 JSX를 직접 계산해야 합니다! +일반적으로 컴포넌트가 특정 순서대로 렌더링될 것이라고 기대하면 안 됩니다. y = 2xy = 5x보다 먼저 계산하든 나중에 계산하든 상관없습니다. 두 수식은 서로 독립적으로 결과를 도출하기 때문입니다. 마찬가지로 각 컴포넌트는 "자기 자신만 생각"해야 합니다. 렌더링 도중에 다른 컴포넌트와 영향을 주고받거나, 의존해서는 안 됩니다. 렌더링은 마치 학교 시험과 같습니다. 각 컴포넌트는 자신의 JSX를 직접 계산해야 합니다! @@ -151,9 +151,9 @@ export default function TeaSet() { 아직 전부 사용해본 적은 없을 수 있지만, React에서는 렌더링하는 동안 읽을 수 있는 세 가지 종류의 입력 요소가 있습니다. [Props](/learn/passing-props-to-a-component), [State](/learn/state-a-components-memory), 그리고 [Context](/learn/passing-data-deeply-with-context). 이러한 입력 요소는 항상 읽기전용으로 취급해야 합니다. -사용자의 입력에 따라 무언가를 _변경_ 하려는 경우, 변수 값을 직접 수정하는 대신 [State](/learn/state-a-components-memory)를 설정(set)해야 합니다. 컴포넌트가 렌더링되는 동안엔 기존 변수나 객체를 변경하면 안됩니다. +사용자의 입력에 따라 무언가를 _변경_ 하려는 경우, 변수 값을 직접 수정하는 대신 [State](/learn/state-a-components-memory)를 설정(set)해야 합니다. 컴포넌트가 렌더링되는 동안엔 기존 변수나 객체를 변경하면 안 됩니다. -React는 개발 중에 각 컴포넌트의 함수를 두 번 호출하는 "엄격 모드"를 제공합니다. **컴포넌트 함수를 두 번 호출함으로써, 엄격 모드는 이러한 규칙을 위반하는 컴포넌트를 찾는데 도움을 줍니다.** +React는 개발 중에 각 컴포넌트의 함수를 두 번 호출하는 "엄격 모드"를 제공합니다. **컴포넌트 함수를 두 번 호출함으로써, 엄격 모드는 이러한 규칙을 위반하는 컴포넌트를 찾는 데 도움을 줍니다.** 원래 예시에서 "Guest #1", "Guest #2", "Guest #3" 대신 "Guest #2", "Guest #4", "Guest #6"이 어떻게 표시되었는지 확인해보세요. 기존 함수가 순수하지 않았기에 엄격 모드로 인해 두 번 호출되는 과정에서 로직이 깨져버렸습니다. 그러나 수정된 순수 버전의 함수는 두 번씩 호출되더라도 동작합니다. **순수 함수는 오직 계산만 수행하므로 두 번 호출되더라도 아무것도 변하지 않습니다.** `double(2)`를 두 번 호출해도 반환값은 변하지 않는 것과 y = 2x을 두 번 푼다고 해도 y값이 바뀌지는 않는 것처럼, 항상 같은 입력이면 같은 출력을 내보냅니다. @@ -219,7 +219,7 @@ React에서, **사이드 이펙트는 보통 [이벤트 핸들러](/learn/respon * **자신의 일에만 집중합니다.** 렌더링 전에 존재했던 객체나 변수를 변경하지 않아야 합니다. * **같은 입력, 같은 출력.** 입력이 같을 경우, 컴포넌트는 항상 같은 JSX를 반환해야 합니다. * 렌더링은 언제든지 발생할 수 있으므로 컴포넌트는 서로의 렌더링 순서에 의존하지 않아야 합니다. -* 컴포넌트가 렌더링을 위해 사용하는 입력을 변경해서는 안됩니다. 여기에는 Props, State, Context가 포함됩니다. 화면을 업데이트하려면 기존 객체를 변경하는 대신 [State를 "set"](/learn/state-a-components-memory)하세요. +* 컴포넌트가 렌더링을 위해 사용하는 입력을 변경해서는 안 됩니다. 여기에는 Props, State, Context가 포함됩니다. 화면을 업데이트하려면 기존 객체를 변경하는 대신 [State를 "set"](/learn/state-a-components-memory)하세요. * 반환하는 JSX에서 컴포넌트의 로직을 표현하기 위해 노력하세요. "무언가를 변경"해야 할 경우 일반적으로 이벤트 핸들러에서 변경하고 싶을 것입니다. 최후의 수단으로 `useEffect`를 사용할 수 있습니다. * 순수 함수를 작성하는 것은 약간의 연습이 필요하지만, React 패러다임의 힘을 발휘하게 합니다. diff --git a/src/content/learn/manipulating-the-dom-with-refs.md b/src/content/learn/manipulating-the-dom-with-refs.md index c73edf51b..6bb23570a 100644 --- a/src/content/learn/manipulating-the-dom-with-refs.md +++ b/src/content/learn/manipulating-the-dom-with-refs.md @@ -346,7 +346,7 @@ li { Strict Mode가 활성화되어 있다면 개발 모드에서 ref 콜백이 두 번 실행됩니다. -ref 콜백에서 [이 방식이 버그를 찾는데 어떻게 도움이 되는지](/reference/react/StrictMode#fixing-bugs-found-by-re-running-ref-callbacks-in-development) 자세히 알아보세요. +ref 콜백에서 [이 방식이 버그를 찾는 데 어떻게 도움이 되는지](/reference/react/StrictMode#fixing-bugs-found-by-re-running-ref-callbacks-in-development) 자세히 알아보세요. @@ -460,7 +460,7 @@ export default function Form() { React의 모든 갱신은 [두 단계](/learn/render-and-commit#step-3-react-commits-changes-to-the-dom)로 나눌 수 있습니다. * **렌더링** 단계에서 React는 화면에 무엇을 그려야 하는지 알아내도록 컴포넌트를 호출합니다. -* **커밋** 단계에서 React는 변경사항을 DOM에 적용합니다. +* **커밋** 단계에서 React는 변경 사항을 DOM에 적용합니다. 일반적으로 렌더링하는 중 ref에 접근하는 것을 [원하지 않습니다](/learn/referencing-values-with-refs#best-practices-for-refs). DOM 노드를 보유하는 ref도 마찬가지입니다. 첫 렌더링에서 DOM 노드는 아직 생성되지 않아서 `ref.current`는 `null`인 상태입니다. 그리고 갱신에 의한 렌더링에서 DOM 노드는 아직 업데이트되지 않은 상태입니다. 두 상황 모두 ref를 읽기에 너무 이른 상황입니다. diff --git a/src/content/learn/passing-props-to-a-component.md b/src/content/learn/passing-props-to-a-component.md index b07ed8027..32ab983ab 100644 --- a/src/content/learn/passing-props-to-a-component.md +++ b/src/content/learn/passing-props-to-a-component.md @@ -740,7 +740,7 @@ JSX 어트리뷰트의 컬렉션이 아닌 JavaScript 객체의 속성으로 구 이번 예시에서는 `Avatar` 가 ``의 넓이와 높이를 결정하는 숫자 `size` prop를 받습니다. `size` prop은 `40`으로 설정되어 있습니다. 그러나 새 탭에서 이미지를 열면, 이미지가 `160픽셀`로 커져 있을 것입니다. 실제 이미지 크기는 요청하는 썸네일 크기에 따라 결정됩니다. -`size` prop에 따라 가장 가까운 이미지 크기를 요청하도록 `Avatar` 컴포넌트를 변경하세요. 특히 `size` 가 `90`보다 작으면 `'s'`("small")을, 아니면 `'b'`("big")을 `getImageUrl` 함수에 전달하세요. `size` prop를 다른 값들을 전달해 보고, 아바타를 렌더링 하는지, 새 탭에서 이미지를 열어 변경사항이 제대로 반영되는지 확인해 보세요. +`size` prop에 따라 가장 가까운 이미지 크기를 요청하도록 `Avatar` 컴포넌트를 변경하세요. 특히 `size`가 `90`보다 작으면 `'s'`("small")을, 아니면 `'b'`("big")을 `getImageUrl` 함수에 전달하세요. `size` prop를 다른 값들을 전달해 보고, 아바타를 렌더링하는지, 새 탭에서 이미지를 열어 변경 사항이 제대로 반영되는지 확인해 보세요. ```js src/App.js diff --git a/src/content/learn/preserving-and-resetting-state.md b/src/content/learn/preserving-and-resetting-state.md index a853bb085..5c759fd69 100644 --- a/src/content/learn/preserving-and-resetting-state.md +++ b/src/content/learn/preserving-and-resetting-state.md @@ -98,7 +98,7 @@ React tree -**이 둘은 각각 트리에서 자기 고유의 위치에 렌더링되어 있으므로 분리되어있는 카운터입니다.** 일반적으로 React를 사용할 때 위치에 대해 생각할 필요는 없지만 React가 어떻게 작동하는지 이해할 때 유용합니다. +**이 둘은 각각 트리에서 자기 고유의 위치에 렌더링되어 있으므로 분리되어 있는 카운터입니다.** 일반적으로 React를 사용할 때 위치에 대해 생각할 필요는 없지만 React가 어떻게 작동하는지 이해할 때 유용합니다. React에서 화면의 각 컴포넌트는 완전히 분리된 State를 가집니다. 예를 들어, 두 `Counter` 컴포넌트를 나란히 렌더링하면 그들은 각각 자신만의 독립된 `score`과 `hover` State를 가지게 됩니다. @@ -697,7 +697,7 @@ label { -이것이 컴포넌트 함수를 중첩해서 정의하면 안되는 이유입니다. +이것이 컴포넌트 함수를 중첩해서 정의하면 안 되는 이유입니다. 여기, `MyComponent` 안에서 `MyTextField` 컴포넌트 함수를 정의하고 있습니다. diff --git a/src/content/learn/react-compiler/incremental-adoption.md b/src/content/learn/react-compiler/incremental-adoption.md index 091f8fc2c..1c58947e5 100644 --- a/src/content/learn/react-compiler/incremental-adoption.md +++ b/src/content/learn/react-compiler/incremental-adoption.md @@ -25,7 +25,7 @@ React 컴파일러는 전체 코드베이스를 자동으로 최적화하도록 점진적 도입은 컴파일러가 발견할 수 있는 React 규칙 위반을 해결하기도 더 쉽게 만듭니다. 전체 코드베이스의 위반을 한 번에 수정하는 대신 컴파일러 적용 범위를 확장하면서 체계적으로 해결할 수 있습니다. 이를 통해 마이그레이션을 관리하기 쉽게 유지하고 버그 도입 위험을 줄일 수 있습니다. -컴파일되는 코드 부분을 제어함으로써 A/B 테스트를 실행하여 컴파일러 최적화의 실제 영향을 측정할 수도 있습니다. 이 데이터는 전체 도입에 대한 정보에 기반한 결정을 내릴 수 있어 팀에게 가치를 입증하는데 도움이 됩니다. +컴파일되는 코드 부분을 제어함으로써 A/B 테스트를 실행하여 컴파일러 최적화의 실제 영향을 측정할 수도 있습니다. 이 데이터는 전체 도입에 대한 정보에 기반한 결정을 내릴 수 있어 팀에게 가치를 입증하는 데 도움이 됩니다. ## 점진적 도입 방법 {/*approaches-to-incremental-adoption*/} diff --git a/src/content/learn/reacting-to-input-with-state.md b/src/content/learn/reacting-to-input-with-state.md index 902c3c09b..83af265a9 100644 --- a/src/content/learn/reacting-to-input-with-state.md +++ b/src/content/learn/reacting-to-input-with-state.md @@ -393,7 +393,7 @@ const [status, setStatus] = useState('typing'); // 'typing', 'submitting', or 's #### Reducer를 사용하여 "불가능한" State 제거 {/*eliminating-impossible-states-with-a-reducer*/} -여기 폼의 State를 나타내는데 충분한 세 가지 변수가 있습니다. 하지만 세 변수는 여전히 말이 안 되는 일부 중간 State를 가지고 있습니다. 예를 들면 `error`가 `null`이 아닌데 `status`가 `success`인 것은 말이 되지 않습니다. State를 조금 더 정확하게 모델링하기 위해서는 [Reducer로 분리](/learn/extracting-state-logic-into-a-reducer)하는 방법도 있습니다. Reducer를 사용하면 여러 State 변수를 하나의 객체로 통합하고 관련된 모든 로직도 합칠 수 있습니다! +여기 폼의 State를 나타내는 데 충분한 세 가지 변수가 있습니다. 하지만 세 변수는 여전히 말이 안 되는 일부 중간 State를 가지고 있습니다. 예를 들면 `error`가 `null`이 아닌데 `status`가 `success`인 것은 말이 되지 않습니다. State를 조금 더 정확하게 모델링하기 위해서는 [Reducer로 분리](/learn/extracting-state-logic-into-a-reducer)하는 방법도 있습니다. Reducer를 사용하면 여러 State 변수를 하나의 객체로 통합하고 관련된 모든 로직도 합칠 수 있습니다! diff --git a/src/content/learn/referencing-values-with-refs.md b/src/content/learn/referencing-values-with-refs.md index 4801840a9..a92dbdd78 100644 --- a/src/content/learn/referencing-values-with-refs.md +++ b/src/content/learn/referencing-values-with-refs.md @@ -70,7 +70,7 @@ export default function Counter() { Ref는 숫자를 가리키지만, [State](/learn/state-a-components-memory)처럼 문자열, 객체, 심지어 함수 등 모든 것을 가리킬 수 있습니다. State와 달리 Ref는 읽고 수정할 수 있는 `current` 프로퍼티를 가진 일반 자바스크립트 객체입니다. -**컴포넌트는 모든 증가에 대하여 다시 렌더링 되지 않습니다.** State와 마찬가지로 Ref도 React에 리렌더에 의해 유지됩니다. 그러나, State를 설정하면 컴포넌트가 다시 렌더링 됩니다. Ref를 변경하면 다시 렌더링 되지 않습니다! +**컴포넌트는 모든 증가에 대하여 다시 렌더링 되지 않습니다.** State와 마찬가지로 Ref도 React의 리렌더링에 의해 유지됩니다. 그러나, State를 설정하면 컴포넌트가 다시 렌더링 됩니다. Ref를 변경하면 다시 렌더링 되지 않습니다! ## 예시: 스톱워치 작성하기 {/*example-building-a-stopwatch*/} @@ -176,7 +176,7 @@ Ref가 State보다 덜 "엄격한" 것으로 생각될 수 있습니다. 예를 | Ref | State | |--------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------| -| `useRef(initialValue)` 는 `{ current: initialValue }`를 반환합니다. | `useState(initialValue)`는 State 변수의 현재 값과 Setter 함수 `[value, setValue]`를 반환합니다. | +| `useRef(initialValue)`는 `{ current: initialValue }`를 반환합니다. | `useState(initialValue)`는 State 변수의 현재 값과 Setter 함수 `[value, setValue]`를 반환합니다. | | `current` 값을 바꿔도 리렌더링 하지 않습니다. | State를 바꾸면 리렌더링 합니다. | | Mutable: 렌더링 프로세스 외부에서 `current` 값을 수정 및 업데이트할 수 있습니다. | Immutable: State를 수정하기 위해서는 State 설정 함수를 반드시 사용하여 리렌더링 대기열에 넣어야 합니다. | | 렌더링 중에는 `current` 값을 읽거나 쓰면 안 됩니다. | 언제든지 State를 읽을 수 있습니다. 그러나 각 렌더링마다 변경되지 않는 자체적인 State의 [Snapshot](/learn/state-as-a-snapshot)이 있습니다. | diff --git a/src/content/learn/removing-effect-dependencies.md b/src/content/learn/removing-effect-dependencies.md index 148c1fadd..2a8ce4a0c 100644 --- a/src/content/learn/removing-effect-dependencies.md +++ b/src/content/learn/removing-effect-dependencies.md @@ -1476,7 +1476,7 @@ html, body { min-height: 300px; } 이 예시에서는 'Toggle theme'을 누를 때마다 채팅이 다시 연결됩니다. 왜 이런 일이 발생하나요? 서버 URL을 편집하거나 다른 채팅방을 선택할 때만 채팅이 다시 연결되도록 실수를 수정하세요. -`chat.js`를 외부 서드파티 라이브러리로 취급하여 API를 확인하기 위해 참조할 수는 있지만 편집해서는 안됩니다. +`chat.js`를 외부 서드파티 라이브러리로 취급하여 API를 확인하기 위해 참조할 수는 있지만 편집해서는 안 됩니다. diff --git a/src/content/learn/render-and-commit.md b/src/content/learn/render-and-commit.md index dfd654cb4..51f622bad 100644 --- a/src/content/learn/render-and-commit.md +++ b/src/content/learn/render-and-commit.md @@ -4,14 +4,14 @@ title: 렌더링 그리고 커밋 -컴포넌트를 화면에 표시하기 이전에 React에서 렌더링을 해야 합니다. 해당 과정의 단계를 이해하면 코드가 어떻게 실행되는지 이해할 수 있고 React 렌더링 동작에 관해 설명하는데 도움이 됩니다. +컴포넌트를 화면에 표시하기 이전에 React에서 렌더링을 해야 합니다. 해당 과정의 단계를 이해하면 코드가 어떻게 실행되는지 이해할 수 있고 React 렌더링 동작에 관해 설명하는 데 도움이 됩니다. * React에서 렌더링의 의미 -* React가 컴포넌트를 언제, 왜 렌더링 하는지 +* React가 컴포넌트를 언제, 왜 렌더링하는지 * 화면에 컴포넌트를 표시하는 단계 * 렌더링이 항상 DOM 업데이트를 하지 않는 이유 @@ -131,10 +131,10 @@ img { margin: 0 10px 10px 0; } 렌더링은 항상 [순수한 계산](/learn/keeping-components-pure): -* **동일한 입력에는 동일한 출력을 해야합니다.** 동일한 입력이 주어지면 컴포넌트는 항상 동일한 JSX를 반환해야 합니다. (누군가 토마토 샐러드를 주문하면 그들은 양파가 있는 샐러드를 받으면 안 됩니다!) -* **이전의 state를 변경해서는 안됩니다.** 렌더링 전에 존재했던 객체나 변수를 변경해서는 안 됩니다. (누군가의 주문이 다른 사람의 주문을 변경해서는 안 됩니다.) +* **동일한 입력에는 동일한 출력을 해야 합니다.** 동일한 입력이 주어지면 컴포넌트는 항상 동일한 JSX를 반환해야 합니다. (누군가 토마토 샐러드를 주문하면 그들은 양파가 있는 샐러드를 받으면 안 됩니다!) +* **이전의 state를 변경해서는 안 됩니다.** 렌더링 전에 존재했던 객체나 변수를 변경해서는 안 됩니다. (누군가의 주문이 다른 사람의 주문을 변경해서는 안 됩니다.) -그렇지 않으면 코드베이스가 복잡해짐에 따라 혼란스러운 버그와 예측할 수 없는 동작이 발생할 수 있습니다. "Strict Mode"에서 개발할 때 React는 각 컴포넌트의 함수를 두 번 호출하여 순수하지 않은 함수로 인한 실수를 표면화하는데 도움을 받을 수 있습니다. +그렇지 않으면 코드베이스가 복잡해짐에 따라 혼란스러운 버그와 예측할 수 없는 동작이 발생할 수 있습니다. "Strict Mode"에서 개발할 때 React는 각 컴포넌트의 함수를 두 번 호출하여 순수하지 않은 함수로 인한 실수를 표면화하는 데 도움을 받을 수 있습니다. @@ -146,7 +146,7 @@ img { margin: 0 10px 10px 0; } -## 3단계: React가 DOM에 변경사항을 커밋 {/*step-3-react-commits-changes-to-the-dom*/} +## 3단계: React가 DOM에 변경 사항을 커밋 {/*step-3-react-commits-changes-to-the-dom*/} 컴포넌트를 렌더링(호출)한 후 React는 DOM을 수정합니다. diff --git a/src/content/learn/rendering-lists.md b/src/content/learn/rendering-lists.md index c80e8833e..506114060 100644 --- a/src/content/learn/rendering-lists.md +++ b/src/content/learn/rendering-lists.md @@ -288,7 +288,7 @@ Warning: Each child in a list should have a unique "key" prop. -Key는 각 컴포넌트가 어떤 배열 항목에 해당하는지 React에 알려주어 나중에 일치시킬 수 있도록 합니다. 이는 배열 항목이 정렬 등으로 인해 이동하거나 삽입되거나 삭제될 수 있는 경우 중요해집니다. `key`를 잘 선택하면 React가 정확히 무슨 일이 일어났는지 추론하고 DOM 트리에 올바르게 업데이트 하는데 도움이 됩니다. +Key는 각 컴포넌트가 어떤 배열 항목에 해당하는지 React에 알려주어 나중에 일치시킬 수 있도록 합니다. 이는 배열 항목이 정렬 등으로 인해 이동하거나 삽입되거나 삭제될 수 있는 경우 중요해집니다. `key`를 잘 선택하면 React가 정확히 무슨 일이 일어났는지 추론하고 DOM 트리에 올바르게 업데이트하는 데 도움이 됩니다. 즉석에서 key를 생성하는 대신 데이터 안에 key를 포함해야 합니다. diff --git a/src/content/learn/responding-to-events.md b/src/content/learn/responding-to-events.md index da9f93c7f..684d02a1e 100644 --- a/src/content/learn/responding-to-events.md +++ b/src/content/learn/responding-to-events.md @@ -462,7 +462,7 @@ function Button({ onClick, children }) { 이 핸들러 내에서 부모의 `onClick` 이벤트 핸들러를 호출하는 부분 앞에 코드를 더 추가할 수도 있습니다. 이러한 패턴은 전파의 대안을 제공합니다. 부모 컴포넌트가 일부 추가적인 동작에 특화되도록 하면서 자식 컴포넌트가 이벤트를 처리할 수 있도록 합니다. 전파와는 다르게 자동으로 동작하지 않습니다. 이 패턴의 장점은 일부 이벤트의 결과로 실행되는 전체 코드 체인을 명확히 좇을 수 있게 해줍니다. -전파를 활용하고 있지만 어떤 핸들러가 왜 실행되는 지 추적하는데 어려움을 겪고 있다면 이러한 접근법을 시도해 보시기 바랍니다. +전파를 활용하고 있지만 어떤 핸들러가 왜 실행되는지 추적하는 데 어려움을 겪고 있다면 이러한 접근법을 시도해 보시기 바랍니다. ### 기본 동작 방지하기 {/*preventing-default-behavior*/} @@ -520,7 +520,7 @@ button { margin-left: 5px; } 가능합니다! 이벤트 핸들러는 사이드 이펙트를 위한 최고의 위치입니다. -함수를 렌더링하는 것과 다르게 이벤트 핸들러는 [순수할](/learn/keeping-components-pure) 필요가 없기에 무언가를 *변경*하는데 최적의 위치입니다. 예를 들어 타이핑에 반응해 입력 값을 수정하거나, 버튼 입력에 따라 리스트를 변경할 때 적절합니다. 그러나 일부 정보를 수정하기 위해서는 먼저 그 정보를 저장하기 위한 수단이 필요합니다. React에서는 [컴포넌트의 기억 역할을 하는 state](/learn/state-a-components-memory)를 이용할 수 있습니다. 해당 기능의 모든 것에 대해 다음 페이지에서 배울 것입니다. +함수를 렌더링하는 것과 다르게 이벤트 핸들러는 [순수할](/learn/keeping-components-pure) 필요가 없기에 무언가를 *변경*하는 데 최적의 위치입니다. 예를 들어 타이핑에 반응해 입력 값을 수정하거나, 버튼 입력에 따라 리스트를 변경할 때 적절합니다. 그러나 일부 정보를 수정하기 위해서는 먼저 그 정보를 저장하기 위한 수단이 필요합니다. React에서는 [컴포넌트의 기억 역할을 하는 state](/learn/state-a-components-memory)를 이용할 수 있습니다. 해당 기능의 모든 것에 대해 다음 페이지에서 배울 것입니다. diff --git a/src/content/learn/reusing-logic-with-custom-hooks.md b/src/content/learn/reusing-logic-with-custom-hooks.md index 7207f2798..6e38dc005 100644 --- a/src/content/learn/reusing-logic-with-custom-hooks.md +++ b/src/content/learn/reusing-logic-with-custom-hooks.md @@ -1877,7 +1877,7 @@ html, body { min-height: 300px; } - 모든 Hook은 컴포넌트가 재렌더링될 때 마다 재실행됩니다. - 커스텀 Hook의 코드는 컴포넌트 코드처럼 순수해야 합니다. - 커스텀 Hook을 통해 받는 이벤트 핸들러는 Effect로 감싸야 합니다. -- `useMount`같은 커스텀 Hook을 생성하면 안 됩니다. 용도를 명확히 하세요. +- `useMount` 같은 커스텀 Hook을 생성하면 안 됩니다. 용도를 명확히 하세요. - 코드의 경계를 선택하는 방법과 위치는 여러분이 결정할 수 있습니다. diff --git a/src/content/learn/separating-events-from-effects.md b/src/content/learn/separating-events-from-effects.md index 315fd506c..56e74d2d8 100644 --- a/src/content/learn/separating-events-from-effects.md +++ b/src/content/learn/separating-events-from-effects.md @@ -1157,7 +1157,7 @@ button { margin: 10px; } -`onTick`은 Effect 이벤트이므로 내부의 코드는 반응형이 아닙니다. `increment`가 변해도 Effect를 트리거 하지 않습니다. +`onTick`은 Effect 이벤트이므로 내부의 코드는 반응형이 아닙니다. `increment`가 변해도 Effect를 트리거하지 않습니다. diff --git a/src/content/learn/sharing-state-between-components.md b/src/content/learn/sharing-state-between-components.md index 424806622..f3a1b2f3e 100644 --- a/src/content/learn/sharing-state-between-components.md +++ b/src/content/learn/sharing-state-between-components.md @@ -178,7 +178,7 @@ h3, p { margin: 5px 0px; } 상태 끌어올리기는 종종 state로 저장하고 있는 것의 특성을 바꿉니다. -이 케이스에서는, 한 번에 하나의 패널만 활성화되어야 합니다. 이를 위해 공통 부모 컴포넌트인 `Accordion`은 *어떤* 패널이 활성화된 패널인지 추적하고 있어야 합니다. state 변수에 `boolean` 값을 사용하는 대신, 활성화되어있는 `Panel`의 인덱스 숫자를 사용할 수 있습니다. +이 케이스에서는, 한 번에 하나의 패널만 활성화되어야 합니다. 이를 위해 공통 부모 컴포넌트인 `Accordion`은 *어떤* 패널이 활성화된 패널인지 추적하고 있어야 합니다. state 변수에 `boolean` 값을 사용하는 대신, 활성화되어 있는 `Panel`의 인덱스 숫자를 사용할 수 있습니다. ```js const [activeIndex, setActiveIndex] = useState(0); @@ -294,7 +294,7 @@ h3, p { margin: 5px 0px; } 비제어 컴포넌트는 설정할 것이 적어 부모 컴포넌트에서 사용하기 더 쉽습니다. 하지만 여러 컴포넌트를 함께 조정하려고 할 때 비제어 컴포넌트는 덜 유연합니다. 제어 컴포넌트는 최대한으로 유연하지만, 부모 컴포넌트에서 props로 충분히 설정해주어야 합니다. -실제로 "제어"와 "비제어"는 엄격한 기술 용어가 아니며 일반적으로 컴포넌트는 지역 state와 props를 혼합해서 사용합니다. 그러나 이런 구분은 컴포넌트의 설계와 제공하는 기능에 관해 설명하는데 유용한 방법입니다. +실제로 "제어"와 "비제어"는 엄격한 기술 용어가 아니며 일반적으로 컴포넌트는 지역 state와 props를 혼합해서 사용합니다. 그러나 이런 구분은 컴포넌트의 설계와 제공하는 기능에 관해 설명하는 데 유용한 방법입니다. 컴포넌트를 작성할 때 어떤 정보가 (props를 통해) 제어되어야 하고 어떤 정보가 (state를 통해) 제어되지 않아야 하는지 고려하세요. 그렇지만 언제든 마음이 바뀔 수 있고 나중에 리팩토링 할 수 있습니다. diff --git a/src/content/learn/start-a-new-react-project.md b/src/content/learn/start-a-new-react-project.md index 48956ab35..5f066ec9e 100644 --- a/src/content/learn/start-a-new-react-project.md +++ b/src/content/learn/start-a-new-react-project.md @@ -44,7 +44,7 @@ npx create-next-app@latest Next.js를 처음 사용하는 분이라면 [Next.js 배우기 코스](https://nextjs.org/learn)를 읽어보세요. -Next.js는 [Vercel](https://vercel.com/)이 관리합니다. 어떤 Node.js 서버, 서버리스 호스팅 또는 직접 소유한 서버 어느 곳에서라도 [Next.js 애플리케이션을 배포](https://nextjs.org/docs/app/building-your-application/deploying)할 수 있습니다. Next.js는 서버가 필요없는 [정적 내보내기Static Exports](https://nextjs.org/docs/pages/building-your-application/deploying/static-exports) 도 제공합니다. +Next.js는 [Vercel](https://vercel.com/)이 관리합니다. 어떤 Node.js 서버, 서버리스 호스팅 또는 직접 소유한 서버 어느 곳에서라도 [Next.js 애플리케이션을 배포](https://nextjs.org/docs/app/building-your-application/deploying)할 수 있습니다. Next.js는 서버가 필요 없는 [정적 내보내기Static Exports](https://nextjs.org/docs/pages/building-your-application/deploying/static-exports) 도 제공합니다. ### Remix {/*remix*/} @@ -93,7 +93,7 @@ React를 지속적으로 개선할 방법을 찾아가는 과정에서, 우리 **[Next.js의 App Router](https://nextjs.org/docs)는 React 팀의 풀스택 아키텍처 비전을 구현하기 위해 재설계된 Next.js API입니다.** 이를 통해 서버에서 또는 빌드 중에 실행되는 비동기 컴포넌트에서 데이터를 가져올 수 있습니다. -Next.js는 [Vercel](https://vercel.com/)이 관리합니다. 어떤 Node.js 서버, 서버리스 호스팅 또는 직접 소유한 서버 어느 곳에라도 [Next.js 애플리케이션을 배포](https://nextjs.org/docs/app/building-your-application/deploying)할 수 있습니다. Next.js 는 서버가 필요없는 [정적 내보내기Static Exports](https://nextjs.org/docs/pages/building-your-application/deploying/static-exports)도 제공합니다. +Next.js는 [Vercel](https://vercel.com/)이 관리합니다. 어떤 Node.js 서버, 서버리스 호스팅 또는 직접 소유한 서버 어느 곳에라도 [Next.js 애플리케이션을 배포](https://nextjs.org/docs/app/building-your-application/deploying)할 수 있습니다. Next.js는 서버가 필요 없는 [정적 내보내기Static Exports](https://nextjs.org/docs/pages/building-your-application/deploying/static-exports)도 제공합니다. diff --git a/src/content/learn/state-as-a-snapshot.md b/src/content/learn/state-as-a-snapshot.md index e466d904e..d2b568021 100644 --- a/src/content/learn/state-as-a-snapshot.md +++ b/src/content/learn/state-as-a-snapshot.md @@ -88,7 +88,7 @@ React가 컴포넌트를 다시 렌더링할 때. -컴포넌트의 메모리로써 state는 함수가 반환된 후 사라지는 일반 변수와 다릅니다. state는 실제로 함수 외부에 마치 선반에 있는 것처럼 React 자체에 "존재"합니다. React가 컴포넌트를 호출하면 특정 렌더링에 대한 state의 스냅샷을 제공합니다. 컴포넌트는 **해당 렌더링의 state 값을 사용해** 계산된 새로운 props 세트와 이벤트 핸들러가 포함된 UI의 스냅샷을 JSX에 반환합니다! +컴포넌트의 메모리로서 state는 함수가 반환된 후 사라지는 일반 변수와 다릅니다. state는 실제로 함수 외부에 마치 선반에 있는 것처럼 React 자체에 "존재"합니다. React가 컴포넌트를 호출하면 특정 렌더링에 대한 state의 스냅샷을 제공합니다. 컴포넌트는 **해당 렌더링의 state 값을 사용해** 계산된 새로운 props 세트와 이벤트 핸들러가 포함된 UI의 스냅샷을 JSX에 반환합니다! diff --git a/src/content/learn/synchronizing-with-effects.md b/src/content/learn/synchronizing-with-effects.md index 6542ef3b1..7c1c9a96f 100644 --- a/src/content/learn/synchronizing-with-effects.md +++ b/src/content/learn/synchronizing-with-effects.md @@ -133,7 +133,7 @@ video { width: 250px; } -이 코드가 올바르지 않은 이유는 렌더링 중에 DOM 노드를 조작하려고 시도하기 때문입니다. React에서는 [렌더링이 JSX의 순수한 계산](/learn/keeping-components-pure)이어야 하며, DOM 수정과 같은 부수 효과를 포함해서는 안됩니다. +이 코드가 올바르지 않은 이유는 렌더링 중에 DOM 노드를 조작하려고 시도하기 때문입니다. React에서는 [렌더링이 JSX의 순수한 계산](/learn/keeping-components-pure)이어야 하며, DOM 수정과 같은 부수 효과를 포함해서는 안 됩니다. 게다가, 처음으로 `VideoPlayer`가 호출될 때 해당 DOM이 아직 존재하지 않습니다! React는 컴포넌트가 JSX를 반환할 때까지 어떤 DOM을 생성할지 모르기 때문에 `play()` 또는 `pause()`를 호출할 DOM 노드가 아직 없습니다. @@ -349,7 +349,7 @@ video { width: 250px; } }, [isPlaying]); // ...여기에 선언되어야겠네! ``` -이제 모든 의존성이 의존성 배열 안에 선언되어 오류가 없을 것입니다. 의존성 배열로 `[isPlaying]`을 지정하면 React에게 이전 렌더링 중에 `isPlaying`이 이전과 동일하다면 Effect를 다시 실행하지 않도록 해야 한다고 알려줍니다. 이 변경으로 입력란에 입력을 입력하면 Effect가 다시 실행되지 않고, 재생/일시 정지 버튼을 누르면 Effect가 실행됩니다. +이제 모든 의존성이 의존성 배열 안에 선언되어 오류가 없을 것입니다. 의존성 배열로 `[isPlaying]`을 지정하면 React에게 이전 렌더링 중에 `isPlaying`이 이전과 동일하다면 Effect를 다시 실행하지 않도록 해야 한다고 알려줍니다. 이 변경으로 입력란에 값을 입력하면 Effect가 다시 실행되지 않고, 재생/일시 정지 버튼을 누른 경우에만 Effect가 실행됩니다. @@ -397,9 +397,9 @@ video { width: 250px; } -의존성 배열에는 여러 개의 종속성을 포함할 수 있습니다. React는 지정한 모든 종속성이 이전 렌더링의 그것과 정확히 동일한 값을 가진 경우에만 Effect를 다시 실행하지 않습니다. React는 [`Object.is`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is) 비교를 사용하여 종속성 값을 비교합니다. 자세한 내용은 [`useEffect` 참조 문서](/reference/react/useEffect#reference)를 참조하세요. +의존성 배열에는 여러 개의 의존성을 포함할 수 있습니다. React는 지정한 모든 의존성이 이전 렌더링의 그것과 정확히 동일한 값을 가진 경우에만 Effect를 다시 실행하지 않습니다. React는 [`Object.is`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is) 비교를 사용하여 의존성 값을 비교합니다. 자세한 내용은 [`useEffect` 참조 문서](/reference/react/useEffect#reference)를 참조하세요. -**의존성을 "선택"할 수 없다는 점에 유의하세요.** 의존성 배열에 지정한 종속성이 Effect 내부의 코드를 기반으로 React가 기대하는 것과 일치하지 않으면 린트 에러가 발생합니다. 이를 통해 코드 내의 많은 버그를 잡을 수 있습니다. 코드가 다시 실행되길 원하지 않는 경우, [*Effect 내부를 수정하여* 그 종속성이 "필요"하지 않도록 만드세요.](/learn/lifecycle-of-reactive-effects#what-to-do-when-you-dont-want-to-re-synchronize) +**의존성을 "선택"할 수 없다는 점에 유의하세요.** 의존성 배열에 지정한 의존성이 Effect 내부의 코드를 기반으로 React가 기대하는 것과 일치하지 않으면 린트 에러가 발생합니다. 이를 통해 코드 내의 많은 버그를 잡을 수 있습니다. 코드가 다시 실행되길 원하지 않는 경우, [*Effect 내부를 수정하여* 그 의존성이 "필요"하지 않도록 만드세요.](/learn/lifecycle-of-reactive-effects#what-to-do-when-you-dont-want-to-re-synchronize) @@ -474,7 +474,7 @@ useEffect(() => { }); ``` -매번 재렌더링 후에 채팅 서버에 연결하는 것은 느리므로 의존성 배열을 추가합니다. +매번 다시 렌더링한 후에 채팅 서버에 연결하는 것은 느리므로 의존성 배열을 추가합니다. ```js {4} useEffect(() => { @@ -483,7 +483,7 @@ useEffect(() => { }, []); ``` -**Effect 내부의 코드는 어떠한 props나 상태도 사용하지 않으므로, 의존성 배열은 `[]` (빈 배열)입니다. 이는 React에게 이 코드를 컴포넌트가 "마운트"될 때만 실행하도록 알려줍니다. 즉, 화면에 처음으로 나타날 때에만 실행되게 됩니다.** +**Effect 내부의 코드는 어떠한 Props나 State도 사용하지 않으므로, 의존성 배열은 `[]` (빈 배열)입니다. 이는 React에게 이 코드를 컴포넌트가 "마운트"될 때만 실행하도록 알려줍니다. 즉, 화면에 처음으로 나타날 때에만 실행하게 됩니다.** 이 코드를 실행해 보겠습니다. @@ -524,7 +524,7 @@ input { display: block; margin-bottom: 20px; } 이 Effect는 마운트될 때만 실행되므로 콘솔에 "✅ 연결 중..."이 한 번 출력될 것으로 예상할 수 있습니다. 그러나 콘솔을 확인해 보면 "✅ 연결 중..."이 두 번 출력됩니다. 왜 그럴까요? -ChatRoom 컴포넌트가 여러 화면으로 구성된 큰 앱의 일부라고 가정해 보겠습니다. 사용자가 ChatRoom 페이지에서 여정을 시작합니다. 컴포넌트가 마운트되고 `connection.connect()`를 호출합니다. 그런 다음 사용자가 다른 화면으로 이동한다고 상상해보세요. 예를 들어, 설정 페이지로 이동할 수 있습니다. ChatRoom 컴포넌트가 마운트 해제됩니다. 마지막으로 사용자가 뒤로 가기 버튼을 클릭하고 ChatRoom이 다시 마운트됩니다. 이렇게 되면 두 번째 연결이 설정되지만 첫 번째 연결은 종료되지 않았습니다! 사용자가 앱을 탐색하는 동안 연결은 종료되지 않고 계속 쌓일 것입니다. +`ChatRoom` 컴포넌트가 여러 화면으로 구성된 큰 앱의 일부라고 가정해 보겠습니다. 사용자가 `ChatRoom` 페이지에서 여정을 시작합니다. 컴포넌트가 마운트되고 `connection.connect()`를 호출합니다. 그런 다음 사용자가 다른 화면으로 이동한다고 상상해보세요. 예를 들어, 설정 페이지로 이동할 수 있습니다. `ChatRoom` 컴포넌트가 마운트 해제됩니다. 마지막으로 사용자가 뒤로 가기 버튼을 클릭하고 `ChatRoom`이 다시 마운트됩니다. 이렇게 되면 두 번째 연결이 설정되지만 첫 번째 연결은 종료되지 않았습니다! 사용자가 앱을 탐색하는 동안 연결은 종료되지 않고 계속 쌓일 것입니다. 이와 같은 버그는 앱의 이곳저곳을 수동으로 테스트해보지 않으면 놓치기 쉽습니다. 이러한 문제를 빠르게 파악할 수 있도록 React는 개발 모드에서 초기 마운트 후 모든 컴포넌트를 한 번 다시 마운트합니다. @@ -580,13 +580,13 @@ input { display: block; margin-bottom: 20px; } -이제 개발 모드에서 세 개의 콘솔 로그를 확인할 수 있습니다: +이제 개발 모드에서 세 개의 콘솔 로그를 확인할 수 있습니다. 1. `"✅ 연결 중..."` 2. `"❌ 연결 해제됨"` 3. `"✅ 연결 중..."` -**이것이 개발 모드에서 올바른 동작입니다.** 컴포넌트를 다시 마운트함으로써 React는 사용자가 다른 부분을 탐색하고 다시 돌아와도 코드가 깨지지 않을 것임을 확인합니다. 연결을 해제하고 다시 연결하는 것이 바로 일어나는 일입니다! 클린업을 잘 구현하면 Effect를 한 번 실행하는 것과 실행, 클린업, 이후 다시 실행하는 것 사이에 사용자에게 보이는 차이가 없어야 합니다. 개발 중에는 연결/해제 호출이 하나 더 있는데, 이는 React가 개발 중에 코드를 검사하여 버그를 찾는 것입니다. 이것은 정상적인 동작입니다 - 이것을 없애려고 하지 마세요! +**이것이 개발 모드에서 올바른 동작입니다.** 컴포넌트를 다시 마운트함으로써 React는 사용자가 다른 부분을 탐색하고 다시 돌아와도 코드가 깨지지 않을 것임을 확인합니다. 연결을 해제하고 다시 연결하는 것이 바로 일어나는 일입니다! 클린업을 잘 구현하면 Effect를 한 번 실행하는 것과 실행, 클린업, 이후 다시 실행하는 것 사이에 사용자에게 보이는 차이가 없어야 합니다. 개발 중에는 연결/해제 호출이 하나 더 있는데, 이는 React가 개발 중에 코드를 검사하여 버그를 찾는 것입니다. 이것은 정상적인 동작입니다. 이것을 없애려고 하지 마세요! **배포 환경에서는 `"✅ 연결 중..."`이 한 번만 출력됩니다.** 컴포넌트를 다시 마운트하는 것은 개발 중에만 발생하며 클린업이 필요한 Effect를 찾아주는 데 도움을 줍니다. 개발 동작에서 벗어나려면 [Strict Mode](/reference/react/StrictMode)를 끄는 것도 가능하지만, 켜둘 것을 권장합니다. 이렇게 하면 위와 같은 많은 버그를 찾을 수 있습니다. @@ -682,7 +682,7 @@ useEffect(() => { 개발 중에는 불투명도가 `1`로 설정되고, 그런 다음 `0`으로 설정되고, 다시 `1`로 설정됩니다. 이것은 제품 환경에서 `1`로 직접 설정하는 것과 동일한 동작을 가집니다. tweening을 지원하는 서드파티 애니메이션 라이브러리를 사용하는 경우 클린업 함수에서 타임라인을 초기 상태로 재설정해야 합니다. -### 데이터 페칭 {/*fetching-data*/} +### 데이터 가져오기Fetching {/*fetching-data*/} 만약 Effect가 어떤 데이터를 가져온다면, 클린업 함수에서는 [fetch를 중단](https://developer.mozilla.org/en-US/docs/Web/API/AbortController)하거나 결과를 무시해야 합니다. @@ -717,7 +717,7 @@ function TodoList() { // ... ``` -이렇게 하면 개발 환경을 개선하는데 도움이 될 뿐만 아니라 애플리케이션의 반응 속도도 향상됩니다. 예를 들어 사용자가 뒤로 가기 버튼을 눌렀을 때 데이터를 다시 로드하는 것을 기다릴 필요가 없습니다. 데이터가 캐시되기 때문입니다. 이러한 캐시를 직접 구축하거나 비슷한 효과를 누릴 수 있는 여러 대안 중 하나를 사용할 수 있습니다. +이렇게 하면 개발 환경을 개선하는 데 도움이 될 뿐만 아니라 애플리케이션의 반응 속도도 향상됩니다. 예를 들어 사용자가 뒤로 가기 버튼을 눌렀을 때 데이터를 다시 로드하는 것을 기다릴 필요가 없습니다. 데이터가 캐시되기 때문입니다. 이러한 캐시를 직접 구축하거나 비슷한 효과를 누릴 수 있는 여러 대안 중 하나를 사용할 수 있습니다. @@ -733,7 +733,7 @@ Effect 안에서 `fetch` 호출을 작성하는 것은 [데이터를 가져오 이 단점 목록은 React에만 해당되는 것은 아닙니다. 어떤 라이브러리에서든 마운트 시에 데이터를 가져온다면 비슷한 단점이 존재합니다. 마운트 시에 데이터를 페칭하는 것도 라우팅과 마찬가지로 잘 수행하기 어려운 작업이므로 다음 접근 방식을 권장합니다. - **[프레임워크](/learn/creating-a-react-app#full-stack-frameworks)를 사용하고 있다면, 그 프레임워크가 제공하는 내장 데이터 패칭 기능을 사용하세요.** 최신 React 프레임워크는 효율적인 데이터 패칭 메커니즘을 내장하고 있으며, 앞서 언급한 단점을 겪지 않습니다. -- **사용하지 않는다면, 클라이언트 사이드 캐시를 사용하거나 직접 구축하는 것을 고려하세요.** 인기있는 오픈소스 솔루션으로는 [React Query](https://tanstack.com/query/latest), [useSWR](https://swr.vercel.app/), [React Router 6.4+](https://beta.reactrouter.com/en/main/start/overview)가 있습니다. 직접 구현할 수도 있는데, 이 경우에는 Effects를 사용하되, 요청 중복 제거, 응답 캐싱, 네트워크 워터폴 방지를 위한 로직을 추가해야 합니다(데이터를 미리 로드하거나, 필요한 데이터를 상위 라우트로 호이스팅하는 방식으로). +- **사용하지 않는다면, 클라이언트 사이드 캐시를 사용하거나 직접 구축하는 것을 고려하세요.** 인기 있는 오픈소스 솔루션으로는 [React Query](https://tanstack.com/query/latest), [useSWR](https://swr.vercel.app/), [React Router 6.4+](https://beta.reactrouter.com/en/main/start/overview)가 있습니다. 직접 구현할 수도 있는데, 이 경우에는 Effect를 사용하되, 요청 중복 제거, 응답 캐싱, 네트워크 워터폴 방지를 위한 로직을 추가해야 합니다(데이터를 미리 로드하거나, 필요한 데이터를 상위 라우트로 호이스팅하는 방식으로). 이러한 접근 방식 중 어느 것도 적합하지 않은 경우, Effect 내에서 데이터를 직접 가져오는 것을 계속하셔도 됩니다. @@ -794,7 +794,7 @@ useEffect(() => { } ``` -**만약 컴포넌트를 다시 마운트했을 때 애플리케이션의 로직이 깨진다면, 기존에 존재하던 버그가 드러난 것입니다.** 사용자의 관점에서 페이지를 방문하는 것과 페이지를 방문하고, 링크를 클릭한 다음, 뒤로 가기 버튼을 눌러서 다시 페이지로 돌아온것 과 차이가 없어야 합니다. React는 개발 환경에서 컴포넌트를 한 번 다시 마운트하여 이 원칙을 준수하는지 확인합니다. +**만약 컴포넌트를 다시 마운트했을 때 애플리케이션의 로직이 깨진다면, 기존에 존재하던 버그가 드러난 것입니다.** 사용자의 관점에서 페이지를 방문하는 것과 페이지를 방문하고, 링크를 클릭한 다음, 뒤로 가기 버튼을 눌러서 다시 페이지로 돌아온 것과 차이가 없어야 합니다. React는 개발 환경에서 컴포넌트를 한 번 다시 마운트하여 이 원칙을 준수하는지 확인합니다. ## 위에서 설명한 모든 것들 적용해보기 {/*putting-it-all-together*/} diff --git a/src/content/learn/thinking-in-react.md b/src/content/learn/thinking-in-react.md index 75d500da9..9bc8edc6b 100644 --- a/src/content/learn/thinking-in-react.md +++ b/src/content/learn/thinking-in-react.md @@ -457,7 +457,7 @@ function SearchBar({ filterText, inStockOnly }) { ## Step 5: 역 데이터 흐름 추가하기 {/*step-5-add-inverse-data-flow*/} -지금까지 우리는 계층 구조 아래로 흐르는 Props와 State의 함수로써 앱을 만들었습니다. 이제 사용자 입력에 따라 State를 변경하려면 반대 방향의 데이터 흐름을 만들어야 합니다. 이를 위해서는 계층 구조의 하단에 있는 컴포넌트에서 `FilterableProductTable`의 State를 업데이트할 수 있어야 합니다. +지금까지 우리는 계층 구조 아래로 흐르는 Props와 State의 함수로서 앱을 만들었습니다. 이제 사용자 입력에 따라 State를 변경하려면 반대 방향의 데이터 흐름을 만들어야 합니다. 이를 위해서는 계층 구조의 하단에 있는 컴포넌트에서 `FilterableProductTable`의 State를 업데이트할 수 있어야 합니다. React는 데이터 흐름을 명시적으로 보이게 만들어 줍니다. 그러나 이는 전통적인 양방향 데이터 바인딩보다 조금 더 많은 타이핑이 필요합니다. diff --git a/src/content/learn/tutorial-tic-tac-toe.md b/src/content/learn/tutorial-tic-tac-toe.md index 23ed57e67..c563a7220 100644 --- a/src/content/learn/tutorial-tic-tac-toe.md +++ b/src/content/learn/tutorial-tic-tac-toe.md @@ -391,7 +391,7 @@ export default function Square() { ![한 줄에 X가 채워진 9개의 사각형](../images/tutorial/nine-x-filled-squares.png) -이런! 사각형이 보드에 필요한 격자 모양이 아니라 한 줄로 되어있습니다. 이 문제를 해결하려면 `div`를 사용하여 사각형을 행으로 그룹화하고 몇 가지 CSS 클래스를 추가해야 합니다. 이 과정에서 각 사각형에 번호를 부여하여 표시되는 위치를 알 수 있게 하겠습니다. +이런! 사각형이 보드에 필요한 격자 모양이 아니라 한 줄로 되어 있습니다. 이 문제를 해결하려면 `div`를 사용하여 사각형을 행으로 그룹화하고 몇 가지 CSS 클래스를 추가해야 합니다. 이 과정에서 각 사각형에 번호를 부여하여 표시되는 위치를 알 수 있게 하겠습니다. `App.js` 파일에서 `Square` 컴포넌트를 다음과 같이 업데이트하세요. @@ -801,7 +801,7 @@ function Square() { } ``` -`onClick` 핸들러에서 `set` 함수를 호출함으로써 React에 `