1. Node.js와 NPM
1) Node.js
Node.js란 브라우저가 아닌 환경에서 JS를 실행할 수 있도록 하는 환경이다.
JavsScript 런타임 환경으로 React.js 더 편리하게 사용할 수 있도록 해주는 도구를 제공해 준다.
이전에는 JS가 브라우저에서만 실행할 수 있었지만 Node.js로 자바스크립트를 브라우저 밖에서도 실행할 수 있게 되었다.
Node.js를 설치시
NPM
이라고 불리는 패키지 매니저도 자동으로 설치 된다.
2) NPM
NPM
패키지 매니저를 통해 React에 필요한 다양한 모듈을 다운, 업데이트 할 수 있도록 한다.
전 세계 자바스크립트 개발자들이 모두 자바스크립트 라이브러리를 공개된 저장소에 올려놓고 npm 명령어로 라이브러리를 다운받을 수 있다.
1
2
# NPM 프로젝트 초기화 명령 실행 (package.json 파일 생성)
$ npm init-y
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// package.json
{
"name": "webpack",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": [
],
"devDependencies": [
],
}
- scripts: 해당 속성에 실행을 원하는 명령어를 설정할 수 있다.
npm run + 실행 이름
으로 가동된다.
- dependencies:
npm install
을 통해 설치되는 모듈 리스트 (애플리케이션의 로직과 관련있는 라이브러리)- ex) react, angular, chart 등
- devDependencies
npm install -D
를 통해 설치되는 모듈 리스트 (개발 보조 라이브러리)- ex) webpack, js-compression, sass, eslint, imagein 등
개발용 라이브러리와 배포용 라이브러리 구분하기
NPM 지역설치를 할 때에는 해당 라이브러리가 배포용(dependencies)인지 개발용 (devDependencies)인지 꼭 구분해야 한다.
- 배포용 라이브러리는
npm run build
로 빌드를 하면 최종 애플리케이션 코드에 포함된다. - 개발용 라이브러리는 빌드하고 배포할 때 애플리케이션 코드에서 빠지게 된다.
1
2
3
4
5
6
7
8
9
10
11
12
13
# 모듈 설치
$ npm install 모듈이름
$ npm install 모듈이름 --save-prod
# 모듈 삭제
$ npm uninstall 모듈이름
# 전역 설치 명령어
$ npm install 모듈이름 --global
# dev 설치
$ npm install 모듈이름 -D
$ npm install 모듈이름 --save-dev
- 지역 설치
- node_modules 폴더가 생성되고 그 하위에 라이브러리 파일들이 설치된다.
- package.json의 dependencies에 추가된다.
- global 설치
- windwo 전역 설치 경로:
%USERPROFILE%\AppData\Roaming\npm\node_modules
- mac 전역 설치 경로:
/usr/local/lib/node_modules
- 시스템 레벨에 전역으로 설치하기 위함이다.
- windwo 전역 설치 경로:
- dev 설치
- node_modules 폴더가 생성되고 그 하위에 라이브러리 파일들이 설치된다.
- package.json의 devDependencies에 추가된다.
2. Module
Module이란 여러 기능들에 관한 코드가 모여있는 하나의 파일이다.
애플리케이션의 규모가 커짐에 따라 JS코드를 여러 파일과 폴더에 나누어 작성하고 서로를 효율적으로 불러올 수 있도록 하는 시스템이 필요했고 이를 해결하기 위해 ES6부터 JS는 모듈 기능을 사용할 수 있게 되었다.
1) Module의 특징
- 유지 보수성
- 코드를 다시 작성하지 않고도 쉽게 의존성을 변경할 수 있다.
- 애플리케이션을 유지 보수할 때 관련 있는 모듈만 업데이트 하면 된다.
- 네임 스페이스
- JS는 파일 스코프가 존재하지 않는다. 변수는 모두 전역변수를 사용하기 때문에 애플리케이션이 커질 수록 변수명이 겹치는 경우가 많아질 수 있다.
- Module은 Module만의 네임 스페이스를 갖고 있기 때문에 위와 같은 문제를 해결할 수 있다.
- 재 사용성
- Module로 분리 시켜 필요할 때마다 다시 재 사용할 수 있다.
2) 번들러 등장 배경
- 브라우저별 HTTP 요청 숫자의 제약
- TCP 스펙에 따라 브라우저에서 한 번에 서버로 보낼 수 있는 HTTP 요청 숫자는 제약되어 있다.
- HTTP 요청 숫자를 줄이는 것이 웹 애플리케이션의 성능을 높여줄 뿐만 아니라 사용자가 사이트를 조작하는 시간을 당길 수 있다.
- **프로젝트 규모가 커지면서 많은 모듈을 사용하게 되었고 수 많은 모듈을 일일이 요청하는 것을 피하기 위해 번들러의 필요성이 대두되었다. **
- 트리 쉐이킹, 코드 스플릿, 소스맵, 코드 최적화 필요성 대두 (추후 서술)
3. Bundler
1) Bundling
애플리케이션을 구성하는 수 많은 자원들을 하나의 파일로 병합 및 압축해주는 동작을 Module Budling이라고 한다.
번들링은 웹 애플리케이션을 동작시키기 위한 자원 (HTML, CSS, JS, Images 등)들을 각각의 모듈로 보고 하나로 묶고 조합해서 하나의 정적인 결과물을 만든다.
- 많은 자원들의 연관관계를 파악한 후, 묶고 조합한다.
- 하나로 묶여있지 않으면, 그만큼 서버에 필요한 자원을 여러번 요청해야 하다.
- 하나로 묶어서 경량화 시켜주면 그만큼 서버에 가하는 부하도 적어지고 로딩시간도 높일 수 있어 성능적으로 유리하다.
또한, 앱에 많은 기능이 필요해질수록 모듈 종속성의 올바른 순서를 추적하고 로드하는 번거로움이 더 커지게 된다.
- 코드 베이스를 모듈로 분할 관리하고 묶어 주어야 한다.
2) 번들러의 부가 기능
번들러는 애플리케이션에 필요한 모든 모듈을 알아서 매핑하며 매핑된 결과를 가지고 하나 이상의 번들을 생성한다.
- 트리 쉐이킹 (Tree Shaking)
- 트리쉐이킹은 최종 번들에서 사용되지 않을 코드를 제거한다.
- 애플리케이션에서 사용되지 않는 코드가 번들에 포함될 수도 있다. 사용되지 않는 코드 조각은 번들 크기를 불필요하게 키우므로 번들 과정에서 제거해야 한다. 이런 과정이 마치 나무 흔들기와 비슷해서 TreeShaking이라고 부른다.
- JS 번들 크기를 줄여 앱의 실행 속도를 향상시킬 수 있다.
- 코드 분할 (Code Spliting)
- 코드 분할은 런타임 중에 나뉘어진 chunk 파일을 동적으로 불러오는 것을 말한다.
- 즉, 사용자가 애플리케이션을 모듈이 필요해지면 번들러가 필요한 하위 번들을 처리한다. (Dinamic Loading, Lazy Loading)
- 앱이 커지면 결국 번들 또한 사이즈가 커진다. 특히 3rd-party 라이브러리를 추가할 때 앱이 더욱 커져서 로드 시간이 길어질 수 있다.
- 번들이 거대해지는 것을 방지하기 위해 좋은 방법은 코드를 나누는 것이다.
- 앱의 코드 양을 줄이지 않고도 사용자가 필요하지 않은 코드를 불러오지 않게 하며 앱의 초기화 로딩에 필요한 비용을 줄여준다.
- 코드 최적화, 소스맵 (Code Optimization, SourceMap)
- 수많은 모듈을 번들하는 동안 수행해야 하는 코드 최적화(코드 압축)를 할 수 있다.
- 번들 파일이 생성되면 브라우저에서 이를 해석하여 처리 하는데, 코드 최적화를 위해 주석, 공백 또는 긴 변수, 함수 이름 등을 모두 축소 또는 제거하여 파일의 크기를 크게 줄일 수 있다. 하지만, 이 코드는 압축되었기에 사람이 읽기 매우 어렵다.
- 사람이 읽기 어려운 코드는 디버깅도 쉽지 않아 코드를 추적 가능한 소스맵을 제공하는 기능이 필요하다.
- 즉, 소스맵은 배포할 때 성능최적화를 위해 압축한 코드를 원본 파일과 연결시켜준다.