diff --git "a/10\354\236\245/\352\271\200\353\217\231\352\267\234.md" "b/10\354\236\245/\352\271\200\353\217\231\352\267\234.md" new file mode 100644 index 0000000..aa9b297 --- /dev/null +++ "b/10\354\236\245/\352\271\200\353\217\231\352\267\234.md" @@ -0,0 +1,170 @@ +# 10장 리액트 17과 18의 변경 사항 살펴보기 + +#스터디-리액트딥다이브 +현재 리액트로 운영중인 웹 애플리케이션은 16버전을 가장 많이 사용하고 있다. 함수형 컴포넌트와 훅으로 인해 고착화 된 듯 보이지만 최신 버전에 대해서 알아야 한다. + +## 10.1 리액트 17 버전 살펴보기 + +16버전과 Breaking Changes를 최소화 했다는 것을 가장 큰 특징으로 꼽는다. + +### 10.1.1 리액트의 점진적인 업그레이드 + +리액트는 시멘틱 버저닝 방법으로 업데이트를 진행하고 있다. 전체 애플리케이션이 17버전이지만, 일부 트리와 컴포넌트에 대해서만 18버전을 선택하는 점진적인 버전 업이 가능하다. +리액트 17 애플리케이션을 16을 내부적으로 Lazy하게 불러온다. 다만, 이것은 임시방편이고 한꺼번에 업데이트 하는것이 복잡성 감소 측면에 좋다. + +### 10.1.2 이벤트 위임 방식의 변경 + +그냥 버튼의 이벤트 핸들러는 DOM을 직접 참조해서 가져오고 onclick 함수를 직접 추가한다. 하지만 리액트 버튼의 이벤트 핸들러는 아무런 동작도 하지 않는다. +이벤트 타입당 하나의 핸들러를 루트에 부착한다. (이벤트 위임) + +- **캡처:** 이벤트 핸들러가 최상단 -> 실제 이벤트 타깃 요소 까지 내려가는 것을 의미 +- **타깃:** 이벤트 핸들러가 노드에 도달하는 단계 +- **버블링:** 이벤트가 발생한 요소에서부터 시작해 최상위 요소까지 다시 올라간다. + +**이벤트 위임**이란 이런 원리를 이용해 상위 컴포넌트에만 이벤트를 부착하는 것을 말한다. 결국, 자식 요소와 상관없이 상위 컴포넌트에서만 관리하면 되기에 효율적이다. +리액트 17부터는 이벤트 위임이 document가 아닌 컴포넌트 최상단 트리인 루트요소로 변경 되었다. + +- 점진적 업그레이드 지원 및 다른 바닐라 자바스크립트 코드 또는 JQuery 등이 혼재 되어 있는 경우 혼란을 방지하기 위해서다. + +### 10.1.3 import React from ‘react’가 더 이상 필요 없다: 새로운 JSX transform + +16 버전에는 `import React from 'react'` 코드가 없다면 에러가 발생했다. 17 버전 부터는 “바벨과 협력하여 이런 import 구문 없이도 jsx를 변환할 수 있다.” + +```sh +npx react-codemod update-react-imports +``` + +명령어를 통해 기존에 추가된 구문들을 모두 삭제할 수 있다. eslint를 활용하는 방법도 있다. + +### 10.1.4 그 밖의 주요 변경 사항 + +#### 이벤트 풀링 제거 + +SyntheticEvent 풀을 만들어서 이벤트가 발생할 때마다 가져오는 것을 의미한다. + +- 비동기 코드로 이벤트 핸들러에 접근하기 위해서 별도 메모리 공간에 합성 이벤트 객체를 할당 +- 모던 브러우저에서는 이와 같은 방식이 성능 향상에 크게 도움이 되지 않는다. + 2가지 잉로 이벤트 풀링 개념이 삭제 되었다. + +#### useEffect 클린업 함수의 비동기 실행 + +16버전 까지는 클린업 함수가 동기적으로 처리 되었다. 17버전 부터는 비동기적으로 실행된다. 즉, 화면 업데이트가 완전히 끝난 이후 실행된다. + +#### 컴포넌트의 undefined 반환에 대한 일관적인 처리 + +17 부터 undefined가 반환되는 경우 에러가 정상적으로 발생. 18부터는 undefiend를 반환해도 에러가 발생하지 않는다. + +### 10.1.5 정리 + +16버전을 사용하고 있다면 17버전으로 업데이트하는 것을 권장한다. + +## 10.2 리액트 18 버전 살펴보기 + +리액트 18의 가장 큰 변경점은 동시성 지원이다. + +### 10.2.1 새로 추가된 훅 살펴보기 + +#### useId + +컴포넌트별로 유니크한 값을 생성하는 훅이다. + +#### useTransition + +UI 변경을 가로막지 않고 상태를 업데이트할 수 있는 리액트 훅이다. 무거운 렌더링 작업을 조금 미룰 수 있다. 마치 async await처럼 동시성을 다룰 수 있는 훅이다. + +#### useDeferredValue + +컴포넌트 트리에서 리렌더링이 급하지 않은 부분을 지연할 수 있게 도와주는 훅이다. 디바운스와 비슷하지만, 고정된 지연 시간 없이 렌더링 완료된 이후에 실행한다. +useTransition과의 차이는 state를 업데이트를 하는 함수를 감싸서 사용하는 반면, useDeferredValue는 state 값 자체만을 감싸서 사용하는 것을 볼 수 있다. + +- 직접 변경 가능 = useTransition +- 불가능 = useDeferredValue + +#### useSyncExternalStore + +리액트 17의 useSubscription이 리액트 18 대체된 훅이다. useTransition이나 useDeferredValue 같은 훅으로 인해 동시성 이슈가 발생할 수 있다. 내부적으로는 처리 되어있지만, 값을 사용하는 외부에서는 값이 찢어지는 테어링 현상이 일어 날 수 있다. 이러한 문제를 해결하기 위한 훅이다. +이 훅의 외부 스토어 데이터 변경 또한 리렌더링을 발생시킬 수 있다. + +#### useInsertionEffect + +CSS-in-js 라이브러리를 위한 훅이다. DOM이 실제로 변경되기 전에 동기적으로 실행된다. 브라우저가 레이아웃을 계산하기 전에 실행될 수 있게끔 해서 좀 더 자연스러운 스타일 삽입이 가능해진다. + +### 10.2.2 react-dom/client + +클라이언트에서 리액트 트리를 만들 때 사용되는 API가 변경됐다. + +#### createRoot + +기존의 react-dom에 있던 render 메서드를 대체할 새로운 메서드이다. + +#### hydrateRoot + +서버 사이드 렌더링 애플리케이션에서 하이드레이션을 하기 위한 새로운 메서드이다. + +### 10.2.3 react-dom/server + +#### renderToPipeableStream + +리액트 컴포넌트를 HTML로 렌더링하는 메서드이다. 클라이언트에서는 중간에 script를 삽입하는 등의 작업을 할 수 있다. + +#### rederToReadableStream + +웹 스트림을 기반으로 작동한다는 차이가 있다. + +### 10.2.4 자동 배치 + +여러 상태 업데이트를 하나로 묶어서 성능을 향상시키는 방법을 의미한다. Priomise를 사용해 고의로 실행을 지연시키는 sleep 함수를 호출하지 않으면 버전과 상관없이 동일하게 한 번만 렌더링 된다. +이런 자동 배치를 하고싶지 않거나, 이런 방식이 기존 코드에 영향을 미칠 것 으로 예상된다면 `flushSync`를 사용하자. + +### 10.2.5 더욱 엄격해진 엄격 모드 + +#### 리액트의 엄격 모드 + +리액트에서 제공하는 컴포넌트 중 하나로, 잠재적인 버그를 찾는 데 도움이 되는 컴포넌트이다. + +- 더 이상 안전하지 않은 특정 생명주기를 사용하는 컴포넌트에 대한 경고 +- 문자열 ref 사용 금지 + - 여러 컴포넌트에 걸쳐 사용될 수 있으므로 충돌의 여지가 있다. + - 어떤 ref에서 참조되고 있는지 파악하기 어렵다. + - 컴포넌트 ref의 값을 추적해야 하기에 성능이슈가 있다. +- findDOMNode에 대한 경고 출력 +- 구 Context API 사용 시 발생하는 경고 +- 예상치 못한 부작용(Side-Effect) 검사 + +#### 리액트 18에서 추가된 엄격 모드 + +컴포넌트 트리에서 해제 되더라도 내부 상태값은 유지 되는 기능 추가를 위한 엄격모드를 추가 했다. + +```생각 & 의견 +https://ko.vuejs.org/guide/built-ins/keep-alive +Vue에서는 Keep-Alive라고 별도 컴포넌트로 제공해주고 있어요! +``` + +### 10.2.6 Suspense 기능 강화 + +기존의 문제점들이 있었다. + +- 컴포넌트가 보이기 전에 useEffect가 실행 되는 문제가 존재했다. +- 서버에서 사용할 수 없다. + 위의 문제들을 해결했다. + +```생각 & 의견 +Next.js(13, react 18)에서 Suspense 사용할 때 그냥 되나요?? 저는 안되는 것 던데... +``` + +### 10.2.7 인터넷 익스플로러 지원 중단에 따른 추가 폴리필 필요 + +- Promise +- Symbol +- Object.assign + 이 3가지 기능을 지원한다라는 가정하에 리액트는 배포된다. 지원안하는 경우 폴리필이 필요하다. + +### 10.2.8 그 밖에 알아두면 좋은 사항 + +- undefined 반환은 null 반환과 동일하게 처리된다. +- 도 null과 동일하게 처리된다. +- renderToNodeStream이 지원 중단되었다. renderToPieableStream을 사용하는 것이 권장된다. + +### 10.2.9 정리 + +리액트 18버전의 핵심은 동시성 렌더링이다. 많은 기능이 추가 되었지만, 핵심은 점진적으로 기능을 채택할 수 있게 하는 것이다. 앞으로 개발할 애플리케이션에서 동시성 모드를 염두에 두고 있다면 사용하고자 하는 라이브러리가 이를 완벽하게 지원하는지 검토가 필요하다.