원문: React 19.3 — React Blog 원문은 CC-BY-4.0 라이선스로 제공되며, 이 글은 한국어로 번역한 2차 저작물입니다.
새로운 React 기능
View Transitions
새로운
<ViewTransition> 컴포넌트를 사용하면 브라우저의 View Transition API를 사용하여 요소가 진입, 퇴장, 이동 또는 크기 조정될 때 애니메이션을 적용할 수 있습니다. 작년에 실험적인 API로 공유되었던 이 기능이 19.3에서는 안정화되어 사용할 준비가 되었습니다.UI의 일부를 애니메이션하려면
<ViewTransition>으로 감싸십시오.이제 Transition으로 표시된 업데이트가 하위 컴포넌트의 스타일을 변경하거나
ViewTransition이 마운트 또는 언마운트되도록 하면 React가 해당 업데이트를 애니메이션 처리합니다.React는 트리가 변경된 방식에 따라 실행할 애니메이션을 선택합니다.
- enter:
이 추가됩니다.<ViewTransition> - exit:
이 제거됩니다.<ViewTransition> - update:
의 자식이 스타일이나 콘텐츠를 변경합니다.<ViewTransition> - share: 명명된
이 한 곳에서 제거되고 다른 곳에서 추가됩니다.<ViewTransition>
Transition으로 표시되지 않은 업데이트는 긴급하며 UI에 즉시 반영되어야 하므로 애니메이션을 트리거하지 않습니다. startTransition 내부의 상태 업데이트,
<Suspense> 표시 또는 useDeferredValue의 업데이트는 모두 View Transition 애니메이션을 트리거합니다.다음은 진입/퇴장 애니메이션의 간단한 예입니다.
기본적으로
<ViewTransition>은 부드러운 크로스페이드로 애니메이션 처리됩니다. View Transition Class를 전달하고 CSS에서 애니메이션을 정의하여 각 애니메이션 종류를 사용자 정의하거나, Web Animations API를 사용하여 이벤트 props (onEnter, onExit, onShare, onUpdate)로 명령적으로 애니메이션을 트리거할 수 있습니다.현재
<ViewTransition>은 DOM에서만 작동합니다. React Native 및 기타 플랫폼에 대한 지원을 작업 중입니다.더 많은 정보는
<ViewTransition> 문서를 참조하십시오.addTransitionType
addTransitionType때로는 동일한 상태 업데이트에 대한 애니메이션을 사용자 정의하고 싶을 것입니다. 예를 들어, 캐러셀을 세 번째 슬라이드로 앞으로 탐색하면 슬라이드가 오른쪽에서 왼쪽으로 애니메이션 처리되어야 하지만, 뒤로 탐색하면 현재 슬라이드가 3으로 설정되더라도 왼쪽에서 오른쪽으로 애니메이션 처리됩니다.
상태 업데이트와 함께
addTransitionType을 호출하여 특정 View Transition의 애니메이션을 사용자 정의할 수 있습니다. 이렇게 하면 특정 전환의 _원인_에 대한 추가 정보를 추가할 수 있습니다.그런 다음 해당 전환 유형을 기반으로 다른 애니메이션을 지정할 수 있습니다.
다음은 예시입니다.
React는 모든 Transition Type을 요소에 브라우저 view transition type으로 추가하므로
:active-view-transition-type(...)을 사용하여 CSS에서 애니메이션을 범위 지정할 수 있습니다.더 알아보려면
addTransitionType 문서를 참조하십시오.Suspense를 사용한 대체, 이미지 및 글꼴 애니메이션
React의 View Transitions에서 가장 흥미로운 점 중 하나는 Suspense와의 통합 방식입니다.
<ViewTransition>으로 감싸서 Suspense 경계가 자식을 표시할 때 애니메이션을 적용할 수 있습니다.자식 로딩이 완료되면 React는 대체에서 최종 콘텐츠로 업데이트 애니메이션을 트리거합니다.
예시입니다. ➕를 눌러 처음 렌더링될 때 일시 중지되는 LazyVideo를 렌더링해 보세요.
이것은 작동하지만, 비디오가 이미 로드되었음에도 불구하고 후속 표시 시에도 비디오가 위아래로 애니메이션 처리되는 것을 알 수 있습니다. (또한 대체가 처음 표시될 때 페이드 인되는 것을 알 수 있습니다.)
일반적으로 Suspense를 사용한 애니메이션은 sparingly 사용될 때 가장 잘 작동하며, 즉시 표시되는 캐시된 UI에는 피하는 것이 좋습니다.
Suspense로 애니메이션 처리할 때 좋은 UX를 달성하기 위한 몇 가지 원칙이 있습니다.
- 대체는 애니메이션 없이 즉시 표시되어야 합니다.
- 대체는 애니메이션과 함께 최종 콘텐츠로 업데이트되어야 합니다.
- 일시 중지되지 않는 자식은 애니메이션 없이 즉시 표시되어야 합니다.
이렇게 하면 UI가 캐시된 경우에도 빠르게 느껴지도록 하고, 대체에서 최종 콘텐츠로의 업데이트를 더 원활하게 만들기 위해 애니메이션을 사용합니다.
위의 예제를 수정하려면 업데이트 외의 모든 애니메이션을 비활성화할 수 있습니다.
이제 어떻게 작동하는지 살펴보겠습니다.
버튼을 탭할 때 대체가 즉시 나타나 UI가 사용자 작업에 반응하는 느낌을 유지하는 것을 볼 수 있습니다. 또한 비디오가 로드되면 토글하는 것이 즉시 작동합니다.
달성하려는 효과에 따라 사용할 수 있는 다른 패턴도 있습니다. 더 알아보려면 Suspense로 애니메이션 처리하는 방법에 대한 문서를 확인하세요.
대체 애니메이션 외에도 View Transitions는 이미지 또는 글꼴을 로드하는 동안 Suspense를 트리거하는 옵션으로 사용할 수 있습니다.
이를 통해 브라우저의 기본 동작(이미지 또는 글꼴이 로딩을 마칠 때 깜박일 수 있음)을 방지하고 대신 컴포넌트의 모든 리소스를 고려하는 조정된 로딩 시퀀스를 구축할 수 있습니다.
로드되는 동안 Suspense를 트리거하려면 이미지 또는 글꼴을
<ViewTransition> 안에 래핑하십시오.다음은 데이터, 이미지 및 글꼴이 모두 로드될 때까지 일시 중지되는 컴포넌트의 예입니다.
이미지, 글꼴 또는 스타일시트 로드를 기다리는 것에 대해 자세히 알아보려면 Suspense 문서를 참조하십시오.
Fragment Refs
컴포넌트의 DOM 노드에 대한 저수준 제어가 필요한 경우(예: 이벤트 리스너 연결, 가시성 관찰 또는 초점 이동) 일반적으로 ref를 사용할 수 있습니다. 하지만 다음과 같은 경우 이 작업이 어려운 경우가 있습니다.
- 단일 부모 없이 형제 집합을 렌더링하는 컴포넌트
prop을 다른 요소로 전달하지 않는 컴포넌트ref
ref를 보유하기 위해 래퍼
<div>를 추가하는 것이 때로는 작동하지만 컴포넌트의 스타일이나 레이아웃을 방해할 수도 있습니다. 또한 컴포넌트가 ref prop을 노출하지 않는 경우 컴포넌트를 수정해야 할 수 있으며, 이는 제어하지 않는 라이브러리에서 오는 경우 불가능할 수 있습니다.Fragment Refs는 이러한 문제를 해결하여 React 컴포넌트가 렌더링하는 것과 상관없이 모든 React 컴포넌트와 작동하는 제한된 수의 일반적인 DOM 메서드를 제공합니다.
19.3에서는
ref를 <Fragment>에 직접 전달하여 사용할 수 있습니다. 이 ref는 Fragment의 DOM 자식을 처리하는 데 사용할 수 있는 FragmentInstance를 제공합니다.FragmentInstance는 구조를 변경하지 않고 자식의 DOM을 그룹으로 작동합니다.
,addEventListener
,removeEventListener
는 첫 번째 수준 자식에 대한 이벤트를 관리합니다.dispatchEvent
,focus
,focusLast
는 깊이 우선으로 중첩된 자식을 통해 초점을 이동합니다.blur
,observeUsing
은unobserveUsing
또는IntersectionObserver
를 연결합니다.ResizeObserver
,getClientRects
,getRootNode
,compareDocumentPosition
를 사용하면 조각의 첫 번째 수준 자식의 크기를 측정하고 스크롤할 수 있습니다.scrollIntoView
따라서 Fragment Refs를 사용하면 컴포넌트의 내부를 수정하지 않고도 다른 컴포넌트에 동작을 연결하거나 이미 생성된 DOM 구조를 변경하지 않고도 연결할 수 있습니다.
이 예제는
onChange prop을 가진 InView 컴포넌트를 보여줍니다. 자식이 뷰포트에 진입하거나 퇴장할 때마다 작동합니다.InView가 단일 부모 DOM 요소가 없음에도 불구하고 Card가 ref prop을 노출하지 않음에도 불구하고 자식에게 동작을 추가할 수 있는 방법을 확인하십시오.Fragment Refs를 사용하여 작업하는 것에 대해 자세히 알아보려면
<Fragment> 문서를 참조하십시오.새로운 React DOM 기능
browser
browser앱에서 서버 렌더링을 사용하는 경우 컴포넌트는 두 가지 다른 환경에서 렌더링됩니다.
- 서버에서 컴포넌트는 초기 HTML을 생성하기 위해 렌더링됩니다.
- 클라이언트에서 컴포넌트는 이벤트 핸들러를 추가하기 위해 렌더링됩니다.
대부분의 경우 컴포넌트는 초기 클라이언트 렌더링 출력과 일치하는 HTML을 생성할 수 있어야 하므로, 초기 로드 시 최대한 많은 콘텐츠를 사용자에게 표시하면서도 올바르게 hydration되도록 할 수 있습니다.
하지만 드문 경우지만, 컴포넌트가 서버에서 의미 있는 UI를 생성하지 못할 수 있습니다. 예를 들어,
localStorage와 같은 브라우저 전용 API에 의존하거나 브라우저의 로컬 시간대를 읽을 수 있습니다. 이러한 경우 해당 컴포넌트를 서버 렌더링에서 완전히 제외하는 것이 좋습니다.이전에는 효과에서 업데이트할 상태를 사용하거나
window와 같은 브라우저 API의 존재를 확인하여 이를 수행했을 수 있습니다.19.3에서는 React가 이 기술에 대한 1급 API를 포함합니다.
컴포넌트는
use(browser())를 호출하여 서버 측 렌더링에서 제외될 수 있습니다.이렇게 하면 서버에서 Suspense가 트리거되지만 클라이언트에서는 트리거되지 않습니다. 서버 측 렌더링 중에 가장 가까운 Suspense 경계의 대체가 HTML에 표시됩니다. 컴포넌트가 클라이언트에서 hydration된 후
use(browser())는 일시 중지되지 않아 컴포넌트가 정상적으로 렌더링을 계속할 수 있습니다.다음은 장치의 로컬 시간대를 렌더링하는 컴포넌트의 예입니다. Reload를 눌러 초기 HTML과 React의 첫 번째 클라이언트 렌더링을 확인하십시오.
TimeZone이 서버에서 일시 중지되기 때문에 초기 HTML에는 Suspense 대체가 포함됩니다. 짧은 인위적인 지연 후 React가 페이지를 hydration하여 컴포넌트가 브라우저에서 정상적으로 렌더링될 수 있도록 합니다.
따라서 서버 렌더링 중에 의미 있는 UI를 생성하지 못하는 컴포넌트의 경우
browser를 사용하면 Suspense를 로딩 상태에 사용하여 다른 컴포넌트와 통합되어 준비될 때까지 렌더링을 일시 중지할 수 있습니다.use에 대한 다른 호출과 마찬가지로 use(browser())는 조건문 내에서 또는 조기 반환 후에 호출할 수 있습니다. 이렇게 하면 컴포넌트 또는 사용자 정의 Hooks를 작성하여 prop 값과 같은 조건에 따라 서버 렌더링을 제외할 수 있습니다.위의 동일한 예제를 사용하되, 이제 TimeZone 컴포넌트가 초기 HTML의 일부로 렌더링할 수 있는 선택적 기본값을 허용하도록 하겠습니다.
TimeZone이 두 번째 경우, 즉 기본값이 제공되지 않을 때만 일시 중지되는 것을 볼 수 있습니다.
이 패턴의 또 다른 유용한 예는
useQuery와 같은 데이터 가져오기 Hook을 서버 렌더링에서 제외하는 것입니다. 단, 해당 쿼리의 초기 데이터가 (예: 서버 컴포넌트 또는 프레임워크의 로더 함수에서) 전달된 경우를 제외합니다.이제 ProductDetails 컴포넌트는
initialData가 서버 렌더링 중에 제공되는 경우 HTML에 포함될 수 있습니다. 그렇지 않으면 브라우저에서 렌더링될 때까지 일시 중지되며, 그 후 useQuery는 정상적으로 데이터를 가져오거나 캐시에서 읽을 수 있습니다.browser에 대해 자세히 알아보려면 문서를 확인하십시오.Trusted Types 지원
React 19.3은 브라우저 Trusted Types API와 통합됩니다. 이 보안 기능은 DOM 기반 XSS 공격을 방지하는 데 도움이 됩니다. 사이트가
Content-Security-Policy: require-trusted-types-for 'script'로 Trusted Types를 시행하는 경우, 브라우저는 innerHTML과 같은 삽입 싱크에 전달되는 값이 일반 문자열이 아닌 해당 위생 정책을 통해 생성된 형식화된 객체 (TrustedHTML, TrustedScript, TrustedScriptURL)여야 한다고 요구합니다. React는 이제 이러한 값을 강제 변환 없이 통과시키므로 브라우저가 유효성을 검사하고 Trusted Types 정책이 의도한 대로 작동합니다.새로운 React 서버 컴포넌트 기능
<Context>
를 서버 컴포넌트에서 직접 렌더링 가능
<Context>서버 컴포넌트가 Context를 _생성_할 수는 없지만,
'use client' 모듈에서 가져와 Context를 _렌더링_할 수 있습니다.이전에는 클라이언트 모듈이 별도의 래퍼 컴포넌트(종종 Provider라고 함)를 내보내야 했습니다.
이 예제에서 Provider는 서버 컴포넌트의 prop을 Context에 직접 전달하는 것 외에는 아무것도 하지 않는다는 점에 유의하십시오.
React 19.3에서는 서버 컴포넌트가 추가 래핑 컴포넌트 없이
'use client' 모듈에서 직접 Context를 가져와 렌더링할 수 있습니다.이것은 서버 컴포넌트가 나머지 클라이언트 트리에 데이터를 공유할 수 있도록 하는 Context에 특히 유용합니다.
변경 로그
기타 주목할 만한 변경 사항
: 느린 Transition이 관련 없는 Transition을 방해하지 않도록 Transition을 단일 렌더링으로 얽매는 대신 독립적으로 렌더링합니다.react
: 조건문에서react
를 잘못 사용했을 때 경고를 추가합니다.use
:react
오류 메시지에서 "form state"를 "action state"로 이름을 변경합니다.useActionState
:react-dom
및onFullscreenChange
이벤트 지원을 추가합니다.onFullscreenError
:react-dom
SVG 속성에 대한 지원을 추가합니다.maskType
: 모듈 리소스에 대해react-dom
를 지원합니다.fetchPriority
: 서버 작업 후 React가 양식을 자동으로 재설정할 때react-dom
을 발생시킵니다.onReset
:react-dom
이벤트에submit
를 포함합니다.submitter
: iframe에서react-dom
를 부울 속성으로 인식합니다.credentialless
: 다음 프레임까지react-dom
이벤트의 업데이트를 배치합니다.resize
:react-server
및Error.cause
를 클라이언트로 전송합니다.AggregateError.errors
: Flight에서react-server
를 지원합니다.<Activity>
주목할 만한 버그 수정
:react
가 오래된 값에 고정되는 문제를 수정합니다.useDeferredValue
: Suspense 대체로의 컨텍스트 전파 및 일시 중지된 Suspense 경계를 통한 컨텍스트 전파를 수정합니다.react
: 숨겨진 트리 내에서 비활성화된 Suspense 경계를 업데이트할 때 발생하는 중단 문제를 수정합니다.react
:react
트리가 숨겨져 있는 동안 발생한<Activity>
의 저장소 변경 사항 누락 문제를 수정합니다.useSyncExternalStore
:react
가useEffectEvent
및forwardRef
컴포넌트에서 최신 값을 읽도록 수정합니다.memo
: 컴포넌트 상태가 업데이트될 때 폼 상태가 재설정되는 문제를 수정합니다.react
:react
,lazy
및 컴포넌트 종류를 변경하는 편집 시 Fast Refresh의 여러 버그를 수정합니다.memo
:react
에 포함된<Activity>
이<title>
이 포함된<title>
가<Activity>
에서visible
모드로 변경된 후에도hidden
로 계속 호이스트되는 버그를 수정합니다.<head>
: 숨겨진react
에서 오류가 벗어나지 않도록 합니다.<Activity>
: 숨겨진react
내에서 렌더링된 포털 콘텐츠를 숨깁니다.<Activity>
: 오류 메시지에서 내부react
유형을 참조하지 않도록 합니다.<Offscreen>
: 위임되거나 이미 초점이 맞춰진 요소의 초점 문제를 수정합니다.react-dom
: DOM 사양에 따라 캡처 옵션을 정규화하여react-dom
리스너 누수를 수정합니다.FragmentInstance
: 모바일 사파리에서react-dom
충돌을 수정합니다.<ViewTransition>
:react-dom
에서SuspenseList
충돌을 수정합니다.<ViewTransition>
:react-dom
입력의type="number"
를 다른 입력 유형과 일치하도록 업데이트합니다.defaultValue
:react-dom
이 변경되지 않은 경우 설정하지 않도록 합니다.innerHTML
:react-dom
속성에서 잘못된 hydration 불일치를 수정합니다.nonce
: Deno에서react-dom
가 중단되는 문제를 수정합니다.react-dom/server
:react-server
에서 누락된decodeReplyFromBusboy
항목을 수정합니다.FormData
: 깊은 비동기 체인에서의 스택 오버플로 및 지수형 디버그 정보 증가로 인한react-server
를 수정합니다.RangeError
모든 변경 사항 목록은 변경 로그를 참조하십시오.



