0. 태초에 혼돈이 있었다
혼돈이 아니고서는 이것을 설명할 수 없었다.
문법 수준으로 모듈이 지원되기 시작한 것은 ES2015부터인데,
이 전 상황은 혼돈 그 자체다.
모든 코드가 하나의 HTML 파일 안에서 실행되면서. 모든 함수가 전역 공간에 노출된다.
따라서 다른 파일에서 같은 이름을 쓰면 충돌이 일어난다.
=> 모든 파일의 모든 함수명을 다르게 작성해야 했다
1. 스코프 사용
따라서 함수 스코프를 사용하게 되었다.
iife방식의 모듈을 이용해 함수 스코프를 만든다.
따라서 외부에서 접근할 수 없는 '함수 스코프'라는 공간에 함수가 격리된다.
=> 함수 외부에서(같은 파일에서도) 같은 이름을 사용하더라도 충돌이 일어나지 않는다. == 접근할 수 없다
이러한 방시을 이용해서 각 커뮤니티 각각의 스펙을 제안해서 모듈을 구현했다.
📌 AMD( Asynchronous Module Definition )
비동기로 로딩되는 환경에서 모듈을 사용하는 것이 목표. 브라우저 환경
📌 UMD( Universal Module Definition )
AMD 기반으로 CommonJS까지 지원하는 통합 형태
그러나 모든 브라우저에서 모듈을 지원하지는 않았다.
브라우저간 쓸 수 있는 모듈이 다르거나 모듈을 사용하지 못하는 브라우저도 있었다.
이런 문제를 해결하기 위해 웹팩이 등장했다
✍ 여기까지 정리
파일이 달라도 상관없이 모든 파일의 코드들이 하나의 HTML에서 합쳐지는 과정에서 모든 함수의 이름, 이 안의 변수 이름까지 하나라도 겹치게 되면 에러가 발생했다.
얼마나 힘들었을까! 변수명을 어쩌고파일_안에있는더하기함수_이안에있는~~일을하는더하기 라고 짓지 않고서야 변수명을 겹치지 않게 하기 정말 힘들었을 것 같다
그래서 iife( Immediately Invoked Function Expression ,즉시 실행 함수 표현)를 사용해서 함수 스코프를 만드는 방식으로 함수 내부의 변수가 전역 상태에 올라가 변수명 충돌을 일으키는 것을 막았다.
이 아이디어를 이용해 각 커뮤니티 각각의 스펙을 제안해 모듈을 구현했는데 이 것이 AMD와 UMD.
그러나 모든 브라우저에서 같은 모듈을 지원하지 않았다.
따라서 이 문제를 해결하기 위해 웹팩이 등장한 것
2. 📚 웹팩
웹팩은 여러 개의 파일을 하나로 합쳐주는 번들러(bundler)이다.
하나의 시작점(entry point)로부터 의존적인 모듈을 다 찾아내 하나의 결과를 만들어 낸다.
설치
$ npm install -D webpack webpack-cli
- webpack : 번들 작업
- webpack-cli 웹팩 터미널 도구
웹팩에서 사용할 수 있는 옵션 중
- --mode : 개발 버전인 development를 지정
- --entry : 시작점 경로를 지정
- --output : 번들링한 결과물의 위치 경로
위 세개만 사용하면 코드를 묶을 수 있다,
- --config : 웹팩 설정파일의 경로를 지정할 수 있다.
webpack.config.js 파일에
mode, entry, output을 설정하고
package.json에 웹팩 실행을 위한 NPM 커스텀 명령어를 추가한다.
=> npm run build만 실행하면 웹팩 작업이 가능하다
📕 로더
웹팩은 모든 파일을 모듈로 바라본다. js 모듈 뿐만 아니라 css, 이미지, 폰트까지 모두 모듈로 본다
따라서 import 구문을 사용하면 이들을 자바스크립트 코드 안으로 가져와 사용할 수 있다
=> 이것이 가능한 이유가 웹팩의 로더 덕분.
로더는 타입스크립트 등의 다른 언어를 자바스크립트 문법으로 변환해주거나
이미지를 data URL 형식의 문자열로 변환
css 파일 또한 js에서 직접 로딩할 수 있게 한다.
css - loader
스타일시트 또한 import 구문으로 불러올 수 있다.
이 때 css파일을 js에서 사용하려면 css를 모듈로 먼저 변환해야 한다.
이 작업을 css-loader가 해준다
설치
$ npm install -D css-loader
webpack.config.js 파일에 css-loader을 추가해준다
module.exports = {
module: {
rules: [
{
test: /\.css$/, // .css 확장자로 끝나는 모든 파일
use: ["css-loader"], // css-loader를 적용한다
},
],
},
}
* jeonghwan-kim님, 감사합니다
이 코드로 인해
웹팩은 entry point 부터 모듈을 검색하다가 CSS 파일을 찾게 되면 css-loader를 이용해 모듈로 변경한다
style - loader
이렇게 모듈로 변경된 스타일 시트는 아직 브라우저가 해석할 수 없다.
css-loader로 처리하여 자바스크립트 코드로만 변경된 css 파일은 아직 돔에 적용되지 않았기 때문에 브라우저는 이 파일을 해석할 수 없다.
따라서 styled-loader을 이용해서 변경된 스타일 모듈을 동적으로 돔에 추가해주어야 한다
설치
$ npm install -D style-loader
webpack.config.js 파일에 style-loader을 추가해준다
module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: ["style-loader", "css-loader"], // style-loader를 앞에 추가한다
},
],
},
}
배열로 설정하게 되면 뒤에서부터 로더가 동작하기 때문에
css-loader을 먼저 읽고
style-loader을 적용하기 위해 예시처럼 설정해준다.
✍ 여기까지 정리
웹팩을 설치한 후 여기서 사용할 수 있는 옵션 중
--entry(시작 지점) / --output(번들링된 결과물의 경로) / --mode(개발 버전 지정)
을 이용해 코드를 묶을 수 있다
이 때 순수 js 파일 뿐만 아니라 이미지 경로, css 스타일 등의 파일 또한
1. 모듈화하여
2. 돔에 추가해야지
브라우저가 파일을 읽어내려갈 수 있는데
이를 위해 필요한 것이 바로 '로더'이다
로더를 이용해서 TS같은 정적 타입 언어를 JS로 변환해줄 수도 있고 css파일또한 브라우저가 읽을 수 있도록 변환할 수 있다.
위에서 배운 내용은 css파일을 로더를 통해 모듈화하는 방법이었다.
css 파일을 브라우저가 읽을 수 있는 모듈로 만들려면 두 가지 방법을 거쳐야 하는데
1. css 파일을 모듈화해주는 css-loader
2. 모듈화된(자바스크립트 코드로 변경된) css를 돔에 추가해서 브라우저가 읽을 수 있게 해주는 style-loader
의 절차를 거쳐야 한다.
이 절차는 webpack.config.js 파일 안에 명시되는데
test :파일 확장자가 css인 파일을 test할 때
use : [ "style-loader", "css-loader" ] // 배열의 순서를 잘 기억하자! => 배열을 읽어내리는 순서 때문
로 작성해야 한다
file - loader
소스코드에서 사용하는 모든 파일을 모듈로 사용할 수 있게 한다.
파일을 모듈 형태로 지원하고 웹팩 output에 옮겨주는 일을 한다.
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.png$/, // .png 확장자로 마치는 모든 파일
loader: "file-loader", // 파일 로더를 적용한다
},
],
},
}
예를 들어 png 확장자로 끝나는 파일이 있다고 하면
test : 확장장가 png로 끝나는 파일을 발견하면
loader : file-loader을 사용한다,
그러나 문제가 있다
file-loader을 사용해서 만들어진 새로운 이미지 경로는 원래 이미지 경로와 다르기 때문에
원래 이미지 경로를 부르고 있는 많은 코드들은 이미지 로딩에 실패하게 된다
=>
따라서 file-loader 옵션을 통해 경로를 다시 잡아주어야 한다
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.png$/, // .png 확장자로 마치는 모든 파일
loader: "file-loader",
options: {
publicPath: "./dist/", // prefix를 아웃풋 경로로 지정
name: "[name].[ext]?[hash]", // 파일명 형식
},
},
],
},
}
📌 publicPath
file-loader가 처리하는 파일 경로 앞에 추가되는 문자열
위 코드에서 ./dist/를 작성했으므로 dist 폴더에 이미지가 옮겨간다. 이미지 이름은 dist/이미지이름.png로 저장되어 사용된다.
📌 name
로더가 파일을 아웃풋에 복사할 시 사용되는 파일 이름이다.
url - loader
사용하는 이미지 수가 많으면 성능에 영향을 줄 수도 있다.
따라서 한 페이지에서 작은 이미지 여러 개를 사용하면 Data URI Scheme을 이용하는 것도 좋다.
=> 이미지를 Base64로 인코딩하여 문자열 형태로 소스코드에 넣는 형식
이 과정을 자동화는 것이 바로 url-loader이다.
설치
$ npm install -D url-loader
webpack.config.js
{
test: /\.png$/,
use: {
loader: 'url-loader', // url 로더를 설정한다
options: {
publicPath: './dist/', // file-loader와 동일
name: '[name].[ext]?[hash]', // file-loader와 동일
limit: 5000 // 5kb 미만 파일만 data url로 처리
}
}
}
* 마지막 limit 속성은 파일 크기가 5kb미만인 파일만 url-loader을 적용하면 된다.
이유
이보다 큰 이미지 파일은 여전히 파일로 존재하기 때문에(fallback의 기본값이 file-loader이라)
✍ 여기까지 정리
file-loader을 통해 이용하는 이미지 파일의 등의 파일을 모듈로 사용할 수 있다.
url-loader을 통해 아이콘과 같은 작은 이미지를 Base64로 인코딩하여 문자열 형태로 소스코드에 담아 사이트의 부담을 던다
📗 플러그인
지금까지 배웠던 로더는 파일 단위로 모듈화를 처리하는 반면
플러그인은 번들된 결과물을 처리한다.
=> 번들링된 자바스크립트를 난독화한다거나 특정 텍스트를 추출하는 용도로 사용
또한 플러그인은 로더와 다르게 클래스로 제작한다
자주 사용하는 플러그인으로는
BannerPlugin
- 결과물에 빌드 정보나 커밋 버전을 추가할 수 있다.
- 생성자 함수에 전달하는 옵션 객체의 banner 속성에 문자열을 전달
- 컴파일 타임에 얻을 수 있는 정보(빌드 시간, 커밋정보)의 전달을 위해 함수로 전달할 수도 있다
DefinePlugin
- 같은 소스 코드를 두 환경에 배포하기 위해서는 환경 의존적인 정보를 소스가 아닌 곳에서 관리하는 것이 좋다
- 이 정보를 제공하는 것이 DefinePlugin
- 빈 객체를 전달해도 노드 환경정보인 process.env.NODE_ENV를 전달한다 (웹팩의 mode 값이 여기 들어간다)
- 웹팩 컴파일 타임에 결정되는 값을 전역 상수 문자열로 나타낼 수 있다.
- 빌드 타임에 결정된 값을 어플리케이션에 전달할 때 사용한다
HtmlWebpackPlugin
- 써드 파티 패키지
- HTML 파일을 후처리하는데 사용
- 동적으로 HTML 코드를 생성한다
- 웹팩으로 빌드한 결과물을 자동으로 로딩하는 코드를 주입한다
CleanWebpackPlugin
- 빌드 이전 결과물 제거
- 충돌을 피하기 위해
MiniCssExtractPlugin
- 개발 환경에선 css를 하나의 모듈로 처리해도 상관없지만 프로덕션 환경에서는 분리하는 것이 효과적
- => css를 별도 파일로 뽑아내는 플러그인
🙇♀️🙇♀️🙇♀️🙇♀️🙇♀️
https://jeonghwan-kim.github.io/series/2019/12/10/frontend-dev-env-webpack-basic.html#44-url-loader
'✍ 공부 > 개발환경 & 그 외' 카테고리의 다른 글
CORS에러란? (CORS와 SOP, CORS header) (0) | 2022.11.14 |
---|