
이번 주에 React v19.2 변경 로그를 보다가, 새로 추가된 Activity 컴포넌트가 눈에 띄더라. 바로 테스트용으로 작은 프로젝트에 적용해봤는데… 와, 진짜 괜찮다!
아래는 내가 직접 써본 후기와 예시, 그리고 생각해본 엣지 케이스들이다.
<Activity>는 자식 컴포넌트의 UI와 내부 상태를 숨기거나 복원할 수 있는 컴포넌트다.
출처: 리액트 공식문서
이 컴포넌트가 중요한 이유는 두 가지:
&&)나 조건부 삼항 연산자, 혹은 display:none 스타일에 의존해야 했다.기존에는 조건부 렌더링을 이렇게 처리했다:
1. 논리 연산자 이용
{ showComponent && <Component/> }
이 경우, 조건이 false면 <Component/>가 DOM에서 사라지고(unmount) 내부 상태도 전부 초기화된다.
예를 들어 input 값을 가지고 있던 컴포넌트라면, 다시 보이게 했을 때 그 값이 다 날아간다.
2. 삼항 연산자 이용
return showComponent ? <Component/> : <></>;
결과는 위와 동일 — 아예 언마운트되어 상태가 날아감.
3. CSS display 방식
<div style={{
display: showComponent ? 'block' : 'none'
}}>
<Component/>
</div>
이 방식은 컴포넌트를 숨기더라도 DOM에는 남아 있기 때문에 상태는 유지된다.
하지만 React는 여전히 해당 컴포넌트의 렌더/이펙트/이벤트를 모두 계속 처리한다.
컴포넌트가 많아질수록 퍼포먼스가 심각하게 나빠진다.
이제 <Activity> 하나로 조건부 렌더링과 CSS 방식의 단점을 모두 해결할 수 있다.
<Activity>는 mode prop으로 작동하며, 값으로 'visible' 또는 'hidden'을 갖는다.
mode="visible"일 때는 React.Fragment처럼 단순한 래퍼로 동작하고,
mode="hidden"일 때는 내부적으로 마법처럼 동작하기 시작한다.

공식 문서 표현을 빌리면, Activity는 마치 “백그라운드 렌더링 메커니즘”처럼 동작한다.
즉, 나중에 다시 노출될 가능성이 높은 UI를 완전히 버리지 않고, 상태를 유지한 채 숨긴다.
이때 숨겨진 콘텐츠는 불필요한 렌더나 이펙트 실행이 중단되어 성능상으로 큰 이점이 있다.
내가 만든 테스트 페이지에서는 Activity 방식과 전통적인 조건부 렌더링 방식을 직접 비교해봤다.
코드는 간단한 카운터 예제다.

어떤 사람들은 Activity를 Angular 1의 ng-show / ng-hide 디렉티브랑 비슷하다고 말하지만,
그건 완전 잘못된 비교다.
Angular의 그 디렉티브들은 단순히 .ng-hide CSS 클래스를 붙였다 뗐다 하는 정도일 뿐,
퍼포먼스 최적화는 전혀 없다.
하지만 Activity는 완전히 다르다:
게다가 mode라는 prop 이름도 의미가 있다.
향후엔 'visible'과 'hidden' 외의 새로운 모드들도 생길지도 모른다 (개인적인 예상 😎).
이건 재밌는 케이스다.
만약 <Activity> 안에 단순 텍스트만 렌더링한다면,
mode="hidden"을 줘도 그 텍스트는 안 숨겨진다.
<Activity mode="hidden">Hello World</Activity>
왜냐면 Activity가 display:none을 적용할 DOM 엘리먼트 자체가 없기 때문이다.
요즘 우리 집 근처에 자주 오는 길냥이가 있는데,
얘가 마치 Activity 컴포넌트로 감싸져 있는 것 같다.
isHungry가 true일 때만 보이는 듯한 느낌이랄까 😅
ReactJS에 진짜 괜찮은 컴포넌트가 추가됐다.
당분간은 기존 코드에도 슬슬 Activity를 적용해볼 생각이다.
성능 이득까지 있으니 일석이조!
도움이 됐다면 다행이다. 개발자 친구들에게도 한 번씩 알려주자 😄
ciao!