코드 스플리팅 Code Splitting이란 말 그대로 코드를 분할하여 큰 번들파일을 쪼개서 작은 사이즈의 파일로 만드는 것이다. 그렇다면 코드를 왜 분할하는 것일까?

위의 사진은 cra-bundle-analyzer을 사용한 번들 분석 결과이다.
webpack-bundle-analyzer도 있지만 지금은 CRA로 만든 프로젝트를 분석해본 것이기 때문에 cra-bundle-analyzer를 사용했다. 물론 eject를 하거나 craco 같은 별도의 라이브러리를 통해 webpack-bundle-analyzer를 사용해도 된다.
분석 결과를 보면 refractor라는 것이 번들의 절반을 차지하고 있다. 그럼 이것이 무엇인지 확인하려면 package-lock.json을 한 번 살펴보자!
확인해 보니 코드 문법을 하이라이팅 시키는 react-syntax-highlighter라이브러리에 필요한 라이브러리로써 사용되고 있었다.
1
2
3
4
5
6
7
8
9
10
11
12
13
"react-syntax-highlighter": {
"version": "12.2.1",
"resolved": "생략",
"integrity": "생략",
"requires": {
"@babel/runtime": "^7.3.1",
"highlight.js": "~9.15.1",
"lowlight": "1.12.1",
"prismjs": "^1.8.4",
// 여기서 사용 됨
"refractor": "^2.4.1"
}
},
이것을 확인했다고 해서 최적화를 어떻게 진행할 수 있을까? 먼저 이 라이브러리가 어디에서 쓰이는 지 확인해 봐야 할것이다. 현재 이 라이브러리는 게시글의 상세화면에서만 사용하고 있다.
즉, 게시물 전체를 보여주는 화면에서는 굳이 로딩될 필요가 없는 것이다! 이 때 바로 Code Splitting을 사용하여 불필요한 리소스를 줄이고 페이지의 로딩속도를 향상시킬 수 있다.
Code Splitting의 패턴
코드 스플리팅은 몇 가지의 패턴을 가지고 있다.
- 페이지 별로 코드를 분할
- 모듈 별로 코드를 분할 (여러 페이지에서 같은 모듈을 사용할 경우)
- 위의 두 가지 방법을 적절히 섞은 방법
코드 스플리팅의 가장 핵심은 불필요한 코드, 중복된 코드 없이 적절한 사이즈의 코드가 적절한 타이밍에 로드되도록 하는 것이다.
Code Splitting 방법
자세한 내용은 React 공식 홈페이지에서 확인할 수 있다.
가장 간단하게는 React Router라이브러리를 사용해서 라우트 기반의 코드 스플리팅을 하는 것이다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import React, { Suspense, lazy } from 'react';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
const Home = lazy(() => import('./routes/Home'));
const About = lazy(() => import('./routes/About'));
const App = () => (
<Router>
<Suspense fallback={<div>Loading...</div>}>
<Switch>
<Route exact path="/" component={Home}/>
<Route path="/about" component={About}/>
</Switch>
</Suspense>
</Router>
);
하지만 이렇게 한다고 해서 바로 사용할 수 있는 것이 아니다! 😱 코드 스플리팅을 하는 주체는 리액트가 아니라 웹팩이기 때문에 웹팩에서 별도의 설정을 해줘야 한다!
CRA로 프로젝트를 구성했을 경우 별도의 설정을 할 필요는 없다!
위 코드와 같이 코드 스플리팅을 했을 경우 번들 분석결과는 아래와 같다.

처음과 다르게 react-dom 부분이 별도로 분리된 모습을 볼 수 있다!
Lighthouse 결과

오우 🚀 중간에 진행했던 몇몇의 최적화와 코드 스플리팅을 하는 것 만으로도 51점에서 96점이 되었다!!
하지만 이것은 production 모드에서 측정을 한 것이 아니라 development 모드에서 진행한 것이다. 성능 측정은 production 모드에서 측정을 해야한다. 그 이유는 웹팩 설정에 따라 production 모드에서는 코드를 minify 하거나 uglify 하기 때문에 development와 성능차이가 있을 수 있기 때문이다
텍스트 압축
서버에서 보내는 리소스를 압축해서 서비스를 하는 것이다! 이렇게 하면 다운로드 하는 리소스의 크기가 줄어들어 더 빠르게 컨텐츠를 로드할 수 있다.

네트워크 탭에서 현재 요청하고 있는 API의 응답 헤더를 살펴보면 Content-Encoding에 gzip이라고 되어 있는 부분이 있다 이 의미는 gzip이라는 인코딩 방식을 통해 압축되어 있다는 의미이다.

이와 반대로 빌드된 main.js를 보면 응답 헤더에서는 Content-Encoding를 찾아볼 수 없다. 이 의미는 번들링된 파일은 압축되어 있지 않다는 의미이다.
웹상에서 사용하는 압축 알고리즘에는 보통
gzip과Deflate이 있다. gzip이 Deflate보다 높은 압축률을 가지고 있다.
그리고, 압축여부를 확인할 때 응답 헤더에서 확인되는 것으로 유추했을 때 클라이언트에서 하는게 아니라 번들 파일을 서비스 해주는 서버에서 해줘야 한다.
유의해야 할 점
서버에서 압축 설정이 되어 있는데 네트워크 탭을 보면 어떤 파일은 gzip으로 압축이 잘 되어 있고, 어떤 파일은 압축이 되어있지 않는 경우도 있을 것이다. 그 이유는 서버에서 압축을 하면 클라이언트에서는 압축을 해제해야 하는데 무분별하게 모든 파일을 압축해버리면 오히려 시간이 더 걸릴 수도 있기 때문이다.
보통
2kb를 기준으로 압축 유무를 결정한다.
느낀점
텍스트 압축은 정말 가성비 좋은 최적화 방법인것 같다. 물론 서버에서도 설정해야 하지만