![[Webpack] 웹팩 최적화 1](https://img1.daumcdn.net/thumb/R750x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FS9iUR%2FbtsBVBbYCq9%2FrpvbfKursf7qbXCo7zIrN0%2Fimg.png)
* 웹팩 (webpack) 이란?
웹팩은 오픈 소스 자바스크립트 모듈 번들러로써
여러개로 나누어져 있는 파일들의
의존성을 해결하며
하나의 자바스크립트 코드로 압축 (번들링) 하고
최적화해서
성능 향상과 로딩 시간 단축을 위해 사용되는 라이브러리 이다.
* 모듈 (Module)
프로그래밍에서 독립적인 기능을 갖고 있는 작은 코드 조각을 말한다.
모듈은 일반적으로 특정 기능이나 작업을 수행하는 코드의 조각으로,
모듈화를 통해 코드를 세분화해서
유지보수성을 높이고 코드의 재사용성을 높일 수 있다.
* 번들러 (Bundler)
모듈 번들링(Module Bundling)을 수행하는 도구로,
여러 개의 모듈 (js파일, css파일, 이미지 등) 을 가져와서
이를 하나 또는 여러 개의 번들로 묶어주는 도구를 의미한다.
작업의 결과물을 번들(Bundle) 이라고 한다.
* 모듈 번들러 (Module Bundler) 란?
웹 애플리케션을 구성하는 자원 (HTML, CSS, JS, Image 등) 을
모두 각각의 모듈로 보고,
이를 조합해서 병합된 하나의 결과물을
만드는 도구 이다.
* 그렇다면 웹팩 이라는게 왜 나오게 됐을까?
Javascript의 모듈화의 한계 때문에 나오게 됐다.
javascript에서는 script 태그를 분리해서 모듈처럼 사용하고 있었는데,
이렇게 이용하게 된다면 전역을 공유하기 때문에
같은 변수 이름에 대해서 문제가 발생하게 된다.
물론 웹팩이 등장하기 전에도,
이 문제에 대한 해결방안들은 존재했다.
해결방법 1. IIFE (즉시실행함수) 사용
웹팩이 등장하기 전에는 즉시실행함수를 이용해서
전역 스코프의 오염과 모듈 간의 충돌을 방지했다.
이전에는 스크립트 파일을 로드하면
전역 스코프에 있는 변수나 함수들이
동일한 스코프를 공유하여 충돌이 발생할 수 있었다.
이를 방지하기 위해 모듈을 즉시 실행 함수로 래핑하여 해당 모듈의 스코프를 만들고,
필요한 부분만 공개(API로 노출)하여 다른 모듈에서 사용할 수 있도록 했다.
하지만
즉시 실행 함수로 감싼 모듈은
명시적인 의존성을 선언하는 방식이 아니기 때문에
모듈 간의 의존성 관리가 어렵다.
이는 코드베이스가 커지고 모듈 수가 많아질수록 가독성도 떨어지고 유지보수가 어렵다.
해결방법 2. AMD, CommonJS 등의 다양한 모듈스펙
이전에는 웹 개발에서 모듈화를 위해
여러 가지 다른 모듈 시스템과 스펙이 사용되었다.
대표적으로 AMD (Asynchronous Module Definition) 와 CommonJS 가 있다.
이러한 다양한 모듈 시스템은 각자의 장단점을 가졌고,
웹 개발 생태계에서 모듈화를 위한 다양한 시도와 접근 방식을 보여줬다.
그러나
이러한 다양성은 모듈을 가져오고 내보내는 방법에 대한 표준이 없어서,
브라우저와 서버 간에 모듈을 공유하거나 이식하기 어려운 측면이 있었다.
이후 ECMAScript 6(ES6)부터는 JavaScript에서 공식적인 모듈 시스템이 도입되고
import와 export 구문을 통해 표준화된 모듈 시스템을 사용할 수 있게 되었다.
이러한 ES6 모듈 시스템이
웹팩, Parcel 등의 모듈 번들러에서도 널리 지원되고 사용되고 있다.
* 그러면
웹팩이 등장하게 된 이유는 알게됐는데
어떻게 최적화를 시키는거야?
웹팩의 최적화는
1. 번들 사이즈 줄이기
2. 빌드 속도 줄이기
이 두개로 나눠서 얘기해보겠다.
1. 번들 사이즈 줄이기
일단 번들 사이즈는 왜 줄여야 하는걸까?
1) 네트워크 비용
파일이 무거울수록 네트워크 통신이 오래걸림.
2) 파싱 및 컴파일 비용
브라우저의 메인 쓰레드는 js를 파싱 및 컴파일 하고
사용자의 이벤트를 받아서 처리해준다.
그런데 만약에 js 파일의 크기가 크다면
파싱과 컴파일을 하는데에 시간이 오래걸릴거고
이벤트를 처리하는 시간이 길어지기 때문에
사용자 경험을 해칠 수 있다.
3) 메모리 비용
코드가 실행되지 않는 경우에도
RAM에는 코드가 올라가기 때문에
메모리를 낭비하게 된다.
메모리가 작은 핸드폰 기종의 경우에는
성능이 떨어져서 사용자 경험을 해칠 수 있다.
번들 사이즈를 줄이는 방법 4가지를 알아보자
1. webpack mode
2. source map
3. code splitting
4. tree shaking
1. webpack mode
웹팩의 모드에는
none, development, production
세개로 나눠져있다.
* 모드를 설정 안할 시에는 기본적으로 production 으로 설정된다.
- Development :
강력한 소스 매핑,
로컬 서버에서는
hot module replacement (HMR) 기능을 목적으로 이용한다.
* Hot Module Replacement (HMR) :
HMR은 브라우저를 새로 고치지 않아도
웹팩으로 빌드한 결과물이 웹 애플리케이션에 실시간으로 반영될 수 있게 도와주는 설정이다.
브라우저 새로 고침을 위한 LiveReload 대신에 사용할 수 있으며
웹팩 DEV 서버와 함께 사용할 수도 있다.
- Production :
로드 시간을 줄이기 위해서
번들 최소화, 가벼운 소스맵 및 리소스 최적화에
초점을 맞춘다.
* Production mode에서는 기본적으로 tursur Plugin을 이용해서 코드를 압축화, 난독화를 한다.
2. source map
소스 맵(source map) 은
원본(original) 소스 코드와
변환된(transpiled) 소스 코드 사이의
매핑 정보가 선언된 파일 이다.
보통 서버에서
빠르게 전달되고 보안성을 높이기 위해서
난독화와 압축이 사용되는데,
만약 페이지에서 에러가 발생한다면
디버깅하기가 힘들어진다.
브라우저의 디버깅툴은
난독화된 코드에서 에러가 난 부분을 지목하기 때문에
에러가 난 코드가 애초에 무엇인지 알 도리가 없다.
그래서 소스맵 (sourceMap)이 등장했다.
소스맵은 원본코드를 특정한 알고리즘으로 인코딩해서
특정 키워드로 맵핑을 시켜놓으면
나중에 브라우저에서는 난독화된 코드를
그대로 디코딩해서 복원시킬 수 있다.
그렇다면
소스맵 (sourceMap)은 어떻게 이루어져 있을까?
* version :
소스맵의 버전을 나타낸다.
소스맵의 구조나 형식이 변경될 때마다
버전을 업데이트하여 이전과의 호환성을 유지하고,
새로운 소스맵 형식의 기능을 추가할 때 버전을 증가시킨다.
소스맵의 version을 직접적으로 조작하거나 수정하지는 않고
이 값은 소스맵 생성 도구가 자동으로 설정하고 관리해준다.
* file : 연결된 파일명을 나타낸다.
* sources : bundle.js를 만드는데 활용된 소스코드 파일 목록이다.
* names : 소스코드의 모든 변수와 함수이름이 기록된다.
* mappings : 실제코드와 매핑할 수 있도록 하는 데이터이며, Base64 VLQ로 인코딩되어 기록된다.
3. Code Splitting
code spliting은
애플리케이션을 작은 코드 조각 또는 "청크(chunk)"로 나누는 기술이다.
이 기술은 애플리케이션의 전체 코드를 한 번에 로드하는 대신,
사용자가 필요로 하는 코드 부분만 로드하여 성능을 향상시키고
초기 로딩 시간을 단축하는 데 도움을 준다.
웹팩(Webpack)과 같은 번들러에서 코드 스플리팅은 주로 다음과 같은 방법으로 진행된다.
1) 동적 임포트(Dynamic Import):
ES6의 동적 import() 구문을 사용하여 코드를 동적으로 로드한다.
이를 통해 특정 이벤트나 조건에 따라 필요한 모듈을 추가적으로 가져올 수 있다.
2) Entry Points 설정:
웹팩 설정에서 여러 개의 진입점(entry points)을 설정하여,
각각의 진입점을 기반으로 번들을 생성할 수 있다.
이를 통해 여러 개의 번들을 만들어
사용자가 필요로 하는 페이지나 기능에 따라 동적으로 로딩할 수 있다.
3) 분할된 청크 관리:
웹팩은 코드 스플리팅된 청크를 관리하고,
필요한 청크들을 요청할 때 마다 로드하여 동적으로 실행한다.
이를 통해 초기 로딩 시간을 최소화하고
필요한 모듈만을 효율적으로 로딩할 수 있다.
4. tree shaking
짧게 말하자면 사용하지 않는 코드를 제거하는 방식을 말한다.
나무를 흔들면 죽은 잎사귀들이 떨어지는 모습을 보고,
Tree-shaking 이라는 이름을 지었다고 한다.
코드를 털어서 필요없는 코드를 제거하는 것이라고 생각하면 될 것 같다.
모듈 번들러에서 사용되는 최적화 기법 중 하나 이고,
번들된 파일에서 사용되지 않는 (import 되지 않는) 코드를
식별하고 제거하여 최종 번들 크기를 줄인다.
tree shaking의 동작방식은 다음과 같다.
1. 모듈 단위로 코드를 분석하고, import 및 export 구문을 통해 모듈 간의 의존성을 파악한다.
2. 사용되지 않는(import되지 않은) 코드나 변수, 함수, 클래스 등을 식별하여 마킹한다.
3. 번들링할 때 이러한 사용되지 않는 코드를 제거하고 번들에 포함시키지 않는다.
tree shaking은 production 환경에서
코드 번들 크기를 줄이고 성능을 향상시킨다.
* 번들러가 처리하는거기 때문에,
코드만으로 예시를 들기는 어렵지만,
번들러가 처리해준다는 가정하에
tree shaking의 예시를 보자.
tree shaking을 할 때, 고려해야할 점.
1. 라이브러리의 sideEffects 설정
2. 트리 쉐이킹과 사이드 이펙트의 관계
3. 개발자의 책임
1. 라이브러리의 sideEffects 설정:
일부 라이브러리는 자체적으로 사이드 이펙트를 가지고 있다는 정보를
Webpack에게 알려주기 위해 package.json 파일의 sideEffects 필드를 설정해야 한다.
이 설정은 Webpack에게 트리 쉐이킹을 적용할 때
어떤 파일이 사이드 이펙트를 가지고 있는지 알려준다.
2. 트리 쉐이킹과 사이드 이펙트의 관계:
일부 라이브러리에서 사이드 이펙트가 발생할 수 있는 코드는
트리 쉐이킹의 대상에서 제외될 수 있다.
Webpack은 사용하지 않는 코드이더라도
사이드 이펙트가 발생할 가능성이 있는 코드에는 트리 쉐이킹을 적용하지 않는다.
이는 Webpack이 코드가 사이드 이펙트를 일으킬 가능성을 정확하게 판단하지 못하기 때문이다.
3. 개발자의 책임:
따라서, 트리 쉐이킹이 올바르게 동작하도록 보장하기 위해서는
개발자가 적절한 sideEffects 설정을 해주어야 한다.
만약 코드가 사이드 이펙트를 일으키지 않을 것으로 판단되는 경우,
package.json 파일의 sideEffects: false 속성을 설정하여
Webpack에게 해당 파일이 사이드 이펙트를 가지고 있지 않다는 것을 명시해야 한다.
'개발 > 개발환경' 카테고리의 다른 글
file-loader VS url-loader (3) | 2024.01.29 |
---|---|
ESLint 와 Prettier 설정해보기 (1) | 2023.12.11 |
내가 보려고 쓴 NginX 를 이용한 SSL 인증서 적용 (0) | 2023.06.20 |
Safari 브라우저 에서 Cross-browser 신경써보기 (0) | 2023.05.28 |
Intellij Tomcat debugger port 에러 (0) | 2023.05.23 |
개발 블로그
포스팅이 좋았다면 "좋아요❤️" 누르기 !