Files
2nd/10_Wiki/Topics/Coding/Frontend_React_Compiler_Deep.md
T
2026-05-10 22:08:15 +09:00

7.1 KiB

id, title, category, status, source_trust_level, verification_status, created_at, updated_at, tags, tech_stack, applied_in, aliases
id title category status source_trust_level verification_status created_at updated_at tags tech_stack applied_in aliases
frontend-react-compiler-deep React Compiler — 자동 memoization deep Coding draft B conceptual 2026-05-09 2026-05-09
frontend
react
compiler
vibe-coding
language applicable_to
TS / React
Frontend
React Compiler
React Forget
automatic memoization
ESLint react-compiler
useMemoCache

React Compiler Deep

React 19 의 stable feature. Compiler 가 useMemo / useCallback / React.memo 자동. 사용자 가 plain code, compiler 가 optimize.

📖 핵심 개념

  • Babel plugin 가 transform.
  • 매 component 의 hook 자동 추가.
  • Rules of React 가 baseline.
  • ESLint plugin 가 violation 감지.

💻 코드 패턴

옛 (manual)

const sorted = useMemo(() => items.sort(), [items]);
const onClick = useCallback((id) => handle(id), [handle]);

const Item = React.memo(({ item }: ItemProps) => {
  return <div>{item.name}</div>;
});

새 (compiler)

// 그냥 plain.
const sorted = items.sort();
const onClick = (id) => handle(id);

const Item = ({ item }: ItemProps) => {
  return <div>{item.name}</div>;
};

// Compiler 가 자동 memoize.

Setup (Vite)

import reactCompiler from 'babel-plugin-react-compiler';

export default {
  plugins: [
    react({
      babel: { plugins: [['babel-plugin-react-compiler', { target: '19' }]] },
    }),
  ],
};

Setup (Next.js 15+)

// next.config.js
module.exports = {
  experimental: {
    reactCompiler: true,
  },
};

ESLint

yarn add -D eslint-plugin-react-compiler

# .eslintrc.json
{
  "plugins": ["react-compiler"],
  "rules": { "react-compiler/react-compiler": "error" }
}

→ Violation 가 compile 못 함.

Output (compiled)

// Input
function Counter({ count, onIncrement }) {
  return <button onClick={onIncrement}>{count}</button>;
}

// Output (대략)
function Counter(props) {
  const $ = _c(2);
  let t0;
  if ($[0] !== props.count || $[1] !== props.onIncrement) {
    t0 = <button onClick={props.onIncrement}>{props.count}</button>;
    $[0] = props.count;
    $[1] = props.onIncrement;
    $[2] = t0;
  } else {
    t0 = $[2];
  }
  return t0;
}

_c = useMemoCache (자동 cache).

Rules of React (compile baseline)

// ❌ Component 안 mutation 외부
let counter = 0;
function Counter() {
  counter++;       // 외부 mutation
  return <div>{counter}</div>;
}

// ✅ State / ref 사용
function Counter() {
  const [count, setCount] = useState(0);
  return <div>{count}</div>;
}

Mutation 안 됨

// ❌ Props mutation
function Item({ item }) {
  item.name = item.name.toUpperCase();  // mutation
  return <div>{item.name}</div>;
}

// ✅ 새 object
function Item({ item }) {
  const upper = item.name.toUpperCase();
  return <div>{upper}</div>;
}

Effect dependency

// Compiler 가 useEffect 도 optimize.
useEffect(() => {
  doSomething(value);
}, [value]);

// → 자동 dependency tracking (compiler 가 보장).

→ Linter 가 dep 체크 가 unnecessary 가 됨.

useMemo / useCallback 가 obsolete?

대부분: yes.
- Compiler 가 자동.
- 더 정확.

남은 use case:
- Manual fine-grained control.
- Compiler 옵트아웃 file.
- 매우 expensive computation (compiler 가 보장 X).

React.memo 가 obsolete?

대부분: yes.
- Compiler 가 component 자동 memo.

남은:
- 외부 lib component (compiler 가 못 보는).
- 정밀 prop comparison.

"use no memo" (옵트아웃)

'use no memo';

function Component() {
  // Compiler 가 optimize X.
}

→ 안 optimize 의 file.

Performance gain

Real-world:
- 10-30% 빠름 (개발자 실수 fix).
- 큰 list = 더 큰.
- 작은 component = 작은.

→ "Manual perfect 한 코드" = gain 0.
"Manual 부족 한 코드" = 큰 gain.

Side effect detection

function Component() {
  // ❌ Render 중 side effect
  localStorage.setItem('x', 'y');
  
  return <div />;
}
// → Compiler 가 거부.

// ✅
useEffect(() => {
  localStorage.setItem('x', 'y');
}, []);

Conditional hook (안 됨)

// ❌
if (cond) {
  useState(0);   // hook 가 conditional
}

// ✅
const [x, setX] = useState(cond ? 0 : null);

Closure stale (자동 fix)

// 옛 (stale)
function Component({ value }) {
  const onClick = useCallback(() => log(value), []);  // dep 빠짐 = stale
  return <button onClick={onClick} />;
}

// Compiler:
const onClick = () => log(value);  // 자동 dep tracking.

→ Compiler 가 stale closure bug 감소.

Not a silver bullet

Compiler 가 안 fix:
- Logic bug (correct 동작 X).
- Network / async race.
- DOM manipulation 직접.
- Effect 의 timing.

→ Quality 가 매우 ↑ but not magic.

Compatibility

React 18: 부분 (experimental).
React 19+: stable.
React Native 0.75+: 가능.

Production 사용

  • Meta (FB): 큰 internal.
  • Anthropic Claude: 모든 React 가 compiled.
  • Vercel / Next: native.
  • 다양 modern app.

Migration

1. Existing app (no compiler).
2. ESLint react-compiler 활성.
3. Violation fix (1-2 일).
4. Compiler 활성.
5. Manual memo 점차 제거.

Bundle size

Compiler: 0 (build-time).
useMemoCache: 작은 runtime addition.
React 19 자체: 약간 작음.

Common violation

- Mutation in render.
- 외부 변수 변경.
- Hook 가 conditional.
- Side effect render 중.
- Function 안 hook 호출.

→ ESLint 가 모두 catch.

Testing

// React Testing Library
test('counter', () => {
  const { getByText } = render(<Counter />);
  fireEvent.click(getByText('+'));
  expect(getByText('1')).toBeInTheDocument();
});

→ Compiler 가 transparent. Test 가 same.

Devtools

React DevTools 가 compiled component:
- "Memo" badge.
- Cache hit / miss visible.

→ Profiler 가 도움.

Profiler

import { Profiler } from 'react';

<Profiler id="App" onRender={(...) => log(...)}>
  <App />
</Profiler>

Future

- Compiler stable (현재).
- Compiler 가 RSC 도 optimize.
- React Native 도.
- "Plain code, compiler 가 fast" 가 standard.

vs Solid / Svelte 5 (signal)

React Compiler: VDOM + memo.
Solid: signal (no VDOM diff).
Svelte 5: rune (signal).

→ React 가 backwards compatible.
Solid / Svelte 가 더 빠름 (specific).

🤔 의사결정 기준

상황 추천
New React app React 19 + Compiler
Existing Gradual migrate
Specific opt-out "use no memo"
Library author Compile by default
Manual control useMemo (rare)
큰 perf gap Profile + Million.js

안티패턴

  • Manual memo + compiler: redundant.
  • Mutation in render: violation.
  • ESLint 무시: silent break.
  • Compiler 가 fix all: profile.
  • "use no memo" 모든 file: pointless.
  • Side effect render 중: violation.

🤖 LLM 활용 힌트

  • React Compiler = automatic memo (React 19+).
  • ESLint react-compiler 가 violation catch.
  • Manual useMemo 가 obsolete.
  • Plain code → compiler 가 optimize.

🔗 관련 문서