개요
리액트 19 버전의 출시가 얼마 남지 않았습니다. 이번 업데이트에서 특히 주목받는 주제는 '리액트 컴파일러'인데요. 이 컴파일러는 이미 인스타그램의 서비스 환경에서 테스트되고 있으며, 앞으로 메타의 다른 서비스에도 확대될 예정입니다. 오픈 소스로도 공개 준비 중인 리액트 컴파일러가 무엇인지, 또 어떤 이점을 제공하는지 정리해 보았습니다.
컴파일러의 동작 방식
컴파일러는 고수준 프로그래밍 언어의 소스 코드를 컴퓨터가 이해할 수 있는 기계어로 변환하는 도구입니다
소스 코드를 컴파일하고 기계어를 생성하기 위해 따라야 할 여러 단계가 있습니다.

- 어휘분석
어휘 분석기는 코드에서 각각의 단어를 토큰으로 분리합니다.
int
,main
,(
,)
,{
,int
,x
,=
,5
,;
,int
,y
,=
,10
,;
,int
,z
,=
,x
,+
,y
,;
,return
,z
,;
,}
이 토큰들은 컴파일러에 의해 저장되어 이후 단계에서 사용됩니다.
- 구문분석
구문 분석 단계에서는 어휘 분석에서 만들어진 토큰을 모아 코드의 구조를 이해할 수 있는 트리 형태로 정리합니다. 이 트리 구조를 추상 구문 트리라고 부릅니다.
예를 들어, 구문 분석기는 다음과 같은 구조를 만들어냅니다:

- 의미분석
구문이 맞더라도 의미가 맞는지 분석하는 단계입니다.
- 변수가 선언된 이후에 사용되는지
- 변수 타입이 일치하는지
- 반환 값이 올바른 타입인지
- 중간코드(IR) 생성
의미 분석이 끝나면 중간 코드가 생성됩니다. 소스 코드와 기계어 사이의 중간 단계로 생성되는 코드입니다. 중간코드는 특정 하드웨어나 운영체제에 종속되지 않습니다.
예를 들어, 아래 C 코드가 있다고 할 때:
int x = 5;
int y = 10;
int z = x + y;
이를 중간 코드로 변환하면:
t1 = 5
t2 = 10
t3 = t1 + t2
이렇게 x
, y
, z
대신 t1
, t2
, t3
와 같은 임시 변수를 사용해 값들을 저장합니다. 중간 코드는 수학적인 연산이나 변수 할당을 표현하기 위해 간결한 명령어 형식으로 구성되므로, 여러 플랫폼에서 기계어로 변환하기 쉽고, 최적화하기에 용이한 구조입니다.
- 최적화
중간 코드가 생성된 후, 컴파일러는 이를 최적화하여 더 효율적인 코드를 만듭니다. 예를 들어, 만약 z
가 사용되지 않는다면, 이를 최적화할 수 있습니다.
- 기계어 생성
최종 단계에서는 최적화된 중간 코드를 실제 기계어로 변환합니다. 각 명령어는 CPU에서 실행 가능한 기계어 명령으로 바뀝니다. 예를 들어, 컴파일러는 다음과 같은 x86 기계어를 생성할 수 있습니다:
MOV R1, 5 ; 레지스터 R1에 5 저장
MOV R2, 10 ; 레지스터 R2에 10 저장
ADD R3, R1, R2 ; R1과 R2를 더한 값을 R3에 저장
MOV R0, R3 ; R3의 값을 반환 (R0에 저장)
이와 같은 방식으로 컴파일러는 고수준의 소스 코드를 기계어로 변환합니다.
리액트 컴파일러
React 컴파일러는 React 앱을 자동으로 최적화해주는 도구입니다. 컴파일러가 앱의 코드를 분석하고 필요 없는 재렌더링을 줄여주기 때문에, 개발자가 복잡한 최적화 코드를 추가하지 않아도 성능을 향상시킬 수 있습니다.
빌드 과정에서만 작동하므로, 코드 수정 없이도 기존 JavaScript와 함께 잘 작동합니다. 또한, ESLint 플러그인을 포함하고 있어서 코드 작성 시 컴파일러가 실시간으로 피드백을 주어, 최적화와 관련된 조언이나 경고를 확인하며 코딩할 수 있습니다.
컴파일러의 주요 구성 요소
리액트 컴파일러는 크게 3가지 중요한 부분으로 구성됩니다.
바벨 플러그인
- 바벨은 최신 JavaScript(ES6+)나 JSX 코드를 오래된 브라우저에서도 동작하는 형태로 변환해주는 도구입니다.
- JSX 문법을 일반적인 JavaScript로 변환해주는 일도 맡고 있습니다
ESLint 플러그인
- ESLint는 코드에 규칙을 적용하고 오류를 검사하는 도구입니다.
- 리액트와 관련된 잘못된 패턴이나 규칙 위반이 있는지 검사할 수 있습니다.
컴파일러 코어
- 컴파일러 코어는 컴파일러의 핵심 엔진입니다.
- 코드 분석과 최적화를 수행하는 역할을 하며, 이 엔진을 바탕으로 바벨 플러그인이나 ESLint 플러그인이 작동합니다.
기존 메모이제이션의 문제
React는 상태 변화 시 불필요하게 많이 다시 렌더링될 수 있습니다. 이를 해결하기 위해 useMemo
, useCallback
, memo
를 사용해 수동 메모이제이션 기법을 활용해 왔습니다. 그러나 이러한 수동 접근은 코드 복잡성을 증가시키고, 실수할 가능성을 높이며, 유지 관리에도 어려워지는 단점이 있습니다.
React 팀은 이러한 문제를 해결하기 위해 개발자가 직접 메모이제이션을 설정하지 않아도, 상태가 변경될 때 필요한 UI 부분만 자동으로 업데이트될 수 있는 방법을 모색해왔습니다. UI를 간단한 함수로 표현하고 표준 JavaScript를 사용해 많은 개발자들이 쉽게 접근할 수 있도록 만든 React의 접근 방식을 유지하며, 최적화할 컴파일러를 개발하기로 결정했습니다.
컴파일러 미리 사용해보기
리액트 19의 정식 출시 전 버전(RC)에는 기본적으로 필요한 파일들이 모두 포함되어 있지 않습니다. 그래서 리액트 19 프로젝트를 사용하려면, 몇 가지 필요한 파일들을 직접 설치하고, 컴파일러가 리액트를 제대로 처리할 수 있도록 설정을 해줘야 합니다.


- RC 버전 설치하기
npm install --save-exact react@rc react-dom@rc
- 컴파일 설정 전 코드베이스가 호환되는지 확인
npx react-compiler-healthcheck@experimental
이 명령을 실행하면 다음 세 가지를 점검해 줍니다:
- 최적화 가능 컴포넌트: 컴파일러가 최적화할 수 있는 컴포넌트가 얼마나 되는지 확인해 줍니다.
<StrictMode>
사용 여부 확인- 호환성 문제: 지금 프로젝트에 컴파일러와 충돌할 수 있는 라이브러리가 있는지 알려줍니다.
Next로 만든 블로그에 검사를 해봤는데 StrictMode usage not found.
에러가 떠서 next.config.js 에서 reactStrictMode를 설정해줬습니다.
StrictMode
는 React의 개발 도구로, 애플리케이션에서 잠재적인 문제를 미리 감지하고 경고해줍니다. 프로덕션 환경에는 영향을 주지 않으며, 주로 개발 모드에서만 활성화되어 다음을 검사합니다:
// next.config.js
module.exports = {
reactStrictMode: true,
};

- 리액트 컴파일과 관련된 ESLint 플러그인 설치
npm install eslint-plugin-react-compiler@experimental
리액트 컴파일러를 사용할 때 코드가 최적화 규칙을 잘 따르고 있는지 검사해주는 역할을 합니다. 리액트 컴파일러를 쓰려면 코드가 특정 규칙을 따라야 하는데, 이 플러그인을 설치하면 코드에서 컴파일러 규칙을 자동으로 체크해줘요.
설치 후 ESLint 설정 파일 .eslintrc(Vite의 경우 .eslintrc.cjs
)에서 다음을 추가하세요.
module.exports = {
plugins: ["eslint-plugin-react-compiler"],
rules: {
"react-compiler/react-compiler": "error",
},
};
- 리액트 컴파일용 바벨 플로그인을 설치
npm install babel-plugin-react-compiler@experimental
Babel이 코드 변환을 수행하면서 리액트 컴파일러의 최적화 규칙을 적용할 수 있습니다.
설치가 완료되면 바벨 설정 파일 babel.config.js
에 옵션을 추가하여 설정을 완료해야 합니다. Vite를 사용하고 있으므로 vite.config.js
파일을 열고 내용을 다음 코드로 교체해주세요.
// babel.config.js
const ReactCompilerConfig = {
/* ... */
};
module.exports = function () {
return {
plugins: [
["babel-plugin-react-compiler", ReactCompilerConfig], // must run first!
// ...
],
};
};
//vite.config.js
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
react({
babel: {
plugins: [["babel-plugin-react-compiler"]],
},
}),
],
});
리액트 컴파일러의 기능을 활용하기 위해 설정을 완료했습니다. 이제부터 리액트 컴파일러를 사용해 최적화된 리액트 앱을 가지게 되었습니다!! 🎉 리액트 컴파일러는 프로젝트의 모든 컴포넌트와 훅을 검토하여 최적화를 시도할 것입니다.
더 이상 코드에서 memo
, useMemo()
, 또는 useCallback()
을 사용할 필요가 없습니다 ! ✨
리액트 개발자 도구에서의 리액트 컴파일러

리액트 DevTools 버전 5.0 이상은 리액트 컴파일러에 대한 내장 지원을 제공합니다. 리액트 컴파일러에 의해 최적화된 컴포넌트 옆에 Memo
텍스트가 있는 배지를 볼 수 있습니다.
마무리
지금 까지 useMemo와 useCallback, memo를 직접 사용해서 메모이제이션을 했었는데, 이제 리액트 컴파일러가 나온다면 DX도 매우 올라갈 것 같습니다 . 편리하게 최적화도 하고, 유지보수가 더욱 편해질 것 같아요. 빨리 컴파일된 버전이 나와서 적용해보고 싶습니다. XD
참고 블로그
https://www.freecodecamp.org/news/react-compiler-complete-guide-react-19/
https://react.dev/learn/react-compiler
https://react.dev/blog/2024/02/15/react-labs-what-we-have-been-working-on-february-2024