[React] 공식 블로그 러버덕

dee·2023년 1월 26일
2

react

목록 보기
6/6
post-thumbnail

🤔 공식 블로그를 읽게 된 계기?

최근 2주간 러버덕 중심으로 Be real FE 스터디 친구들과 공부하고 있다. 이번에 React 공식 문서를 읽으면서 새로 추가된 내용들이 있었고 이에 조금 더 이해하기 위해 최근 블로그 내용을 읽으며 러버덕을 하게 되었다. React v17, 18에 대한 이해한 일부 내용을 블로그로 정리해보자.


1. Changes to Event Delegation

이벤트 핸들러가 React 17버전부터 더이상 document level에 붙이지 않게 되었다. document level에 이벤트 핸들러를 등록한 것은 e.stopPropagation()호출할 때 문제점이 발견되곤 했기 때문이다. e.stopPropagation()가 호출되도 이벤트의 주체는 document가 되기 때문에 여전히 해당 이벤트를 받는다. 이런 문제로 17버전은 가까운 rootNode에 이벤트 핸들러를 등록하고 있다.


2. Event Pooling

이전에는 이벤트 풀링을 썼었지만 React 17버전부터는 쓰지 않는다. 16 버전에서는 이벤트 핸들러가 호출된 후에 SyntheticEvent objects를 재사용하고 모든 속성들을 null처리를 했다. 그렇기에 아래 예시와 같이 e.persist를 호출하지 않으면 setTimeout안의 e.target에 접근하지 못하고 에러가 났다. 이는 React를 사용하는 개발자들에게도 혼동을 주었다.

// React 16
function handleChange(e) {
  e.persist();

  setTimeout(() => {
    console.log(e.target.value); 
  }, 100);
}

하지만 React 17 버전에서는 Evnet pooling optimization을 제거했기 때문에 e.persisit를 호출하지 않아도 개발자가 예상하는 대로 작동을 하고 있다.


3. New JSX Transform

React는 초창기 JSX라는 것을 통해 개발자들이 익숙한 HTML처럼 마크업을 작성할 수 있도록 했다. 그리고 내부적으로 React.createElement함수를 사용하여 브라우저가 이해할 수 있도록 변환해주었다. 하지만 이는 곧 JSX를 사용하기 위해서 React와 React.createElemetn가 있어야 컴파일할 수 있다는 의미였다. 또한 React.createElement에서 허용하지 않는 몇 가지 성능 향상과 단순화가 있다고 한다.(아직 이부분은 무슨 의미인지 알 수 없다.)
React 17 버전은 이러한 이슈를 해결하고자 bable과 typescript와 같은 컴파일러에서 사용할 수 있는 new entry point를 React 패키지에 도입했다. 이 new entry point는 특수 함수를 자동으로 임포트하여 JSX를 변환한다. 이로 인해 더이상 React 컴포넌트를 만들 때 import React from 'react'구문이 필요없게 되었다.


4. render에서 createRoot로 바뀜

ReactDOM.render는 React 18 버전부터는 지원하지 않는다. 대신에 createRoot를 사용하고 있다. 새로운 root API를 지원함으로써 공학적 관점에서 보다 나은 root 관리를 할 수 있고 concurrent renderer(동시성 렌더)를 지원한다고 한다.

import { createRoot } from 'react-dom/client';
const container = document.getElementById('app');
const root = createRoot(container); // createRoot(container!) if you use TypeScript
root.render(<App tab="home" />);

5. Automatic batching

React 18 이전에는 React 이벤트 핸들러 내에 setState한해서 batching이 되고 있었다. React 18에서 createRoot로 업데이트되면서 모두 자동적으로 batching되게 되었다. 이는 timout, promise, native event Handler안의 업데이트와 또다른 이벤트들도 React 이벤트 핸들러와 같이 자동적으로 batching이 된다는 의미이다.

batching을 해지하고 싶으면 flushSync를 사용하면 된다.


6. Update StrictMode

React 18 버전에서 모든 component가 처음 mount될 때마다 자동으로 unmount하고 다시 mount할 수 있도록 한다. 그리고 두 번째 mount에서는 이전 state 값을 기억하여 갖는다.(회복한다.) 이는 React 공식문서에서 보여주는 메세지를 보면 이해가 더 잘 된다.

// React 18 이전
* React mounts the component.
    * Layout effects are created.
    * Effect effects are created.
// React 18
* React mounts the component.
    * Layout effects are created.
    * Effect effects are created.
* React simulates unmounting the component.
    * Layout effects are destroyed.
    * Effects are destroyed.
* React simulates mounting the component with the previous state.
    * Layout effect setup code runs
    * Effect setup code runs

7. concurrent rendering

React 18 업데이트에서 가장 중요한 부분이라고 생각한다. 왜냐 이 concurrent가 suspense, startTransition 등과 관련이 있기 때문이다.

concurrent에 대해 찾아보면 CS의 개념 concurrent/parallel를 알고 나니 조금 와닿았다. concurrent는 동시에 실행되는 것처럼 보이는 것이고 parallel는 실제로 동시에 작업이 처리 되는 것이다. 이를 보면 React는 결국 자바스크립트를 사용하는 라이브러리이니 자바스크립트를 따라야 되는데 자바스크립트는 다중 코어를 이용하지 않는다. 이에 자바스크립트는 이벤트 루프를 사용하여 다중 코어를 이용하지 않는 한계점을 해결하려 했다. 이처럼 React도 concurrent 개념을 통해 동시성을 도입하겠다는 의미를 담고 있음을 이해했다.

concurrent rendering은 문서와 다른 블로그 글을 읽어보면 1차적으로 이해가 되었지만 아직 내가 내 글로 정리하기엔 이해가 되지 않았다. 이는 앞으로 더 공부를 하면서 업데이트를 해야겠다.


참고 자료
리액트 공식문서
https://programming119.tistory.com/242
https://nesoy.github.io/articles/2018-09/OS-Concurrency-Parallelism

profile
웹 프론트엔드 개발자

0개의 댓글