diff --git a/.claude/agents/docs-reviewer.md b/.claude/agents/docs-reviewer.md
new file mode 100644
index 000000000..af0a856e4
--- /dev/null
+++ b/.claude/agents/docs-reviewer.md
@@ -0,0 +1,28 @@
+---
+name: docs-reviewer
+description: "Lean docs reviewer that dispatches reviews docs for a particular skill."
+model: opus
+color: cyan
+---
+
+You are a direct, critical, expert reviewer for React documentation.
+
+Your role is to use given skills to validate given doc pages for consistency, correctness, and adherence to established patterns.
+
+Complete this process:
+
+## Phase 1: Task Creation
+1. CRITICAL: Read the skill requested.
+2. Understand the skill's requirements.
+3. Create a task list to validate skills requirements.
+
+## Phase 2: Validate
+
+1. Read the docs files given.
+2. Review each file with the task list to verify.
+
+## Phase 3: Respond
+
+You must respond with a checklist of the issues you identified, and line number.
+
+DO NOT respond with passed validations, ONLY respond with the problems.
diff --git a/.claude/settings.json b/.claude/settings.json
new file mode 100644
index 000000000..111403183
--- /dev/null
+++ b/.claude/settings.json
@@ -0,0 +1,32 @@
+{
+ "skills": {
+ "suggest": [
+ {
+ "pattern": "src/content/learn/**/*.md",
+ "skill": "docs-writer-learn"
+ },
+ {
+ "pattern": "src/content/reference/**/*.md",
+ "skill": "docs-writer-reference"
+ }
+ ]
+ },
+ "permissions": {
+ "allow": [
+ "Skill(docs-voice)",
+ "Skill(docs-components)",
+ "Skill(docs-sandpack)",
+ "Skill(docs-rsc-sandpack)",
+ "Skill(docs-writer-learn)",
+ "Skill(docs-writer-reference)",
+ "Bash(yarn lint:*)",
+ "Bash(yarn lint-heading-ids:*)",
+ "Bash(yarn lint:fix:*)",
+ "Bash(yarn tsc:*)",
+ "Bash(yarn check-all:*)",
+ "Bash(yarn fix-headings:*)",
+ "Bash(yarn deadlinks:*)",
+ "Bash(yarn prettier:diff:*)"
+ ]
+ }
+}
diff --git a/.claude/skills/docs-components/SKILL.md b/.claude/skills/docs-components/SKILL.md
new file mode 100644
index 000000000..4b75f27a1
--- /dev/null
+++ b/.claude/skills/docs-components/SKILL.md
@@ -0,0 +1,518 @@
+---
+name: docs-components
+description: Comprehensive MDX component patterns (Note, Pitfall, DeepDive, Recipes, etc.) for all documentation types. Authoritative source for component usage, examples, and heading conventions.
+---
+
+# MDX Component Patterns
+
+## Quick Reference
+
+### Component Decision Tree
+
+| Need | Component |
+|------|-----------|
+| Helpful tip or terminology | `` |
+| Common mistake warning | `` |
+| Advanced technical explanation | `` |
+| Canary-only feature | `` or `` |
+| Server Components only | `` |
+| Deprecated API | `` |
+| Experimental/WIP | `` |
+| Visual diagram | `` |
+| Multiple related examples | `` |
+| Interactive code | `` (see `/docs-sandpack`) |
+| Console error display | `` |
+| End-of-page exercises | `` (Learn pages only) |
+
+### Heading Level Conventions
+
+| Component | Heading Level |
+|-----------|---------------|
+| DeepDive title | `####` (h4) |
+| Titled Pitfall | `#####` (h5) |
+| Titled Note | `####` (h4) |
+| Recipe items | `####` (h4) |
+| Challenge items | `####` (h4) |
+
+### Callout Spacing Rules
+
+Callout components (Note, Pitfall, DeepDive) require a **blank line after the opening tag** before content begins.
+
+**Never place consecutively:**
+- `` followed by `` - Combine into one with titled subsections, or separate with prose
+- `` followed by `` - Combine into one, or separate with prose
+
+**Allowed consecutive patterns:**
+- `` followed by `` - OK for multi-part explorations (see useMemo.md)
+- `` followed by `` - OK when DeepDive explains "why" behind the Pitfall
+
+**Separation content:** Prose paragraphs, code examples (Sandpack), or section headers.
+
+**Why:** Consecutive warnings create a "wall of cautions" that overwhelms readers and causes important warnings to be skimmed.
+
+**Incorrect:**
+```mdx
+
+Don't do X.
+
+
+
+Don't do Y.
+
+```
+
+**Correct - combined:**
+```mdx
+
+
+##### Don't do X {/*pitfall-x*/}
+Explanation.
+
+##### Don't do Y {/*pitfall-y*/}
+Explanation.
+
+
+```
+
+**Correct - separated:**
+```mdx
+
+Don't do X.
+
+
+This leads to another common mistake:
+
+
+Don't do Y.
+
+```
+
+---
+
+## ``
+
+Important clarifications, conventions, or tips. Less severe than Pitfall.
+
+### Simple Note
+
+```mdx
+
+
+The optimization of caching return values is known as [_memoization_](https://en.wikipedia.org/wiki/Memoization).
+
+
+```
+
+### Note with Title
+
+Use `####` (h4) heading with an ID.
+
+```mdx
+
+
+#### There is no directive for Server Components. {/*no-directive*/}
+
+A common misunderstanding is that Server Components are denoted by `"use server"`, but there is no directive for Server Components. The `"use server"` directive is for Server Functions.
+
+
+```
+
+### Version-Specific Note
+
+```mdx
+
+
+Starting in React 19, you can render `` as a provider.
+
+In older versions of React, use ``.
+
+
+```
+
+---
+
+## ``
+
+Common mistakes that cause bugs. Use for errors readers will likely make.
+
+### Simple Pitfall
+
+```mdx
+
+
+We recommend defining components as functions instead of classes. [See how to migrate.](#alternatives)
+
+
+```
+
+### Titled Pitfall
+
+Use `#####` (h5) heading with an ID.
+
+```mdx
+
+
+##### Calling different memoized functions will read from different caches. {/*pitfall-different-caches*/}
+
+To access the same cache, components must call the same memoized function.
+
+
+```
+
+### Pitfall with Wrong/Right Code
+
+```mdx
+
+
+##### `useFormStatus` will not return status information for a `;
+}
+```
+
+Instead call `useFormStatus` from inside a component located inside `
+```
+
+---
+
+## ``
+
+Optional deep technical content. **First child must be `####` heading with ID.**
+
+### Standard DeepDive
+
+```mdx
+
+
+#### Is using an updater always preferred? {/*is-updater-preferred*/}
+
+You might hear a recommendation to always write code like `setAge(a => a + 1)` if the state you're setting is calculated from the previous state. There's no harm in it, but it's also not always necessary.
+
+In most cases, there is no difference between these two approaches. React always makes sure that for intentional user actions, like clicks, the `age` state variable would be updated before the next click.
+
+
+```
+
+### Comparison DeepDive
+
+For comparing related concepts:
+
+```mdx
+
+
+#### When should I use `cache`, `memo`, or `useMemo`? {/*cache-memo-usememo*/}
+
+All mentioned APIs offer memoization but differ in what they memoize, who can access the cache, and when their cache is invalidated.
+
+#### `useMemo` {/*deep-dive-usememo*/}
+
+In general, you should use `useMemo` for caching expensive computations in Client Components across renders.
+
+#### `cache` {/*deep-dive-cache*/}
+
+In general, you should use `cache` in Server Components to memoize work that can be shared across components.
+
+
+```
+
+---
+
+## ``
+
+Multiple related examples showing variations. Each recipe needs ``.
+
+```mdx
+
+
+#### Counter (number) {/*counter-number*/}
+
+In this example, the `count` state variable holds a number.
+
+
+{/* code */}
+
+
+
+
+#### Text field (string) {/*text-field-string*/}
+
+In this example, the `text` state variable holds a string.
+
+
+{/* code */}
+
+
+
+
+
+```
+
+**Common titleText/titleId combinations:**
+- "Basic [hookName] examples" / `examples-basic`
+- "Examples of [concept]" / `examples-[concept]`
+- "The difference between [A] and [B]" / `examples-[topic]`
+
+---
+
+## ``
+
+End-of-page exercises. **Learn pages only.** Each challenge needs problem + solution Sandpack.
+
+```mdx
+
+
+#### Fix the bug {/*fix-the-bug*/}
+
+Problem description...
+
+
+Optional hint text.
+
+
+
+{/* problem code */}
+
+
+
+
+Explanation...
+
+
+{/* solution code */}
+
+
+
+
+
+```
+
+**Guidelines:**
+- Only at end of standard Learn pages
+- No Challenges in chapter intros or tutorials
+- Each challenge has `####` heading with ID
+
+---
+
+## ``
+
+For deprecated APIs. Content should explain what to use instead.
+
+### Page-Level Deprecation
+
+```mdx
+
+
+In React 19, `forwardRef` is no longer necessary. Pass `ref` as a prop instead.
+
+`forwardRef` will be deprecated in a future release. Learn more [here](/blog/2024/04/25/react-19#ref-as-a-prop).
+
+
+```
+
+### Method-Level Deprecation
+
+```mdx
+### `componentWillMount()` {/*componentwillmount*/}
+
+
+
+This API has been renamed from `componentWillMount` to [`UNSAFE_componentWillMount`.](#unsafe_componentwillmount)
+
+Run the [`rename-unsafe-lifecycles` codemod](codemod-link) to automatically update.
+
+
+```
+
+---
+
+## ``
+
+For APIs that only work with React Server Components.
+
+### Basic RSC
+
+```mdx
+
+
+`cache` is only for use with [React Server Components](/reference/rsc/server-components).
+
+
+```
+
+### Extended RSC (for Server Functions)
+
+```mdx
+
+
+Server Functions are for use in [React Server Components](/reference/rsc/server-components).
+
+**Note:** Until September 2024, we referred to all Server Functions as "Server Actions".
+
+
+```
+
+---
+
+## `` and ``
+
+For features only available in Canary releases.
+
+### Canary Wrapper (inline in Intro)
+
+```mdx
+
+
+`` lets you group elements without a wrapper node.
+
+Fragments can also accept refs, enabling interaction with underlying DOM nodes.
+
+
+```
+
+### CanaryBadge in Section Headings
+
+```mdx
+### FragmentInstance {/*fragmentinstance*/}
+```
+
+### CanaryBadge in Props Lists
+
+```mdx
+* **optional** `ref`: A ref object from `useRef` or callback function.
+```
+
+### CanaryBadge in Caveats
+
+```mdx
+* If you want to pass `ref` to a Fragment, you can't use the `<>...>` syntax.
+```
+
+---
+
+## ``
+
+Visual explanations of module dependencies, render trees, or data flow.
+
+```mdx
+
+`'use client'` segments the module dependency tree, marking `InspirationGenerator.js` and all dependencies as client-rendered.
+
+```
+
+**Attributes:**
+- `name`: Diagram identifier (used for image file)
+- `height`: Height in pixels
+- `width`: Width in pixels
+- `alt`: Accessible description of the diagram
+
+---
+
+## `` (Use Sparingly)
+
+Numbered callouts in prose. Pairs with code block annotations.
+
+### Syntax
+
+In code blocks:
+```mdx
+```js [[1, 4, "age"], [2, 4, "setAge"], [3, 4, "42"]]
+import { useState } from 'react';
+
+function MyComponent() {
+ const [age, setAge] = useState(42);
+}
+```
+```
+
+Format: `[[step_number, line_number, "text_to_highlight"], ...]`
+
+In prose:
+```mdx
+1. The current state initially set to the initial value.
+2. The `set` function that lets you change it.
+```
+
+### Guidelines
+
+- Maximum 2-3 different colors per explanation
+- Don't highlight every keyword - only key concepts
+- Use for terms in prose, not entire code blocks
+- Maintain consistent usage within a section
+
+✅ **Good use** - highlighting key concepts:
+```mdx
+React will compare the dependencies with the dependencies you passed...
+```
+
+🚫 **Avoid** - excessive highlighting:
+```mdx
+When an Activity boundary is hidden during its initial render...
+```
+
+---
+
+## ``
+
+Display console output (errors, warnings, logs).
+
+```mdx
+
+Uncaught Error: Too many re-renders.
+
+```
+
+**Levels:** `error`, `warning`, `info`
+
+---
+
+## Component Usage by Page Type
+
+### Reference Pages
+
+For component placement rules specific to Reference pages, invoke `/docs-writer-reference`.
+
+Key placement patterns:
+- `` goes before `` at top of page
+- `` goes after `` for page-level deprecation
+- `` goes after method heading for method-level deprecation
+- `` wrapper goes inline within ``
+- `` appears in headings, props lists, and caveats
+
+### Learn Pages
+
+For Learn page structure and patterns, invoke `/docs-writer-learn`.
+
+Key usage patterns:
+- Challenges only at end of standard Learn pages
+- No Challenges in chapter intros or tutorials
+- DeepDive for optional advanced content
+- CodeStep should be used sparingly
+
+### Blog Pages
+
+For Blog page structure and patterns, invoke `/docs-writer-blog`.
+
+Key usage patterns:
+- Generally avoid deep technical components
+- Note and Pitfall OK for clarifications
+- Prefer inline explanations over DeepDive
+
+---
+
+## Other Available Components
+
+**Version/Status:** ``, ``, ``, ``, ``
+
+**Visuals:** ``, ``, ``, ``, ``
+
+**Console:** ``, ``
+
+**Specialized:** ``, ``, ``, ``, ``, ``, `
새로운 기능에 맞춰
업그레이드 하기
diff --git a/src/components/Layout/SidebarNav/SidebarNav.tsx b/src/components/Layout/SidebarNav/SidebarNav.tsx
index 77beb4d72..678d483c1 100644
--- a/src/components/Layout/SidebarNav/SidebarNav.tsx
+++ b/src/components/Layout/SidebarNav/SidebarNav.tsx
@@ -12,7 +12,6 @@
import {Suspense} from 'react';
import * as React from 'react';
import cn from 'classnames';
-import {Feedback} from '../Feedback';
import {SidebarRouteTree} from '../Sidebar/SidebarRouteTree';
import type {RouteItem} from '../getRouteMeta';
@@ -63,9 +62,6 @@ export default function SidebarNav({
-
-
-
diff --git a/src/components/Layout/TopNav/TopNav.tsx b/src/components/Layout/TopNav/TopNav.tsx
index 08342d4b3..ad34057c4 100644
--- a/src/components/Layout/TopNav/TopNav.tsx
+++ b/src/components/Layout/TopNav/TopNav.tsx
@@ -29,7 +29,6 @@ import {IconHamburger} from 'components/Icon/IconHamburger';
import {IconSearch} from 'components/Icon/IconSearch';
import {Search} from 'components/Search';
import {Logo} from '../../Logo';
-import {Feedback} from '../Feedback';
import {SidebarRouteTree} from '../Sidebar';
import type {RouteItem} from '../getRouteMeta';
import {siteConfig} from 'siteConfig';
@@ -42,22 +41,6 @@ declare global {
}
}
-const react18Icon = (
-
-);
-
const darkIcon = (
+
+
+ {message}
+
+
);
}
diff --git a/src/components/PageHeading.tsx b/src/components/PageHeading.tsx
index ee92f5e55..3cfb6337d 100644
--- a/src/components/PageHeading.tsx
+++ b/src/components/PageHeading.tsx
@@ -14,8 +14,12 @@ import Tag from 'components/Tag';
import {H1} from './MDX/Heading';
import type {RouteTag, RouteItem} from './Layout/getRouteMeta';
import * as React from 'react';
+import {useState, useEffect} from 'react';
+import {useRouter} from 'next/router';
import {IconCanary} from './Icon/IconCanary';
import {IconExperimental} from './Icon/IconExperimental';
+import {IconCopy} from './Icon/IconCopy';
+import {Button} from './Button';
interface PageHeadingProps {
title: string;
@@ -27,6 +31,51 @@ interface PageHeadingProps {
breadcrumbs: RouteItem[];
}
+function CopyAsMarkdownButton() {
+ const {asPath} = useRouter();
+ const [copied, setCopied] = useState(false);
+
+ useEffect(() => {
+ if (!copied) return;
+ const timer = setTimeout(() => setCopied(false), 2000);
+ return () => clearTimeout(timer);
+ }, [copied]);
+
+ async function fetchPageBlob() {
+ const cleanPath = asPath.split(/[?#]/)[0];
+ const res = await fetch(cleanPath + '.md');
+ if (!res.ok) throw new Error('Failed to fetch');
+ const text = await res.text();
+ return new Blob([text], {type: 'text/plain'});
+ }
+
+ async function handleCopy() {
+ try {
+ await navigator.clipboard.write([
+ // Don't wait for the blob, or Safari will refuse clipboard access
+ new ClipboardItem({'text/plain': fetchPageBlob()}),
+ ]);
+ setCopied(true);
+ } catch {
+ // Silently fail
+ }
+ }
+
+ return (
+
+ );
+}
+
function PageHeading({
title,
status,
@@ -37,7 +86,12 @@ function PageHeading({
return (
- {breadcrumbs ? : null}
+
+
+ {breadcrumbs ? : null}
+
+
+
{title}
{version === 'canary' && (
diff --git a/src/content/blog/2023/03/22/react-labs-what-we-have-been-working-on-march-2023.md b/src/content/blog/2023/03/22/react-labs-what-we-have-been-working-on-march-2023.md
index dcc29aab1..0cc8e0ef1 100644
--- a/src/content/blog/2023/03/22/react-labs-what-we-have-been-working-on-march-2023.md
+++ b/src/content/blog/2023/03/22/react-labs-what-we-have-been-working-on-march-2023.md
@@ -31,7 +31,7 @@ RSC는 서버 중심의 멀티 페이지 애플리케이션의 간단한 "요청
이제 데이터 가져오기Fetching가 어느 정도 잘 정리되었으므로 다른 방향을 살펴보고 있습니다. 바로 클라이언트에서 서버로 데이터를 전송하여 데이터베이스 변경을 실행하고 폼을 구현할 수 있도록 하는 것입니다. 서버와 클라이언트의 경계를 넘어 서버 액션 함수를 전달하면 클라이언트가 이를 호출하여 원활한 RPC를 제공할 수 있습니다. 서버 액션은 또한 자바스크립트를 불러오기 전에 점진적으로 향상된 폼을 제공합니다.
-React 서버 컴포넌트는 [Next.js App 라우터](/learn/start-a-new-react-project#nextjs-app-router)에 포함되어 있습니다. Next.js에서는 라우터와 깊은 결합을 통해 RSC를 기본 요소로 받아들이는 것을 보여줍니다. 그러나 이 방법이 RSC와 호환할 수 있는 라우터나 프레임워크를 구축하는 유일한 방법은 아닙니다. RSC 명세와 구현에서 제공하는 기능에는 명확한 구분이 있습니다. React 서버 컴포넌트는 호환할 수 있는 React 프레임워크에서 동작하는 컴포넌트에 대한 명세입니다.
+React 서버 컴포넌트는 [Next.js App 라우터](/learn/creating-a-react-app#nextjs-app-router)에 포함되어 있습니다. Next.js에서는 라우터와 깊은 결합을 통해 RSC를 기본 요소로 받아들이는 것을 보여줍니다. 그러나 이 방법이 RSC와 호환할 수 있는 라우터나 프레임워크를 구축하는 유일한 방법은 아닙니다. RSC 명세와 구현에서 제공하는 기능에는 명확한 구분이 있습니다. React 서버 컴포넌트는 호환할 수 있는 React 프레임워크에서 동작하는 컴포넌트에 대한 명세입니다.
우리는 일반적으로 기존 프레임워크를 권장하지만, 직접 사용자 지정 프레임워크를 구축해야 하는 경우도 가능합니다. RSC와 호환할 수 있는 프레임워크를 직접 구축하는 것은 번들러와의 깊은 결합을 필요로하기 때문에 생각만큼 쉽지 않습니다. 현재 세대의 번들러는 클라이언트에서 사용하기에는 훌륭하지만, 서버와 클라이언트 간에 단일 모듈 그래프를 분할하는 것을 우선으로 지원하도록 설계되지 않았습니다. 이것이 지금 RSC를 내장하기 위한 기본 요소를 얻기 위해 번들러 개발자들과 직접 협력하는 이유입니다.
@@ -92,7 +92,7 @@ React 컴포넌트의 순수한 자바스크립트를 반응형으로 만들기
## 트랜지션 추적 {/*transition-tracing*/}
-트랜지션 추적 API를 통해 [React 트랜지션](/reference/react/useTransition)이 느려지는 시점을 감지하고 느려지는 이유를 조사할 수 있습니다. 지난 업데이트 이후 API의 초기 설계를 마무리하고 [RFC](https://github.com/reactjs/rfcs/pull/238)를 공개했습니다. 기본 기능도 함께 구현되었습니다. 이 프로젝트는 현재 보류 중입니다. RFC에 대한 피드백을 환영하며, 개발을 재개하여 React를 위한 더 나은 성능 측정 도구를 제공할 수 있기를 기대합니다. 이는 [Next.js App 라우터](/learn/start-a-new-react-project#nextjs-app-router)와 같이 React 트랜지션 위에 구축된 라우터에서는 특히 더 유용할 것입니다.
+트랜지션 추적 API를 통해 [React 트랜지션](/reference/react/useTransition)이 느려지는 시점을 감지하고 느려지는 이유를 조사할 수 있습니다. 지난 업데이트 이후 API의 초기 설계를 마무리하고 [RFC](https://github.com/reactjs/rfcs/pull/238)를 공개했습니다. 기본 기능도 함께 구현되었습니다. 이 프로젝트는 현재 보류 중입니다. RFC에 대한 피드백을 환영하며, 개발을 재개하여 React를 위한 더 나은 성능 측정 도구를 제공할 수 있기를 기대합니다. 이는 [Next.js App 라우터](/learn/creating-a-react-app#nextjs-app-router)와 같이 React 트랜지션 위에 구축된 라우터에서는 특히 더 유용할 것입니다.
* * *
이번 업데이트 외에도 최근 우리 팀은 커뮤니티 팟캐스트와 라이브스트림에 초청자로 출연하여 우리의 작업에 대해 더 많은 이야기를 나누고 질문에 답변했습니다.
diff --git a/src/content/blog/2024/05/22/react-conf-2024-recap.md b/src/content/blog/2024/05/22/react-conf-2024-recap.md
index 39662d070..5a1efa194 100644
--- a/src/content/blog/2024/05/22/react-conf-2024-recap.md
+++ b/src/content/blog/2024/05/22/react-conf-2024-recap.md
@@ -43,14 +43,14 @@ _[1일 차 전체 스트리밍 시청하기.](https://www.youtube.com/watch?v=T8
- [Josh Story](https://twitter.com/joshcstory): [React 19 심층 탐구: HTML 조정](https://www.youtube.com/watch?v=T8TZQ6k4SLE&t=24916s)
- [Aurora Walberg Scharff](https://twitter.com/aurorascharff): [React 서버 컴포넌트로 폼 향상](https://www.youtube.com/watch?v=0ckOUBiuxVY&t=25280s)
- [Dan Abramov](https://bsky.app/profile/danabra.mov): [두 대의 컴퓨터용 React](https://www.youtube.com/watch?v=T8TZQ6k4SLE&t=18825s)
-- [Kent C. Dodds](https://twitter.com/kentcdodds): [이제 React 서버 컴포넌트를 이해합니다](https://www.youtube.com/watch?v=0ckOUBiuxVY&t=11256s)
+- [Kent C. Dodds](https://twitter.com/kentcdodds): [이제 React 서버 컴포넌트를 이해합니다](https://www.youtube.com/watch?v=0ckOUBiuxVY&t=11256s)
마지막으로 [Joe Savona](https://twitter.com/en_JS), [Sathya Gunasekaran](https://twitter.com/_gsathya), [Mofei Zhang](https://twitter.com/zmofei)은 React 컴파일러가 [오픈소스](https://github.com/facebook/react/pull/29061)로 공개되었음을 알리고, 실험 버전을 공유했습니다.
컴파일러 사용법과 동작 방식은 [관련 문서](/learn/react-compiler) 및 관련 강연을 확인하세요.
- [Lauren Tan](https://twitter.com/potetotes): [Memo를 신경 쓰지 마세요](https://www.youtube.com/watch?v=T8TZQ6k4SLE&t=12020s)
-- [Sathya Gunasekaran](https://twitter.com/_gsathya) & [Mofei Zhang](https://twitter.com/zmofei): [React 컴파일러 심층 탐구](https://www.youtube.com/watch?v=0ckOUBiuxVY&t=9313s)
+- [Sathya Gunasekaran](https://twitter.com/_gsathya) & [Mofei Zhang](https://twitter.com/zmofei): [React 컴파일러 심층 탐구](https://www.youtube.com/watch?v=0ckOUBiuxVY&t=9313s)
1일 차 기조연설 전체 시청하기
@@ -85,7 +85,7 @@ _[2일 차 전체 스트리밍 시청하기](https://www.youtube.com/watch?v=0ck
React와 React Native 팀은 매일 Q&A 세션으로 하루를 마무리했습니다.
-- [Michael Chan](https://twitter.com/chantastic)이 진행한 [React Q&A](https://www.youtube.com/watch?v=T8TZQ6k4SLE&t=27518s)
+- [Michael Chan](https://twitter.com/chantastic)이 진행한 [React Q&A](https://www.youtube.com/watch?v=T8TZQ6k4SLE&t=27518s)
- [Jamon Holmgren](https://twitter.com/jamonholmgren)이 진행한 [React Native Q&A](https://www.youtube.com/watch?v=0ckOUBiuxVY&t=27935s)
## 그리고... {/*and-more*/}
diff --git a/src/content/blog/2024/12/05/react-19.md b/src/content/blog/2024/12/05/react-19.md
index e60c6f735..951e33d76 100644
--- a/src/content/blog/2024/12/05/react-19.md
+++ b/src/content/blog/2024/12/05/react-19.md
@@ -117,7 +117,7 @@ function UpdateName({}) {
액션은 데이터 제출을 자동으로 관리합니다.
-- **대기 상태**: 액션은 요청 시작 시 대기 상태를 활성화하고 최종 상태가 커밋되었을때 자동으로 초기화합니다.
+- **대기 상태**: 액션은 요청 시작 시 대기 상태를 활성화하고 최종 상태가 커밋되었을 때 자동으로 초기화합니다.
- **낙관적 업데이트**: 액션은 새로운 [`useOptimistic`](#new-hook-optimistic-updates)훅을 통해 사용자가 요청을 제출하는 동안 즉각적인 피드백을 표시할 수 있습니다.
- **에러 처리**: 액션은 요청 실패 시 Error Boundary를 보여주고 낙관적 업데이트를 원래 값으로, 자동으로 돌려놓습니다.
- **폼**: `
- {/* Opt-out of ViewTransition for the content. */}
- {/* Content can define it's own ViewTransition. */}
+ {/* 콘텐츠에 대해 ViewTransition을 사용하지 않습니다. */}
+ {/* 콘텐츠는 자체 ViewTransition을 정의할 수 있습니다. */}
{children}
@@ -1806,13 +1806,13 @@ export function Router({ children }) {
useEffect(() => {
function handlePopState() {
- // This should not animate because restoration has to be synchronous.
- // Even though it's a transition.
+ // 복원은 동기적으로 이루어져야 하므로 애니메이션되면 안 됩니다.
+ // 트랜지션이더라도 마찬가지입니다.
startTransition(() => {
setRouterState({
url: document.location.pathname + document.location.search,
pendingNav() {
- // Noop. URL has already updated.
+ // 아무 작업도 하지 않습니다. URL은 이미 업데이트되었습니다.
},
});
});
@@ -2457,7 +2457,7 @@ root.render(
-Since our router already updates the route using `startTransition`, this one line change to add `` activates with the default cross-fade animation.
+라우터가 이미 `startTransition`으로 라우트를 업데이트하고 있으므로, ``을 추가하는 이 한 줄 변경만으로 기본 크로스 페이드 애니메이션이 활성화됩니다.
어떻게 동작하는지 궁금하다면 [How does `` work?](/reference/react/ViewTransition#how-does-viewtransition-work) 문서를 참고하세요.
@@ -2465,7 +2465,7 @@ Since our router already updates the route using `startTransition`, this one lin
#### `` 애니메이션 건너뛰기 {/*opting-out-of-viewtransition-animations*/}
-In this example, we're wrapping the root of the app in `` for simplicity, but this means that all transitions in the app will be animated, which can lead to unexpected animations.
+이 예시에서는 단순화를 위해 앱의 루트를 ``으로 감싸고 있습니다. 하지만 이렇게 하면 앱의 모든 트랜지션이 애니메이션되므로, 예상치 못한 애니메이션이 생길 수 있습니다.
이를 해결하기 위해 각 페이지에서 자체적으로 애니메이션을 제어할 수 있도록 라우트 자식 요소를 `"none"`으로 감싸고 있습니다.
@@ -2476,7 +2476,7 @@ In this example, we're wrapping the root of the app in `` for si
```
-In practice, navigations should be done via "enter" and "exit" props, or by using Transition Types.
+실제로는 네비게이션을 `"enter"`와 `"exit"` prop으로 처리하거나, 트랜지션 타입을 사용해야 합니다.
@@ -2494,7 +2494,7 @@ In practice, navigations should be done via "enter" and "exit" props, or by usin
```
-And define `slow-fade` in CSS using [view transition classes](/reference/react/ViewTransition#view-transition-class):
+그리고 [뷰 트랜지션 클래스](/reference/react/ViewTransition#view-transition-class)를 사용해서 CSS에서 `slow-fade`를 정의합니다.
```css
::view-transition-old(.slow-fade) {
@@ -2519,8 +2519,8 @@ import { useRouter } from "./router";
export default function App() {
const { url } = useRouter();
- // Define a default animation of .slow-fade.
- // See animations.css for the animation definition.
+ // 기본 애니메이션으로 .slow-fade를 지정합니다.
+ // 애니메이션 정의는 animations.css를 참고하세요.
return (
{url === '/' ? : }
@@ -2790,8 +2790,8 @@ export default function Page({ heading, children }) {
{isPending && }
- {/* Opt-out of ViewTransition for the content. */}
- {/* Content can define it's own ViewTransition. */}
+ {/* 콘텐츠는 ViewTransition을 적용하지 않습니다. */}
+ {/* 콘텐츠에서 자체적으로 ViewTransition을 정의할 수 있습니다. */}
{children}
@@ -2806,8 +2806,8 @@ export default function Page({ heading, children }) {
import {useState} from 'react';
import {Heart} from './Icons';
-// A hack since we don't actually have a backend.
-// Unlike local state, this survives videos being filtered.
+// 실제로는 백엔드가 없어서 쓰는 임시 처리입니다.
+// 로컬 상태와 달리, 비디오 목록을 필터링해도 이 값은 유지됩니다.
const likedVideos = new Set();
export default function LikeButton({video}) {
@@ -3016,14 +3016,14 @@ export function Router({ children }) {
});
}
function navigate(url) {
- // Update router state in transition.
+ // 트랜지션 안에서 라우터 상태를 업데이트합니다.
startTransition(() => {
go(url);
});
}
function navigateBack(url) {
- // Update router state in transition.
+ // 트랜지션 안에서 라우터 상태를 업데이트합니다.
startTransition(() => {
go(url);
});
@@ -3031,13 +3031,13 @@ export function Router({ children }) {
useEffect(() => {
function handlePopState() {
- // This should not animate because restoration has to be synchronous.
- // Even though it's a transition.
+ // 복원은 동기적으로 처리되어야 하므로 여기서는 애니메이션되면 안 됩니다.
+ // 트랜지션이더라도 마찬가지입니다.
startTransition(() => {
setRouterState({
url: document.location.pathname + document.location.search,
pendingNav() {
- // Noop. URL has already updated.
+ // 아무 작업도 하지 않습니다. URL은 이미 업데이트되었습니다.
},
});
});
@@ -3638,7 +3638,7 @@ ul {
```css src/animations.css
-/* Define .slow-fade using view transition classes */
+/* 뷰 트랜지션 클래스를 사용해서 .slow-fade를 정의합니다 */
::view-transition-old(.slow-fade) {
animation-duration: 500ms;
}
@@ -3712,9 +3712,9 @@ import { useRouter } from "./router";
export default function App() {
const { url } = useRouter();
- // Keeping our default slow-fade.
- // This allows the content not in the shared
- // element transition to cross-fade.
+ // 기본 slow-fade는 그대로 둡니다.
+ // 공유 요소 트랜지션에 포함되지 않는 콘텐츠가
+ // 크로스 페이드되도록 하기 위함입니다.
return (
{url === "/" ? : }
@@ -3984,8 +3984,8 @@ export default function Page({ heading, children }) {
{isPending && }
- {/* Opt-out of ViewTransition for the content. */}
- {/* Content can define it's own ViewTransition. */}
+ {/* 콘텐츠에 대해 ViewTransition을 사용하지 않습니다. */}
+ {/* 콘텐츠는 자체 ViewTransition을 정의할 수 있습니다. */}
{children}
@@ -4031,8 +4031,8 @@ export default function LikeButton({video}) {
import { useState, ViewTransition } from "react"; import LikeButton from "./LikeButton"; import { useRouter } from "./router"; import { PauseIcon, PlayIcon } from "./Icons"; import { startTransition } from "react";
export function Thumbnail({ video, children }) {
- // Add a name to animate with a shared element transition.
- // This uses the default animation, no additional css needed.
+ // 공유 요소 트랜지션으로 애니메이션되도록 name을 추가합니다.
+ // 기본 애니메이션을 사용하므로 추가 CSS가 필요하지 않습니다.
return (
{
function handlePopState() {
- // This should not animate because restoration has to be synchronous.
- // Even though it's a transition.
+ // 복원은 동기적으로 이루어져야 하므로 애니메이션되면 안 됩니다.
+ // 트랜지션이더라도 마찬가지입니다.
startTransition(() => {
setRouterState({
url: document.location.pathname + document.location.search,
pendingNav() {
- // Noop. URL has already updated.
+ // 아무 작업도 하지 않습니다. URL은 이미 업데이트되었습니다.
},
});
});
@@ -4832,7 +4832,7 @@ ul {
```css src/animations.css
-/* No additional animations needed */
+/* 추가 애니메이션은 필요하지 않습니다 */
@@ -4842,7 +4842,7 @@ ul {
-/* Previously defined animations below */
+/* 이전에 정의된 애니메이션은 아래에 있습니다 */
@@ -4905,14 +4905,14 @@ root.render(
```js {4,11}
function navigate(url) {
startTransition(() => {
- // Transition type for the cause "nav forward"
+ // 전환 원인이 "nav forward"인 경우의 트랜지션 타입
addTransitionType('nav-forward');
go(url);
});
}
function navigateBack(url) {
startTransition(() => {
- // Transition type for the cause "nav backward"
+ // 전환 원인이 "nav backward"인 경우의 트랜지션 타입
addTransitionType('nav-back');
go(url);
});
@@ -4936,22 +4936,22 @@ Transition Types을 사용하면 ``에 Props를 통해 커스텀
```css
::view-transition-old(.slide-forward) {
- /* when sliding forward, the "old" page should slide out to left. */
+ /* 앞으로 전환할 때 "old" 페이지는 왼쪽으로 슬라이드되어 나가야 합니다. */
animation: ...
}
::view-transition-new(.slide-forward) {
- /* when sliding forward, the "new" page should slide in from right. */
+ /* 앞으로 전환할 때 "new" 페이지는 오른쪽에서 슬라이드되어 들어와야 합니다. */
animation: ...
}
::view-transition-old(.slide-back) {
- /* when sliding back, the "old" page should slide out to right. */
+ /* 뒤로 전환할 때 "old" 페이지는 오른쪽으로 슬라이드되어 나가야 합니다. */
animation: ...
}
::view-transition-new(.slide-back) {
- /* when sliding back, the "new" page should slide in from left. */
+ /* 뒤로 전환할 때 "new" 페이지는 왼쪽에서 슬라이드되어 들어와야 합니다. */
animation: ...
}
```
@@ -5234,7 +5234,7 @@ export default function Page({ heading, children }) {
- {/* Custom classes based on transition type. */}
+ {/* 트랜지션 타입에 따라 커스텀 클래스를 적용합니다. */}
}
- {/* Opt-out of ViewTransition for the content. */}
- {/* Content can define it's own ViewTransition. */}
+ {/* 콘텐츠에 대해 ViewTransition을 사용하지 않습니다. */}
+ {/* 콘텐츠는 자체 ViewTransition을 정의할 수 있습니다. */}
{children}
@@ -5297,8 +5297,8 @@ import { PauseIcon, PlayIcon } from "./Icons";
import { startTransition } from "react";
export function Thumbnail({ video, children }) {
- // Add a name to animate with a shared element transition.
- // This uses the default animation, no additional css needed.
+ // 공유 요소 트랜지션으로 애니메이션되도록 name을 추가합니다.
+ // 기본 애니메이션을 사용하므로 추가 CSS가 필요하지 않습니다.
return (
{
- // Transition type for the cause "nav forward"
+ // 전환 원인이 "nav forward"인 경우의 트랜지션 타입
addTransitionType('nav-forward');
go(url);
});
}
function navigateBack(url) {
startTransition(() => {
- // Transition type for the cause "nav backward"
+ // 전환 원인이 "nav backward"인 경우의 트랜지션 타입
addTransitionType('nav-back');
go(url);
});
@@ -5475,13 +5475,13 @@ export function Router({ children }) {
useEffect(() => {
function handlePopState() {
- // This should not animate because restoration has to be synchronous.
- // Even though it's a transition.
+ // 복원은 동기적으로 이루어져야 하므로 애니메이션되면 안 됩니다.
+ // 트랜지션이더라도 마찬가지입니다.
startTransition(() => {
setRouterState({
url: document.location.pathname + document.location.search,
pendingNav() {
- // Noop. URL has already updated.
+ // 아무 작업도 하지 않습니다. URL은 이미 업데이트되었습니다.
},
});
});
@@ -6093,27 +6093,27 @@ ul {
```css src/animations.css
-/* Animations for view transition classed added by transition type */
+/* 트랜지션 타입에 의해 추가된 View Transition 클래스용 애니메이션 */
::view-transition-old(.slide-forward) {
- /* when sliding forward, the "old" page should slide out to left. */
+ /* 앞으로 전환할 때 "old" 페이지는 왼쪽으로 슬라이드되어 나가야 합니다. */
animation: 150ms cubic-bezier(0.4, 0, 1, 1) both fade-out,
400ms cubic-bezier(0.4, 0, 0.2, 1) both slide-to-left;
}
::view-transition-new(.slide-forward) {
- /* when sliding forward, the "new" page should slide in from right. */
+ /* 앞으로 전환할 때 "new" 페이지는 오른쪽에서 슬라이드되어 들어와야 합니다. */
animation: 210ms cubic-bezier(0, 0, 0.2, 1) 150ms both fade-in,
400ms cubic-bezier(0.4, 0, 0.2, 1) both slide-from-right;
}
::view-transition-old(.slide-back) {
- /* when sliding back, the "old" page should slide out to right. */
+ /* 뒤로 전환할 때 "old" 페이지는 오른쪽으로 슬라이드되어 나가야 합니다. */
animation: 150ms cubic-bezier(0.4, 0, 1, 1) both fade-out,
400ms cubic-bezier(0.4, 0, 0.2, 1) both slide-to-right;
}
::view-transition-new(.slide-back) {
- /* when sliding back, the "new" page should slide in from left. */
+ /* 뒤로 전환할 때 "new" 페이지는 왼쪽에서 슬라이드되어 들어와야 합니다. */
animation: 210ms cubic-bezier(0, 0, 0.2, 1) 150ms both fade-in,
400ms cubic-bezier(0.4, 0, 0.2, 1) both slide-from-left;
}
@@ -6161,7 +6161,7 @@ ul {
}
}
-/* Previously defined animations. */
+/* 이전에 정의된 애니메이션 */
/* Default .slow-fade. */
::view-transition-old(.slow-fade) {
@@ -6212,9 +6212,9 @@ root.render(
### Suspense Boundaries 애니메이팅 {/*animating-suspense-boundaries*/}
-Suspense will also activate View Transitions.
+Suspense도 View Transitions를 활성화합니다.
-콘텐츠에 대한 폴백 애니메이션을 적용하려면 `Suspense`를 ``으로 래핑하면 됩니다.
+콘텐츠에 대한 폴백 애니메이션을 적용하려면 `Suspense`를 ``으로 래핑하면 됩니다.
```js
@@ -6250,7 +6250,7 @@ export default function App() {
import { use, Suspense, ViewTransition } from "react"; import { fetchVideo, fetchVideoDetails } from "./data"; import { Thumbnail, VideoControls } from "./Videos"; import { useRouter } from "./router"; import Layout from "./Layout"; import { ChevronLeft } from "./Icons";
function VideoDetails({ id }) {
- // Cross-fade the fallback to content.
+ // 폴백에서 콘텐츠로 크로스 페이드합니다.
return (
}>
@@ -6506,7 +6506,7 @@ export default function Page({ heading, children }) {
- {/* Custom classes based on transition type. */}
+ {/* 트랜지션 타입에 따라 커스텀 클래스를 적용합니다. */}
}
- {/* Opt-out of ViewTransition for the content. */}
- {/* Content can define it's own ViewTransition. */}
+ {/* 콘텐츠에 대해 ViewTransition을 사용하지 않습니다. */}
+ {/* 콘텐츠는 자체 ViewTransition을 정의할 수 있습니다. */}
{children}
@@ -6569,8 +6569,8 @@ import { PauseIcon, PlayIcon } from "./Icons";
import { startTransition } from "react";
export function Thumbnail({ video, children }) {
- // Add a name to animate with a shared element transition.
- // This uses the default animation, no additional css needed.
+ // 공유 요소 트랜지션으로 애니메이션되도록 name을 추가합니다.
+ // 기본 애니메이션을 사용하므로 추가 CSS가 필요하지 않습니다.
return (
{}, url: document.location.pathname});
function navigate(url) {
startTransition(() => {
- // Transition type for the cause "nav forward"
+ // 전환 원인이 "nav forward"인 경우의 트랜지션 타입
addTransitionType('nav-forward');
go(url);
});
}
function navigateBack(url) {
startTransition(() => {
- // Transition type for the cause "nav backward"
+ // 전환 원인이 "nav backward"인 경우의 트랜지션 타입
addTransitionType('nav-back');
go(url);
});
@@ -6744,13 +6744,13 @@ export function Router({ children }) {
useEffect(() => {
function handlePopState() {
- // This should not animate because restoration has to be synchronous.
- // Even though it's a transition.
+ // 복원은 동기적으로 이루어져야 하므로 애니메이션되면 안 됩니다.
+ // 트랜지션이더라도 마찬가지입니다.
startTransition(() => {
setRouterState({
url: document.location.pathname + document.location.search,
pendingNav() {
- // Noop. URL has already updated.
+ // 아무 작업도 하지 않습니다. URL은 이미 업데이트되었습니다.
},
});
});
@@ -7362,17 +7362,17 @@ ul {
```css src/animations.css
-/* Slide the fallback down */
+/* 폴백을 아래로 슬라이드합니다 */
::view-transition-old(.slide-down) {
animation: 150ms ease-out both fade-out, 150ms ease-out both slide-down;
}
-/* Slide the content up */
+/* 콘텐츠를 위로 슬라이드합니다 */
::view-transition-new(.slide-up) {
animation: 210ms ease-in 150ms both fade-in, 400ms ease-in both slide-up;
}
-/* Define the new keyframes */
+/* 새로운 키프레임을 정의합니다 */
@keyframes slide-up {
from {
transform: translateY(10px);
@@ -7391,34 +7391,34 @@ ul {
}
}
-/* Previously defined animations below */
+/* 이전에 정의된 애니메이션은 아래에 있습니다 */
-/* Animations for view transition classed added by transition type */
+/* 트랜지션 타입에 의해 추가된 View Transition 클래스용 애니메이션 */
::view-transition-old(.slide-forward) {
- /* when sliding forward, the "old" page should slide out to left. */
+ /* 앞으로 전환할 때 "old" 페이지는 왼쪽으로 슬라이드되어 나가야 합니다. */
animation: 150ms cubic-bezier(0.4, 0, 1, 1) both fade-out,
400ms cubic-bezier(0.4, 0, 0.2, 1) both slide-to-left;
}
::view-transition-new(.slide-forward) {
- /* when sliding forward, the "new" page should slide in from right. */
+ /* 앞으로 전환할 때 "new" 페이지는 오른쪽에서 슬라이드되어 들어와야 합니다. */
animation: 210ms cubic-bezier(0, 0, 0.2, 1) 150ms both fade-in,
400ms cubic-bezier(0.4, 0, 0.2, 1) both slide-from-right;
}
::view-transition-old(.slide-back) {
- /* when sliding back, the "old" page should slide out to right. */
+ /* 뒤로 전환할 때 "old" 페이지는 오른쪽으로 슬라이드되어 나가야 합니다. */
animation: 150ms cubic-bezier(0.4, 0, 1, 1) both fade-out,
400ms cubic-bezier(0.4, 0, 0.2, 1) both slide-to-right;
}
::view-transition-new(.slide-back) {
- /* when sliding back, the "new" page should slide in from left. */
+ /* 뒤로 전환할 때 "new" 페이지는 왼쪽에서 슬라이드되어 들어와야 합니다. */
animation: 210ms cubic-bezier(0, 0, 0.2, 1) 150ms both fade-in,
400ms cubic-bezier(0.4, 0, 0.2, 1) both slide-from-left;
}
-/* Keyframes to support our animations above. */
+/* 위 애니메이션을 지원하기 위한 키프레임 */
@keyframes fade-in {
from {
opacity: 0;
@@ -7528,12 +7528,12 @@ CSS로 `slide-down`과 `slide-up`을 정의하는 방법은 다음과 같습니
```css {1, 6}
::view-transition-old(.slide-down) {
- /* Slide the fallback down */
+ /* 폴백을 아래로 슬라이드합니다 */
animation: ...;
}
::view-transition-new(.slide-up) {
- /* Slide the content up */
+ /* 콘텐츠를 위로 슬라이드합니다 */
animation: ...;
}
```
@@ -7567,13 +7567,13 @@ function VideoDetails({ id }) {
return (
}
>
- {/* Animate the content up */}
+ {/* 콘텐츠를 위로 애니메이션합니다 */}
@@ -7827,7 +7827,7 @@ export default function Page({ heading, children }) {
- {/* Custom classes based on transition type. */}
+ {/* 트랜지션 타입에 따라 커스텀 클래스를 적용합니다. */}
}
- {/* Opt-out of ViewTransition for the content. */}
- {/* Content can define it's own ViewTransition. */}
+ {/* 콘텐츠에 대해 ViewTransition을 사용하지 않습니다. */}
+ {/* 콘텐츠는 자체 ViewTransition을 정의할 수 있습니다. */}
{children}
@@ -7890,8 +7890,8 @@ import { PauseIcon, PlayIcon } from "./Icons";
import { startTransition } from "react";
export function Thumbnail({ video, children }) {
- // Add a name to animate with a shared element transition.
- // This uses the default animation, no additional css needed.
+ // 공유 요소 트랜지션으로 애니메이션되도록 name을 추가합니다.
+ // 기본 애니메이션을 사용하므로 추가 CSS가 필요하지 않습니다.
return (
{}, url: document.location.pathname});
function navigate(url) {
startTransition(() => {
- // Transition type for the cause "nav forward"
+ // 전환 원인이 "nav forward"인 경우의 트랜지션 타입
addTransitionType('nav-forward');
go(url);
});
}
function navigateBack(url) {
startTransition(() => {
- // Transition type for the cause "nav backward"
+ // 전환 원인이 "nav backward"인 경우의 트랜지션 타입
addTransitionType('nav-back');
go(url);
});
@@ -8065,13 +8065,13 @@ export function Router({ children }) {
useEffect(() => {
function handlePopState() {
- // This should not animate because restoration has to be synchronous.
- // Even though it's a transition.
+ // 복원은 동기적으로 이루어져야 하므로 애니메이션되면 안 됩니다.
+ // 트랜지션이더라도 마찬가지입니다.
startTransition(() => {
setRouterState({
url: document.location.pathname + document.location.search,
pendingNav() {
- // Noop. URL has already updated.
+ // 아무 작업도 하지 않습니다. URL은 이미 업데이트되었습니다.
},
});
});
@@ -8683,17 +8683,17 @@ ul {
```css src/animations.css
-/* Slide the fallback down */
+/* 폴백을 아래로 슬라이드합니다 */
::view-transition-old(.slide-down) {
animation: 150ms ease-out both fade-out, 150ms ease-out both slide-down;
}
-/* Slide the content up */
+/* 콘텐츠를 위로 슬라이드합니다 */
::view-transition-new(.slide-up) {
animation: 210ms ease-in 150ms both fade-in, 400ms ease-in both slide-up;
}
-/* Define the new keyframes */
+/* 새로운 키프레임을 정의합니다 */
@keyframes slide-up {
from {
transform: translateY(10px);
@@ -8712,34 +8712,34 @@ ul {
}
}
-/* Previously defined animations below */
+/* 이전에 정의된 애니메이션은 아래에 있습니다 */
-/* Animations for view transition classed added by transition type */
+/* 트랜지션 타입에 의해 추가된 View Transition 클래스용 애니메이션 */
::view-transition-old(.slide-forward) {
- /* when sliding forward, the "old" page should slide out to left. */
+ /* 앞으로 전환할 때 "old" 페이지는 왼쪽으로 슬라이드되어 나가야 합니다. */
animation: 150ms cubic-bezier(0.4, 0, 1, 1) both fade-out,
400ms cubic-bezier(0.4, 0, 0.2, 1) both slide-to-left;
}
::view-transition-new(.slide-forward) {
- /* when sliding forward, the "new" page should slide in from right. */
+ /* 앞으로 전환할 때 "new" 페이지는 오른쪽에서 슬라이드되어 들어와야 합니다. */
animation: 210ms cubic-bezier(0, 0, 0.2, 1) 150ms both fade-in,
400ms cubic-bezier(0.4, 0, 0.2, 1) both slide-from-right;
}
::view-transition-old(.slide-back) {
- /* when sliding back, the "old" page should slide out to right. */
+ /* 뒤로 전환할 때 "old" 페이지는 오른쪽으로 슬라이드되어 나가야 합니다. */
animation: 150ms cubic-bezier(0.4, 0, 1, 1) both fade-out,
400ms cubic-bezier(0.4, 0, 0.2, 1) both slide-to-right;
}
::view-transition-new(.slide-back) {
- /* when sliding back, the "new" page should slide in from left. */
+ /* 뒤로 전환할 때 "new" 페이지는 왼쪽에서 슬라이드되어 들어와야 합니다. */
animation: 210ms cubic-bezier(0, 0, 0.2, 1) 150ms both fade-in,
400ms cubic-bezier(0.4, 0, 0.2, 1) both slide-from-left;
}
-/* Keyframes to support our animations above. */
+/* 위 애니메이션을 지원하기 위한 키프레임 */
@keyframes fade-in {
from {
opacity: 0;
@@ -8883,17 +8883,17 @@ import Layout from "./Layout";
import { ChevronLeft } from "./Icons";
function VideoDetails({id}) {
- // Animate from Suspense fallback to content
+ // 페이지 간 교차 페이드 애니메이션을 적용합니다.
return (
}
>
- {/* Animate the content up */}
+ {/* 콘텐츠를 위로 애니메이션합니다 */}
@@ -8953,14 +8953,14 @@ function VideoInfo({ id }) {
import { useId, useState, use, useDeferredValue, ViewTransition } from "react";import { Video } from "./Videos";import Layout from "./Layout";import { fetchVideos } from "./data";import { IconSearch } from "./Icons";
function SearchList({searchText, videos}) {
- // Activate with useDeferredValue ("when")
+ // useDeferredValue로 활성화합니다("언제")
const deferredSearchText = useDeferredValue(searchText);
const filteredVideos = filterVideos(videos, deferredSearchText);
return (
{filteredVideos.map((video) => (
- // Animate each item in list ("what")
+ // 리스트의 각 항목을 애니메이션합니다("무엇")
@@ -9154,7 +9154,7 @@ export default function Page({ heading, children }) {
- {/* Custom classes based on transition type. */}
+ {/* 트랜지션 타입에 따라 커스텀 클래스를 적용합니다. */}
}
- {/* Opt-out of ViewTransition for the content. */}
- {/* Content can define it's own ViewTransition. */}
+ {/* 콘텐츠에 대해 ViewTransition을 사용하지 않습니다. */}
+ {/* 콘텐츠는 자체 ViewTransition을 정의할 수 있습니다. */}
{children}
@@ -9217,8 +9217,8 @@ import { PauseIcon, PlayIcon } from "./Icons";
import { startTransition } from "react";
export function Thumbnail({ video, children }) {
- // Add a name to animate with a shared element transition.
- // This uses the default animation, no additional css needed.
+ // 공유 요소 트랜지션으로 애니메이션되도록 name을 추가합니다.
+ // 기본 애니메이션을 사용하므로 추가 CSS가 필요하지 않습니다.
return (
{}, url: document.location.pathname});
function navigate(url) {
startTransition(() => {
- // Transition type for the cause "nav forward"
+ // 전환 원인이 "nav forward"인 경우의 트랜지션 타입
addTransitionType('nav-forward');
go(url);
});
}
function navigateBack(url) {
startTransition(() => {
- // Transition type for the cause "nav backward"
+ // 전환 원인이 "nav backward"인 경우의 트랜지션 타입
addTransitionType('nav-back');
go(url);
});
@@ -9392,13 +9392,13 @@ export function Router({ children }) {
useEffect(() => {
function handlePopState() {
- // This should not animate because restoration has to be synchronous.
- // Even though it's a transition.
+ // 복원은 동기적으로 이루어져야 하므로 애니메이션되면 안 됩니다.
+ // 트랜지션이더라도 마찬가지입니다.
startTransition(() => {
setRouterState({
url: document.location.pathname + document.location.search,
pendingNav() {
- // Noop. URL has already updated.
+ // 아무 작업도 하지 않습니다. URL은 이미 업데이트되었습니다.
},
});
});
@@ -10010,7 +10010,7 @@ ul {
```css src/animations.css
-/* No additional animations needed */
+/* 추가 애니메이션은 필요하지 않습니다 */
@@ -10020,7 +10020,7 @@ ul {
-/* Previously defined animations below */
+/* 이전에 정의된 애니메이션은 아래에 있습니다 */
@@ -10036,32 +10036,32 @@ ul {
animation: 210ms ease-in 150ms both fade-in, 400ms ease-in both slide-up;
}
-/* Animations for view transition classed added by transition type */
+/* 트랜지션 타입에 의해 추가된 View Transition 클래스용 애니메이션 */
::view-transition-old(.slide-forward) {
- /* when sliding forward, the "old" page should slide out to left. */
+ /* 앞으로 전환할 때 "old" 페이지는 왼쪽으로 슬라이드되어 나가야 합니다. */
animation: 150ms cubic-bezier(0.4, 0, 1, 1) both fade-out,
400ms cubic-bezier(0.4, 0, 0.2, 1) both slide-to-left;
}
::view-transition-new(.slide-forward) {
- /* when sliding forward, the "new" page should slide in from right. */
+ /* 앞으로 전환할 때 "new" 페이지는 오른쪽에서 슬라이드되어 들어와야 합니다. */
animation: 210ms cubic-bezier(0, 0, 0.2, 1) 150ms both fade-in,
400ms cubic-bezier(0.4, 0, 0.2, 1) both slide-from-right;
}
::view-transition-old(.slide-back) {
- /* when sliding back, the "old" page should slide out to right. */
+ /* 뒤로 전환할 때 "old" 페이지는 오른쪽으로 슬라이드되어 나가야 합니다. */
animation: 150ms cubic-bezier(0.4, 0, 1, 1) both fade-out,
400ms cubic-bezier(0.4, 0, 0.2, 1) both slide-to-right;
}
::view-transition-new(.slide-back) {
- /* when sliding back, the "new" page should slide in from left. */
+ /* 뒤로 전환할 때 "new" 페이지는 왼쪽에서 슬라이드되어 들어와야 합니다. */
animation: 210ms cubic-bezier(0, 0, 0.2, 1) 150ms both fade-in,
400ms cubic-bezier(0.4, 0, 0.2, 1) both slide-from-left;
}
-/* Keyframes to support our animations above. */
+/* 위 애니메이션을 지원하기 위한 키프레임 */
@keyframes slide-up {
from {
transform: translateY(10px);
@@ -10186,7 +10186,7 @@ import {ViewTransition} from 'react'; import Details from './Details'; import Ho
export default function App() {
const {url} = useRouter();
- // Animate with a cross fade between pages.
+ // 페이지 간을 크로스페이드로 애니메이션합니다.
return (
{url === '/' ? : }
@@ -10199,17 +10199,17 @@ export default function App() {
import { use, Suspense, ViewTransition } from "react"; import { fetchVideo, fetchVideoDetails } from "./data"; import { Thumbnail, VideoControls } from "./Videos"; import { useRouter } from "./router"; import Layout from "./Layout"; import { ChevronLeft } from "./Icons";
function VideoDetails({id}) {
- // Animate from Suspense fallback to content
+ // Suspense 폴백에서 콘텐츠로 전환되는 애니메이션
return (
}
>
- {/* Animate the content up */}
+ {/* 콘텐츠를 위로 애니메이션합니다 */}
@@ -10269,14 +10269,14 @@ function VideoInfo({ id }) {
import { useId, useState, use, useDeferredValue, ViewTransition } from "react";import { Video } from "./Videos";import Layout from "./Layout";import { fetchVideos } from "./data";import { IconSearch } from "./Icons";
function SearchList({searchText, videos}) {
- // Activate with useDeferredValue ("when")
+ // useDeferredValue로 활성화합니다("언제")
const deferredSearchText = useDeferredValue(searchText);
const filteredVideos = filterVideos(videos, deferredSearchText);
return (
{filteredVideos.map((video) => (
- // Animate each item in list ("what")
+ // 리스트의 각 항목을 애니메이션합니다("무엇")
@@ -10469,7 +10469,7 @@ export default function Page({ heading, children }) {
- {/* Custom classes based on transition type. */}
+ {/* 트랜지션 타입에 따라 커스텀 클래스를 적용합니다. */}
}
- {/* Opt-out of ViewTransition for the content. */}
- {/* Content can define it's own ViewTransition. */}
+ {/* 콘텐츠에 대해 ViewTransition을 사용하지 않습니다. */}
+ {/* 콘텐츠는 자체 ViewTransition을 정의할 수 있습니다. */}
{children}
@@ -10528,7 +10528,7 @@ export default function LikeButton({video}) {
import { useState, ViewTransition } from "react"; import LikeButton from "./LikeButton"; import { useRouter } from "./router"; import { PauseIcon, PlayIcon } from "./Icons"; import { startTransition } from "react";
export function Thumbnail({ video, children }) {
- // Add a name to animate with a shared element transition.
+ // 공유 요소 트랜지션으로 애니메이션되도록 name을 추가합니다.
return (
{
- // Transition type for the cause "nav forward"
+ // 전환 원인이 "nav forward"인 경우의 트랜지션 타입
addTransitionType('nav-forward');
go(url);
});
}
function navigateBack(url) {
startTransition(() => {
- // Transition type for the cause "nav backward"
+ // 전환 원인이 "nav backward"인 경우의 트랜지션 타입
addTransitionType('nav-back');
go(url);
});
@@ -10705,13 +10705,13 @@ export function Router({ children }) {
useEffect(() => {
function handlePopState() {
- // This should not animate because restoration has to be synchronous.
- // Even though it's a transition.
+ // 복원은 동기적으로 이루어져야 하므로 애니메이션되면 안 됩니다.
+ // 트랜지션이더라도 마찬가지입니다.
startTransition(() => {
setRouterState({
url: document.location.pathname + document.location.search,
pendingNav() {
- // Noop. URL has already updated.
+ // 아무 작업도 하지 않습니다. URL은 이미 업데이트되었습니다.
},
});
});
@@ -11323,7 +11323,7 @@ ul {
```css src/animations.css
-/* Slide animations for Suspense the fallback down */
+/* Suspense 폴백을 아래로 슬라이드하는 애니메이션 */
::view-transition-old(.slide-down) {
animation: 150ms ease-out both fade-out, 150ms ease-out both slide-down;
}
@@ -11332,32 +11332,32 @@ ul {
animation: 210ms ease-in 150ms both fade-in, 400ms ease-in both slide-up;
}
-/* Animations for view transition classed added by transition type */
+/* 트랜지션 타입에 의해 추가된 View Transition 클래스용 애니메이션 */
::view-transition-old(.slide-forward) {
- /* when sliding forward, the "old" page should slide out to left. */
+ /* 앞으로 전환할 때 "old" 페이지는 왼쪽으로 슬라이드되어 나가야 합니다. */
animation: 150ms cubic-bezier(0.4, 0, 1, 1) both fade-out,
400ms cubic-bezier(0.4, 0, 0.2, 1) both slide-to-left;
}
::view-transition-new(.slide-forward) {
- /* when sliding forward, the "new" page should slide in from right. */
+ /* 앞으로 전환할 때 "new" 페이지는 오른쪽에서 슬라이드되어 들어와야 합니다. */
animation: 210ms cubic-bezier(0, 0, 0.2, 1) 150ms both fade-in,
400ms cubic-bezier(0.4, 0, 0.2, 1) both slide-from-right;
}
::view-transition-old(.slide-back) {
- /* when sliding back, the "old" page should slide out to right. */
+ /* 뒤로 전환할 때 "old" 페이지는 오른쪽으로 슬라이드되어 나가야 합니다. */
animation: 150ms cubic-bezier(0.4, 0, 1, 1) both fade-out,
400ms cubic-bezier(0.4, 0, 0.2, 1) both slide-to-right;
}
::view-transition-new(.slide-back) {
- /* when sliding back, the "new" page should slide in from left. */
+ /* 뒤로 전환할 때 "new" 페이지는 왼쪽에서 슬라이드되어 들어와야 합니다. */
animation: 210ms cubic-bezier(0, 0, 0.2, 1) 150ms both fade-in,
400ms cubic-bezier(0.4, 0, 0.2, 1) both slide-from-left;
}
-/* Keyframes to support our animations above. */
+/* 위 애니메이션을 지원하기 위한 키프레임 */
@keyframes slide-up {
from {
transform: translateY(10px);
@@ -11466,13 +11466,13 @@ _View Transition을 구축한 배경에 대한 자세한 내용은 다음을 참
-**`` is now available in React’s Canary channel.**
+**``는 이제 React의 Canary 채널에서 사용할 수 있습니다.**
-[Learn more about React’s release channels here.](/community/versioning-policy#all-release-channels)
+[React의 릴리스 채널에 대해 더 알아보기](/community/versioning-policy#all-release-channels).
-In [past](/blog/2022/06/15/react-labs-what-we-have-been-working-on-june-2022#offscreen) [updates](/blog/2024/02/15/react-labs-what-we-have-been-working-on-february-2024#offscreen-renamed-to-activity), we shared that we were researching an API to allow components to be visually hidden and deprioritized, preserving UI state with reduced performance costs relative to unmounting or hiding with CSS.
+[이전](/blog/2022/06/15/react-labs-what-we-have-been-working-on-june-2022#offscreen) [업데이트](/blog/2024/02/15/react-labs-what-we-have-been-working-on-february-2024#offscreen-renamed-to-activity)에서, 컴포넌트를 시각적으로 숨기고 우선순위를 낮출 수 있도록 하는 API를 연구하고 있다고 공유했습니다. 이 API는 컴포넌트를 마운트 해제하거나 CSS로 숨기는 방식에 비해 더 낮은 성능 비용으로 UI 상태를 유지하는 것을 목표로 합니다.
이제 API와 그 작동 방식을 공유할 준비가 되었고, 실험적인 React 버전에서 테스트를 시작할 수 있습니다.
@@ -11549,9 +11549,9 @@ export default function App() {
const { url } = useRouter();
return (
- // View Transitions know about Activity
+ // View Transitions는 Activity를 인식합니다
- {/* Render Home in Activity so we don't lose state */}
+ {/* 상태를 잃지 않도록 Home을 Activity로 렌더링합니다 */}
@@ -11574,13 +11574,13 @@ function VideoDetails({id}) {
return (
}
>
- {/* Animate the content up */}
+ {/* 콘텐츠를 위로 애니메이션합니다 */}
@@ -11640,7 +11640,7 @@ function VideoInfo({ id }) {
import { useId, useState, use, useDeferredValue, ViewTransition } from "react";import { Video } from "./Videos";import Layout from "./Layout";import { fetchVideos } from "./data";import { IconSearch } from "./Icons";
function SearchList({searchText, videos}) {
- // Activate with useDeferredValue ("when")
+ // useDeferredValue로 활성화합니다("언제")
const deferredSearchText = useDeferredValue(searchText);
const filteredVideos = filterVideos(videos, deferredSearchText);
return (
@@ -11650,7 +11650,7 @@ function SearchList({searchText, videos}) {
)}
{filteredVideos.map((video) => (
- // Animate each item in list ("what")
+ // 리스트의 각 항목을 애니메이션합니다("무엇")
@@ -11840,7 +11840,7 @@ export default function Page({ heading, children }) {
- {/* Custom classes based on transition type. */}
+ {/* 트랜지션 타입에 따라 커스텀 클래스를 적용합니다. */}
}
- {/* Opt-out of ViewTransition for the content. */}
- {/* Content can define it's own ViewTransition. */}
+ {/* 콘텐츠에 대해 ViewTransition을 사용하지 않습니다. */}
+ {/* 콘텐츠는 자체 ViewTransition을 정의할 수 있습니다. */}
{children}
@@ -11903,8 +11903,8 @@ import { PauseIcon, PlayIcon } from "./Icons";
import { startTransition } from "react";
export function Thumbnail({ video, children }) {
- // Add a name to animate with a shared element transition.
- // This uses the default animation, no additional css needed.
+ // 공유 요소 트랜지션으로 애니메이션되도록 name을 추가합니다.
+ // 기본 애니메이션을 사용하므로 추가 CSS가 필요하지 않습니다.
return (
{}, url: document.location.pathname});
function navigate(url) {
startTransition(() => {
- // Transition type for the cause "nav forward"
+ // 전환 원인이 "nav forward"인 경우의 트랜지션 타입
addTransitionType('nav-forward');
go(url);
});
}
function navigateBack(url) {
startTransition(() => {
- // Transition type for the cause "nav backward"
+ // 전환 원인이 "nav backward"인 경우의 트랜지션 타입
addTransitionType('nav-back');
go(url);
});
@@ -12078,13 +12078,13 @@ export function Router({ children }) {
useEffect(() => {
function handlePopState() {
- // This should not animate because restoration has to be synchronous.
- // Even though it's a transition.
+ // 복원은 동기적으로 이루어져야 하므로 애니메이션되면 안 됩니다.
+ // 트랜지션이더라도 마찬가지입니다.
startTransition(() => {
setRouterState({
url: document.location.pathname + document.location.search,
pendingNav() {
- // Noop. URL has already updated.
+ // 아무 작업도 하지 않습니다. URL은 이미 업데이트되었습니다.
},
});
});
@@ -12696,7 +12696,7 @@ ul {
```css src/animations.css
-/* No additional animations needed */
+/* 추가 애니메이션은 필요하지 않습니다 */
@@ -12706,14 +12706,14 @@ ul {
-/* Previously defined animations below */
+/* 이전에 정의된 애니메이션은 아래에 있습니다 */
-/* Slide animations for Suspense the fallback down */
+/* Suspense 폴백을 아래로 슬라이드하는 애니메이션 */
::view-transition-old(.slide-down) {
animation: 150ms ease-out both fade-out, 150ms ease-out both slide-down;
}
@@ -12722,32 +12722,32 @@ ul {
animation: 210ms ease-in 150ms both fade-in, 400ms ease-in both slide-up;
}
-/* Animations for view transition classed added by transition type */
+/* 트랜지션 타입에 의해 추가된 View Transition 클래스용 애니메이션 */
::view-transition-old(.slide-forward) {
- /* when sliding forward, the "old" page should slide out to left. */
+ /* 앞으로 전환할 때 "old" 페이지는 왼쪽으로 슬라이드되어 나가야 합니다. */
animation: 150ms cubic-bezier(0.4, 0, 1, 1) both fade-out,
400ms cubic-bezier(0.4, 0, 0.2, 1) both slide-to-left;
}
::view-transition-new(.slide-forward) {
- /* when sliding forward, the "new" page should slide in from right. */
+ /* 앞으로 전환할 때 "new" 페이지는 오른쪽에서 슬라이드되어 들어와야 합니다. */
animation: 210ms cubic-bezier(0, 0, 0.2, 1) 150ms both fade-in,
400ms cubic-bezier(0.4, 0, 0.2, 1) both slide-from-right;
}
::view-transition-old(.slide-back) {
- /* when sliding back, the "old" page should slide out to right. */
+ /* 뒤로 전환할 때 "old" 페이지는 오른쪽으로 슬라이드되어 나가야 합니다. */
animation: 150ms cubic-bezier(0.4, 0, 1, 1) both fade-out,
400ms cubic-bezier(0.4, 0, 0.2, 1) both slide-to-right;
}
::view-transition-new(.slide-back) {
- /* when sliding back, the "new" page should slide in from left. */
+ /* 뒤로 전환할 때 "new" 페이지는 왼쪽에서 슬라이드되어 들어와야 합니다. */
animation: 210ms cubic-bezier(0, 0, 0.2, 1) 150ms both fade-in,
400ms cubic-bezier(0.4, 0, 0.2, 1) both slide-from-left;
}
-/* Keyframes to support our animations above. */
+/* 위 애니메이션을 지원하기 위한 키프레임 */
@keyframes slide-up {
from {
transform: translateY(10px);
@@ -12889,7 +12889,7 @@ export default function App() {
return (
- {/* Render videos in Activity to pre-render them */}
+ {/* 미리 렌더링하기 위해 Activity로 비디오를 렌더링합니다 */}
{videos.map(({id}) => (
@@ -12907,19 +12907,19 @@ export default function App() {
import { use, Suspense, ViewTransition } from "react"; import { fetchVideo, fetchVideoDetails } from "./data"; import { Thumbnail, VideoControls } from "./Videos"; import { useRouter } from "./router"; import Layout from "./Layout"; import { ChevronLeft } from "./Icons";
function VideoDetails({id}) {
- // Animate from Suspense fallback to content.
- // If this is pre-rendered then the fallback
- // won't need to show.
+ // Suspense 폴백에서 콘텐츠로 애니메이션합니다.
+ // 미리 렌더링되어 있다면 폴백을 표시할 필요가 없습니다.
+
return (
}
>
- {/* Animate the content up */}
+ {/* 콘텐츠를 위로 애니메이션합니다 */}
@@ -12978,7 +12978,7 @@ function VideoInfo({ id }) {
import { useId, useState, use, useDeferredValue, ViewTransition } from "react";import { Video } from "./Videos";import Layout from "./Layout";import { fetchVideos } from "./data";import { IconSearch } from "./Icons";
function SearchList({searchText, videos}) {
- // Activate with useDeferredValue ("when")
+ // useDeferredValue로 활성화합니다("언제")
const deferredSearchText = useDeferredValue(searchText);
const filteredVideos = filterVideos(videos, deferredSearchText);
return (
@@ -12988,7 +12988,7 @@ function SearchList({searchText, videos}) {
)}
{filteredVideos.map((video) => (
- // Animate each item in list ("what")
+ // 리스트의 각 항목을 애니메이션합니다("무엇")
@@ -13178,7 +13178,7 @@ export default function Page({ heading, children }) {
- {/* Custom classes based on transition type. */}
+ {/* 트랜지션 타입에 따라 커스텀 클래스를 적용합니다. */}
}
- {/* Opt-out of ViewTransition for the content. */}
- {/* Content can define it's own ViewTransition. */}
+ {/* 콘텐츠에 대해 ViewTransition을 사용하지 않습니다. */}
+ {/* 콘텐츠는 자체 ViewTransition을 정의할 수 있습니다. */}
{children}
@@ -13241,8 +13241,8 @@ import { PauseIcon, PlayIcon } from "./Icons";
import { startTransition } from "react";
export function Thumbnail({ video, children }) {
- // Add a name to animate with a shared element transition.
- // This uses the default animation, no additional css needed.
+ // 공유 요소 트랜지션으로 애니메이션되도록 name을 추가합니다.
+ // 기본 애니메이션을 사용하므로 추가 CSS가 필요하지 않습니다.
return (
{}, url: document.location.pathname});
function navigate(url) {
startTransition(() => {
- // Transition type for the cause "nav forward"
+ // 전환 원인이 "nav forward"인 경우의 트랜지션 타입
addTransitionType('nav-forward');
go(url);
});
}
function navigateBack(url) {
startTransition(() => {
- // Transition type for the cause "nav backward"
+ // 전환 원인이 "nav backward"인 경우의 트랜지션 타입
addTransitionType('nav-back');
go(url);
});
@@ -13416,13 +13416,13 @@ export function Router({ children }) {
useEffect(() => {
function handlePopState() {
- // This should not animate because restoration has to be synchronous.
- // Even though it's a transition.
+ // 복원은 동기적으로 이루어져야 하므로 애니메이션되면 안 됩니다.
+ // 트랜지션이더라도 마찬가지입니다.
startTransition(() => {
setRouterState({
url: document.location.pathname + document.location.search,
pendingNav() {
- // Noop. URL has already updated.
+ // 아무 작업도 하지 않습니다. URL은 이미 업데이트되었습니다.
},
});
});
@@ -14034,7 +14034,7 @@ ul {
```css src/animations.css
-/* No additional animations needed */
+/* 추가 애니메이션은 필요하지 않습니다 */
@@ -14044,14 +14044,14 @@ ul {
-/* Previously defined animations below */
+/* 이전에 정의된 애니메이션은 아래에 있습니다 */
-/* Slide animations for Suspense the fallback down */
+/* Suspense 폴백을 아래로 슬라이드하는 애니메이션 */
::view-transition-old(.slide-down) {
animation: 150ms ease-out both fade-out, 150ms ease-out both slide-down;
}
@@ -14060,32 +14060,32 @@ ul {
animation: 210ms ease-in 150ms both fade-in, 400ms ease-in both slide-up;
}
-/* Animations for view transition classed added by transition type */
+/* 트랜지션 타입에 의해 추가된 View Transition 클래스용 애니메이션 */
::view-transition-old(.slide-forward) {
- /* when sliding forward, the "old" page should slide out to left. */
+ /* 앞으로 전환할 때 "old" 페이지는 왼쪽으로 슬라이드되어 나가야 합니다. */
animation: 150ms cubic-bezier(0.4, 0, 1, 1) both fade-out,
400ms cubic-bezier(0.4, 0, 0.2, 1) both slide-to-left;
}
::view-transition-new(.slide-forward) {
- /* when sliding forward, the "new" page should slide in from right. */
+ /* 앞으로 전환할 때 "new" 페이지는 오른쪽에서 슬라이드되어 들어와야 합니다. */
animation: 210ms cubic-bezier(0, 0, 0.2, 1) 150ms both fade-in,
400ms cubic-bezier(0.4, 0, 0.2, 1) both slide-from-right;
}
::view-transition-old(.slide-back) {
- /* when sliding back, the "old" page should slide out to right. */
+ /* 뒤로 전환할 때 "old" 페이지는 오른쪽으로 슬라이드되어 나가야 합니다. */
animation: 150ms cubic-bezier(0.4, 0, 1, 1) both fade-out,
400ms cubic-bezier(0.4, 0, 0.2, 1) both slide-to-right;
}
::view-transition-new(.slide-back) {
- /* when sliding back, the "new" page should slide in from left. */
+ /* 뒤로 전환할 때 "new" 페이지는 왼쪽에서 슬라이드되어 들어와야 합니다. */
animation: 210ms cubic-bezier(0, 0, 0.2, 1) 150ms both fade-in,
400ms cubic-bezier(0.4, 0, 0.2, 1) both slide-from-left;
}
-/* Keyframes to support our animations above. */
+/* 위 애니메이션을 지원하기 위한 키프레임 */
@keyframes slide-up {
from {
transform: translateY(10px);
@@ -14219,13 +14219,13 @@ Activity에서 고려 중인 또 다른 모드는 메모리가 너무 많이 사
# 개발 중인 기능 {/*features-in-development*/}
-We're also developing features to help solve the common problems below.
+또한 아래와 같은 일반적인 문제를 해결하기 위한 기능들도 개발 중입니다.
-As we iterate on possible solutions, you may see some potential APIs we're testing being shared based on the PRs we are landing. Please keep in mind that as we try different ideas, we often change or remove different solutions after trying them out.
+가능한 해결책을 반복적으로 검토하는 과정에서, 현재 병합 중인 PR을 통해 실험 중인 잠재적 API가 일부 공유될 수 있습니다. 다양한 아이디어를 시도하는 과정에서, 실험 결과에 따라 일부 해결책은 변경되거나 제거되기도 합니다.
-When the solutions we're working on are shared too early, it can create churn and confusion in the community. To balance being transparent and limiting confusion, we're sharing the problems we're currently developing solutions for, without sharing a particular solution we have in mind.
+아직 충분히 검증되지 않은 해결책이 너무 이르게 공유되면, 커뮤니티에 혼란과 불필요한 변동을 초래할 수 있습니다. 투명성과 혼란 최소화 사이의 균형을 위해, 현재는 구체적인 해결책을 공개하지 않고 우리가 해결하려는 문제 자체만 공유하고 있습니다.
-As these features progress, we'll announce them on the blog with docs included so you can try them out.
+이 기능들이 더 진전되면, 문서와 함께 블로그를 통해 공개하여 직접 사용해 볼 수 있도록 안내할 예정입니다.
## React Performance Tracks {/*react-performance-tracks*/}
@@ -14258,7 +14258,7 @@ hooks를 출시했을 때, 저희는 세 가지 동기가 있었습니다:
- **생명주기가 아닌 함수의 관점에서 사고**: hooks는 생명주기 메서드를 기반으로 한 분할을 강제하는 것이 아니라 관련된 부분(구독 설정이나 데이터 가져오기 등)을 기반으로 하나의 컴포넌트를 더 작은 함수로 분할할 수 있게 해주었습니다.
- **사전 컴파일 지원**: hooks는 생명주기 메서드로 인한 의도하지 않은 최적화 해제 문제와 클래스의 제약사항을 줄이면서 사전 컴파일을 지원하도록 설계되었습니다.
-Since their release, hooks have been successful at *sharing code between components*. Hooks are now the favored way to share logic between components, and there are less use cases for render props and higher order components. Hooks have also been successful at supporting features like Fast Refresh that were not possible with class components.
+출시 이후 hooks는 *컴포넌트 간 코드 공유* 측면에서 성공을 거두었습니다. 현재 hooks는 컴포넌트 간 로직을 공유하는 데 선호되는 방식이며, 렌더링 props와 고차 컴포넌트를 사용할 필요가 있는 경우도 줄어들었습니다. 또한 hooks는 클래스 컴포넌트로는 가능하지 않았던 Fast Refresh와 같은 기능을 지원하는 데에도 성공했습니다.
### Effects는 어려울 수 있습니다 {/*effects-can-be-hard*/}
@@ -14272,11 +14272,11 @@ Since their release, hooks have been successful at *sharing code between compone
```js
useEffect(() => {
- // Your Effect connected to the room specified with roomId...
+ // roomId로 지정된 방에 연결된 effect...
const connection = createConnection(serverUrl, roomId);
connection.connect();
return () => {
- // ...until it disconnected
+ // ...연결이 끊어질 때까지
connection.disconnect();
};
}, [roomId]);
@@ -14290,7 +14290,7 @@ useEffect(() => {
Effects가 컴포넌트 관점에서 생각되는 이유를 연구하는 데 시간을 보냈고, 그 이유 중 하나가 의존성 배열이라고 생각합니다. 작성해야 하므로, 바로 거기에 있고 여러분이 무엇에 "반응"하고 있는지를 상기시키며 '이 값들이 변경될 때 이것을 하라'는 멘탈 모델로 유도합니다.
-hooks를 출시할 때, 사전 컴파일로 사용하기 더 쉽게 만들 수 있다는 것을 알고 있었습니다. React Compiler를 사용하면, 이제 대부분의 경우 `useCallback`과 `useMemo`를 직접 작성하는 것을 피할 수 있습니다. Effects의 경우, 컴파일러가 의존성을 자동으로 삽입할 수 있습니다:
+hooks를 출시할 때, 사전 컴파일로 사용하기 더 쉽게 만들 수 있다는 것을 알고 있었습니다. React 컴파일러를 사용하면, 이제 대부분의 경우 `useCallback`과 `useMemo`를 직접 작성하는 것을 피할 수 있습니다. Effects의 경우, 컴파일러가 의존성을 자동으로 삽입할 수 있습니다:
```js
useEffect(() => {
@@ -14299,20 +14299,20 @@ useEffect(() => {
return () => {
connection.disconnect();
};
-}); // compiler inserted dependencies.
+}); // 컴파일러가 삽입한 의존성
```
-With this code, the React Compiler can infer the dependencies for you and insert them automatically so you don't need to see or write them. With features like [the IDE extension](#compiler-ide-extension) and [`useEffectEvent`](/reference/react/useEffectEvent), we can provide a CodeLens to show you what the Compiler inserted for times you need to debug, or to optimize by removing a dependency. This helps reinforce the correct mental model for writing Effects, which can run at any time to synchronize your component or hook's state with something else.
+이 코드에서는 React 컴파일러가 의존성을 자동으로 추론해 삽입하므로, 개발자가 직접 보거나 작성할 필요가 없습니다. [IDE 확장](#compiler-ide-extension)이나 [`useEffectEvent`](/reference/react/useEffectEvent) 같은 기능을 사용하면, 디버깅이 필요하거나 의존성을 제거해 최적화해야 할 때 컴파일러가 무엇을 삽입했는지 보여주는 CodeLens를 제공할 수 있습니다. 이는 컴포넌트나 Hook의 상태를 다른 무언가와 동기화하기 위해 언제든 실행될 수 있는 Effect를 작성할 때, 올바른 사고 모델을 강화하는 데 도움이 됩니다.
-Our hope is that automatically inserting dependencies is not only easier to write, but that it also makes them easier to understand by forcing you to think in terms of what the Effect does, and not in component lifecycles.
+저희의 바람은 의존성을 자동으로 삽입하는 방식이 작성하기 쉬울 뿐만 아니라, 컴포넌트 생명주기가 아니라 Effect가 무엇을 하는지에 집중하도록 강제함으로써 이해하기도 더 쉬워지는 것입니다.
---
## Compiler IDE Extension {/*compiler-ide-extension*/}
-Later in 2025 [we shared](/blog/2025/10/07/react-compiler-1) the first stable release of React Compiler, and we're continuing to invest in shipping more improvements.
+2025년 말, 저희는 React 컴파일러의 첫 번째 안정화 릴리스를 [공유했으며](/blog/2025/10/07/react-compiler-1), 이후에도 더 많은 개선 사항을 제공하기 위해 지속적으로 투자하고 있습니다.
-또한 React Compiler를 사용해서 코드 이해와 디버깅을 향상시킬 수 있는 정보를 제공하는 방법을 탐구하기 시작했습니다. 저희가 탐구하기 시작한 아이디어 중 하나는 [Lauren Tan의 React Conf 발표](https://conf2024.react.dev/talks/5)에서 사용된 확장 프로그램과 유사한, React Compiler를 기반으로 하는 새로운 실험적 LSP 기반 React IDE 확장 프로그램입니다.
+또한 React 컴파일러를 사용해서 코드 이해와 디버깅을 향상시킬 수 있는 정보를 제공하는 방법을 탐구하기 시작했습니다. 저희가 탐구하기 시작한 아이디어 중 하나는 [Lauren Tan의 React Conf 발표](https://conf2024.react.dev/talks/5)에서 사용된 확장 프로그램과 유사한, React 컴파일러를 기반으로 하는 새로운 실험적 LSP 기반 React IDE 확장 프로그램입니다.
저희의 아이디어는 컴파일러의 정적 분석을 사용해서 IDE에서 직접 더 많은 정보, 제안, 최적화 기회를 제공할 수 있다는 것입니다. 예를 들어, React의 규칙을 위반하는 코드에 대한 진단을 제공하거나, 컴포넌트와 hooks가 컴파일러에 의해 최적화되었는지 보여주는 호버, 또는 [자동으로 삽입된 Effect 의존성](#automatic-effect-dependencies)을 볼 수 있는 CodeLens를 제공할 수 있습니다.
@@ -14332,34 +14332,34 @@ Fragment refs는 아직 연구 중입니다. 최종 API가 완성에 가까워
## Gesture Animations {/*gesture-animations*/}
-We're also researching ways to enhance View Transitions to support gesture animations such as swiping to open a menu, or scroll through a photo carousel.
+또한 메뉴를 스와이프로 열거나 사진 캐러셀을 스크롤하는 것과 같은 제스처 애니메이션을 지원하도록 View Transitions를 확장하는 방법도 연구하고 있습니다.
제스처는 몇 가지 이유로 새로운 도전을 제시합니다:
-- **Gestures are continuous**: as you swipe the animation is tied to your finger placement time, rather than triggering and running to completion.
-- **Gestures don't complete**: when you release your finger gesture animations can run to completion, or revert to their original state (like when you only partially open a menu) depending on how far you go.
-- **Gestures invert old and new**: while you're animating, you want the page you are animating from to stay "alive" and interactive. This inverts the browser View Transition model where the "old" state is a snapshot and the "new" state is the live DOM.
+- **제스처는 연속적입니다**: 스와이프하는 동안 애니메이션은 트리거되어 끝까지 실행되는 것이 아니라, 손가락 위치와 시간에 직접적으로 연결됩니다.
+- **제스처는 항상 완료되지 않습니다**: 손가락을 놓았을 때, 제스처 애니메이션은 끝까지 실행될 수도 있고, 이동한 거리와 정도에 따라(예: 메뉴를 부분적으로만 연 경우) 원래 상태로 되돌아갈 수도 있습니다.
+- **제스처는 old와 new를 뒤집습니다**: 애니메이션이 진행되는 동안에는 출발 지점이 되는 페이지가 계속 "살아 있는" 상태로 상호작용 가능해야 합니다. 이는 "old" 상태가 스냅샷이고 "new" 상태가 실제 DOM인 브라우저의 View Transition 모델과는 반대입니다.
-We believe we’ve found an approach that works well and may introduce a new API for triggering gesture transitions. For now, we're focused on shipping ``, and will revisit gestures afterward.
+저희는 잘 동작하는 접근 방식을 찾았다고 생각하며, 제스처 전환을 트리거하기 위한 새로운 API를 도입할 수도 있습니다. 다만 현재는 ``을 제공하는 데 집중하고 있으며, 제스처 지원은 그 이후에 다시 다룰 예정입니다.
---
## Concurrent Stores {/*concurrent-stores*/}
-When we released React 18 with concurrent rendering, we also released `useSyncExternalStore` so external store libraries that did not use React state or context could [support concurrent rendering](https://github.com/reactwg/react-18/discussions/70) by forcing a synchronous render when the store is updated.
+동시 렌더링을 포함한 React 18을 출시하면서, React 상태나 context를 사용하지 않는 외부 스토어 라이브러리도 스토어 업데이트 시 동기 렌더링을 강제함으로써 [동시 렌더링을 지원](https://github.com/reactwg/react-18/discussions/70)할 수 있도록 `useSyncExternalStore`를 함께 출시했습니다.
-Using `useSyncExternalStore` comes at a cost though, since it forces a bail out from concurrent features like transitions, and forces existing content to show Suspense fallbacks.
+다만 `useSyncExternalStore`를 사용하면 비용이 따릅니다. 트랜지션과 같은 동시성 기능에서 빠져나오게 되고, 기존 콘텐츠에 Suspense 폴백이 표시되도록 강제하기 때문입니다.
-Now that React 19 has shipped, we're revisiting this problem space to create a primitive to fully support concurrent external stores with the `use` API:
+이제 React 19가 출시됨에 따라, `use` API로 동시 외부 스토어를 완전히 지원하기 위한 기본 요소를 만들기 위해 이 문제 영역을 다시 살펴보고 있습니다:
```js
const value = use(store);
```
-Our goal is to allow external state to be read during render without tearing, and to work seamlessly with all of the concurrent features React offers.
+목표는 외부 상태를 렌더링 중에 찢김(tearing) 없이 읽을 수 있도록 하고, React가 제공하는 모든 동시성 기능과 자연스럽게 동작하게 하는 것입니다.
-This research is still early. We'll share more, and what the new APIs will look like, when we're further along.
+이 연구는 아직 초기 단계입니다. 더 진행되면 새로운 API의 형태와 함께 추가 내용을 공유하겠습니다.
---
-_Thanks to [Aurora Scharff](https://bsky.app/profile/aurorascharff.no), [Dan Abramov](https://bsky.app/profile/danabra.mov), [Eli White](https://twitter.com/Eli_White), [Lauren Tan](https://bsky.app/profile/no.lol), [Luna Wei](https://github.com/lunaleaps), [Matt Carroll](https://twitter.com/mattcarrollcode), [Jack Pope](https://jackpope.me), [Jason Bonta](https://threads.net/someextent), [Jordan Brown](https://github.com/jbrown215), [Jordan Eldredge](https://bsky.app/profile/capt.dev), [Mofei Zhang](https://threads.net/z_mofei), [Sebastien Lorber](https://bsky.app/profile/sebastienlorber.com), [Sebastian Markbåge](https://bsky.app/profile/sebmarkbage.calyptus.eu), and [Tim Yung](https://github.com/yungsters) for reviewing this post._
+_이 게시물을 검토해 준 [Aurora Scharff](https://bsky.app/profile/aurorascharff.no), [Dan Abramov](https://bsky.app/profile/danabra.mov), [Eli White](https://twitter.com/Eli_White), [Lauren Tan](https://bsky.app/profile/no.lol), [Luna Wei](https://github.com/lunaleaps), [Matt Carroll](https://twitter.com/mattcarrollcode), [Jack Pope](https://jackpope.me), [Jason Bonta](https://threads.net/someextent), [Jordan Brown](https://github.com/jbrown215), [Jordan Eldredge](https://bsky.app/profile/capt.dev), [Mofei Zhang](https://threads.net/z_mofei), [Sebastien Lorber](https://bsky.app/profile/sebastienlorber.com), [Sebastian Markbåge](https://bsky.app/profile/sebmarkbage.calyptus.eu), 및 [Tim Yung](https://github.com/yungsters)에게 감사드립니다._
diff --git a/src/content/blog/2025/10/07/react-compiler-1.md b/src/content/blog/2025/10/07/react-compiler-1.md
index 80017d2ac..202b9da22 100644
--- a/src/content/blog/2025/10/07/react-compiler-1.md
+++ b/src/content/blog/2025/10/07/react-compiler-1.md
@@ -69,17 +69,17 @@ _[React 컴파일러 Playground](https://playground.react.dev/#N4Igzg9grgTgxgUxA
npm
-{`npm install --save-dev --save-exact babel-plugin-react-compiler@latest`}
+npm install --save-dev --save-exact babel-plugin-react-compiler@latest
pnpm
-{`pnpm add --save-dev --save-exact babel-plugin-react-compiler@latest`}
+pnpm add --save-dev --save-exact babel-plugin-react-compiler@latest
yarn
-{`yarn add --dev --exact babel-plugin-react-compiler@latest`}
+yarn add --dev --exact babel-plugin-react-compiler@latest
안정 버전 출시의 일환으로, React 컴파일러를 프로젝트에 더 쉽게 추가할 수 있도록 하고 컴파일러가 메모이제이션을 생성하는 방식을 최적화했습니다. React 컴파일러는 이제 옵셔널 체이닝과 배열 인덱스를 의존성으로 지원합니다. 이러한 개선 사항은 궁극적으로 재렌더링을 줄이고 더 반응적인 UI를 만들면서도, 관용적인 선언적 코드를 계속 작성할 수 있게 해줍니다.
@@ -101,17 +101,17 @@ React 컴파일러에는 [React의 규칙](/reference/rules)을 위반하는 코
npm
-{`npm install --save-dev eslint-plugin-react-hooks@latest`}
+npm install --save-dev eslint-plugin-react-hooks@latest
pnpm
-{`pnpm add --save-dev eslint-plugin-react-hooks@latest`}
+pnpm add --save-dev eslint-plugin-react-hooks@latest
yarn
-{`yarn add --dev eslint-plugin-react-hooks@latest`}
+yarn add --dev eslint-plugin-react-hooks@latest
```js {6}
@@ -153,19 +153,19 @@ Expo, Vite, Next.js 팀과 협력하여 새로운 앱 경험에 컴파일러를
[Expo SDK 54](https://docs.expo.dev/guides/react-compiler/) 이상에서는 컴파일러가 기본적으로 활성화되어 있으므로, 새로운 앱은 처음부터 자동으로 컴파일러의 이점을 활용할 수 있습니다.
-{`npx create-expo-app@latest`}
+npx create-expo-app@latest
[Vite](https://vite.dev/guide/) 및 [Next.js](https://nextjs.org/docs/app/api-reference/cli/create-next-app) 사용자는 `create-vite` 및 `create-next-app`에서 컴파일러가 활성화된 템플릿을 선택할 수 있습니다.
-{`npm create vite@latest`}
+npm create vite@latest
-{`npx create-next-app@latest`}
+npx create-next-app@latest
## React 컴파일러 점진적으로 도입하기 {/*adopt-react-compiler-incrementally*/}
diff --git a/src/content/blog/2025/10/16/react-conf-2025-recap.md b/src/content/blog/2025/10/16/react-conf-2025-recap.md
index bb367f1e8..7475c15fd 100644
--- a/src/content/blog/2025/10/16/react-conf-2025-recap.md
+++ b/src/content/blog/2025/10/16/react-conf-2025-recap.md
@@ -41,11 +41,11 @@ Jack Pope는 Canary에 도입될 새로운 기능들을 발표했으며, 여기
* [``](https://react.dev/reference/react/ViewTransition) — 페이지 전환에 애니메이션을 적용하는 새로운 컴포넌트.
* [Fragment Refs](https://react.dev/reference/react/Fragment#fragmentinstance) — Fragment로 감싸진 DOM 노드와 상호작용하는 새로운 방식.
-Lauren Tan은 [React Compiler v1.0](/blog/2025/10/07/react-compiler-1)을 발표하고, 다음과 같은 이점 때문에 모든 앱에서 React Compiler를 사용할 것을 권장했습니다.
+Lauren Tan은 [React 컴파일러 v1.0](/blog/2025/10/07/react-compiler-1)을 발표하고, 다음과 같은 이점 때문에 모든 앱에서 React 컴파일러를 사용할 것을 권장했습니다.
* React 코드를 이해하는 [자동 메모이제이션](/learn/react-compiler/introduction#what-does-react-compiler-do).
-* 모범 사례를 알려주는 React Compiler 기반의 [새로운 린트 규칙](/learn/react-compiler/installation#eslint-integration).
+* 모범 사례를 알려주는 React 컴파일러 기반의 [새로운 린트 규칙](/learn/react-compiler/installation#eslint-integration).
* Vite, Next.js, Expo의 새로운 앱에 대한 [기본 지원](/learn/react-compiler/installation#basic-setup).
-* 기존 앱이 React Compiler로 마이그레이션하기 위한 [마이그레이션 가이드](/learn/react-compiler/incremental-adoption).
+* 기존 앱이 React 컴파일러로 마이그레이션하기 위한 [마이그레이션 가이드](/learn/react-compiler/incremental-adoption).
마지막으로, Seth Webster는 React의 오픈소스 개발과 커뮤니티를 관리할 [React Foundation](/blog/2025/10/07/introducing-the-react-foundation) 설립을 발표했습니다.
@@ -81,7 +81,7 @@ Ruben Norte와 Alex Hunt는 기조연설을 마무리하며 다음을 발표했
* [Profiling with React Performance tracks](https://www.youtube.com/watch?v=zyVRg2QR6LA&t=8276s) [(Ruslan Lesiutin)](https://x.com/ruslanlesiutin)은 새로운 React Performance Tracks를 사용하여 성능 문제를 디버깅하고 훌륭한 앱을 구축하는 방법을 보여주었습니다.
* [React Strict DOM](https://www.youtube.com/watch?v=p9OcztRyDl0&t=9026s) [(Nicolas Gallagher)](https://nicolasgallagher.com/)는 Meta의 웹 코드를 네이티브에서 사용하는 접근 방식에 대해 이야기했습니다.
* [View Transitions and Activity](https://www.youtube.com/watch?v=zyVRg2QR6LA&t=4870s) [(Chance Strickland)](https://x.com/chancethedev) — Chance는 React 팀과 협력하여 빠르고 네이티브 느낌의 애니메이션을 구축하기 위해 [``](https://react.dev/reference/react/Activity) 및 [``](https://react.dev/reference/react/ViewTransition)를 사용하는 방법을 시연했습니다.
-* [In case you missed the memo](https://www.youtube.com/watch?v=zyVRg2QR6LA&t=9525s) [(Cody Olsen)](https://bsky.app/profile/codey.bsky.social) - Cody는 Sanity Studio에서 Compiler를 채택하기 위해 React 팀과 협력했으며, 그 경험을 공유했습니다.
+* [In case you missed the memo](https://www.youtube.com/watch?v=zyVRg2QR6LA&t=9525s) [(Cody Olsen)](https://bsky.app/profile/codey.bsky.social) - Cody는 Sanity Studio에서 컴파일러를 채택하기 위해 React 팀과 협력했으며, 그 경험을 공유했습니다.
## React 프레임워크 발표 {/*react-framework-talks*/}
둘째 날 후반부에는 다음을 포함하여 React 프레임워크 팀의 연속 발표가 있었습니다.
diff --git a/src/content/blog/2025/12/03/critical-security-vulnerability-in-react-server-components.md b/src/content/blog/2025/12/03/critical-security-vulnerability-in-react-server-components.md
new file mode 100644
index 000000000..310a84116
--- /dev/null
+++ b/src/content/blog/2025/12/03/critical-security-vulnerability-in-react-server-components.md
@@ -0,0 +1,208 @@
+---
+title: "Critical Security Vulnerability in React Server Components"
+author: The React Team
+date: 2025/12/03
+description: There is an unauthenticated remote code execution vulnerability in React Server Components. A fix has been published in versions 19.0.1, 19.1.2, and 19.2.1. We recommend upgrading immediately.
+
+---
+
+December 3, 2025 by [The React Team](/community/team)
+
+---
+
+
+
+There is an unauthenticated remote code execution vulnerability in React Server Components.
+
+We recommend upgrading immediately.
+
+
+
+---
+
+On November 29th, Lachlan Davidson reported a security vulnerability in React that allows unauthenticated remote code execution by exploiting a flaw in how React decodes payloads sent to React Server Function endpoints.
+
+Even if your app does not implement any React Server Function endpoints it may still be vulnerable if your app supports React Server Components.
+
+This vulnerability was disclosed as [CVE-2025-55182](https://www.cve.org/CVERecord?id=CVE-2025-55182) and is rated CVSS 10.0.
+
+The vulnerability is present in versions 19.0, 19.1.0, 19.1.1, and 19.2.0 of:
+
+* [react-server-dom-webpack](https://www.npmjs.com/package/react-server-dom-webpack)
+* [react-server-dom-parcel](https://www.npmjs.com/package/react-server-dom-parcel)
+* [react-server-dom-turbopack](https://www.npmjs.com/package/react-server-dom-turbopack?activeTab=readme)
+
+## Immediate Action Required {/*immediate-action-required*/}
+
+A fix was introduced in versions [19.0.1](https://github.com/facebook/react/releases/tag/v19.0.1), [19.1.2](https://github.com/facebook/react/releases/tag/v19.1.2), and [19.2.1](https://github.com/facebook/react/releases/tag/v19.2.1). If you are using any of the above packages please upgrade to any of the fixed versions immediately.
+
+If your app’s React code does not use a server, your app is not affected by this vulnerability. If your app does not use a framework, bundler, or bundler plugin that supports React Server Components, your app is not affected by this vulnerability.
+
+### Affected frameworks and bundlers {/*affected-frameworks-and-bundlers*/}
+
+Some React frameworks and bundlers depended on, had peer dependencies for, or included the vulnerable React packages. The following React frameworks & bundlers are affected: [next](https://www.npmjs.com/package/next), [react-router](https://www.npmjs.com/package/react-router), [waku](https://www.npmjs.com/package/waku), [@parcel/rsc](https://www.npmjs.com/package/@parcel/rsc), [@vitejs/plugin-rsc](https://www.npmjs.com/package/@vitejs/plugin-rsc), and [rwsdk](https://www.npmjs.com/package/rwsdk).
+
+See the [update instructions below](#update-instructions) for how to upgrade to these patches.
+
+### Hosting Provider Mitigations {/*hosting-provider-mitigations*/}
+
+We have worked with a number of hosting providers to apply temporary mitigations.
+
+You should not depend on these to secure your app, and still update immediately.
+
+### Vulnerability overview {/*vulnerability-overview*/}
+
+[React Server Functions](https://react.dev/reference/rsc/server-functions) allow a client to call a function on a server. React provides integration points and tools that frameworks and bundlers use to help React code run on both the client and the server. React translates requests on the client into HTTP requests which are forwarded to a server. On the server, React translates the HTTP request into a function call and returns the needed data to the client.
+
+An unauthenticated attacker could craft a malicious HTTP request to any Server Function endpoint that, when deserialized by React, achieves remote code execution on the server. Further details of the vulnerability will be provided after the rollout of the fix is complete.
+
+## Update Instructions {/*update-instructions*/}
+
+
+
+These instructions have been updated to include the new vulnerabilities:
+
+- **Denial of Service - High Severity**: [CVE-2025-55184](https://www.cve.org/CVERecord?id=CVE-2025-55184) and [CVE-2025-67779](https://www.cve.org/CVERecord?id=CVE-2025-67779) (CVSS 7.5)
+- **Source Code Exposure - Medium Severity**: [CVE-2025-55183](https://www.cve.org/CVERecord?id=CVE-2025-55183) (CVSS 5.3)
+- **Denial of Service - High Severity**: January 26, 2026 [CVE-2026-23864](https://www.cve.org/CVERecord?id=CVE-2026-23864) (CVSS 7.5)
+
+See the [follow-up blog post](/blog/2025/12/11/denial-of-service-and-source-code-exposure-in-react-server-components) for more info.
+
+-----
+
+_Updated January 26, 2026._
+
+
+### Next.js {/*update-next-js*/}
+
+All users should upgrade to the latest patched version in their release line:
+
+```bash
+npm install next@14.2.35 // for 13.3.x, 13.4.x, 13.5.x, 14.x
+npm install next@15.0.8 // for 15.0.x
+npm install next@15.1.12 // for 15.1.x
+npm install next@15.2.9 // for 15.2.x
+npm install next@15.3.9 // for 15.3.x
+npm install next@15.4.11 // for 15.4.x
+npm install next@15.5.10 // for 15.5.x
+npm install next@16.0.11 // for 16.0.x
+npm install next@16.1.5 // for 16.1.x
+
+npm install next@15.6.0-canary.60 // for 15.x canary releases
+npm install next@16.1.0-canary.19 // for 16.x canary releases
+```
+
+15.0.8, 15.1.12, 15.2.9, 15.3.9, 15.4.10, 15.5.10, 15.6.0-canary.61, 16.0.11, 16.1.5
+
+If you are on version `13.3` or later version of Next.js 13 (`13.3.x`, `13.4.x`, or `13.5.x`) please upgrade to version `14.2.35`.
+
+If you are on `next@14.3.0-canary.77` or a later canary release, downgrade to the latest stable 14.x release:
+
+```bash
+npm install next@14
+```
+
+See the [Next.js blog](https://nextjs.org/blog/security-update-2025-12-11) for the latest update instructions and the [previous changelog](https://nextjs.org/blog/CVE-2025-66478) for more info.
+
+### React Router {/*update-react-router*/}
+
+If you are using React Router's unstable RSC APIs, you should upgrade the following package.json dependencies if they exist:
+
+```bash
+npm install react@latest
+npm install react-dom@latest
+npm install react-server-dom-parcel@latest
+npm install react-server-dom-webpack@latest
+npm install @vitejs/plugin-rsc@latest
+```
+
+### Expo {/*expo*/}
+
+To learn more about mitigating, read the article on [expo.dev/changelog](https://expo.dev/changelog/mitigating-critical-security-vulnerability-in-react-server-components).
+
+### Redwood SDK {/*update-redwood-sdk*/}
+
+Ensure you are on rwsdk>=1.0.0-alpha.0
+
+For the latest beta version:
+
+```bash
+npm install rwsdk@latest
+```
+
+Upgrade to the latest `react-server-dom-webpack`:
+
+```bash
+npm install react@latest react-dom@latest react-server-dom-webpack@latest
+```
+
+See [Redwood docs](https://docs.rwsdk.com/migrating/) for more migration instructions.
+
+### Waku {/*update-waku*/}
+
+Upgrade to the latest `react-server-dom-webpack`:
+
+```bash
+npm install react@latest react-dom@latest react-server-dom-webpack@latest waku@latest
+```
+
+See [Waku announcement](https://github.com/wakujs/waku/discussions/1823) for more migration instructions.
+
+### `@vitejs/plugin-rsc` {/*vitejs-plugin-rsc*/}
+
+Upgrade to the latest RSC plugin:
+
+```bash
+npm install react@latest react-dom@latest @vitejs/plugin-rsc@latest
+```
+
+### `react-server-dom-parcel` {/*update-react-server-dom-parcel*/}
+
+Update to the latest version:
+
+ ```bash
+ npm install react@latest react-dom@latest react-server-dom-parcel@latest
+ ```
+
+### `react-server-dom-turbopack` {/*update-react-server-dom-turbopack*/}
+
+Update to the latest version:
+
+ ```bash
+ npm install react@latest react-dom@latest react-server-dom-turbopack@latest
+ ```
+
+### `react-server-dom-webpack` {/*update-react-server-dom-webpack*/}
+
+Update to the latest version:
+
+ ```bash
+npm install react@latest react-dom@latest react-server-dom-webpack@latest
+ ```
+
+
+### React Native {/*react-native*/}
+
+For React Native users not using a monorepo or `react-dom`, your `react` version should be pinned in your `package.json`, and there are no additional steps needed.
+
+If you are using React Native in a monorepo, you should update _only_ the impacted packages if they are installed:
+
+- `react-server-dom-webpack`
+- `react-server-dom-parcel`
+- `react-server-dom-turbopack`
+
+This is required to mitigate the security advisory, but you do not need to update `react` and `react-dom` so this will not cause the version mismatch error in React Native.
+
+See [this issue](https://github.com/facebook/react-native/issues/54772#issuecomment-3617929832) for more information.
+
+
+## Timeline {/*timeline*/}
+
+* **November 29th**: Lachlan Davidson reported the security vulnerability via [Meta Bug Bounty](https://bugbounty.meta.com/).
+* **November 30th**: Meta security researchers confirmed and began working with the React team on a fix.
+* **December 1st**: A fix was created and the React team began working with affected hosting providers and open source projects to validate the fix, implement mitigations and roll out the fix
+* **December 3rd**: The fix was published to npm and the publicly disclosed as CVE-2025-55182.
+
+## Attribution {/*attribution*/}
+
+Thank you to [Lachlan Davidson](https://github.com/lachlan2k) for discovering, reporting, and working to help fix this vulnerability.
diff --git a/src/content/blog/2025/12/11/denial-of-service-and-source-code-exposure-in-react-server-components.md b/src/content/blog/2025/12/11/denial-of-service-and-source-code-exposure-in-react-server-components.md
new file mode 100644
index 000000000..6bdd93a47
--- /dev/null
+++ b/src/content/blog/2025/12/11/denial-of-service-and-source-code-exposure-in-react-server-components.md
@@ -0,0 +1,202 @@
+---
+title: "Denial of Service and Source Code Exposure in React Server Components"
+author: The React Team
+date: 2025/12/11
+description: Security researchers have found and disclosed two additional vulnerabilities in React Server Components while attempting to exploit the patches in last week’s critical vulnerability. High vulnerability Denial of Service (CVE-2025-55184), and medium vulnerability Source Code Exposure (CVE-2025-55183)
+
+
+---
+
+December 11, 2025 by [The React Team](/community/team)
+
+_Updated January 26, 2026._
+
+---
+
+
+
+Security researchers have found and disclosed two additional vulnerabilities in React Server Components while attempting to exploit the patches in last week’s critical vulnerability.
+
+**These new vulnerabilities do not allow for Remote Code Execution.** The patch for React2Shell remains effective at mitigating the Remote Code Execution exploit.
+
+
+
+---
+
+The new vulnerabilities are disclosed as:
+
+- **Denial of Service - High Severity**: [CVE-2025-55184](https://www.cve.org/CVERecord?id=CVE-2025-55184), [CVE-2025-67779](https://www.cve.org/CVERecord?id=CVE-2025-67779), and [CVE-2026-23864](https://www.cve.org/CVERecord?id=CVE-2026-23864) (CVSS 7.5)
+- **Source Code Exposure - Medium Severity**: [CVE-2025-55183](https://www.cve.org/CVERecord?id=CVE-2025-55183) (CVSS 5.3)
+
+We recommend upgrading immediately due to the severity of the newly disclosed vulnerabilities.
+
+
+
+#### The patches published earlier are vulnerable. {/*the-patches-published-earlier-are-vulnerable*/}
+
+If you already updated for the previous vulnerabilities, you will need to update again.
+
+If you updated to 19.0.3, 19.1.4, and 19.2.3, [these are incomplete](#additional-fix-published), and you will need to update again.
+
+Please see [the instructions in the previous post](/blog/2025/12/03/critical-security-vulnerability-in-react-server-components#update-instructions) for upgrade steps.
+
+-----
+
+_Updated January 26, 2026._
+
+
+
+Further details of these vulnerabilities will be provided after the rollout of the fixes are complete.
+
+## Immediate Action Required {/*immediate-action-required*/}
+
+These vulnerabilities are present in the same packages and versions as [CVE-2025-55182](/blog/2025/12/03/critical-security-vulnerability-in-react-server-components).
+
+This includes 19.0.0, 19.0.1, 19.0.2, 19.0.3, 19.1.0, 19.1.1, 19.1.2, 19.1.3, 19.2.0, 19.2.1, 19.2.2, and 19.2.3 of:
+
+* [react-server-dom-webpack](https://www.npmjs.com/package/react-server-dom-webpack)
+* [react-server-dom-parcel](https://www.npmjs.com/package/react-server-dom-parcel)
+* [react-server-dom-turbopack](https://www.npmjs.com/package/react-server-dom-turbopack?activeTab=readme)
+
+Fixes were backported to versions 19.0.4, 19.1.5, and 19.2.4. If you are using any of the above packages please upgrade to any of the fixed versions immediately.
+
+As before, if your app’s React code does not use a server, your app is not affected by these vulnerabilities. If your app does not use a framework, bundler, or bundler plugin that supports React Server Components, your app is not affected by these vulnerabilities.
+
+
+
+#### It’s common for critical CVEs to uncover follow‑up vulnerabilities. {/*its-common-for-critical-cves-to-uncover-followup-vulnerabilities*/}
+
+When a critical vulnerability is disclosed, researchers scrutinize adjacent code paths looking for variant exploit techniques to test whether the initial mitigation can be bypassed.
+
+This pattern shows up across the industry, not just in JavaScript. For example, after [Log4Shell](https://nvd.nist.gov/vuln/detail/cve-2021-44228), additional CVEs ([1](https://nvd.nist.gov/vuln/detail/cve-2021-45046), [2](https://nvd.nist.gov/vuln/detail/cve-2021-45105)) were reported as the community probed the original fix.
+
+Additional disclosures can be frustrating, but they are generally a sign of a healthy response cycle.
+
+
+
+### Affected frameworks and bundlers {/*affected-frameworks-and-bundlers*/}
+
+Some React frameworks and bundlers depended on, had peer dependencies for, or included the vulnerable React packages. The following React frameworks & bundlers are affected: [next](https://www.npmjs.com/package/next), [react-router](https://www.npmjs.com/package/react-router), [waku](https://www.npmjs.com/package/waku), [@parcel/rsc](https://www.npmjs.com/package/@parcel/rsc), [@vite/rsc-plugin](https://www.npmjs.com/package/@vitejs/plugin-rsc), and [rwsdk](https://www.npmjs.com/package/rwsdk).
+
+Please see [the instructions in the previous post](/blog/2025/12/03/critical-security-vulnerability-in-react-server-components#update-instructions) for upgrade steps.
+
+### Hosting Provider Mitigations {/*hosting-provider-mitigations*/}
+
+As before, we have worked with a number of hosting providers to apply temporary mitigations.
+
+You should not depend on these to secure your app, and still update immediately.
+
+### React Native {/*react-native*/}
+
+For React Native users not using a monorepo or `react-dom`, your `react` version should be pinned in your `package.json`, and there are no additional steps needed.
+
+If you are using React Native in a monorepo, you should update _only_ the impacted packages if they are installed:
+
+- `react-server-dom-webpack`
+- `react-server-dom-parcel`
+- `react-server-dom-turbopack`
+
+This is required to mitigate the security advisories, but you do not need to update `react` and `react-dom` so this will not cause the version mismatch error in React Native.
+
+See [this issue](https://github.com/facebook/react-native/issues/54772#issuecomment-3617929832) for more information.
+
+---
+
+## High Severity: Multiple Denial of Service {/*high-severity-multiple-denial-of-service*/}
+
+**CVEs:** [CVE-2026-23864](https://www.cve.org/CVERecord?id=CVE-2026-23864)
+**Base Score:** 7.5 (High)
+**Date**: January 26, 2026
+
+Security researchers discovered additional DoS vulnerabilities still exist in React Server Components.
+
+The vulnerabilities are triggered by sending specially crafted HTTP requests to Server Function endpoints, and could lead to server crashes, out-of-memory exceptions or excessive CPU usage; depending on the vulnerable code path being exercised, the application configuration and application code.
+
+The patches published January 26th mitigate these DoS vulnerabilities.
+
+
+
+#### Additional fixes published {/*additional-fix-published*/}
+
+The original fix addressing the DoS in [CVE-2025-55184](https://www.cve.org/CVERecord?id=CVE-2025-55184) was incomplete.
+
+This left previous versions vulnerable. Versions 19.0.4, 19.1.5, 19.2.4 are safe.
+
+-----
+
+_Updated January 26, 2026._
+
+
+
+---
+
+## High Severity: Denial of Service {/*high-severity-denial-of-service*/}
+
+**CVEs:** [CVE-2025-55184](https://www.cve.org/CVERecord?id=CVE-2025-55184) and [CVE-2025-67779](https://www.cve.org/CVERecord?id=CVE-2025-67779)
+**Base Score:** 7.5 (High)
+
+Security researchers have discovered that a malicious HTTP request can be crafted and sent to any Server Functions endpoint that, when deserialized by React, can cause an infinite loop that hangs the server process and consumes CPU. Even if your app does not implement any React Server Function endpoints it may still be vulnerable if your app supports React Server Components.
+
+This creates a vulnerability vector where an attacker may be able to deny users from accessing the product, and potentially have a performance impact on the server environment.
+
+The patches published today mitigate by preventing the infinite loop.
+
+## Medium Severity: Source Code Exposure {/*low-severity-source-code-exposure*/}
+
+**CVE:** [CVE-2025-55183](https://www.cve.org/CVERecord?id=CVE-2025-55183)
+**Base Score**: 5.3 (Medium)
+
+A security researcher has discovered that a malicious HTTP request sent to a vulnerable Server Function may unsafely return the source code of any Server Function. Exploitation requires the existence of a Server Function which explicitly or implicitly exposes a stringified argument:
+
+```javascript
+'use server';
+
+export async function serverFunction(name) {
+ const conn = db.createConnection('SECRET KEY');
+ const user = await conn.createUser(name); // implicitly stringified, leaked in db
+
+ return {
+ id: user.id,
+ message: `Hello, ${name}!` // explicitly stringified, leaked in reply
+ }}
+```
+
+An attacker may be able to leak the following:
+
+```txt
+0:{"a":"$@1","f":"","b":"Wy43RxUKdxmr5iuBzJ1pN"}
+1:{"id":"tva1sfodwq","message":"Hello, async function(a){console.log(\"serverFunction\");let b=i.createConnection(\"SECRET KEY\");return{id:(await b.createUser(a)).id,message:`Hello, ${a}!`}}!"}
+```
+
+The patches published today prevent stringifying the Server Function source code.
+
+
+
+#### Only secrets in source code may be exposed. {/*only-secrets-in-source-code-may-be-exposed*/}
+
+Secrets hardcoded in source code may be exposed, but runtime secrets such as `process.env.SECRET` are not affected.
+
+The scope of the exposed code is limited to the code inside the Server Function, which may include other functions depending on the amount of inlining your bundler provides.
+
+Always verify against production bundles.
+
+
+
+---
+
+## Timeline {/*timeline*/}
+* **December 3rd**: Leak reported to Vercel and [Meta Bug Bounty](https://bugbounty.meta.com/) by [Andrew MacPherson](https://github.com/AndrewMohawk).
+* **December 4th**: Initial DoS reported to [Meta Bug Bounty](https://bugbounty.meta.com/) by [RyotaK](https://ryotak.net).
+* **December 6th**: Both issues confirmed by the React team, and the team began investigating.
+* **December 7th**: Initial fixes created and the React team began verifying and planning new patch.
+* **December 8th**: Affected hosting providers and open source projects notified.
+* **December 10th**: Hosting provider mitigations in place and patches verified.
+* **December 11th**: Additional DoS reported to [Meta Bug Bounty](https://bugbounty.meta.com/) by Shinsaku Nomura.
+* **December 11th**: Patches published and publicly disclosed as [CVE-2025-55183](https://www.cve.org/CVERecord?id=CVE-2025-55183) and [CVE-2025-55184](https://www.cve.org/CVERecord?id=CVE-2025-55184).
+* **December 11th**: Missing DoS case found internally, patched and publicly disclosed as [CVE-2025-67779](https://www.cve.org/CVERecord?id=CVE-2025-67779).
+* **January 26th**: Additional DoS cases found, patched, and publicly disclosed as [CVE-2026-23864](https://www.cve.org/CVERecord?id=CVE-2026-23864).
+---
+
+## Attribution {/*attribution*/}
+
+Thank you to [Andrew MacPherson (AndrewMohawk)](https://github.com/AndrewMohawk) for reporting the Source Code Exposure, [RyotaK](https://ryotak.net) from GMO Flatt Security Inc and Shinsaku Nomura of Bitforest Co., Ltd. for reporting the Denial of Service vulnerabilities. Thank you to [Mufeed VH](https://x.com/mufeedvh) from [Winfunc Research](https://winfunc.com), [Joachim Viide](https://jviide.iki.fi), [RyotaK](https://ryotak.net) from [GMO Flatt Security Inc](https://flatt.tech/en/) and Xiangwei Zhang of Tencent Security YUNDING LAB for reporting the additional DoS vulnerabilities.
diff --git a/src/content/blog/2026/02/24/the-react-foundation.md b/src/content/blog/2026/02/24/the-react-foundation.md
new file mode 100644
index 000000000..469e49078
--- /dev/null
+++ b/src/content/blog/2026/02/24/the-react-foundation.md
@@ -0,0 +1,67 @@
+---
+title: "React 재단: Linux 재단이 후원하는 React의 새로운 보금자리"
+author: Matt Carroll
+date: 2026/02/24
+description: React 재단이 Linux 재단의 후원 아래 공식적으로 출범했습니다.
+---
+
+2026년 2월 24일, [Matt Carroll](https://x.com/mattcarrollcode) 작성
+
+---
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+React 재단이 Linux 재단의 후원 아래 공식적으로 출범했습니다.
+
+
+
+---
+
+[지난 10월](/blog/2025/10/07/introducing-the-react-foundation) React 재단 설립 계획을 발표했습니다. 오늘 React 재단이 공식적으로 출범했다는 기쁜 소식을 전해드립니다.
+
+이제 React, React Native, 그리고 JSX와 같은 프로젝트는 Meta의 소유가 아니며, Linux 재단의 후원을 받는 독립 재단인 React 재단의 소유가 되었습니다. 자세한 내용은 [Linux Foundation의 보도자료](https://www.linuxfoundation.org/press/linux-foundation-announces-the-formation-of-the-react-foundation)에서 확인하실 수 있습니다.
+
+### 창립 멤버 {/*founding-members*/}
+
+React 재단에는 8개의 플래티넘 창립 멤버가 있습니다: **Amazon**, **Callstack**, **Expo**, **Huawei**, **Meta**, **Microsoft**, **Software Mansion**, **Vercel**. **Huawei**는 [지난 10월 발표](/blog/2025/10/07/introducing-the-react-foundation) 이후 새롭게 합류했습니다. React 재단은 각 멤버의 대표로 구성된 이사회가 운영하며, [Seth Webster](https://sethwebster.com/)가 상임이사를 맡습니다.
+
+
+
+
+
+
+
+
+
+
+
+
+### 새로운 임시 리더십 위원회 {/*new-provisional-leadership-council*/}
+
+React의 기술 거버넌스는 항상 React 파운데이션 이사회와 독립적으로 유지될 것입니다. 즉, React의 기술적 방향성은 계속해서 React에 기여하고 유지 보수를 하는 사람들이 설정하게 됩니다. 이 구조를 결정하기 위해 임시 리더십 위원회를 구성했습니다. 향후 몇 달 안에 업데이트를 공유할 예정입니다.
+
+### 다음 단계 {/*next-steps*/}
+
+전환을 완료하기 위해 아직 해야 할 작업이 남아 있습니다. 향후 몇 달 동안 다음 작업이 진행될 예정입니다:
+
+* React의 기술 거버넌스 구조 확정
+* 저장소, 웹사이트, 기타 인프라를 React 재단으로 이전
+* React 생태계를 지원하는 프로그램 모색
+* 다음 React Conf 기획 시작
+
+작업이 진행되는 대로 진행 상황을 공유해 드리겠습니다.
+
+### 감사 인사 {/*thank-you*/}
+
+지난 10년간 React를 만들어온 수천 명의 기여자가 없었다면 이 모든 일은 불가능했을 것입니다. 창립 멤버들과, 풀 리퀘스트를 열거나 이슈를 제기하고, 혹은 다른 사람이 React를 배우도록 도와준 모든 기여자 여러분, 그리고 매일 React로 무언가를 만들어가는 수백만 명의 개발자 여러분께 감사드립니다. React 파운데이션은 이 커뮤니티 덕분에 존재하며 앞으로도 미래를 함께 만들어 나가길 기대합니다.
diff --git a/src/content/blog/index.md b/src/content/blog/index.md
index c60b72ccd..1bff9ed49 100644
--- a/src/content/blog/index.md
+++ b/src/content/blog/index.md
@@ -10,6 +10,24 @@ title: React 블로그
+
+
+The React Foundation has officially launched under the Linux Foundation.
+
+
+
+
+
+Security researchers have found and disclosed two additional vulnerabilities in React Server Components while attempting to exploit the patches in last week’s critical vulnerability...
+
+
+
+
+
+There is an unauthenticated remote code execution vulnerability in React Server Components. A fix has been published in versions 19.0.1, 19.1.2, and 19.2.1. We recommend upgrading immediately.
+
+
+
지난주에 React Conf 2025를 개최했습니다. 이 글에서는 행사에서 있었던 강연과 발표 내용을 정리합니다...
@@ -72,7 +90,7 @@ React 19에 추가된 개선 사항들로 인해 일부 주요한 변경 사항<
-React Labs 게시글에서는 현재 연구 개발 중인 프로젝트에 대한 글을 작성합니다. 지난 업데이트 이후 React Compiler, 새로운 기능 및 React 19에서 상당한 진전이 있었으며, 그 내용을 공유하고자 합니다.
+React Labs 게시글에서는 현재 연구 개발 중인 프로젝트에 대한 글을 작성합니다. 지난 업데이트 이후 React 컴파일러, 새로운 기능 및 React 19에서 상당한 진전이 있었으며, 그 내용을 공유하고자 합니다.
diff --git a/src/content/community/conferences.md b/src/content/community/conferences.md
index 43709d803..4e7696152 100644
--- a/src/content/community/conferences.md
+++ b/src/content/community/conferences.md
@@ -9,66 +9,72 @@ React.js 관련 컨퍼런스를 알고 계신가요? 이곳에 추가해주세
## 예정 컨퍼런스 {/*upcoming-conferences*/}
-### React Universe Conf 2025 {/*react-universe-conf-2025*/}
-September 2-4, 2025. Wrocław, Poland.
+### React Paris 2026 {/*react-paris-2026*/}
+March 26 - 27, 2026. In-person in Paris, France (hybrid event)
-[Website](https://www.reactuniverseconf.com/) - [Twitter](https://twitter.com/react_native_eu) - [LinkedIn](https://www.linkedin.com/events/reactuniverseconf7163919537074118657/)
+[Website](https://react.paris/) - [Twitter](https://x.com/BeJS_)
-### React Alicante 2025 {/*react-alicante-2025*/}
-October 2-4, 2025. Alicante, Spain.
+### CityJS London 2026 {/*cityjs-london-2026*/}
+April 14-17, 2026. In-person in London
-[Website](https://reactalicante.es/) - [Twitter](https://x.com/ReactAlicante) - [Bluesky](https://bsky.app/profile/reactalicante.es) - [YouTube](https://www.youtube.com/channel/UCaSdUaITU1Cz6PvC97A7e0w)
+[Website](https://india.cityjsconf.org/) - [Twitter](https://x.com/cityjsconf) - [Bluesky](https://bsky.app/profile/cityjsconf.bsky.social)
-### RenderCon Kenya 2025 {/*rendercon-kenya-2025*/}
-October 04, 2025. Nairobi, Kenya
+### ZurichJS Conf 2026 {/*zurichjs-conf-2026*/}
+September 10-11, 2026. In-person in Zurich, Switzerland
-[Website](https://rendercon.org/) - [Twitter](https://twitter.com/renderconke) - [LinkedIn](https://www.linkedin.com/company/renderconke/) - [YouTube](https://www.youtube.com/channel/UC0bCcG8gHUL4njDOpQGcMIA)
+[Website](https://conf.zurichjs.com?utm_campaign=ZurichJS_Conf&utm_source=referral&utm_content=reactjs_community_conferences) - [Twitter](https://x.com/zurichjs) - [LinkedIn](https://www.linkedin.com/company/zurichjs/)
-### React Conf 2025 {/*react-conf-2025*/}
-October 7-8, 2025. Henderson, Nevada, USA and free livestream
+### React Conf Japan 2027 {/*react-conf-japan-2027*/}
+April 24, 2027. In-person in Tokyo, Japan
-[Website](https://conf.react.dev/) - [Twitter](https://x.com/reactjs) - [Bluesky](https://bsky.app/profile/react.dev)
+[Website](https://reactconf.jp/) - [Twitter](https://x.com/reactconfjp)
-### React India 2025 {/*react-india-2025*/}
-October 31 - November 01, 2025. In-person in Goa, India (hybrid event) + Oct 15 2025 - remote day
+## Past Conferences {/*past-conferences*/}
-[Website](https://www.reactindia.io) - [Twitter](https://twitter.com/react_india) - [Facebook](https://www.facebook.com/ReactJSIndia) - [Youtube](https://www.youtube.com/channel/UCaFbHCBkPvVv1bWs_jwYt3w)
+### CityJS New Delhi 2026 {/*cityjs-newdelhi-2026*/}
+February 12-13, 2026. In-person in New Delhi, India
-### React Summit US 2025 {/*react-summit-us-2025*/}
-November 18 - 21, 2025. In-person in New York, USA + remote (hybrid event)
+[Website](https://india.cityjsconf.org/) - [Twitter](https://x.com/cityjsconf) - [Bluesky](https://bsky.app/profile/cityjsconf.bsky.social)
-[Website](https://reactsummit.us/) - [Twitter](https://x.com/reactsummit)
+### CityJS Singapore 2026 {/*cityjs-singapore-2026*/}
+February 4-6, 2026. In-person in Singapore
+
+[Website](https://india.cityjsconf.org/) - [Twitter](https://x.com/cityjsconf) - [Bluesky](https://bsky.app/profile/cityjsconf.bsky.social)
### React Advanced London 2025 {/*react-advanced-london-2025*/}
November 28 & December 1, 2025. In-person in London, UK + online (hybrid event)
[Website](https://reactadvanced.com/) - [Twitter](https://x.com/reactadvanced)
-### CityJS Singapore 2026 {/*cityjs-singapore-2026*/}
-February 4-6, 2026. In-person in Singapore
-
-[Website](https://india.cityjsconf.org/) - [Twitter](https://x.com/cityjsconf) - [Bluesky](https://bsky.app/profile/cityjsconf.bsky.social)
+### React Summit US 2025 {/*react-summit-us-2025*/}
+November 18 - 21, 2025. In-person in New York, USA + remote (hybrid event)
-### CityJS New Delhi 2026 {/*cityjs-newdelhi-2026*/}
-February 12-13, 2026. In-person in New Delhi, India
+[Website](https://reactsummit.us/) - [Twitter](https://x.com/reactsummit)
-[Website](https://india.cityjsconf.org/) - [Twitter](https://x.com/cityjsconf) - [Bluesky](https://bsky.app/profile/cityjsconf.bsky.social)
+### React India 2025 {/*react-india-2025*/}
+October 31 - November 01, 2025. In-person in Goa, India (hybrid event) + Oct 15 2025 - remote day
+[Website](https://www.reactindia.io) - [Twitter](https://twitter.com/react_india) - [Facebook](https://www.facebook.com/ReactJSIndia) - [Youtube](https://www.youtube.com/channel/UCaFbHCBkPvVv1bWs_jwYt3w)
-### React Paris 2026 {/*react-paris-2026*/}
-March 26 - 27, 2026. In-person in Paris, France (hybrid event)
+### React Conf 2025 {/*react-conf-2025*/}
+October 7-8, 2025. Henderson, Nevada, USA and free livestream
-[Website](https://react.paris/) - [Twitter](https://x.com/BeJS_)
+[Website](https://conf.react.dev/) - [Twitter](https://x.com/reactjs) - [Bluesky](https://bsky.app/profile/react.dev)
+### RenderCon Kenya 2025 {/*rendercon-kenya-2025*/}
+October 04, 2025. Nairobi, Kenya
-### CityJS London 2026 {/*cityjs-london-2026*/}
-April 14-17, 2026. In-person in London
+[Website](https://rendercon.org/) - [Twitter](https://twitter.com/renderconke) - [LinkedIn](https://www.linkedin.com/company/renderconke/) - [YouTube](https://www.youtube.com/channel/UC0bCcG8gHUL4njDOpQGcMIA)
-[Website](https://india.cityjsconf.org/) - [Twitter](https://x.com/cityjsconf) - [Bluesky](https://bsky.app/profile/cityjsconf.bsky.social)
+### React Alicante 2025 {/*react-alicante-2025*/}
+October 2-4, 2025. Alicante, Spain.
+[Website](https://reactalicante.es/) - [Twitter](https://x.com/ReactAlicante) - [Bluesky](https://bsky.app/profile/reactalicante.es) - [YouTube](https://www.youtube.com/channel/UCaSdUaITU1Cz6PvC97A7e0w)
-## Past Conferences {/*past-conferences*/}
+### React Universe Conf 2025 {/*react-universe-conf-2025*/}
+September 2-4, 2025. Wrocław, Poland.
+[Website](https://www.reactuniverseconf.com/) - [Twitter](https://twitter.com/react_native_eu) - [LinkedIn](https://www.linkedin.com/events/reactuniverseconf7163919537074118657/)
### React Nexus 2025 {/*react-nexus-2025*/}
July 03 - 05, 2025. In-person in Bangalore, India
diff --git a/src/content/community/translations.md b/src/content/community/translations.md
index 19147bcb5..72ef4f344 100644
--- a/src/content/community/translations.md
+++ b/src/content/community/translations.md
@@ -30,6 +30,6 @@ React 문서는 전 세계의 글로벌 커뮤니티에 의해 다양한 언어
번역 작업에 기여할 수 있습니다!
-커뮤니티는 "react.dev"의 각 언어별 포크Fork에서 React 문서의 번역 작업을 수행합니다. 일반적인 번역 작업은 Markdown 파일을 직접 번역하고 PR을 생성하는 것을 포함합니다. 위의 "기여하기" 링크를 클릭하여 해당 언어의 GitHub 저장소로 이동하고, 지침을 따라 번역 작업에 도움을 주실 수 있습니다.
+커뮤니티는 "react.dev"의 각 언어별 포크Fork에서 React 문서의 번역 작업을 수행합니다. 일반적인 번역 작업은 Markdown 파일을 직접 번역하고 PR을 생성하는 것을 포함합니다. 위의 "기여하기" 링크를 클릭하여 해당 언어의 GitHub 저장소로 이동하고, 지침을 따라 번역 작업에 도움을 주실 수 있습니다.
새로운 언어로 번역을 시작하고 싶다면 [translations.react.dev](https://github.com/reactjs/translations.react.dev)를 방문하세요.
diff --git a/src/content/learn/add-react-to-an-existing-project.md b/src/content/learn/add-react-to-an-existing-project.md
index 7f4d143a2..4f117c2ee 100644
--- a/src/content/learn/add-react-to-an-existing-project.md
+++ b/src/content/learn/add-react-to-an-existing-project.md
@@ -20,7 +20,7 @@ title: 기존 프로젝트에 React 추가하기
다음과 같이 설정하는 것을 추천합니다.
-1. [React 기반 프레임워크](/learn/start-a-new-react-project) 중 하나를 사용하여 **앱의 React 부분을 빌드하세요.**
+1. [React 기반 프레임워크](/learn/creating-a-react-app) 중 하나를 사용하여 **앱의 React 부분을 빌드하세요.**
2. 사용하는 프레임워크 설정에서 **`/some-app` 을 *기본 경로**Base Path*로 명시하세요**. (이때, [Next.js](https://nextjs.org/docs/app/api-reference/config/next-config-js/basePath), [Gatsby](https://www.gatsbyjs.com/docs/how-to/previews-deploys-hosting/path-prefix/)를 사용하세요!)
3. **서버 또는 프록시를 구성**하여 `/some-app/` 하위의 모든 요청이 React 앱에서 처리되도록 하세요.
@@ -151,7 +151,7 @@ root.render();
기존에 존재하던 `index.html`의 원본 HTML 컨텐츠가 그대로 남아있는 것을 확인할 수 있습니다. 하지만 이제는 `