React Compiler: Everything You Need to Know
Mohamed Jubair님의 포스트 React Compiler: Everything You Need to Know를 번역하였습니다.
원본 바로가기
우리가 리액트 코드를 메모이제이션과 리렌더링 문제를 신경쓰지 않고도 작성할 수 있다면 어떨까요? 이게 바로 React 19(곧 다가올 널리 사용되는 자바스크립트 유저 인터페이스 생성 라이브러리의 메이저 버전)가 제공하기 약속한 것입니다. 이것은 메모이제이션과 리렌더링 과정을 컴파일러 아키텍쳐로 옮김으로써 간단하게 만드는 것을 목표로 합니다. 이 글에서는 컴파일러가 필요한 이유와 그것이 해결하는 과제에 대해서 살펴보겠습니다.
서론
최근의 블로그 게시물에서 리액트팀이 Actions, Directive, Document Metadata 및 Asset Loading과 함께 React 컴파일러를 포함하여 리액트 19에서 배포될 것으로 예상되는 몇가지 흥미로운 기능을 공개하였습니다.
그들은 또한 프로덕션에서 이미 인스타그램에 적용중인 새로운 컴파일러에 대해 언급하였습니다. 그리고 그들은 컴파일러의 첫 번째 오픈소스 버전을 출시하기 위해 노력하고 있습니다.
리액트의 근본 원리를 이해하는 것으로 이제 시작하겠습니다.
리액트의 멘탈 모델
리액트는 '애플리케이션 상태 변화에 따른 UI 리렌더링'이라는 핵심 원칙으로 작동합니다. 이것은 개발자들이 UI의 암시적으로 DOM을 어떻게 조작할 것인지 단계별 지시를 작성하기 보다는 원하는 최종 상태를 묘사하게 해줍니다.
내부적으로, 리액트는 가상 DOM이라는 현명한 전략을 선택합니다. 그러면 이 in-memory UI 표현은 리액트가 효율적으로 업데이트 필요한 특정 DOM 요소들 을 판별하도록 해줍니다. 애플리케이션 상태 변화에 따라, 리액트는 실제 DOM과 가상 DOM을 비교하고, 수정이 필요한 사항의 최소한의 구성을 짚어주고, 정확하게 실제 DOM을 업데이트합니다.
하지만 여기에서 한 가지 문제가 있는데, 그것은 리액트가 성능 문제의 원인이 되는 불필요한 리렌더를 발생킨다는 것입니다.
불필요한 리렌더들
리액트의 반응성은 강점이지만, 그것은 때로 과도한 리렌더를 야기합니다. 자바스크립트의 객체나 배열 같은 복잡한 데이터 구조들을 비교하는게 계산적으로 비싸기 때문입니다. 만약 컴포넌트가 새로운 객체나 배열을 매 렌더마다 생성한다면, 콘텐츠가 실제로 변경된 아닐지라도, 리액트 안에서는 불필요한 리렌더가 발생할 수 있습니다.
이걸 방지하려면, 개발자들은 메모이제이션 기술을 사용해서 컴포넌트들을 의도적으로 최적화해 리액트가 데이터가 정말로 변경되었을 때만 업데이트되독 해야합니다.
메모이제이션이란?
리액트에서 메모이제이션은 입력 매개변수를 기반으로 비싼 계산이나 컴포넌트 결과를 저장하고 재사용하는 성능 최적화 기술입니다. 주요 목적은 컴포넌트의 불필요한 리렌더링을 방지하고, 이에 따라 전체적인 리액트 애플리케이션의 효율성을 향상시키는 것입니다.
리액트는 컴포넌트를 메모이제이션 할 수 잇는 다양항 방법을 제공하여, 리렌더링을 방지하고 있습니다.
React.memo
props가 변경되지 않았을 때 컴포넌트 리렌더링을 건너뛸 수 있게 해주는 고차함수입니다.
const MemoizedComponent = React.memo((props) => {
// Component logic here
});
useMemo
리렌더 사이의 계산결과를 캐시해주는 리액트 훅입니다.
const memoizedResult = useMemo(() => {
// Expensive computation
}, [dependency1, dependency2]);
useCallback
리렌서 사이의 함수 정의를 캐시해주는 리액트 훅입니다.
const memoizedCallback = useCallback(() => {
// Callback logic
}, [dependency1, dependency2]);
현재로는, 개발자들이 데이터가 변경될 때 앱의 리렌더 부분을 직접 제어하기 위해서 이러한 useMemo, useCallback, memo와 같은 API들이 필요합니다. 이건 좀 고통입니다! 이것은 코드를 어지럽히고, 에러를 발생시키기 쉬우며, 지속적인 유지보수를 필요로 합니다. 이것은 또한 리액트 멘탈 모델의 핵심 원칙에서 멀어지게 합니다. 리액트는 지금 애플리케이션 상태에 기반하여 선언적으로 렌더링하기 보다는 암시적으로 우리가 UI를 어떻게 렌더할 것인지 설명하도록 하고 있습니다.
컴파일러의 필요성
전통적으로, 리액트는 JSX 코드를 브라우저를 위한 최적화된 자바스크립트 파일로 변환하는 번들링이라고 불리는 과정을 사용합니다. 새로운 컴파일러는 이 개념을 한 단계 확장합니다. 그것은 컴포넌트 간의 구조와 의존성을 이해하여 더 깊은 곳에서부터 코드를 분석합니다.
이렇게 하면 리액트는 개발자들이 리액트에 대해 어떻게 생각하고 적용해야하는 지에 대한 멘탈 모델을 바꾸지 않고도 자동으로 리렌더 행위를 최적화하게 됩니다. 이게 리액트를 위한 최적화된 컴파일러를 개발하 는데 투자하는 이유입니다. - 이것은 업데이트에 대해서 리액트가 더 똑똑할 수 있게 도와줍니다.
이것에 대해 생각할 수 있는 한가지 방법은 리액트가 현재로는 객체의 식별이 변했을 때 리렌더 하는 것입니다. 새 컴파일러로는, 깊은 비교를 위한 런타임 비용발생 없이도 리액트는 의미있는 값의 변화가 있을 때 리렌더합니다.
리액트 컴파일러로의 이동
리액트 컴파일러가 제공해줄 수 있는 잠재적인 효과는 부정할 수 없습니다. 이 프로젝트가 진행됨에 따라, 우리는 리액트 애플케이션이 어떻게 빌드되고 최적화되는지에 대한 중요한 변화를 예상해볼 수 있으며, 이 변화는 핵심적인 성능 향상, 간소화된 개발자 경험 그리고 코드 유지보수에 대한 향상으로도 이어진다고 예상할 수 있습니다.
이것은 리액트의 미래에 대한 중요한 움직임입니다. 이것은 지속적으로 프레임워크를 향상시키고 개발자들이 뛰어난 사용자 경험을 만들어낼 수 있도록 하는 리액트팀의 지속적인 노력에 대한 입증입니다.