본문 바로가기
React

2021.08.20 React 코드 스플리팅

by 해맑은 코린이 2021. 8. 20.

2021.08.20 React 코드 스플리팅_정리노트

 

약간 이제는 리액트의 개념보다는 다양한 기능들을 리액트에 적용시키는 느낌으로 가고 있다..! 프로젝트를 빼면 리.다.기 완독이 얼마 남지 않았다..! 화이텡

 

코드 스플리팅

리액트뿐만 아니라 자바스크립트로 애플리케이션을 개발하게 되면, 기본적으로 하나의 파일에 모든 로직들이 들어가게 되는데, 프로젝트의 규모가 커질수록 자바스크립트 파일의 용량이 커지겠지!! 그러면 인터넷이 느린 환경에서는 첫 페이지 로딩 속도도 현저히 느려질 것이다. 

코드 스플리팅을 하게 되면, 지금 당장 필요한 코드가 아니라면 따로 분리 시켜서 , 나중에 필요할 때 불러와서 사용할 수 있다. 이를 통해서 페이지의 로딩속도를 개선!

이는 웹팩이라는 도구가 담당하는데, 꼭 리액트뿐만 아니라 다른 프레임워크에서도 사용가능! 웹팩에서 별다른 설정을 하지 않으면, 프로젝트에서 사용 중인 모든 자바스크립트 파일이 하나의 파일로 합쳐지고, 모든 CSS 파일도 하나의 파일로 합쳐진다.

 

 

CRA ( create-react-app ) 로 프로젝트를 빌드할 경우 최소 두 개 이상의 자바스크립트 파일이 생성되는데, 기본 웹팩 설정으로 SplitChunks 라는 기능이 적용되어 node-modules 에서 불러온 파일, 일정 크기 이상의 파일, 열러 파일 간에 공유된 파일을 자동으로 분리시켜서 캐싱 (속도가 느린 디스크의 데이터를 속도가 빠른 메모리로 가져와서 메모리상에서 읽고 쓰는 작업) 의 효과를 제대로 누릴 수 있게 해줌!! 

 

 

쨋든 우리는 리액트에서 빌드 작업을 배워보자.

 

$ yarn create react-app spliting-sample
$ cd spliting-sample

// build 명령어를 통해 빌드 파일 생성 
$ yarn build

 

 

 

그럼 build 파일이 생성되고, 안의  파일 이름을 보면, 빌드하는 과정에서 해당 파일의 내용에 따라 해시값이 포함되어 생성된다.

 

 

해시란 특정 알고리즘이나 방법을 이용해서 원문을 다른 문장으로 변경시키는 단방향 암호화 기법으로 인해 으로 해시함수를 이용하여, 고정된 길이의 비트열로 변경하는 것을 말하고, 해시함수를 이용해서 매핑 후 데이터의 값이 바로 해시값..!

 

 

음음 쨋든 이 해시값을 통해 브라우저가 새로 파일을 받아야 할지 받지 말야아 할지 알 수 있다. 

 

현재 js 파일에서 2로 시작하는 파일에는 React,ReactDOM 등 node_module 에서 불러온 라이브러리 관련 코드가 들어있고, main 으로 시작하는 파일에는 직접 프로젝트에 작성하는 App 같은 컴포넌트에 대한 코드가 들어있다. 

 

 

 

 

 

오옹 근데 2로 시작하는 파일이랑 main 으로 시작하는 파일의 길이가 확연히 다른데, SpiltChunks 라는 웹팩 기능을 통해 자주 바뀌지 않는 코드들이 2로 시작하는 파일에 들어있기 때문에 캐싱의 이점을 더 오래 누릴 수 있다네.

 

 

그럼 2로 시작하는 빌드 파일들은 자주 안바뀐다고 했으니까, App 을 변경하면 main 은 어케될려남.

 

src/App

 

App 컴포넌트를 바꾸고,

 

$ yarn build

 

다시 빌드해주면,

 

 

 

 

헐랭 main 만 해시값이 바꼈다. 신기하균. 

 

 

 

이렇게 파일을 분리하는 작업을 코드 스플리팅이라고 하고, 프로젝트 기본 탑재된 SplitChunks 기능을 통한 코드 스필리팅은 단순히 효율적인 캐싱 효과만 있을 뿐이다.

 

 

그러면 아까 로딩속도를 개선하기 위해서 사용한다고 했는데, 만약 SPA 를 개발할 때, 총 A,B,C 페이지가 있다면, 사용자가 A 페이지에 방문했을 때의 로딩속도를 개선하려면 B,C 페이지의 파일을 분리해야 할텐데, 별도로 설정을 하지 않으면 A,B,C 파일이 모두 main 한 파일에 저장되어 버린다. 프로젝트의 규모가 커지면 커질수록 그럼 한 파일의 크기가 매우 커지겠군. 그러면 로딩이 오래 걸려 사용자 경험, 트래픽이 모두 많아지는 결과를 초래한다. 

 

 

 

그럼 이 때 쓸 수 있는 코드 스플리팅 방법은 무엇일까!

 

코드 비동기 로딩

자바스크립트 함수, 객체, 혹은 컴포넌트를 처음에는 불러오지 않고 필요한 시점에 불러와서 사용하기.

 

오느른~~~ 코드 스플리팅 방법 중 하나인 코드 비동기 로딩을 리액트에서 어떻게 하는지 정리 같이 ㄱ ㄱ

 

리액트에 적용하기 전에 자바스크립트에서 먼저 함수 코드 비동기 로딩을 해봅씨단.

 

 

src/notify.js ( 새로 생성 )

 

 

 

 

이렇게 하고 만약에 첫 화면에서 문구를 클릭했을 때 해당 함수가 실행되려면 원래는 이렇게 했음.

 

 

src/App

 

이렇게 상단에 import 를 해와서, 함수를 써주고 실행시키는데, 이렇게 하고 빌드를 하게 되면 notify 코드가 main 파일에 들어가 버림.

 

그런데,

 

 

내부에서 import 함수의 형태로 메서드 안에서 사용하면, 파일을 따로 분리시켜서 저장된다. 그리고 실제 함수가 필요한 시점에 파일을 불러와서 함수를 사용할 수 있다 . 

 

 

저기서 dynamic-import 가 뭐지 하고 찾아보니까 표준은 아니지만 

춣처 - https://tc39.es/

 

요 출처 사이트에서 정의되어 있음. 웹팩에 있는 기능으로 저런 형식으로 쓰면 될 것 같다!

 

이제 실행!

 

실행 화면

 

 

개발자도구의 network 탭에서 확인해보면, 해당 글자를 클릭하는 시점에 chunk.js 라는 파일이 뜨고 내용은 notify 에 관련된 내용만이 뜨게 된다. 

 

다시 yarn build.

 

 

 

 

 

3으로 시작되는 부분에는 notify 관련 코드가 따로 들어가는 것을 확인할 수 있다!

 

 


 

음음 이제 자스에서 이렇게 하는 걸 봤으니 리액트에서 컴포넌트 코드 스플리팅을 할 차례!

 

코드 스플리팅을 위해서는 리액트에 내장된 기능으로 유틸 함수인 React.lazy 를 사용하는 방법과, Suspense 컴포넌트가 있다. 

리액트 16.6v 부터 도입된 기능이며, 이전에서는 import 함수를 통해 불러와 컴포넌트 자체를 state 에 넣는 방식으로 구현해야 한다.

 

밑에처럼 말이즤

 

src/SplitMe.js ( 새로 생성 )

 

 

src/App (클래스 컴포넌트로 변환) 

 

 

실행 화면

 

 

요롷게 해주는게 마냥 어려운건 아니지만서도, 매번 state 를 선언해주어야 하는 점이 불편할뿐..!

 

 

그래서 React.lazy를 사용함!

 

얘를 사용하면 state 를 따로 선언하지 않고도 간편하게 컴포넌트 코드 스플리팅을 할 수 잇다. 

 

const SpitMe = React.lazy(() => import('./SplitMe'));

 

여기에 리액트 내장 컴포넌트인 Suspense 컴포넌트를 사용하여 코드 스플리팅된 컴포넌트를 로딩하도록 발동시킬 수 있고, 로딩이 끝나지 않았을 때의 보여줄 UI 도 설정해줄 수 있음!

 

import React, { Suspense } from 'react' ; 


<Suspense fallback = {<div> loading... </div>}>
	<SplitMe />
 </Suspense>

 

 

src/App ( 다시 함수형으로 )

 

얘는 클래스형이 필요없으므로 다시 함수형으로 전환!

 

이렇게 두 개를 적용해주고, 개발자도구 Network 탭에서 

 

 

로딩 속도를 늦게해주는 버튼을 클릭하고 (Disable cache 체크 박스 옆 탭 ) 실행하게 되면, 

 

 

loading 중 문구가 나타나고 클릭하는 시점에 chunk.js 를 불러옴!!

 


 

코드 스플리팅 라이브러리도 사용해볼까낭

 

Loadable Components

코드 스플리팅을 편하게 하도록 도와주는 서드파티 라이브러리.

이 라이브러리의 장점은 서버 사이드 렌더링을 지원함! 다음장에서 자세히 다루겠지만 

출처 - 내 블로그 

이러한 느낌으로 리액트 같은 SPA 에선 기본적으로 클라이언트 사이드 렌더링이지만, 검색 엔진의 최적화, 초기 렌더링 성능 등의 장점이 있지. 쨋든 얘가 사용이 가능하다는 점과, ( React.lazy, Suspense 는 지원하지 않음 ) 렌더링하기 전에 필요할 때 스플리팅된 파일을 미리 불러올 수 있는 기능도 있다.

 

 

설치하고 시작쓰

$ yarn add @loadable/component

 

 

사용법은 React.lazy 와 매우 비슷. 또 Suspense 컴포넌트를 사용하지 않고 이렇게 UI 를 보여주게 됨.

 

src/App

 

이렇게!

 

 

또 preload 라는 함수를 사용하면,

 

마우스를 갖다대기만 해도 로딩이 시작되어 파일을 불러오고 클릭했을 때는 똑같이 UI 가 렌더링 된다. 

 

 

그 밖에도 타임 아웃, 로딩 UI 딜레이, 서버 사이드 렌더링 호환등의 기능들은 

출처 - 공식문서 https://loadable-components.com/docs/delay/

 

 

공식문서에서 확인할 수 있다!!! 서버 사이드 렌더링을 만약 한다면 , 리액트 공식문서에서도 Loadable Component 를 사용하라고 권장하고 있다. 만약 서버 사이드 렌더링을 하지 않는다면 , React.lazy, Suspense 만으로도 구현 충분!!

 

출처 - 리액트 공식문서

 

 


 

오.. 오늘은 조금 짧...? 지 않..? 나? ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ 휴..... 이제 여러 가지 개념들이 나오면서 코드들을 어떻게 활용하고 잘 쓸 수 있을건지가 나오넴.... 휴 어렵다... 하지만 이럴수록 기초 또 읽고 또 읽는중.. 역시 블로그는 내가 보라고 만든게 맞는듯하다 ㅎㅁㅎ 

그럼 쌍콤하게 오늘의 포스팅 끝!

댓글