---
id: frontend-react-compiler-deep
title: React Compiler — 자동 memoization deep
category: Coding
status: draft
source_trust_level: B
verification_status: conceptual
created_at: 2026-05-09
updated_at: 2026-05-09
tags: [frontend, react, compiler, vibe-coding]
tech_stack: { language: "TS / React", applicable_to: ["Frontend"] }
applied_in: []
aliases: [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)
```tsx
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)
```tsx
// 그냥 plain.
const sorted = items.sort();
const onClick = (id) => handle(id);

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

// Compiler 가 자동 memoize.
```

### Setup (Vite)
```ts
import reactCompiler from 'babel-plugin-react-compiler';

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

### Setup (Next.js 15+)
```js
// next.config.js
module.exports = {
  experimental: {
    reactCompiler: true,
  },
};
```

### ESLint
```bash
yarn add -D eslint-plugin-react-compiler

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

→ Violation 가 compile 못 함.

### Output (compiled)
```tsx
// 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)
```ts
// ❌ 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 안 됨
```ts
// ❌ 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
```tsx
// 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" (옵트아웃)
```tsx
'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
```tsx
function Component() {
  // ❌ Render 중 side effect
  localStorage.setItem('x', 'y');
  
  return <div />;
}
// → Compiler 가 거부.

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

### Conditional hook (안 됨)
```tsx
// ❌
if (cond) {
  useState(0);   // hook 가 conditional
}

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

### Closure stale (자동 fix)
```tsx
// 옛 (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
```tsx
// 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
```tsx
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.

## 🔗 관련 문서
- [[Frontend_Million_Optimization]]
- [[React_useMemo_When_Not_To]]
- [[React_Rendering_Optimization]]
