React 컴파일러에 대해 찾아보면서 알게된 내용들을 기록하려고 합니다.
먼저 React 컴파일러는 빌드 타임에 React 코드를 분석해 자동으로 메모이제이션을 적용하는 컴파일러로, React 19와 함께 도입되었습니다.
핵심 전제는 '애플리케이션을 최적화하기 위해 코드를 자동으로 알아서 마이그레이션'한다는 건데요,
우리가 익히 쓰고 있는 useMemo, useCallback, React.memo 와 같은 메모이제이션 기법들은
React 에게 입력이 변경되지 않았다면 특정 부분을 다시 계산할 필요가 없다고 알릴 수 있어 업데이트 시 작업량을 줄일 수 있지만,
메모이제이션을 적용하는 것을 잊거나 잘못 적용할 수 있어 의도사항과 다르게 앱이 동작할 수 있는 문제가 있습니다.
React 컴파일러는 컴포넌트와 Hook 을 정적으로 분석해, 값이 바뀌지 않았다면 컴포넌트 리렌더링을 자동으로 건너뛰는 자동 메모이제이션 기능을 수행합니다. 또한 React 바깥에서 실행되는 무거운 계산도 자동으로 캐싱하며, React의 규칙을 기반으로 코드를 분석하기 때문에 예측 가능성과 안정성이 높습니다. 이로써 개발자가 직접 작성하지 않아도, 자동으로 불필요한 메모이제이션을 줄이고, 성능을 최적화할 수 있다는 게 React 컴파일러의 가장 큰 장점이 됩니다.
// 예시 코드
function FriendList({ friends }) {
const onlineCount = useFriendOnlineCount();
return (
<div>
<span>{onlineCount} online</span>
{friends.map(f => (
<FriendCard key={f.id} friend={f} />
))}
<MessageButton />
</div>
);
}
위와 같은 컴포넌트가 있다고 할 때, 기존 React 에서는 friends 가 변경되지 않아도
FriendCard, MessageButton 이 리렌더링 될 수 있는데, React 컴파일러는 자동으로
friends 의 참조가 그대로라면 FriendCard 까지 리렌더링할 필요 없다고 판단해
자동으로 메모이제이션을 적용하고, 실제 렌더링 스텝에서 리렌더링을 건너뜁니다.
먼저 React 컴파일러는 ESLint 플러그인을 제공하는데 eslint-plugin-react-hooks 를 설치하면, 에디터에서 React 의 규칙 위반 사항을 확인할 수 있습니다.
npm install --save-dev babel-plugin-react-compiler@rc
npm install --save-dev eslint-plugin-react-hooks@^6.0.0-rc.1
설치가 완료되었으면 Babel 설정을 해야 되는데, 반드시 가장 먼저 실행되는 플러그인어야 합니다.
// babel.config.js
const ReactCompilerConfig = {
target: '18' // '17' | '18' | '19'
};
module.exports = function () {
return {
plugins: [
['babel-plugin-react-compiler', ReactCompilerConfig],
],
};
};
vite 를 사용하고 있다면, vite-plugin-react 에 플러그인을 추가할 수 있습니다.
// vite.config.js
const ReactCompilerConfig = { /* ... */ };
export default defineConfig(() => {
return {
plugins: [
react({
babel: {
plugins: [
["babel-plugin-react-compiler", ReactCompilerConfig],
],
},
}),
],
// ...
};
});
NextJS 에 대한 자세한 정보는 공식문서를 확인해주세요.
React 규칙을 지키지 않은 코드는 최적화 되지 않으며, JavaScript 의 동적 특성 때문에 컴파일러가 완벽하게 판단할 수 없는 경우도 있으므로 주의가 필요합니다. 또한 특정 컴포넌트가 컴파일러와 충돌 나서 동작하지 않는다면, "use no memo" 지시어를 컴포넌트 상단에 추가해 컴파일러 적용을 제외할 수 있습니다. 주의할 점은, 한 번 컴포넌트나 Hook 을 제외하면 해당 지시어가 제거될 때까지 컴파일에서 제외되므로 꼭 필요한 경우에만 지시어를 사용할 것을 권장합니다.