<Activity>
display : none, visuality : hidden 을 곁들인
Activity란
<Activity>는 자식 컴포넌트를 언마운트하지 않고 화면에서 숨길 수 있는 내장 컴포넌트다.
<Activity mode={show ? "visible" : "hidden"}>
<MyComponent />
</Activity>
mode="hidden"일 때 자식은 화면에서 사라지지만, React 내부에서는 그대로 살아 있다. state, ref, DOM 노드 모두 유지된다.
조건부 렌더링과의 차이
조건부 렌더링은 컴포넌트를 Fiber 트리에서 완전히 제거한다. Activity는 Fiber 트리를 유지한 채 브라우저 화면에서만 숨긴다.
// 조건부 렌더링 — Fiber 트리에서 제거, state 소멸
{
show && <MyComponent />;
}
// Activity — Fiber 트리 유지, 화면에서만 숨김
<Activity mode={show ? "visible" : "hidden"}>
<MyComponent />
</Activity>;
조건부 렌더링 (&&) | <Activity mode="hidden"> | |
|---|---|---|
| Fiber 트리 | 제거 | 유지 |
| DOM 노드 | 제거 | 존재 (display: none) |
| state | 초기화 | 유지 |
| Effect (초기 hidden) | - | 실행되지 않음 |
| Effect (visible ↔ hidden) | cleanup → 재마운트 시 재실행 | cleanup 실행 → visible 시 재실행 |
| pre-rendering | 불가 | 가능 |
Activity가 유리한 대표적인 시나리오:
- 탭 전환 — 비활성 탭의 입력값·스크롤 위치 등을 보존
- pre-rendering — 아직 보이지 않는 화면을 미리 렌더링해 전환 속도 향상
- 무거운 컴포넌트 — 마운트·언마운트 비용이 큰 컴포넌트의 반복 생성 방지
Activity는 왜 display: none을 쓸까

공식 문서에 따르면, Activity는 내부적으로 숨긴 자식에 display: none을 적용한다. 여기서 의문이 생길 수 있다.
display: none 이면 렌더 트리에서 사라지니까 상태가 날아가는 거 아닌가?
그렇지 않다. 이를 이해하려면 브라우저의 렌더 트리와 React의 Fiber 트리를 구분해야 한다.
- 렌더 트리 — 브라우저가 화면을 그리기 위해 만드는 트리. DOM + CSSOM을 결합하여 실제로 그릴 요소만 포함한다.
- Fiber 트리 — React가 컴포넌트의 상태와 구조를 관리하는 내부 트리.
useState,useEffect등의 훅 정보가 여기에 저장된다.
display: none은 렌더 트리에서만 제외할 뿐, DOM 노드는 그대로 존재하고, Fiber 트리도 건드리지 않는다. state는 Fiber 트리에 저장되므로 영향을 받지 않는다.
그렇다면 visibility: hidden을 쓰면 안 될까? visibility: hidden은 요소가 보이지 않지만 공간을 계속 차지한다. 탭 전환 같은 시나리오에서 숨긴 콘텐츠가 레이아웃을 차지하면 화면이 깨지기 때문에, 공간까지 제거하는 display: none이 적합하다.
| CSS 속성 | 렌더 트리 | DOM | 공간 차지 | 토글 비용 |
|---|---|---|---|---|
display: none | 제외 | 유지 | X | 리플로우 |
visibility: hidden | 포함 | 유지 | O | 리페인트 |
마무리
"이 컴포넌트를 숨기고 싶다"는 의도를 표현할 때, Activity가 더 직접적으로 표현하는 듯 하다.
다만 둘 중 어느 쪽이 항상 낫다는 정답은 없다. Activity로 숨긴 컴포넌트는 Fiber 트리와 DOM 노드를 계속 들고 있으므로 그만큼 메모리를 차지한다. 다시 보여줄 가능성이 없는 컴포넌트까지 Activity로 감싸면 오히려 낭비다. 상황에 맞게 선택하면 된다.
추가로, 사용자가 다시 상호작용할 가능성이 있는 UI의 임시 상태를 유지해야 한다면 Activity를 사용하는 것이 더 적합할 듯하다.