React를 사용하면 특별한 최적화 작업을 하지 않아도 빠른 사용자 인터페이스를 제공하지만 몇가지 속도를 높일 수 있는 방법이 있다.
프로덕션 빌드 활용
- 축소된 프로덕션 빌드
- React의 수많은 유용한 경고 이용하여 개발하기
- React의 경고는 React를 크고 느리게 하기 때문에 앱을 배포할 때 '프로덕션 버전' 을 사용해야 한다
- React Developer Tools for Chrome ( extension ) 을 설치하여 빌드 프로세스가 올바르게 설정 되었는지 확인할 수 있다.
앱을 개발할때는 개발 모드
사용자에게 앱을 배포할 때는 프로덕션 모드
프로덕션 용도의 앱을 제작할 수 있는 방법
1. Create React App
- npm run build 명령어를 실행하면 프로젝트의 build/ 폴더에 애플리케이션의 프로덕션 빌드 파일이 만들어집니다.
2. 단일 파일 빌드
- React 및 React DOM의 프로덕션 준비 버전을 단일 파일로 제공
// 예시
<script src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script>
* .production.min.js로 끝나는 React 파일만이 프로덕션 환경에 적합하다.
3. Brunch
Brunch 프로덕션 빌드
- npm 혹은 yarn 을 사용하여 terser-brunch 를 설치한다
- 프로덕션 빌드를 생성하기 위해 build 명령어에 -p 플래그를 추가한다.
// 예시
brunch build -p
- 효율성을 위해 개발환경에서는 -p 플래그를 추가하지 말아야 한다
4. Browserify
- npm 혹은 yarn 을 사용하여 Browserify 를 설치한다
- envify 변환은 productiond으로 설정하고 전역(-g)로 변환합니다.
- uglifyify 변환은 개발에서만 사용하는 package를 제거하고 전역 (-g)로 변환시킵니다.
- 최종 bundle은 mangling을 위해 terser로 연결합니다.
// 예시
browserify ./index.js \
-g [ envify --NODE_ENV production ] \
-g uglifyify \
| terser --compress --mangle > ./bundle.js
- 효율성을 위해 개발환경에서는 적용하지 말아야 한다
5. Chrome Performance 탭으로 컴포넌트 프로파일링
- 개발자 도구에서 Performance 탭을 컴포넌트의 마운트, 업데이트, 해제 까지 시각화 할 수 있다.
- 일시적으로 Chrome 확장 프로그램을 비활성화 하고 프로파일링을 한다.
- 개발자 모드에서 애플리케이션이 실행 중인지 확인한다.
- 크롬 개발도구의 Performance 탭을 열고 Record 버튼을 클릭한다.
- 프로파일링 작업을 한다. 20초 이상 NO! 크롬이 멈출 수 있다.
- 기록을 멈추면 React 이벤트는 User Timing 라벨로 그룹화 된다.
- 현재는 Chrome, Edge, IE 만이 이 기능을 지원한다.
6. Profiler DevTools Profiler로 컴포넌트 프로파일링
react-dom 16.5 + 에서는 Profiler를 사용하여 개발 모드에서 향상된 프로파일링 기능을 제공한다.
7. 수백 수천행을 렌더링 하는 경우
애플리케이션에서 수백 수천행을 렌더링 해야하는 경우 'windowing' 이라는 기법을 사용하는 것을 추천한다. 주어진 시간에 목록의 부분 목록만 렌더링하며 컴포넌트를 다시 렌더링 하는데 걸리는 시간과 생성된 DOM의 노드의 수를 크게 줄일 수 있다.
잘 알려진 windowing 라이브러리
- react-window
- react-virtualized
8. Reconciliation ( 또는 "diffing" )를 최대한 피해야 한다
React 는 렌더링 된 UI의 internal representaion ( 내부 관리 ) 를 빌드하고 유지한다. 컴포넌트에서 반환하는 React 엘리먼트 포함. 이 과정에서 React는 "virtual DOM을 사용한다"
- 컴포넌트의 props 나 state에 변화가 생기면 reconciliation 과정을 통해 newly returned 된 엘리먼트와 전에 렌더링 된 엘리먼트를 비교하여 DOM을 update 할지 결정한다.
- re-renderinng 이 필요없는 확실한 컴포넌트에서 React.PureComponent를 사용하여 DOM 업데이트를 막을 수 있다. 혹은 shouldComponentUpdate 메소드의 return 값을 false로 하여 막을 수 있다.
만약 props 의 color 나 count 값이 변경 되었을때만 렌더링을 하고 싶을 시
// 예제
shouldComponentUpdate(nextProps, nextState) {
if (this.props.color !== nextProps.color) {
return true;
}
if (this.state.count !== nextState.count) {
return true;
}
return false;
}
ShouldComponentUpdate 대신 React.PureComponent를 사용할 수 있다.
// 예제
class ListOfWords extends React.PureComponent {
render() {
return <div>{this.props.words.join(',')}</div>;
}
}
class WordAdder extends React.Component {
constructor(props) {
super(props);
this.state = {
words: ['marklar']
};
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
// This section is bad style and causes a bug
const words = this.state.words;
words.push('marklar');
this.setState({words: words});
}
render() {
return (
<div>
<button onClick={this.handleClick} />
<ListOfWords words={this.state.words} />
</div>
);
}
}
- PureComponent 는 shallow comparison ( 얕은 비교 기법)을 사용하여 변화된 this.props.words의 값과 새로운 this.props.words의 값을 비교한다. 하지만 여기서 문제는 handleClick을 했을 때 this.props.words를 직접적으로 변화시켜서 shallow compare을 할때 변화된 값을 인지하지 못한다는 점이다.
- ES6의 스프레드 문법이나 ES8의 오브젝트 스프레드 분법을 사용하여 변경 전의 값을 유지해야 한다.
// spread syntax
handleClick() {
this.setState(state => ({
words: [...state.words, 'marklar'],
}));
};
// object spread syntax
function updateColorMap(colormap) {
return {...colormap, right: 'blue'};
}
'Web > React.js' 카테고리의 다른 글
[STUDY] Hook 개요 (0) | 2021.03.19 |
---|---|
[STUDY] Hook 소개 (0) | 2021.03.18 |
[STUDY] 고차 컴포넌트 (0) | 2021.03.16 |
[STUDY] Ref 전달하기 (0) | 2021.03.15 |
[STUDY] 컨텍스트 (0) | 2021.03.13 |
댓글