C.W.K.
Stream
Lesson 04 of 06 · published

React Compiler — 자동 memoization

~13 min · react-compiler, memoization, build

Level 0React 입문자
0 XP0/54 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete
10년 동안 React 개발자가 re-render 피하려고 useMemo + useCallback 뿌렸어. React Compiler 가 빌드 시 코드 읽고 그 memoization 자동 삽입. '혹시 모르니 다 감싸기' 시대 끝남.

뭘 함

React Compiler 는 Babel 플러그인 (그것 감싸는 Vite/Next 플러그인). JSX 분석하고 memoization 으로 이득 볼 값 감지. 그 다음 빌드 시 useMemo / useCallback 동등물 삽입. 런타임 출력이 모든 관련 값 수동 감싼 것처럼 동작 — 다만 본인은 안 함.

뭘 안 함

  • Semantic 안 바꿈. 컴포넌트 여전히 같이 동작; 단지 더 적게 렌더.
  • useState / useEffect / useContext 대체 안 함. 그것들은 state 와 side effect 용, memoization 아님.
  • 진짜 비싼 계산 최적화 안 함. Render 가 filterMassiveDataset(query) 하면 Compiler 가 dataset reference memoize 하지만 필터는 여전히 query 바뀌면 돔. (Perceived-speed 승리엔 useTransition 이나 useDeferredValue 와 짝.)

활성화 방법

본인 빌드 config 에 babel-plugin-react-compiler 추가. Vite: babel-plugin-react-compiler 설치, @vitejs/plugin-react 의 babel.plugins 옵션에 추가. Dev server 재시작. 끝.

Opt-in 탈출

특정 컴포넌트 동작이 compiler 가 안 바꿔야 할 identity-민감 re-render 의존하면 컴포넌트의 첫 문장으로 'use no memo' 디렉티브 추가. Compiler 가 스킵.

방어적으로 useMemo 손이 안 가게. Compiler 전엔 안 감싸기 비용 = 잠재적 re-render; 감싸기 비용 = 작은 memo allocation. 사람들이 '혹시 모르니' 다 감쌌어. Compiler 활성화 시 방어적 감싸기 = noise. 자연스러운 코드 작성; 빌드가 최적화하게.

Code

vite.config.ts — React Compiler 활성화·ts
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import tailwindcss from "@tailwindcss/vite";

export default defineConfig({
  plugins: [
    react({
      babel: {
        plugins: [
          // npm i -D babel-plugin-react-compiler
          ["babel-plugin-react-compiler", { /* 필요 시 옵션 */ }],
        ],
      },
    }),
    tailwindcss(),
  ],
});
Before vs after — 본인이 쓴 것 vs 도는 것·tsx
// 본인이 쓰는 것 (깔끔, 자연)
function Greeting({ name, tags }: { name: string; tags: string[] }) {
  const full = `Hello, ${name}!`;
  const sortedTags = [...tags].sort();
  const onClick = () => console.log(name);
  return (
    <div>
      <h1>{full}</h1>
      <TagList tags={sortedTags} onItemClick={onClick} />
    </div>
  );
}

// Compiler 가 emit 하는 것 (개념적) — 도움 됐을 자리에 memoized
function Greeting({ name, tags }: { name: string; tags: string[] }) {
  const full = $useMemo(() => `Hello, ${name}!`, [name]);
  const sortedTags = $useMemo(() => [...tags].sort(), [tags]);
  const onClick = $useCallback(() => console.log(name), [name]);
  return (
    <div>
      <h1>{full}</h1>
      <TagList tags={sortedTags} onItemClick={onClick} />
    </div>
  );
}

// 위는 본인이 작성. 아래는 compiler 가 emit. 아래가 name 과 tags 안 바뀐
// 동안 정렬된 array 와 콜백 재생성 안 함.

External links

Exercise

Bootstrap 프로젝트에 React Compiler 활성화. useMemo / useCallback 래퍼 가진 컴포넌트 골라. 제거. 앱 돌리고 동작 안 바뀌었는지 확인. React DevTools Profiler 열고 컴포넌트가 이전과 같은 횟수 re-render 하는지 확인. Compiler 가 뒤에서 memo 작업 하는 중.
Hint
DevTools 가 이전보다 더 많은 re-render 보이면 Compiler 가 활성화 안 됐을 수도 — babel 플러그인 로드 됐는지 확인 (빌드된 JS 에 react-compiler 찾아보거나 dev server 로그 확인).

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고
💛 by 똘이warm

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.