제목 날짜 내용 발행일 23.03.23
해당 포스트는
코드 분할 (Code Spliting)에 대해 학습한 내용을 정리하며 기록한 내용입니다.
React.lazy()와 Suspense 기능을 알기 전에 코드 분할(code spliting)에 대해 알면 조금 더 이해하기가 쉽다고 한다.
대부분 React 앱들은 Webpack, Rollup과 같은 툴을 사용해 번들링(Bundling)한다.
HTML 웹 페이지에 JavaScript를 쉽게 추가할 수 있기 때문이다.
번들된 앱은 모든 JavaScript가 한 곳에 있기 때문에 페이지를 설정하는 데 필요한 호출 수가 적은 링크 태그 하나만 필요하게 된다.
과거에는 이렇게 해도 무리가 없었다.
모던 웹 이전의 웹 JavaScript 코드는 최소한의 수준으로 작성되었기 때문이다.
![[그림] 이제 브라우저 JavaScript 엔진이 해석해야 하는 JavaScript 코드 양이 많아지게 되었습니다.](https://velog.velcdn.com/images/abc2752/post/992f19d1-a71f-4c50-ae8f-55c95ea9a8b8/image.png)
그러나 이제는 번들링하게 되면 특정 지점에서 코드를 해석하고 실행하는 정도가 느려지게 되었다.
모던 웹으로 발전하면서 점점 DOM을 다루는 정도가 정교해지며 JavaScript 코드 자체가 방대해지고 무거워졌기 때문이다.
![[그림] 코드 분할 아이디어 : 번들을 나눈 뒤 필요한 코드만 불러오면 어떨까?](https://velog.velcdn.com/images/abc2752/post/98f57e2f-ea0c-45fb-8717-ebdbb17ff8a1/image.png)
“그렇다면 어느 페이지에서 코드를 해석하고 실행하는 정도가 느려졌는지 파악해서 번들을 나눈 뒤에 지금 필요한 코드만 불러오고 나중에 필요한 코드는 나중에 불러올 수 있지 않을까??”
이것이 코드 분할의 핵심 아이디어다.
번들이 거대해지는 것을 방지하기 위한 좋은 해결 방법은 번들을 물리적으로 나누는 것이다.
코드 분할은 런타임 시 여러 번들을 동적으로 만들고 불러오는 것으로, Webpack, Rollup과 같은 번들러가 지원하는 기능이다.
따라서 코드 분할을 하게 되면 지금 당장 필요한 코드가 아니라면 따로 분리를 시키고, 나중에 필요할 때 불러와서 사용할 수 있다.
이를 통하여 대규모 프로젝트의 앱인 경우에도 페이지의 로딩 속도를 개선할 수 있게 된다.
번들링 되는 파일에는 앱을 만들면서 npm을 통해 다운받는 서드파티(Third Party) 라이브러리도 포함이 된다.
서드파티 라이브러리는 개인 개발자나 프로젝트 팀, 혹은 업체등에서 개발하는 라이브러리로, 즉 제 3자 라이브러리다.
서드파티 라이브러리는 플러그인이나 라이브러리 또는 프레임워크 등이 존재하며, 이 라이브러리를 잘 사용하면 편하고 효율적인 개발을 할 수 있다.
그러나 서드파티 라이브러리는 사용자에게 다양한 메소드를 제공하기 때문에 코드의 양이 많고, 번들링 시 많은 공간을 차지한다.
따라서 사용 중인 라이브러리의 전부를 불러와서 사용하는 것보다 따로 따로 불러와서 사용할 수 있다면 많은 공간을 차지하지 않을 수 있게 된다.
/* 이렇게 lodash 라이브러리를 전체를 불러와서
그 안에 들은 메소드를 꺼내 쓰는 것은 비효율적이다.*/
import _ from 'lodash';
...
_.find([]);
/* 이렇게 lodash의 메소드 중 하나를 불러와 쓰는 것이
앱의 성능에 더 좋다.*/
import find from 'lodash/find';
find([]);
해당 코드는 lodash라는 라이브러리를 예시로 하고 있다.
lodash는 배열, 숫자, 객체, 문자열을 사용할 때 반복적인 작업 같은 것을 할 시 사용하기에 좋은 라이브러리다.
lodash라는 라이브러리는 하나의 폴더와 같고, 그 폴더 안에는 개발 시 다양한 상황에 쓰기 좋은 메소드들, 즉 함수 코드들이 들어 있다.
이 함수 코드들의 양이 상당하기 때문에 전부 가져올 시, 정말로 필요한 것 한두 개만 쓰인다면 나머지는 그냥 쓰이지 않는 코드 뭉치로 앱 내부에 남게 된다.
이는 앱의 성능을 저하시킬 요지가 있기 때문에, 필요한 것 한두 개만 가져다 쓰는 식으로 개발하는 것이 훨씬 좋다.
React는 SPA(Single-Page-Application)인데, 사용하지 않는 모든 컴포넌트까지 한 번에 불러오기 때문에 첫 화면이 렌더링 될때까지의 시간이 오래걸린다.
그래서 사용하지 않는 컴포넌트는 나중에 불러오기 위해 코드 분할 개념을 도입했다.
React에서 코드 분할하는 방법은 dynamic import(동적 불러오기)를 사용하는 것이다.
그 전까지는 코드 파일의 가장 최상위에서 import 지시자를 사용해 사용하고자 하는 라이브러리 및 파일을 불러오는 방법을 사용했었다. 이를 static import(정적 불러오기)라고 한다.
/* 기존에는 파일의 최상위에서 import 지시자를 이용해 라이브러리 및 파일을 불러왔습니다. */
import moduleA from "library";
form.addEventListener("submit", e => {
e.preventDefault();
someFunction();
});
const someFunction = () => {
/* 그리고 코드 중간에서 불러온 파일을 사용했습니다. */
}
기존에는 항상 import 구문은 문서의 상위에 위치해야 했고, 블록문 안에서는 위치할 수 없는 제약 사항이 있었다.
왜냐하면 번들링 시 코드 구조를 분석해 모듈을 한 데 모으고 사용하지 않는 모듈은 제거하는 등의 작업을 하는데, 코드 구조가 간단하고 고정이 되어 있을 때에야만 이 작업이 가능해지기 때문이었다.
그러나 이제는 구문 분석 및 컴파일해야 하는 스크립트의 양을 최소화 시키기 위해 dynamic import 구문을 지원한다.
form.addEventListener("submit", e => {
e.preventDefault();
/* 동적 불러오기는 이런 식으로 코드의 중간에 불러올 수 있게 됩니다. */
import('library.moduleA')
.then(module => module.default)
.then(someFunction())
.catch(handleError());
});
const someFunction = () => {
/* moduleA를 여기서 사용합니다. */
}
이런 식으로 dynamic import를 사용하게 되면 불러온 moduleA 가 다른 곳에서 사용되지 않는 경우, 사용자가 form을 통해 양식을 제출한 경우에만 가져오도록 할 수 있다.
dynamic import는 then 함수를 사용해 필요한 코드만 가져온다.
가져온 코드에 대한 모든 호출은 해당 함수 내부에 있어야 한다.
이 방식을 사용하면 번들링 시 분할된 코드(청크)를 지연 로딩시키거나 요청 시에 로딩할 수 있다.
이 dynamic import는 React.lazy 와 함께 사용할 수 있다.