->Caution:
+>경고
>
->This page describes **experimental features that are [not yet available](/docs/concurrent-mode-adoption.html) in a stable release**. Don't rely on experimental builds of React in production apps. These features may change significantly and without a warning before they become a part of React.
+> 이 페이지의 내용은 **안정된 배포판에서 [사용할 수 없는](/docs/concurrent-mode-adoption.html) 실험적인 기능**입니다. 프로덕션 애플리케이션에 실험적인 React 빌드를 의존하지 마십시오. 이 기능은 React에 편입되기 전에 경고 없이 크게 변경될 수 있습니다.
>
->This documentation is aimed at early adopters and people who are curious. **If you're new to React, don't worry about these features** -- you don't need to learn them right now. For example, if you're looking for a data fetching tutorial that works today, read [this article](https://www.robinwieruch.de/react-hooks-fetch-data/) instead.
+> 이 문서는 얼리어답터와 호기심 넘치는 사람들을 위해 작성되었습니다. **React 초기 입문자라면 이 기능에 신경 쓰지 않아도 괜찮습니다.** -- 이 내용을 지금 당장 배울 필요는 없습니다. 데이터 패칭을 위한 튜토리얼을 찾는다면 [이 문서](https://www.robinwieruch.de/react-hooks-fetch-data/)를 보세요.
-Usually, when we update the state, we expect to see changes on the screen immediately. This makes sense because we want to keep our app responsive to user input. However, there are cases where we might prefer to **defer an update from appearing on the screen**.
-
-For example, if we switch from one page to another, and none of the code or data for the next screen has loaded yet, it might be frustrating to immediately see a blank page with a loading indicator. We might prefer to stay longer on the previous screen. Implementing this pattern has historically been difficult in React. Concurrent Mode offers a new set of tools to do that.
-
-- [Transitions](#transitions)
- - [Wrapping setState in a Transition](#wrapping-setstate-in-a-transition)
- - [Adding a Pending Indicator](#adding-a-pending-indicator)
- - [Reviewing the Changes](#reviewing-the-changes)
- - [Where Does the Update Happen?](#where-does-the-update-happen)
- - [Transitions Are Everywhere](#transitions-are-everywhere)
- - [Baking Transitions Into the Design System](#baking-transitions-into-the-design-system)
-- [The Three Steps](#the-three-steps)
- - [Default: Receded → Skeleton → Complete](#default-receded-skeleton-complete)
- - [Preferred: Pending → Skeleton → Complete](#preferred-pending-skeleton-complete)
- - [Wrap Lazy Features in ``](#wrap-lazy-features-in-suspense)
- - [Suspense Reveal “Train”](#suspense-reveal-train)
- - [Delaying a Pending Indicator](#delaying-a-pending-indicator)
- - [Recap](#recap)
-- [Other Patterns](#other-patterns)
- - [Splitting High and Low Priority State](#splitting-high-and-low-priority-state)
- - [Deferring a Value](#deferring-a-value)
+일반적으로 상태가 갱신될 때 화면의 즉각적인 변화를 기대합니다. 애플리케이션이 사용자 입력에 반응하는 것을 유지하고 싶기 때문입니다. 하지만 **화면에 나타나는 변화를 지연하고** 싶은 경우도 있습니다.
+
+예를 들어 한 페이지에서 다른 페이지로 전환할 때 다음 화면에 필요한 코드나 데이터가 전혀 준비되어 있지 않으면 순간적으로 빈 화면에 로딩 중인 모습이 보이고 답답할 수 있습니다. 이전 화면을 좀 더 길게 보여주고 싶을 때도 있습니다. React에서 이런 패턴을 구현하기란 오랫동안 어려웠습니다. 컨커런트 모드는 이 문제를 해결하기 위한 새로운 도구를 제공합니다.
+
+- [트랜지션](#transitions)
+ - [setState를 트랜지션에 래핑하기](#wrapping-setstate-in-a-transition)
+ - [지연 인디케이터 추가하기](#adding-a-pending-indicator)
+ - [변화 살펴보기](#reviewing-the-changes)
+ - [어디에서 갱신이 발생하나요?](#where-does-the-update-happen)
+ - [트랜지션은 모든 곳에 있습니다](#transitions-are-everywhere)
+ - [디자인 시스템에 트랜지션 구축하기](#baking-transitions-into-the-design-system)
+- [세 단계](#the-three-steps)
+ - [기본: 후퇴 → 스켈레톤 → 완료](#default-receded-skeleton-complete)
+ - [권장: 보류 → 스켈레톤 → 완료](#preferred-pending-skeleton-complete)
+ - [지연평가 요소를 ``로 래핑하기](#wrap-lazy-features-in-suspense)
+ - [서스펜스 공개 '기차'](#suspense-reveal-train)
+ - [보류 인디케이터 지연하기](#delaying-a-pending-indicator)
+ - [요약](#recap)
+- [기타 패턴](#other-patterns)
+ - [낮은 우선순위 상태와 높은 우선순위 상태 분할하기](#splitting-high-and-low-priority-state)
+ - [값 지연하기](#deferring-a-value)
- [SuspenseList](#suspenselist)
-- [Next Steps](#next-steps)
+- [다음 단계](#next-steps)
-## Transitions {#transitions}
+## 트랜지션 {#transitions}
-Let's revisit [this demo](https://codesandbox.io/s/infallible-feather-xjtbu) from the previous page about [Suspense for Data Fetching](/docs/concurrent-mode-suspense.html).
+이전 [데이터를 가져오기 위한 서스펜스](/docs/concurrent-mode-suspense.html) 페이지의 [데모를](https://codesandbox.io/s/infallible-feather-xjtbu) 다시 살펴봅시다.
-When we click the "Next" button to switch the active profile, the existing page data immediately disappears, and we see the loading indicator for the whole page again. We can call this an "undesirable" loading state. **It would be nice if we could "skip" it and wait for some content to load before transitioning to the new screen.**
+프로필을 활성화하기 위해 "Next" 버튼을 누르면 페이지의 데이터가 바로 사라지고 전체 화면에 로딩 화면을 다시 보게 됩니다. '의도치 않은' 로딩 상태라고 할 수 있습니다. **새 화면을 위한 콘텐츠를 불러오는 동안 화면 전환을 생략할 수 있다면 좋을 것입니다.**
-React offers a new built-in `useTransition()` Hook to help with this.
+React는 이 문제를 해결하기 위해 새로운 `useTransition()` 내장 훅을 제공합니다.
-We can use it in three steps.
+세 단계에 걸쳐 사용할 수 있습니다.
-First, we'll make sure that we're actually using Concurrent Mode. We'll talk more about [adopting Concurrent Mode](/docs/concurrent-mode-adoption.html) later, but for now it's sufficient to know that we need to use `ReactDOM.createRoot()` rather than `ReactDOM.render()` for this feature to work:
+먼저 컨커런트 모드를 사용해야 합니다. [컨커런트 모드 채택](/docs/concurrent-mode-adoption.html)에 대해서는 이후 더 많은 이야기를 나눌 것입니다. 지금은 이 기능이 작동하려면 `ReactDOM.render()` 대신 `ReactDOM.createRoot()`를 사용해야 함을 아는 것으로 충분합니다.
```js
const rootElement = document.getElementById("root");
-// Opt into Concurrent Mode
+// 컨커런트 모드로 설정
ReactDOM.createRoot(rootElement).render();
```
-Next, we'll add an import for the `useTransition` Hook from React:
+그 다음 React에서 `useTransition` 훅을 가져와서 사용합니다.
```js
import React, { useState, useTransition, Suspense } from "react";
```
-Finally, we'll use it inside the `App` component:
+마지막으로 `App` 컴포넌트에서 사용합니다.
```js{3-5}
function App() {
@@ -82,18 +82,18 @@ function App() {
// ...
```
-**By itself, this code doesn't do anything yet.** We will need to use this Hook's return values to set up our state transition. There are two values returned from `useTransition`:
+**이 코드만으로는 아무것도 실행하지 않습니다.** 상태를 갱신하기 위해 훅의 반환 값을 사용해야 합니다. `useTransition`의 반환 값은 두가지입니다.
-* `startTransition` is a function. We'll use it to tell React *which* state update we want to defer.
-* `isPending` is a boolean. It's React telling us whether that transition is ongoing at the moment.
+* `startTransition`는 함수입니다. React에 **어떤** 상태변화를 지연하고 싶은지 지정할 수 있습니다.
+* `isPending`는 불리언 값입니다. 트랜지션 진행 여부를 알 수 있습니다.
-We will use them right below.
+바로 아래에서 사용하겠습니다.
-Note we passed a configuration object to `useTransition`. Its `timeoutMs` property specifies **how long we're willing to wait for the transition to finish**. By passing `{timeoutMs: 3000}`, we say "If the next profile takes more than 3 seconds to load, show the big spinner -- but before that timeout it's okay to keep showing the previous screen".
+`useTransition` 훅에 설정 객체를 전달했다는 것을 명심하세요. `timeoutMs` 프로퍼티는 **트랜지션이 완료될 때까지 얼마나 오랫동안 기다릴 것인지** 결정합니다. `{timeoutMs: 3000}` 를 전달한다면 "다음 프로필을 불러오는 데 3초보다 오래 걸린다면 로딩 상태를 보여주고 그전까진 계속 이전 화면을 보여줘도 괜찮아"라는 의미입니다.
-### Wrapping setState in a Transition {#wrapping-setstate-in-a-transition}
+### setState를 트랜지션에 래핑하기 {#wrapping-setstate-in-a-transition}
-Our "Next" button click handler sets the state that switches the current profile in the state:
+"Next" 버튼 클릭 이벤트 핸들러는 현재 프로필 상태를 설정합니다.
```js{4}
- {isPending ? " Loading..." : null}
+ {isPending ? "Loading..." : null}
>
);
}
```
-**[Try it on CodeSandbox](https://codesandbox.io/s/jovial-lalande-26yep)**
+**[CodeSandbox에서 시도해보세요](https://codesandbox.io/s/jovial-lalande-26yep)**
-It took us only seven lines of code to add this transition:
+7줄의 코드만으로 트랜지션을 추가했습니다.
-* We've imported the `useTransition` Hook and used it the component that updates the state.
-* We've passed `{timeoutMs: 3000}` to stay on the previous screen for at most 3 seconds.
-* We've wrapped our state update into `startTransition` to tell React it's okay to delay it.
-* We're using `isPending` to communicate the state transition progress to the user and to disable the button.
+* `useTransition` 훅을 가져와 컴포넌트의 상태 갱신 부분에 사용했습니다.
+* `{timeoutMs: 3000}` 옵션을 전달하여 최대 3초간 이전 화면을 유지하도록 설정했습니다.
+* React가 상태 갱신을 지연할 수 있도록 상태 갱신 코드를 `startTransition` 함수로 래핑했습니다.
+* `isPending`을 이용하여 사용자에게 작업 상황을 알리고 버튼을 비활성화합니다.
-As a result, clicking "Next" doesn't perform an immediate state transition to an "undesirable" loading state, but instead stays on the previous screen and communicates progress there.
+결과적으로 "Next" 버튼을 눌러도 의도하지 않은 로딩 상태로 바로 전환되지 않고 이전 화면에서 진행 상태를 알려줍니다.
-### Where Does the Update Happen? {#where-does-the-update-happen}
+### 어디에서 갱신이 발생하나요? {#where-does-the-update-happen}
-This wasn't very difficult to implement. However, if you start thinking about how this could possibly work, it might become a little mindbending. If we set the state, how come we don't see the result right away? *Where* is the next `` rendering?
+위 예제를 구현하는 것은 엄청 어렵진 않았습니다. 하지만 어떻게 이게 작동하는지에 대해서 생각하기 시작하면 약간 어지러울 수 있습니다. 상태를 설정했는데 어떻게 그 결과를 바로 볼 수 없는 걸까요? **어디에서** 다음 `` 렌더링이 어디에서 일어날까요?
-Clearly, both "versions" of `` exist at the same time. We know the old one exists because we see it on the screen and even display a progress indicator on it. And we know the new version also exists *somewhere*, because it's the one that we're waiting for!
+두 '버전'의 ``가 동시에 존재하는 것은 명확합니다. 이전 스크린 화면에서 로딩 상태까지 보여주고 있기 때문에 이전 버전이 존재한다는 것을 알 수 있습니다. 그리고 새 버전 또한 **어디엔가** 존재한다는 것을 압니다. 왜냐하면 그것을 기다리고 있기 때문이죠!
-**But how can two versions of the same component exist at the same time?**
+**하지만 어떻게 두 가지 버전의 같은 컴포넌트가 동시에 존재할 수 있는 걸까요?**
-This gets at the root of what Concurrent Mode is. We've [previously said](/docs/concurrent-mode-intro.html#intentional-loading-sequences) it's a bit like React working on state update on a "branch". Another way we can conceptualize is that wrapping a state update in `startTransition` begins rendering it *"in a different universe"*, much like in science fiction movies. We don't "see" that universe directly -- but we can get a signal from it that tells us something is happening (`isPending`). When the update is ready, our "universes" merge back together, and we see the result on the screen!
+이것이 컨커런트 모드의 존재 이유입니다. React의 작업은 '브랜치'의 상태 갱신과 비슷하다고 [앞서 언급했습니다](/docs/concurrent-mode-intro.html#intentional-loading-sequences). 이 개념을 잡기 위한 또 다른 방법은 `startTransition` 함수로 상태 갱신 코드를 래핑하는 것은 공상과학 영화처럼 **다른 평행 우주**에서 렌더링한다고 생각하는 것입니다. 다른 우주를 직접 "볼" 수는 없습니다. 하지만 무언가 일어나고 있다는 신호(`isPending`)를 들을 수 있습니다. 갱신이 준비되면 '우주들'이 다시 병합되고 그 결과를 화면에서 볼 수 있습니다!
-Play a bit more with the [demo](https://codesandbox.io/s/jovial-lalande-26yep), and try to imagine it happening.
+[이 데모](https://codesandbox.io/s/jovial-lalande-26yep)를 좀 더 가지고 놀고 무엇이 일어나는지 상상해보세요.
-Of course, two versions of the tree rendering *at the same time* is an illusion, just like the idea that all programs run on your computer at the same time is an illusion. An operating system switches between different applications very fast. Similarly, React can switch between the version of the tree you see on the screen and the version that it's "preparing" to show next.
+물론 두 버전의 트리 렌더링이 **동시에** 일어나진 않습니다. 컴퓨터의 모든 프로그램이 동시에 실행된다는 것이 허상인 것처럼요. 운영체제는 다른 애플리케이션들을 매우 빠르게 전환합니다. 비슷하게 React도 화면에 보이는 트리 버전과 다음에 노출하기 위해 "준비중"인 버전을 전환할 수 있습니다.
-An API like `useTransition` lets you focus on the desired user experience, and not think about the mechanics of how it's implemented. Still, it can be a helpful metaphor to imagine that updates wrapped in `startTransition` happen "on a branch" or "in a different world".
+`useTransition` 같은 API를 사용하면 원하는 사용자 경험에 초점을 맞출 수 있고 어떻게 구현했는지 생각 하지 않아도 됩니다. `startTransition`에 래핑된 트랜지션이 "브랜치"나 "다른 세계"에서 일어난다는 비유는 이해에 도움이 될 수 있습니다.
-### Transitions Are Everywhere {#transitions-are-everywhere}
+### 트랜지션은 모든 곳에 있습니다. {#transitions-are-everywhere}
-As we learned from the [Suspense walkthrough](/docs/concurrent-mode-suspense.html), any component can "suspend" any time if some data it needs is not ready yet. We can strategically place `` boundaries in different parts of the tree to handle this, but it won't always be enough.
+[Suspense walkthrough](/docs/concurrent-mode-suspense.html)에서 어떤 컴포넌트라도 추가적인 데이터가 필요하지만 준비되지 않았다면 언제든지 '서스펜드' 할 수 있다는 것을 배웠습니다. 중단 상태를 처리하기 위해 ``를 트리의 다른 부분에 전략적으로 배치할 수는 있지만 항상 충분하지는 않습니다.
-Let's get back to our [first Suspense demo](https://codesandbox.io/s/frosty-hermann-bztrp) where there was just one profile. Currently, it fetches the data only once. We'll add a "Refresh" button to check for server updates.
+하나의 프로필만 있던 [첫 번째 서스펜스 데모](https://codesandbox.io/s/frosty-hermann-bztrp)로 돌아가 봅시다. 이 예제는 오직 데이터를 한 번만 페치합니다. 서버 변경사항을 검사하기 위한 "Refresh" 버튼을 추가하겠습니다.
-Our first attempt might look like this:
+첫 번째 시도는 다음과 같이 생겼습니다.
```js{6-8,13-15}
const initialResource = fetchUserAndPosts();
@@ -248,13 +248,13 @@ function ProfilePage() {
}
```
-**[Try it on CodeSandbox](https://codesandbox.io/s/boring-shadow-100tf)**
+**[CodeSandbox에서 시도해보세요](https://codesandbox.io/s/boring-shadow-100tf)**
-In this example, we start data fetching at the load *and* every time you press "Refresh". We put the result of calling `fetchUserAndPosts()` into state so that components below can start reading the new data from the request we just kicked off.
+이 예제에선 페이지가 로드되거나 "Refresh" 버튼을 누를 때 마다 데이터를 가져옵니다. `fetchUserAndPosts()`의 반환값을 상태에 저장하여 하위 컴포넌트들이 요청에서 가져온 데이터를 읽을 수 있게 하겠습니다.
-We can see in [this example](https://codesandbox.io/s/boring-shadow-100tf) that pressing "Refresh" works. The `` and `` components receive a new `resource` prop that represents the fresh data, they "suspend" because we don't have a response yet, and we see the fallbacks. When the response loads, we can see the updated posts (our fake API adds them every 3 seconds).
+[이 예제](https://codesandbox.io/s/boring-shadow-100tf)를 보면 "Refresh" 버튼을 누르는 것은 동작합니다. `` 와 `` 컴포넌트들은 새로운 최신 데이터를 표현하는 `resource` 프로퍼티를 전달받습니다. `fetchUserAndPosts` 호출 직후에 아무런 응답을 받지 못했기 때문에 컴포넌트는 바로 '서스펜드' 상태가 되고 화면에는 폴백을 보게 됩니다. 응답을 받은 뒤엔 새롭게 갱신된 포스트를 볼 수 있습니다. (우리의 목 API는 3초 마다 새로운 포스트를 추가합니다.)
-However, the experience feels really jarring. We were browsing a page, but it got replaced by a loading state right as we were interacting with it. It's disorienting. **Just like before, to avoid showing an undesirable loading state, we can wrap the state update in a transition:**
+하지만 위 경험은 자연스럽지 않습니다. 우리는 한 페이지를 브라우징하고 있었는데 버튼을 클릭한 직후에 바로 로딩 상태로 전환되어 사용자를 혼란스럽게 합니다. **이전처럼, 의도치 않은 로딩 상태를 숨기기 위해서 상태 갱신을 트랜지션에 래핑할 수 있습니다:**
```js{2-5,9-11,21}
function ProfilePage() {
@@ -287,15 +287,15 @@ function ProfilePage() {
}
```
-**[Try it on CodeSandbox](https://codesandbox.io/s/sleepy-field-mohzb)**
+**[CodeSandbox에서 시도해보세요](https://codesandbox.io/s/sleepy-field-mohzb)**
-This feels a lot better! Clicking "Refresh" doesn't pull us away from the page we're browsing anymore. We see something is loading "inline", and when the data is ready, it's displayed.
+훨씬 나아 보입니다! "Refresh" 버튼을 클릭해도 우리가 브라우징하고 있는 페이지가 사라지지 않습니다. 우리는 인라인으로 뭔가 로딩되고 있다는 것을 보고 데이터가 준비된 이후에 새로운 데이터가 보입니다.
-### Baking Transitions Into the Design System {#baking-transitions-into-the-design-system}
+### 디자인시스템에 트랜지션 구축하기 {#baking-transitions-into-the-design-system}
-We can now see that the need for `useTransition` is *very* common. Pretty much any button click or interaction that can lead to a component suspending needs to be wrapped in `useTransition` to avoid accidentally hiding something the user is interacting with.
+이제 `useTransition`의 필요성이 **매우** 일반적이라는 걸 알 수 있습니다. 사용자가 상호작용하는 대상을 실수로 숨기지 않도록 컴포넌트를 서스펜드 상태로 만들 수 있는 대부분 버튼클릭이나 상호작용은 `useTransition`으로 래핑해야 합니다.
-This can lead to a lot of repetitive code across components. This is why **we generally recommend to bake `useTransition` into the *design system* components of your app**. For example, we can extract the transition logic into our own `` component:
+위 작업은 컴포넌트 사이에 많은 반복적인 코드 생산으로 이어질 수 있습니다. 이것이 **일반적으로 디자인 시스템에 `useTransition` 사용하는 것을 추천하는 이유입니다**. 예를 들어 트랜지션 로직을 커스텀 `` 컴포넌트로 추출할 수 있습니다.
```js{7-9,20,24}
function Button({ children, onClick }) {
@@ -327,9 +327,9 @@ function Button({ children, onClick }) {
}
```
-**[Try it on CodeSandbox](https://codesandbox.io/s/modest-ritchie-iufrh)**
+**[CodeSandbox에서 시도해보세요](https://codesandbox.io/s/modest-ritchie-iufrh)**
-Note that the button doesn't care *what* state we're updating. It's wrapping *any* state updates that happen during its `onClick` handler into a transition. Now that our `` takes care of setting up the transition, the `` component doesn't need to set up its own:
+명심하세요 버튼은 **어떤** 상태를 갱신하던지 관여하지 않습니다. 이것은 onClick 이벤트 핸들러에서 발생하는 모든 상태 갱신을 transition에 포함합니다. 이제 ``이 트랜지션 설정을 대신해 주기 때문에 `` 컴포넌트에 트랜지션 설정을 해줄 필요가 없습니다.
```js{4-6,11-13}
function ProfilePage() {
@@ -353,37 +353,37 @@ function ProfilePage() {
}
```
-**[Try it on CodeSandbox](https://codesandbox.io/s/modest-ritchie-iufrh)**
+**[CodeSandbox에서 시도해보세요](https://codesandbox.io/s/modest-ritchie-iufrh)**
-When a button gets clicked, it starts a transition and calls `props.onClick()` inside of it -- which triggers `handleRefreshClick` in the `` component. We start fetching the fresh data, but it doesn't trigger a fallback because we're inside a transition, and the 10 second timeout specified in the `useTransition` call hasn't passed yet. While a transition is pending, the button displays an inline loading indicator.
+버튼을 클릭하면 트랜지션이 시작되고 그 안에 `props.onClick()` 이 호출되서 `` 컴포넌트에서 `handleRefreshClick` 함수가 실행됩니다. 새로운 데이터를 가져오기 시작하지만 트랜지션 내부라서 폴백이 보여지지 않으며 'useTransition' 호출에 지정된 10초가 지나지 않았습니다. 트랜지션이 보류중인 동안 버튼에 인라인으로 로딩 인디케이터를 봅니다.
-We can see now how Concurrent Mode helps us achieve a good user experience without sacrificing isolation and modularity of components. React coordinates the transition.
+이제 컨커런트 모드가 컴포넌트의 격리 수준 및 모듈성을 희생하지 않고도 우수한 사용자 경험을 만드는지 배웠습니다. React는 트랜지션을 조정합니다.
-## The Three Steps {#the-three-steps}
+## 세 단계 {#the-three-steps}
-By now we have discussed all of the different visual states that an update may go through. In this section, we will give them names and talk about the progression between them.
+지금까지 갱신에 진행될 수 있는 다양한 시각적 상태를 살펴보았습니다. 이 부문에서는 상태 변화 단계에 이름을 부여하고 단계별로 어떻게 진행되는지 이야기해보겠습니다.
-
+
-At the very end, we have the **Complete** state. That's where we want to eventually get to. It represents the moment when the next screen is fully rendered and isn't loading more data.
+맨 마지막 단계에 **완료** 단계가 있습니다. 최종적으로 우리가 달성하고 싶어 하는 상태입니다. 다음 화면을 전부 렌더링하고 더 로딩할 데이터가 없는 순간을 의미합니다.
-But before our screen can be Complete, we might need to load some data or code. When we're on the next screen, but some parts of it are still loading, we call that a **Skeleton** state.
+화면이 완료 상태가 되기 전에 특정 데이터나 코드를 불러와야 할 수 있습니다. 다음 화면에 있지만 일부 데이터를 여전히 가져오고 있는 경우 "스켈레톤" 상태라고 말합니다.
-Finally, there are two primary ways that lead us to the Skeleton state. We will illustrate the difference between them with a concrete example.
+마지막으로 스켈레톤 상태로 우리를 이끄는 주요한 두 가지 방법이 있습니다. 구체적인 예를 통해 차이점을 설명하겠습니다.
-### Default: Receded → Skeleton → Complete {#default-receded-skeleton-complete}
+### 기본: 후퇴 → 스켈레톤 → 완료 {#default-receded-skeleton-complete}
-Open [this example](https://codesandbox.io/s/prod-grass-g1lh5) and click "Open Profile". You will see several visual states one by one:
+[이 예제](https://codesandbox.io/s/prod-grass-g1lh5)를 열고 "Open Profile" 버튼을 클릭하세요. 여러 시각적 상태를 단계별로 볼 수 있습니다:
-* **Receded**: For a second, you will see the `
Loading the app...
` fallback.
-* **Skeleton:** You will see the `` component with `
Loading posts...
` inside.
-* **Complete:** You will see the `` component with no fallbacks inside. Everything was fetched.
+* **후퇴:** 잠깐 `
Loading the app...
` 폴백이 보입니다.
+* **스켈레톤:** `` 컴포넌트와 내부의 `
Loading posts...
` 폴백이 보입니다.
+* **완료:** 별도의 내부 폴백 없이 `` 가 보입니다. 모든 것이 준비되었습니다.
-How do we separate the Receded and the Skeleton states? The difference between them is that the **Receded** state feels like "taking a step back" to the user, while the **Skeleton** state feels like "taking a step forward" in our progress to show more content.
+어떻게 후퇴와 스켈레톤 상태를 구분할 수 있을까요? 차이점은 **후퇴**상태는 '한 단계 뒤로 가기' 로 느껴지고, **스켈레톤** 상태는 더 많은 콘텐츠를 보여주기 위해서 '한 단계 앞으로 가기' 에 가까운 느낌입니다.
-In this example, we started our journey on the ``:
+이 예제에선 `` 로 여정을 시작합니다:
```js
@@ -392,7 +392,7 @@ In this example, we started our journey on the ``:
```
-After the click, React started rendering the next screen:
+클릭하면 React는 다음 화면을 렌더링하기 시작합니다:
```js
@@ -406,7 +406,7 @@ After the click, React started rendering the next screen:
```
-Both `` and `` need data to render, so they suspend:
+`` 와 `` 모두 렌더링에 필요한 데이터를 준비하는 동안 서스펜드됩니다:
```js{4,6}
@@ -420,16 +420,16 @@ Both `` and `` need data to render, so they sus
```
-When a component suspends, React needs to show the closest fallback. But the closest fallback to `` is at the top level:
+컴포넌트가 서스펜드 되면 React는 가장 가까운 폴백을 표시합니다. ``의 가장 가까운 폴백은 최상위 수준에 있습니다:
```js{2,3,7}
+ // 가 아직 준비되지 않아서 이 폴백이 보입니다.
Loading the app...
}>
- {/* next screen */}
+ {/* 다음 화면 */}
- {/* suspends! */}
+ {/* 서스펜드됩니다! */}
@@ -437,45 +437,45 @@ When a component suspends, React needs to show the closest fallback. But the clo
```
-This is why when we click the button, it feels like we've "taken a step back". The `` boundary which was previously showing useful content (``) had to "recede" to showing the fallback (`
Loading the app...
`). We call that a **Receded** state.
+최상위 수준에서 폴백되기 때문에 버튼을 클릭할 때 "한 단계 뒤로 간 느낌"이 듭니다. 이전에 유용한 콘텐츠를 보여주던 `` 경계는 폴백을 보여주기 위해 '후퇴'해야 합니다. 이것을 **후퇴**상태라고 부릅니다.
-As we load more data, React will retry rendering, and `` can render successfully. Finally, we're in the **Skeleton** state. We see the new page with missing parts:
+더 많은 데이터를 불러올 수록 React는 렌더링을 다시 시도하고 ``는 성공적으로 렌더링됩니다. 마침내 **스켈레톤** 상태에 돌입했습니다. 몇 가지 빠졌지만 새로운 페이지가 보입니다:
```js{6,7,9}
- {/* next screen */}
+ {/* 다음 화면 */}
+ // 가 아직 준비되지 않아서 이 폴백이 보입니다.
Loading posts...
}>
- {/* suspends! */}
+ {/* 서스펜드됩니다! */}
```
-Eventually, they load too, and we get to the **Complete** state.
+마지막으로 부족한 데이터도 준비되어 **완료** 상태가 됩니다.
-This scenario (Receded → Skeleton → Complete) is the default one. However, the Receded state is not very pleasant because it "hides" existing information. This is why React lets us opt into a different sequence (**Pending** → Skeleton → Complete) with `useTransition`.
+이 시나리오 (Receded → Skeleton → Complete)는 가장 기본적인 형태입니다. 하지만 후퇴 상태는 아주 쾌적한 상태는 아닙니다. 왜냐하면 후퇴상태는 기존 정보를 '숨겨버리기' 때문입니다. React가 `useTransition`을 이용하여 다른 시퀀스 (**보류** → 스켈레톤 → 완료)를 선택할 수 있게 하는 이유입니다.
-### Preferred: Pending → Skeleton → Complete {#preferred-pending-skeleton-complete}
+### 권장: 보류 → 스켈레톤 → 완료 {#preferred-pending-skeleton-complete}
-When we `useTransition`, React will let us "stay" on the previous screen -- and show a progress indicator there. We call that a **Pending** state. It feels much better than the Receded state because none of our existing content disappears, and the page stays interactive.
+`useTransition`할 때 React는 이전 화면에 '잔류'할 수 있게 합니다. 그리고 진행 인디케이터를 보여줍니다. 이걸 **보류**상태라고 부릅니다. 기존 콘텐츠가 사라지지 않고 잔류한 채로 상호작용이 가능하기 때문에 **후퇴** 상태보다 훨씬 좋게 느껴집니다.
-You can compare these two examples to feel the difference:
+차이를 느끼기 위해 두 예제를 비교해보세요:
-* Default: [Receded → Skeleton → Complete](https://codesandbox.io/s/prod-grass-g1lh5)
-* **Preferred: [Pending → Skeleton → Complete](https://codesandbox.io/s/focused-snow-xbkvl)**
+* 기본: [후퇴 → 스켈레톤 → 완성](https://codesandbox.io/s/prod-grass-g1lh5)
+* **권장: [보류 → 스켈레톤 → 완성](https://codesandbox.io/s/focused-snow-xbkvl)**
-The only difference between these two examples is that the first uses regular ``s, but the second one uses our custom `` component with `useTransition`.
+두 예제의 유일한 차이점은 첫 번째는 일반 ``을 사용하지만 두 번째는 커스텀 `` 컴포넌트를 `useTransition`와 함께 사용한다는 것입니다.
-### Wrap Lazy Features in `` {#wrap-lazy-features-in-suspense}
+### 지연평가 요소를 ``로 래핑하기 {#wrap-lazy-features-in-suspense}
-Open [this example](https://codesandbox.io/s/nameless-butterfly-fkw5q). When you press a button, you'll see the Pending state for a second before moving on. This transition feels nice and fluid.
+[이 예제](https://codesandbox.io/s/nameless-butterfly-fkw5q)를 열어보세요. 버튼을 누르면 페이지가 전환되기 전에 몇 초간 보류 상태가 보입니다. 이 트랜지션은 자연스럽고 좋습니다.
-We will now add a brand new feature to the profile page -- a list of fun facts about a person:
+완전 새로운 기능을 프로필 페이지에 추가할 것입니다. 한 사람에 대한 재밌는 사실 목록을 말이죠:
```js{8,13-25}
function ProfilePage({ resource }) {
@@ -505,13 +505,13 @@ function ProfileTrivia({ resource }) {
}
```
-**[Try it on CodeSandbox](https://codesandbox.io/s/focused-mountain-uhkzg)**
+**[CodeSandbox에서 시도해보세요](https://codesandbox.io/s/focused-mountain-uhkzg)**
-If you press "Open Profile" now, you can tell something is wrong. It takes a whole seven seconds to make the transition now! This is because our trivia API is too slow. Let's say we can't make the API faster. How can we improve the user experience with this constraint?
+이제 "Open Profile"을 누르면 뭔가 잘못됐다는걸 느낄 겁니다. 트랜지션을 수행하는 데 7초나 걸렸습니다! trivia API가 너무 느리기 때문입니다. API를 좀 더 빠르게 만들 수 없다고 가정해봅시다. 이 제약과 어떻게 사용자 경험을 개선할 수 있을까요?
-If we don't want to stay in the Pending state for too long, our first instinct might be to set `timeoutMs` in `useTransition` to something smaller, like `3000`. You can try this [here](https://codesandbox.io/s/practical-kowalevski-kpjg4). This lets us escape the prolonged Pending state, but we still don't have anything useful to show!
+보류 상태에 너무 오랫동안 잔류하고 싶지 않다면, 처음으로 생각나는 직관적인 방법은 `useTransition`의 `timeoutMs` 설정을 `3000`정도로 작게 만드는 것입니다. 이 방법을 [여기](https://codesandbox.io/s/practical-kowalevski-kpjg4)에서 시도해볼 수 있습니다. 너무 긴 보류 상태에서 벗어날 수는 있지만, 여전히 유용한 정보를 볼 수는 없습니다!
-There is a simpler way to solve this. **Instead of making the transition shorter, we can "disconnect" the slow component from the transition** by wrapping it into ``:
+이 문제를 해결하기 위한 더 간단한 방법이 있습니다. ``를 래핑해서 **트랜지션을 짧게 만드는 것 대신 트랜지션에서 느린 컴포넌트를 제외할 수 있습니다**.
```js{8,10}
function ProfilePage({ resource }) {
@@ -529,21 +529,21 @@ function ProfilePage({ resource }) {
}
```
-**[Try it on CodeSandbox](https://codesandbox.io/s/condescending-shape-s6694)**
+**[CodeSandbox에서 시도해보세요](https://codesandbox.io/s/condescending-shape-s6694)**
-This reveals an important insight. React always prefers to go to the Skeleton state as soon as possible. Even if we use transitions with long timeouts everywhere, React will not stay in the Pending state for longer than necessary to avoid the Receded state.
+위 예제는 중요한 인사이트를 보여줍니다. React는 항상 가능한 빨리 스켈레톤 상태로 가려고 합니다. 어디에서나 긴 시간제한으로 트랜지션을 사용하더라도 React는 후퇴 상태를 피하고자 필요 이상으로 보류 상태를 유지하지 않습니다.
-**If some feature isn't a vital part of the next screen, wrap it in `` and let it load lazily.** This ensures we can show the rest of the content as soon as possible. Conversely, if a screen is *not worth showing* without some component, such as `` in our example, do *not* wrap it in ``. Then the transitions will "wait" for it to be ready.
+**일부 기능이 중요하지 않다면 ``로 래핑하여 나중에 불러올 수 있게 하세요.** 이렇게하면 가능한 빨리 나머지 콘텐츠를 표시할 수 있습니다. 반대로, 예제에서 ``와 같이 일부 컴포넌트 없이 화면을 표시 할 가치가 없는 경우는 ``로 래핑하지 마세요. 그러면 다음 트랜지션이 준비될 때까지 "대기"합니다.
-### Suspense Reveal "Train" {#suspense-reveal-train}
+### 서스펜스 공개 "기차" {#suspense-reveal-train}
-When we're already on the next screen, sometimes the data needed to "unlock" different `` boundaries arrives in quick succession. For example, two different responses might arrive after 1000ms and 1050ms, respectively. If you've already waited for a second, waiting another 50ms is not going to be perceptible. This is why React reveals `` boundaries on a schedule, like a "train" that arrives periodically. This trades a small delay for reducing the layout thrashing and the number of visual changes presented to the user.
+이미 다음 화면에 있을 때 때때로 다른 `` 경계를 '잠금 해제'하는 데 필요한 데이터가 빠르게 연속적으로 도착합니다. 예를 들어, 두 개의 서로 다른 응답이 각각 1000ms와 1050ms 후에 도착할 수 있습니다. 이미 1초 기다렸다면 50ms 더 기다릴 수 없습니다. React가 정기적으로 도착하는 "기차"와 같이 스케줄에 `` 경계를 표시하는 이유입니다. 이것은 레이아웃 쓰레싱 및 사용자에게 보여주는 시각적 변화의 수를 줄이기 위해 약간의 지연을 트레이드오프합니다.
-You can see a demo of this [here](https://codesandbox.io/s/admiring-mendeleev-y54mk). The "posts" and "fun facts" responses come within 100ms of each other. But React coalesces them and "reveals" their Suspense boundaries together.
+[여기에서](https://codesandbox.io/s/admiring-mendeleev-y54mk) 데모를 볼 수 있습니다. "포스트" 및 "재미있는 사실" 응답은 서로 100ms 이내에 있습니다. React는 두 응답을 통합하여 서스펜스 경계를 함께 "공개"합니다.
-### Delaying a Pending Indicator {#delaying-a-pending-indicator}
+### 보류 인디케이터 지연하기 {#delaying-a-pending-indicator}
-Our `Button` component will immediately show the Pending state indicator on click:
+`Button` 컴포넌트가 클릭 되면 즉시 보류 상태 인디케이터를 보여줍니다:
```js{2,13}
function Button({ children, onClick }) {
@@ -564,11 +564,11 @@ function Button({ children, onClick }) {
}
```
-**[Try it on CodeSandbox](https://codesandbox.io/s/floral-thunder-iy826)**
+**[CodeSandbox에서 시도해보세요](https://codesandbox.io/s/floral-thunder-iy826)**
-This signals to the user that some work is happening. However, if the transition is relatively short (less than 500ms), it might be too distracting and make the transition itself feel *slower*.
+이 신호는 사용자에게 뭔가 작업되고 있다고 알려줍니다. 하지만 트랜지션이 상대적으로 짧다면(500ms 이내) 너무 산만해지고 트랜지션 자체가 너무 느리게 느껴질 수 있습니다.
-One possible solution to this is to *delay the spinner itself* from displaying:
+이에 한 가지 가능한 해결책은 **스피너 자체가** 표시되지 않도록 하는 지연하는 것입니다.
```css
.DelayedSpinner {
@@ -598,29 +598,29 @@ return (
);
```
-**[Try it on CodeSandbox](https://codesandbox.io/s/gallant-spence-l6wbk)**
+**[CodeSandbox에서 시도해보세요](https://codesandbox.io/s/gallant-spence-l6wbk)**
-With this change, even though we're in the Pending state, we don't display any indication to the user until 500ms has passed. This may not seem like much of an improvement when the API responses are slow. But compare how it feels [before](https://codesandbox.io/s/thirsty-liskov-1ygph) and [after](https://codesandbox.io/s/hardcore-http-s18xr) when the API call is fast. Even though the rest of the code hasn't changed, suppressing a "too fast" loading state improves the perceived performance by not calling attention to the delay.
+이 변경으로 보류 상태에 있더라도 500ms가 지날 때까지 사용자에게 인디케이터가 보이지 않습니다. API 응답이 느리면 개선되지 않은 것처럼 보일 수 있습니다. 그러나 API 호출이 빠를 때 [이전 예제](https://codesandbox.io/s/thirsty-liskov-1ygph)과 [다음 예제](https://codesandbox.io/s/hardcore-http-s18xr)를 비교해보세요. 나머지 코드는 변경되지 않았지만 "너무 빠른" 로딩 상태를 억제하고 지연에 주의를 주지 않으면서 성능인식을 개선할 수 있습니다.
-### Recap {#recap}
+### 요약 {#recap}
-The most important things we learned so far are:
+지금까지 배운 가장 중요한 것들:
-* By default, our loading sequence is Receded → Skeleton → Complete.
-* The Receded state doesn't feel very nice because it hides existing content.
-* With `useTransition`, we can opt into showing a Pending state first instead. This will keep us on the previous screen while the next screen is being prepared.
-* If we don't want some component to delay the transition, we can wrap it in its own `` boundary.
-* Instead of doing `useTransition` in every other component, we can build it into our design system.
+* 기본적으로 로딩 순서는 후퇴 → 스켈레톤 → 완료 입니다.
+* 후퇴 상태는 기존 콘텐츠를 숨겨버리기 때문에 좋은 인터페이스는 아닙니다.
+* `useTransition`을 사용하여 보류 상태를 보여줄 수 있습니다. 다음 화면이 준비되는 동안 이전 화면을 계속 보여줍니다.
+* 특정 컴포넌트가 트랜지션을 지연하는 걸 원치 않는다면 `` 경계를 래핑하여 회피할 수 있습니다.
+* 매번 `useTransition`을 모든 컴포넌트에서 처리하지 않고 디자인 시스템에 적용해놓을 수 있습니다.
-## Other Patterns {#other-patterns}
+## 기타 패턴들 {#other-patterns}
-Transitions are probably the most common Concurrent Mode pattern you'll encounter, but there are a few more patterns you might find useful.
+트랜지션은 가장 일반적인 컨커런트모드 패턴이지만 몇 가지 유용한 패턴이 더 있습니다.
-### Splitting High and Low Priority State {#splitting-high-and-low-priority-state}
+### 높은 우선순위 상태와 낮은 우선순위 상태 분할하기 {#splitting-high-and-low-priority-state}
-When you design React components, it is usually best to find the "minimal representation" of state. For example, instead of keeping `firstName`, `lastName`, and `fullName` in state, it's usually better keep only `firstName` and `lastName`, and then calculate `fullName` during rendering. This lets us avoid mistakes where we update one state but forget the other state.
+React 컴포넌트를 설계할 때 일반적으로 "최소한 표현" 상태를 찾는 것이 좋습니다. 예를 들어 `firstName`, `lastName`, `fullName`를 전부 상태에 저장해놓기보다는 `firstName`, `lastName`만 저장해놓고 렌더링 과정에서 `fullName`을 계산하는 것이 낫습니다. 상태를 갱신할 때 실수의 여지를 없애고 다른 상태를 신경쓰지 않아도 되기 때문입니다.
-However, in Concurrent Mode there are cases where you might *want* to "duplicate" some data in different state variables. Consider this tiny translation app:
+그런데 컨커런트 모드에서는 다른 상태의 변수들에 데이터 '중복'을 원할 수도 있습니다. 다음 작은 애플리케이션을 생각해봅시다:
```js
const initialQuery = "Hello, world";
@@ -658,11 +658,11 @@ function Translation({ resource }) {
}
```
-**[Try it on CodeSandbox](https://codesandbox.io/s/brave-villani-ypxvf)**
+**[CodeSandbox에서 시도해보세요](https://codesandbox.io/s/brave-villani-ypxvf)**
-Notice how when you type into the input, the `` component suspends, and we see the `
Loading...
` fallback until we get fresh results. This is not ideal. It would be better if we could see the *previous* translation for a bit while we're fetching the next one.
+인풋에 타이핑하면 `` 컴포넌트는 서스펜드되고 데이터가 준비될 때까지 `
Loading...
` 폴백이 보입니다. 이상적인 형태는 아닙니다. 다음 번역을 가져오는 동안 **이전**번역을 볼 수 있다면 더 좋을 것입니다.
-In fact, if we open the console, we'll see a warning:
+사실 콘솔을 열어보면 다음과 같은 경고가 보일 겁니다:
```
Warning: App triggered a user-blocking update that suspended.
@@ -672,7 +672,7 @@ The fix is to split the update into multiple parts: a user-blocking update to pr
Refer to the documentation for useTransition to learn how to implement this pattern.
```
-As we mentioned earlier, if some state update causes a component to suspend, that state update should be wrapped in a transition. Let's add `useTransition` to our component:
+앞에서 말했듯이 일부 상태 갱신으로 컴포넌트가 서스펜드되면 해당 상태 갱신은 트랜지션으로 래핑되어야합니다. 컴포넌트에 `useTransition`을 추가해봅시다:
```js{4-6,10,13}
function App() {
@@ -695,17 +695,17 @@ function App() {
}
```
-**[Try it on CodeSandbox](https://codesandbox.io/s/zen-keldysh-rifos)**
+**[CodeSandbox에서 시도해보세요](https://codesandbox.io/s/zen-keldysh-rifos)**
-Try typing into the input now. Something's wrong! The input is updating very slowly.
+인풋에 입력해보세요. 뭔가 잘못됐습니다! 인풋 갱신이 아주 느립니다.
-We've fixed the first problem (suspending outside of a transition). But now because of the transition, our state doesn't update immediately, and it can't "drive" a controlled input!
+첫번째 문제(트랜지션 바깥에서 서스펜드 되는 것)은 해결했습니다. 하지만 이제 트랜지션 때문에 상태 갱신이 즉각적으로 반영되지 않고 이것은 제어된 인풋을 조작하기엔 부적절합니다!
-The answer to this problem **is to split the state in two parts:** a "high priority" part that updates immediately, and a "low priority" part that may wait for a transition.
+위 문제에 대한 해결책은 **상태를 두 파트로 분리하는 것입니다:** 즉각적으로 갱신되어야 하는 높은 우선순위 파트와 트랜지션에서 조금 기다려도 되는 낮은 우선순위 파트로요.
-In our example, we already have two state variables. The input text is in `query`, and we read the translation from `resource`. We want changes to the `query` state to happen immediately, but changes to the `resource` (i.e. fetching a new translation) should trigger a transition.
+예제에서 우리는 이미 두 상태 변수를 가지고 있습니다. 입력 텍스트는 `query` 그리고 번역 정보를 `resource`에서 읽습니다. `query` 상태는 즉각적으로 반영되어야 하지만 `resource` 변화는 트랜지션을 발생시켜야 합니다. (예를 들어 새로운 번역 데이터를 가져오기 같은 동작)
-So the correct fix is to put `setQuery` (which doesn't suspend) *outside* the transition, but `setResource` (which will suspend) *inside* of it.
+즉 올바른 수정은 `setQuery`를 트랜지션 바깥에 놓고 `setResource`는 그대로 트랜지션 안에 두는 것입니다.
```js{4,5}
function handleChange(e) {
@@ -721,13 +721,13 @@ function handleChange(e) {
}
```
-**[Try it on CodeSandbox](https://codesandbox.io/s/lively-smoke-fdf93)**
+**[CodeSandbox에서 시도해보세요](https://codesandbox.io/s/lively-smoke-fdf93)**
-With this change, it works as expected. We can type into the input immediately, and the translation later "catches up" to what we have typed.
+이 변경으로 예상대로 작동합니다. 입풋 입력은 즉각 반영되고 번역은 타이핑된 내용을 나중에 따라갑니다.
-### Deferring a Value {#deferring-a-value}
+### 값 지연하기 {#deferring-a-value}
-By default, React always renders a consistent UI. Consider code like this:
+기본적으로 React는 항상 일관적인 UI를 렌더링합니다. 다음 코드를 생각해봅시다:
```js
<>
@@ -736,11 +736,13 @@ By default, React always renders a consistent UI. Consider code like this:
>
```
-React guarantees that whenever we look at these components on the screen, they will reflect data from the same `user`. If a different `user` is passed down because of a state update, you would see them changing together. You can't ever record a screen and find a frame where they would show values from different `user`s. (If you ever run into a case like this, file a bug!)
+React는 화면에서 이런 컴포넌트를 볼 때마다 동일한 '사용자'의 데이터를 반영합니다. 상태 업데이트로 인해 다른 `user`가 전달되면 함께 변경되는 것을 볼 수 있습니다. 화면을 기록할 수 없고 다른 사용자의 값을 표시할 프레임을 찾을 수 없습니다. (혹시 이런 상황을 목격하시면 버그를 보고해주세요!)
+
+React는 화면에 이런 컴포넌트를 볼 때마다 동일한 `user` 데이터를 반영합니다. 상태 갱신으로 다른 `user`가 전달되면 함께 변경되는걸 볼 수 있습니다.
-This makes sense in the vast majority of situations. Inconsistent UI is confusing and can mislead users. (For example, it would be terrible if a messenger's Send button and the conversation picker pane "disagreed" about which thread is currently selected.)
+대부분의 상황에선 일관적인 UI가 자연스럽습니다. 비일관적인 UI는 혼란스럽고 사용자들을 오해하게 만듭니다. (예를 들어 메신저의 '보내기' 버튼이 현재 선택된 대화 스레드에 메세지를 보내지 않는다고 생각해보세요.)
-However, sometimes it might be helpful to intentionally introduce an inconsistency. We could do it manually by "splitting" the state like above, but React also offers a built-in Hook for this:
+하지만 때때로 의도적인 비일관성을 도입하는 게 도움 될 때도 있습니다. 위에서 했던 것처럼 직접 '분할'할 수도 있지만, React는 이를 위해 내장 훅을 제공합니다:
```js
import { useDeferredValue } from 'react';
@@ -750,11 +752,11 @@ const deferredValue = useDeferredValue(value, {
});
```
-To demonstrate this feature, we'll use [the profile switcher example](https://codesandbox.io/s/musing-ramanujan-bgw2o). Click the "Next" button and notice how it takes 1 second to do a transition.
+위 기능을 보여주기 위해, [프로필 스위치 예제](https://codesandbox.io/s/musing-ramanujan-bgw2o)를 사용합니다. "Next" 버튼을 클릭하고 전환하는 데 1초가 걸리는지 확인해보세요.
-Let's say that fetching the user details is very fast and only takes 300 milliseconds. Currently, we're waiting a whole second because we need both user details and posts to display a consistent profile page. But what if we want to show the details faster?
+사용자 디테일 정보를 가져오는 작업이 매우 빠르고 300밀리세컨드 안쪽이라고 가정해봅시다. 현재 일관된 프로필 페이지를 표시하려면 사용자 세부 정보와 게시물이 모두 필요하기 때문에 1초간 기다려야 합니다. 하지만 세부 정보를 더 빨리 표시하려면 어떻게 해야 할까요?
-If we're willing to sacrifice consistency, we could **pass potentially stale data to the components that delay our transition**. That's what `useDeferredValue()` lets us do:
+일관성을 희생해서, 트랜지션을 지연시키는 컴포넌트에 부실한(오래된) 데이터를 전달할 수 있습니다. 그것이 `useDeferredValue()`가 하는 일입니다:
```js{2-4,10,11,21}
function ProfilePage({ resource }) {
@@ -786,15 +788,15 @@ function ProfileTimeline({ isStale, resource }) {
}
```
-**[Try it on CodeSandbox](https://codesandbox.io/s/vigorous-keller-3ed2b)**
+**[CodeSandbox에서 시도해보세요](https://codesandbox.io/s/vigorous-keller-3ed2b)**
-The tradeoff we're making here is that `` will be inconsistent with other components and potentially show an older item. Click "Next" a few times, and you'll notice it. But thanks to that, we were able to cut down the transition time from 1000ms to 300ms.
+이 예제의 트레이드오프는 `` 이 다른 컴포넌트들과 비일관적으로 오래된 정보를 보여줄 수 있게 된다는 것입니다. "Next" 버튼을 여러 번 클릭해보면 알게 될 겁니다. 하지만 다행스럽게도 우리는 트랜지션에 드는 시간을 1000ms에서 300ms로 줄였습니다.
-Whether or not it's an appropriate tradeoff depends on the situation. But it's a handy tool, especially when the content doesn't change noticeably between items, and the user might not even realize they were looking at a stale version for a second.
+이런 트레이드오프가 적절한지는 상황에 달려 있습니다. 하지만 이것은 매우 편리한 도구입니다. 특히 콘텐츠 사이의 내용이 눈에 띄게 변경되지 경우에요. 사용자는 짧은 시간 동안 오래된 내용을 보고 있다는 것도 인지하지 못할 수 있습니다.
-It's worth noting that `useDeferredValue` is not *only* useful for data fetching. It also helps when an expensive component tree causes an interaction (e.g. typing in an input) to be sluggish. Just like we can "defer" a value that takes too long to fetch (and show its old value despite other components updating), we can do this with trees that take too long to render.
+`useDeferredValue`는 데이터를 가져올 때 유용할 뿐만 아니라, 무거운 컴포넌트 트리로 상호작용이 느려지는 경우에도 도움이 됩니다(예를 들어 인풋에 타이핑할 때). 긴 요청을 지연시키는 것처럼(그리고 다른 컴포넌트가 갱신되는 동안 예전 값을 보여주고요) 렌더링에 오랜 시간이 필요한 트리에도 적용할 수 있습니다.
-For example, consider a filterable list like this:
+예를 들어 다음과 같은 필터 기능이 포함된 목록을 생각해봅시다:
```js
function App() {
@@ -817,11 +819,11 @@ function App() {
}
```
-**[Try it on CodeSandbox](https://codesandbox.io/s/pensive-shirley-wkp46)**
+**[CodeSandbox에서 시도해보세요](https://codesandbox.io/s/pensive-shirley-wkp46)**
-In this example, **every item in `` has an artificial slowdown -- each of them blocks the thread for a few milliseconds**. We'd never do this in a real app, but this helps us simulate what can happen in a deep component tree with no single obvious place to optimize.
+이 예제에선 **``의 모든 아이템은 고의로 속도 저하를 유도합니다. 각 아이템은 스레드를 몇 밀리세컨드 동안 차단합니다.** 실제 애플리케이션에서는 절대 이렇게 만들진 않겠지만 최적화가 불가능한 깊은 컴포넌트 트리를 시뮬레이션하는 용도로 생각해주세요.
-We can see how typing in the input causes stutter. Now let's add `useDeferredValue`:
+인풋에 타이핑하면 어떻게 버벅대는지 볼 수 있습니다. 이제 `useDeferredValue`를 추가해봅시다:
```js{3-5,18}
function App() {
@@ -847,19 +849,19 @@ function App() {
}
```
-**[Try it on CodeSandbox](https://codesandbox.io/s/infallible-dewdney-9fkv9)**
+**[CodeSandbox에서 시도해보세요](https://codesandbox.io/s/infallible-dewdney-9fkv9)**
-Now typing has a lot less stutter -- although we pay for this by showing the results with a lag.
+이제 타이핑해도 덜 버벅대긴 하지만 결과가 지연되어 보입니다.
-How is this different from debouncing? Our example has a fixed artificial delay (3ms for every one of 80 items), so there is always a delay, no matter how fast our computer is. However, the `useDeferredValue` value only "lags behind" if the rendering takes a while. There is no minimal lag imposed by React. With a more realistic workload, you can expect the lag to adjust to the user’s device. On fast machines, the lag would be smaller or non-existent, and on slow machines, it would be more noticeable. In both cases, the app would remain responsive. That’s the advantage of this mechanism over debouncing or throttling, which always impose a minimal delay and can't avoid blocking the thread while rendering.
+디바운싱과 비교하여 뭐가 다를까요? 우리의 예제는 고정된 지연시간(80항목들에 대해서 3ms)을 가지고, 컴퓨터가 얼마나 빠르던 지연이 발생합니다. 하지만 `useDeferredValue` 값은 렌더링에 시간이 걸리는 경우에만 '지연'됩니다. React로 인해 발생하는 최소 지연은 없습니다. 더욱 현실적인 작업량으로 지연이 사용자의 기기에 맞게 조정될 수 있습니다. 빠른 기계에서는 지연이 더 작거나 존재하지 않으며 느린 기계에서는 눈에 띄게 나타납니다. 두 경우 모두, 앱의 반응성이 유지됩니다. 이 메커니즘이 항상 지연을 발생시키며 렌더링 중 스레드를 차단하는 스로틀링이나 디바운싱에 비해 가지는 장점입니다.
-Even though there is an improvement in responsiveness, this example isn't as compelling yet because Concurrent Mode is missing some crucial optimizations for this use case. Still, it is interesting to see that features like `useDeferredValue` (or `useTransition`) are useful regardless of whether we're waiting for network or for computational work to finish.
+응답성이 향상했더라도 이 예제는 아직 설득력이 부족합니다. 왜냐하면 컨커런트 모드에 이 예제의 주요 최적화를 놓치고 있기 때문입니다. 여전히 'useDeferredValue'(또는 'useTransition`)와 같은 기능이 네트워크를 기다리고 있는지 계산 작업이 완료되는지와 관계없이 유용하다는 점이 흥미롭습니다.
### SuspenseList {#suspenselist}
-`` is the last pattern that's related to orchestrating loading states.
+``는 로딩 상태들을 조율하는 것과 관련된 마지막 패턴입니다.
-Consider this example:
+다음 예제를 살펴봅시다:
```js{5-10}
function ProfilePage({ resource }) {
@@ -877,13 +879,13 @@ function ProfilePage({ resource }) {
}
```
-**[Try it on CodeSandbox](https://codesandbox.io/s/proud-tree-exg5t)**
+**[CodeSandbox에서 시도해보세요](https://codesandbox.io/s/proud-tree-exg5t)**
-The API call duration in this example is randomized. If you keep refreshing it, you will notice that sometimes the posts arrive first, and sometimes the "fun facts" arrive first.
+이 예제에서 API 호출 시간은 무작위입니다. 계속 새로고침 하다 보면 어떨 땐 포스트가 먼저 보이고 어떨 땐 재밌는 사실들이 먼저 보입니다.
-This presents a problem. If the response for fun facts arrives first, we'll see the fun facts below the `
Loading posts...
` fallback for posts. We might start reading them, but then the *posts* response will come back, and shift all the facts down. This is jarring.
+재밌는 사실 응답이 먼저 도착하면 `
Loading posts...
` 포스트 폴백 밑의 재밌는 사실을 보게 됩니다. 재밌는 사실을 읽기 시작하는데 갑자기 포스트 응답도 도착하고 재밌는 사실들은 포스트의 밑으로 밀려납니다. 이건 자연스럽지 않습니다.
-One way we could fix it is by putting them both in a single boundary:
+이 문제를 고치는 한 가지 방법은 두 컴포넌트 모두 같은 서스펜스 경계에 두는 것입니다:
```js
Loading posts and fun facts...}>
@@ -892,19 +894,19 @@ One way we could fix it is by putting them both in a single boundary:
```
-**[Try it on CodeSandbox](https://codesandbox.io/s/currying-violet-5jsiy)**
+**[CodeSandbox에서 시도해보세요](https://codesandbox.io/s/currying-violet-5jsiy)**
-The problem with this is that now we *always* wait for both of them to be fetched. However, if it's the *posts* that came back first, there's no reason to delay showing them. When fun facts load later, they won't shift the layout because they're already below the posts.
+이 방법의 문제는 이제 **항상** 두 데이터를 가져올 때까지 기다려야 한다는 것입니다. 하지만 포스트가 먼저 도착한다면 둘 다 지연시킬 필요는 없습니다. 재밌는 사실이 나중에 로드되면 포스트 영역이 이미 잡혀 있기 때문에 갑자기 레이아웃이 밀려나지 않습니다.
-Other approaches to this, such as composing Promises in a special way, are increasingly difficult to pull off when the loading states are located in different components down the tree.
+Promise를 특정 방법으로 병합하는 것 같은 다른 접근법은 로딩 상태가 트리 밑의 다른 컴포넌트에 있을 때 점점 어려워집니다.
-To solve this, we will import `SuspenseList`:
+이 문제를 해결하기 위해 `SuspenseList`를 가져오겠습니다:
```js
import { SuspenseList } from 'react';
```
-`` coordinates the "reveal order" of the closest `` nodes below it:
+``는 하위 트리에 있는 ``의 공개 순서를 조율합니다:
```js{3,11}
function ProfilePage({ resource }) {
@@ -922,16 +924,16 @@ function ProfilePage({ resource }) {
}
```
-**[Try it on CodeSandbox](https://codesandbox.io/s/black-wind-byilt)**
+**[CodeSandbox에서 시도해보세요](https://codesandbox.io/s/black-wind-byilt)**
-The `revealOrder="forwards"` option means that the closest `` nodes inside this list **will only "reveal" their content in the order they appear in the tree -- even if the data for them arrives in a different order**. `` has other interesting modes: try changing `"forwards"` to `"backwards"` or `"together"` and see what happens.
+`revealOrder="forwards"`옵션은 내부 리스트에 인접한 `` 노드들은 **트리에 나타난 순서대로 '나타난다'는 것을 의미합니다. 설령 다른 순서로 데이터가 도착하더라도 말이죠. ``는 다른 흥미로운 모드도 있습니다. `"forwards"`를 `"backwards"` 나 `"together"`로 바꿔보고 어떻게 되는지 확인해보세요.
-You can control how many loading states are visible at once with the `tail` prop. If we specify `tail="collapsed"`, we'll see *at most one* fallback at a time. You can play with it [here](https://codesandbox.io/s/adoring-almeida-1zzjh).
+얼마나 많은 로딩 상태를 보일 수 있게 할 건지 `tail` 프로퍼티를 사용하여 제어할 수 있습니다. `tail="collapsed"`라고 설정하면 한 번에 최대 하나의 폴백만 보게 됩니다. [여기](https://codesandbox.io/s/adoring-almeida-1zzjh)에서 사용해 볼 수 있습니다.
-Keep in mind that `` is composable, like anything in React. For example, you can create a grid by putting several `` rows inside a `` table.
+``은 React의 다른 요소들처럼 합성가능하다는 점을 상기해두세요. 예를 들어 `` 테이블을 담는 여러 `` 열을 여러개 가진 그리드를 만들 수도 있습니다.
-## Next Steps {#next-steps}
+## 다음 단계 {#next-steps}
-Concurrent Mode offers a powerful UI programming model and a set of new composable primitives to help you orchestrate delightful user experiences.
+컨커런트 모드는 강력한 UI 프로그래밍 모델과 좋은 사용자 경험 조직하는 데 도움을 주는 기본 기능들을 제공합니다.
-It's a result of several years of research and development, but it's not finished. In the section on [adopting Concurrent Mode](/docs/concurrent-mode-adoption.html), we'll describe how you can try it and what you can expect.
+이것은 몇 년의 연구와 개발에 걸친 결과물이지만 아직 끝나지 않았습니다. [컨커런트 모드 채택하기](/docs/concurrent-mode-adoption.html) 부문에서 어떻게 컨커런트 모드를 시작할 수 있고 어떤 것을 기대할 수 있는지 서술하겠습니다.