🌽 크리티컬 렌터링 패스
이미 공부했더랬지
- 웹 페이지의 성능을 높이기 위해서는 리플로우와 리페인트를 줄여야 함
- JS로 보여지는 여부를 결정해야 한다면, transform이나 opacity를 사용하는 것 권장 (display, position 노놉)
- 이 속성들은 GPU가 관여할 수 있는 속성이기 때문에 리플로우 생략됨
- 프로젝트의 규모가 커질수록, 리페인트와 리플로우 최적화에 신경쓰기 => 리액트가 도와줌
🌽 가상 DOM
- 리액트는 가상 DOM 2개 소유 중
- 렌더링 이전의 화면 구조를 나타내는 DOM / 렌더링 이후 화면 구조를 나타내는 DOM
- 브라우저는 DOM 트리나 Render 트리를 만들고 직접 다루는 것에 비해 리액트는 그저 객체 형태로만 DOM을 갖고 있기 때문에 아주 가벼움
리액트의 렌더링 단계
1. render phase : 컴포넌트들이 가상 DOM으로 구성되는 단계
- 컴포넌트 파일들을 해석하여 실제 돔과 똑같은 구조의 트리 형태로 가상 DOM 생성
- 이전 DOM과 비교하여 변경된 요소들 찾기 => 이를 diffing이라 함
- 굉장히 효율적인 알고리즘 사용
- 속성값만 변경되었다면 속성값만 업데이트
- 태그나 컴포넌트가 변경되었다면 해당 노드를 포함한 하위의 모든 노드 제거 & 새 걸로 교체
- Reconciliation (재조정) 단계 진행
- 변경된 요소들만 찾아 실제 브라우저 화면에 반영
- 리액트의 이 과정이 효율적인 이유 = Batch Update 덕분
- 변경된 요소들을 집단으로 묶어 한번에 적용시키는 방식이 Batch Update
2. commit phase : 가상 DOM을 실제 DOM에 반영하는 단계
- 다시 파싱하는 방식이 아님 - 렌더 트리를 새로 만들지 않음. 필요한 부분만 갱신
- 리액트가 가상 DOM을 사용해 변경사항을 계산한 뒤, 필요한 부분에 대한 DOM 조작 명령을 브라우저에 전달
- 브라우저는 변경된 부분에 대해서만 리플로우, 리페인트 진행
가상 DOM은 어떤 점에 있어서 성능에 도움이 되는건데?
- 가상 DOM없이 DOM을 여러 번 조작하면 리페인트와 리플로우가 계속 반복
- 가상 DOM은 변경사항들을 모아 한 번에 적용함으로써 리페인트와 리플로우 최소화
- setState를 여러번 호출해도 마지막 내용만 반영되는 것도 이러한 이유
🌽 컴포넌트 파일 확장자
.js
- 일반적인 자바스크립트 파일 형식
- 트랜스파일러로 인해 JSX도 사용이 가능함 (가능하긴 하지만 JSX는 .jsx에서 사용하자)
.jsx
- HTML 마크업을 편하게 작성하기 위해 개발된 새로운 언어 형식
.tsx
.ts
🌽 패키지
react-scripts
: CRA에서 사용할 수 있는 스크립트 모음. 웹팩, 바벨과 같은 스크립트 포함
@vitejs/plugin-react
: swc. 리액트에서 웹팩과 바벨의 역할을 하는 패키지
🌽 클래스형 컴포넌트 & 함수형 컴포넌트
- 아직 2가지 방식 모두 지원하고 있지만, 함수형 컴포넌트를 사용하자
클래스형 컴포넌트
- 리액트 초기 컴포넌트 형식
- 함수형 컴포넌트에 비해 복잡
함수형 컴포넌트
- 최근 사용하는 컴포넌트 형식
- 함수형 컴포넌트가 초기에는 리액트의 생명주기를 다루지 못해 사용하기에 문제가 있었음
- 리액트 16.8부터 생명주기를 다룰 수 있는 리액트 훅을 제공하면서 함수형 컴포넌트가 매우 효율적인 방식이 됨
리액트 훅
- useState, useEffect, useContext, useReducer, useRef
🌽 리액트에서의 CSS 스타일링
기본 스타일
- 인라인 스타일 : style 속성 사용
- 외부 스타일 : 별도의 css 파일에 작성하고 import하는 방식
- 부모 요소가 아닌 제일 하위의 자식 요소에서 css 파일을 import해도 전역에 반영됨
- css modules : 특정 컴포넌트에만 종속되는 css 코드 작성 방식. 파일명
*.module.css
- 직관적으로 사용하기 위해 컴포넌트명과 파일명 일치시킴 + 같은 폴더 내에 위치
CSS-In-JS
- tailwind css
- styled-components
- emotion
- vanila extract
관련 라이브러리 or 패키지
- classnames 패키지 : 조건에 따라 클래스명을 동적으로 결합하거나 관리할 때 유용 (서드파티 라이브러리)
- 서드파티 라이브러리 : 외부의 제 3자 개발자가 제공하는 코드나 도구
import classNames from "classnames/bind";
import styles from "./Header.module.css";
...
const cx = classNames.bind(styles);
return <h1 className={cx("title", "decoration", { test: true })}>제목</h1>
import classNames from "classnames";
import classNamesBind from 'classnames/bind';
...
return (
<header>
<h1 className={cx("title", "decoration")}>제목</h1>
<h2 className={classNames("title", { decoration: false })}>부제목</h2>
</header>
);
📌 출처
수코딩(https://www.sucoding.kr)