
Activity는 useEffectEvent처럼 React 19에서 추가되었다.
이전에는 사이드바를 접을 때 아래와 같은 코드를 주로 사용했다.
function TabContent({ active }) {
return (
{
active && <HeavyComponent />
}
);
}
active가 false가 되었을 땐 언마운트시키는 방법이다.
그러나 이러면 다시 마운트시켰을 때 내부에서 사용되던 모든 state값들이 초기화되어 버린다.
상태를 보존하기 위해선 CSS 속성에서 display: none을 주면 되는데,
해당 컴포넌트는 보이지 않을 뿐이지 여전히 활성 상태이다.
때문에 내부의 useEffect 같은 로직은 계속 돌아간다.
이는 불필요한 리소스 낭비가 될 수 있다.
이때 Activitiy를 이용한다.
function TabContent({ active }) {
return (
<Activity mode={active ? 'visible' : 'hidden'}>
<HeavyComponent />
</Activity>
);
}
컴포넌트를 언마운트시키지 않고, 비활성 상태로 만든다.
말그대로 일시정지라 다시 활성화되면 input 입력값이나 스크롤 위치까지 다 동일하게 남아있다.
그러나 아무래도 언마운트보다는 메모리를 먹기 때문에 저사양 기기에서는 성능 문제가 생길 수도...
원리
React는 16버전부터 Fiber라는 아키텍처를 쓰고 있다.
거대한 렌더링 작업을 Fiber 노드라는 작은 단위로 쪼개는 방법이다.
그 작업마다 Lane이라는 우선순위를 매기는데, 여기에 따라 중요한 것부터 먼저 렌더링시킨다.
작업을 수행하다가 도중에 사용자의 입력이 들어오면 일단 작업을 멈출 수도 있다.
그 때 도입된 게 Pause와 Resume라는 개념이다. 즉 작업을 멈췄다가 다시 시작하고, 폐기하기도 한다.
결국 Activity 컴포넌트가 mode=hidden이면
내부 요소들의 Lane을 최하로 낮춘 뒤 Pause를 시켜놓는 것이다.
이때 내부 useEffect의 cleanup을 실행해서 작업을 중단시킨다.
즉 컴포넌트가 언마운트될 때 실행될 코드가 실행된다는 것이다.
(+) Fiber에서 렌더링 프로세스는 두 단계로 나뉘는데,
1. Render Phase: 새로운 상태를 반영한 트리를 비동기로 만듦.
2. Commit Phase: 그 결과를 가지고 실제 DOM에 동기로 빠르게 반영.
사이드바 애니메이션을 쓰려면?
Activity의 hidden, visible 속성이 바뀔 때 transform 애니메이션을 쓸 수 있을까 했지만 그건 또 아니었다.
내부적으로 CSS의 display: none을 쓰기 때문.
사이드바를 접는 애니메이션을 만들고 싶으면
1. 먼저 transform을 시켜서 접히는 애니메이션을 보여줌
2. setTimeout으로 몇초 뒤(이건 잘 안씀),
혹은 사이드바의 onTransitionEnd 이벤트 이용해서 언마운트 처리(정석적)
혹은 requestAnimationFrame 안에서 언마운트 처리(좀 복잡한데 세밀한 작업 가능)
// onTransitionEnd 사용
function Sidebar({ isOpen }) {
const [shouldRender, setShouldRender] = useState(isOpen);
const handleTransitionEnd = () => {
if (!isOpen) setShouldRender(false); // 닫기 애니메이션이 끝나면 언마운트
};
// 언마운트
if (!shouldRender) return null;
return (
<div
onTransitionEnd={handleTransitionEnd}
className={`sidebar ${isOpen ? 'open' : 'close'}`}
style={{
transition: 'transform 0.3s ease-in-out',
transform: isOpen ? 'translateX(0)' : 'translateX(-100%)'
}}
>
사이드바 컨텐츠
</div>
);
}
이 과정에서 언마운트 처리 대신 Activity 에 hidden 속성을 준다는 것만 달라진다.
이게 귀찮으면 Framer Motion 라이브러리를 사용하게 되는 것.
'IT > React & Next.js' 카테고리의 다른 글
| [React] useEffectEvent 사용처 (0) | 2026.04.01 |
|---|---|
| [TanStack Query] Query Key factories로 Query Key 관리하기 (0) | 2025.12.05 |
| [React] 훅 안에서 정의한 함수의 클로저 문제 (0) | 2025.10.28 |
| [Infra] Biome.js VSCode 세팅 (1) | 2025.08.31 |
| [React/TypeScript] React-Spilt-Table 오픈소스 라이브러리 (1) | 2025.04.21 |