React 19에서 추가된 <Activity>는 “컴포넌트를 언마운트하지 않고 숨기는” 용도로 쓰는 새 컴포넌트다.
탭/모달/사이드바처럼 자주 보였다 숨겼다 하는 UI에서 상태를 그대로 유지한 채 토글할 수 있게 해준다.
Activity 기본 개념
- <Activity>는 자식 컴포넌트의 생명주기 경계를 만들어 주는 컴포넌트다.
- mode="visible" | "hidden" | "auto" 같은 props로 Activity 안의 UI를 보이거나 숨길 수 있다.
- 숨길 때도 컴포넌트를 언마운트하지 않고 DOM과 React state를 보존하는 것이 핵심이다.
상태가 유지되는 숨김 처리
- 일반적인 조건부 렌더링({isOpen && <Panel />})은 false가 되면 컴포넌트가 언마운트되어 useState 등 로컬 상태가 사라진다.
- <Activity mode="hidden">으로 감싸면, 화면에서는 display: none처럼 보이지 않지만 컴포넌트 인스턴스와 state는 유지된다.
- 다시 visible로 바꾸면, 마치 일시 정지했다가 재생하듯 기존 상태 그대로 UI가 복귀한다.
DOM 상태까지 함께 보존
- Activity 경계 안에서 숨길 때는 브라우저 레벨의 DOM 상태도 유지된다.
- 예를 들어 입력 중이던 <input> 값, <textarea> 내용, 스크롤 위치 등이 숨김/보임 전환 사이에서도 유지된다.
- 작성 중인 폼이 있는 탭 패널이나 멀티 스텝 폼 UI에서, 다른 탭으로 이동했다가 돌아와도 값이 초기화되지 않는 UX를 쉽게 만들 수 있다.
import { useState } from 'react';
export default function Sidebar() {
const [isExpanded, setIsExpanded] = useState(false)
return (
<nav>
<button onClick={() => setIsExpanded(!isExpanded)}>
Overview
<span className={`indicator ${isExpanded ? 'down' : 'right'}`}>
▲
</span>
</button>
{isExpanded && (
<ul>
<li>Section 1</li>
<li>Section 2</li>
<li>Section 3</li>
</ul>
)}
</nav>
);
}
export default function App() {
const [isShowingSidebar, setIsShowingSidebar] = useState(true);
return (
<>
{isShowingSidebar && (
<Sidebar />
)}
<main>
<button onClick={() => setIsShowingSidebar(!isShowingSidebar)}>
Toggle sidebar
</button>
<h1>Main content</h1>
</main>
</>
);
}
기존에 state로 사이드바를 토글 했다면 Sidebar 자체가 DOM에서 사라지면서 다시 나타났을 땐 Sidebar 내부 state는 초기화가 되어있었음.
Activity로 관리한다면
- 숨길 때 해당 boundary 안의 DOM은 display: "none"으로 처리해서 화면과 레이아웃에서 제거
- 동시에 그 안의 Effect들은 파괴(unmount)해서 백그라운드 사이드 이펙트를 막음
- 하지만 컴포넌트의 state와 UI 스냅샷은 유지해서 다시 보이게 만들면 이전 상태 그대로 복원
즉 사이드바 안에서 관리 중인 state는 토글이 되든 말든 값을 계속 유지한다는 것
import { Activity, useState } from 'react';
export default function App() {
const [isShowingSidebar, setIsShowingSidebar] = useState(true);
return (
<>
<Activity mode={isShowingSidebar ? 'visible' : 'hidden'}>
<Sidebar />
</Activity>
<main>
<button onClick={() => setIsShowingSidebar(!isShowingSidebar)}>
Toggle sidebar
</button>
<h1>Main content</h1>
</main>
</>
);
}
미리 렌더링과 체감 속도 향상
- 아직 사용자에게 보이지 않을 UI를 미리 렌더링해 두고 싶을 때도 <Activity>를 활용할 수 있다.
- mode="hidden" 상태로 렌더링해 두면, 화면에는 나오지 않지만 컴포넌트가 이미 준비되고 Suspense 기반 데이터 로딩도 진행된다.
- 사용자가 탭을 전환하거나 모달을 열 때 이미 로딩이 끝나 있어서, 로딩 스피너 없이 바로 UI를 보여줄 수 있어 체감 성능이 좋아진다.
Hydration 및 상호작용 성능 최적화
- 서버 렌더링(SSR)과 Hydration 환경에서 <Activity>는 UI 트리를 나누는 경계로 활용할 수 있다.
- 상호작용이 중요한 버튼, 네비게이션 등은 먼저 hydrate하고, 덩치 큰 UI는 Activity 경계 안에서 나중에 활성화되도록 조절할 수 있다.
- 이 방식은 초기 페이지 로딩 시 “클릭은 바로 먹히는데, 나머지 무거운 뷰는 뒤에서 준비되는” 구조를 만들 때 유용하다.
언제 쓰면 좋은가
- 탭 패널, 아코디언, 사이드바, 모달처럼 자주 토글되지만 상태 초기화가 싫은 UI.
- 긴 폼, 에디터, 멀티 스텝 UI처럼 입력 값과 스크롤을 그대로 유지해야 하는 화면.
- 사용자 행동에 앞서 화면을 미리 준비해 두고, 전환 시 로딩 없이 “즉시 표시”를 원하는 경우.
- SSR + Hydration 환경에서 주요 인터랙션을 먼저 활성화하고, 덩치 큰 UI를 점진적으로 활성화하고 싶은 경우.
'FrontEnd > React.js' 카테고리의 다른 글
| 추가로 발견 된 리액트 취약점 (0) | 2025.12.12 |
|---|---|
| React Server Components CVE-2025-55182 취약점 분석 (0) | 2025.12.05 |
| JWT 관련 면접 질문 모음 (0) | 2025.04.26 |
| 토스의 "자료구조를 활용한 복잡한 프론트엔드 컴포넌트 제작하기"를 구현해보기 (3) (0) | 2025.04.14 |
| 토스의 "자료구조를 활용한 복잡한 프론트엔드 컴포넌트 제작하기"를 구현해보기 (2) (0) | 2025.04.13 |