바벨의 플러그인인 es5로 변환할수 있는 것만 변경해준다. es5에 이미 존재 했었던 개념은 플러그인으로 변경이 가능하지만 ECMAScript2015+에서 새롭게 등장한 개념은 플러그인을 통해서 변경이 되지 않는다. 예를 들어 화살표 함수의 경우에는 일반 함수로 변경이 가능하지만, Promise같은 새로운 개념은 변경이 안된다. 그래서 이렇게 새롭게 등장한 개념에 대한 변경이 가능하도록 폴리필이라고 부르는 코드조각을 추가해서 해결하게 된다. 폴리필로 사용되는 것중 하나에 core-js가 존재한다.
브라우저마다 사용하는 언어가 달라서 프론트엔드 코드는 일관적이지 못할때가 많다. 프론트엔드 개발에서 크로스브라우징 이슈는 코드의 일관성을 헤친다. 크로스브라우징의 혼란을 해결할수 있는 것이 바벨이다. ECMAScript2015+로 작성한 코드를 모든 브라우저에서 동작하도록 호환성을 지켜준다.
바벨의 기본동작
바벨은 ECMAScript2015이상의 코드를 적당한 하위버전으로 바꾸는 것이 주된 역할이다. 이렇게 바뀐 코드는 오래된 버전의 브라우저에서도 작동할수 있도록 해준다.
파싱(Parsing)
코드를 읽고 추상 구문 트리로 변환하는 단계
변환(Transforming)
추상 구문 트리를 변경하는 것이 변환으로써, 실제로 코드를 변경하는 작업
출력(Printing)
변경된 결과물을 출력
바벨 설치하기
@babel/cli는 터미널도구로 사용하기 위해서 설치해야 한다.
1
npm install @babel/core @babel/cli
아래의 명령어로 바벨을 실행시키면 콘솔로 출력 해준다.
1
npx babel 파일경로
바벨 플러그인
기본적으로 바벨은 파싱과 출력만 담당을 하고 변환작업은 플러그인에게 맡긴다. 그래서 플러그인이 설치되어 있지 않으면 기본적으로 입력된 것과 동일한 출력만 하게 된다.
커스텀 플러그인
모듈 함수를 실행하면 visitor 객체를 가진 객체를 반환해야 한다. 그리고 visitor 객체는 Identifier 메소드를 가지고 path 파라미터를 넘겨준다. visitor에는 여러개의 메소드를 작성할수 있는데 이미 정해져 있는 메소드명을 사용해야 원하는 결과를 얻을수 있다.
ECMAScript2015+를 변환할때 사용한다. 바벨7 이전 버전에는 연도별로 각 프리셋을 제공했지만(babel-reset-es2015, babel-reset-es2016, babel-reset-es2017, babel-reset-latest) 지금은 preset-env로 통합되었다.
1
npm install -D @babel/preset-env
preset-typescript
타입스크립트를 변환하기 위한 프리셋이다.
@babel/preset- 으로 시작하는 모듈은 바벨의 프리셋이라고 보면 될것이다.
타겟브라우저
지원하는 브라우저의 버전을 명시할수 있다. 예를 들어 A라는 회사의 홈페이지는 크롬 최신버전만 지원한다. 이럴 경우 IE를 위한 변환은 불필요하다. 타켓브라우저를 사용해서 최적의 코드로 출력할수 있다.
classMyPlugin{ apply(compiler) { // 플러그인이 완료 된 후 실행될 콜백함수를 지정한다. compiler.hooks.done.tap('My Plugin', stats => { console.log('MyPlugin: done'); });
// 실제로 플러그인이 처리할 코드가 들어가는 부분이다. compiler.plugin('emit', (compliation, callback) => { // compliation.assets['main.js'].source();를 통해서 번들링 된 파일을 가져올수 있다. const source = compliation.assets['main.js'].source();
주의 할 점은 값이 문자열이 아니라 계산식이라는 것이다. 첫번째 값이 ‘1+1’은 문자열이 아니라 계산되어 2라는 값이 TWO에 저장된다. ‘1+1’이라는 문자열을 사용하고 싶으면 JSON.stringify를 사용하여야 한다. 키가 api.domian 이런식으로 등록하면 실제 사용할때는 객체 형식으로 접근이 가능하다.
스타일 시트의 양이 많을때 자바스크립트 하나로 결과물을 모두 번들링 하게 되면 부담이 커진다. 번들 결과에서 스타일시트 코드만 뽑아서 별도의 css 파일로 관리 할수 있다. 최종 결과물이 css 파일하나, js 파일 하나가 된다(물론 그 이상도 만들수 있다). 개발 모드일때는 하나의 js로 하는게 작업에 좋다고 한다. 배포시에만 설정하도록 해보자.
로더(Loader)는 웹팩이 웹 애플리케이션을 해석할 때 자바스크립트 파일이 아닌 웹 자원(HTML, CSS, Images, 폰트 등)들을 변환할 수 있도록 도와주는 속성이다. 로더를 사용하면 모든 파일을 모듈로 변환해 주기 때문에 자바스크립트에서 import 구문을 통해서 자바스크립트 영역에서 사용이 가능하다.
1. 모든 파일을 자바스크립트의 모듈처럼 만들어준다. 2. 타입스크립트 같은 다른 언어를 자바스킙트 문법으로 변환해 준다. 3. 이미지를 data URL 형식의 문자열로도 변환 가능하다. 4. CSS 파일을 자바스크립트에서 직접 로딩할수 있게 해준다. 결론 네가지의 역할 뿐 아니라 로더는 각 파일들을 처리 할때 사용할수있다.
커스텀 로더 만들기
로더는 함수 형식으로 만든다. 함수의 파라미터로 content를 받아온다. 이 content에는 파일의 content가 저장되어 있다. 그래서 로더는 파일의 내용을 변경하거나 처리할때에 사용할수 있다.
로더는 webpack.config.js의 module.rules 배열에 들어간다. 로더는 파일 유형별로 처리할 로더들을 등록 해준다. 하나의 로더에 처리할 파일들을 등록 하는게 아닌, 파일 하나(또는 그 이상)에 처리할 로더를 등록 해주는 것이기 때문에, 파일 유형별로 여러개의 로더가 등록 가능하다.
사용하는 이미지 개수가 많다면 네트워크 리소스를 사용하는 부담이 생겨 사이트 성능에 영향을 준다. 한 페이지에 작은 이미지를 여러개 사용한다면 DATA URI Scheme을 이용하는 것이 좋은 방안이 될수 있다(네트워크 통신을 안하게 해준다). 이러한 처리를 해주는 것이 url-loader이다.
사용방법은 file-loader와 유사하다. url-loader는 limit라는 옵션을 사용가능한데 해당 파일의 크기 이하는 url-loader를 사용하고 그 이상은 file-loader를 사용하도록 해준다. 그래서 웹팩에 url-loader만 등록 하더라도 file-loader가 설치되어 있어야 한다(물론 limit 이하만 사용하는 경우에는 에러는 발생하지 않는다. limit 초과하는 파일이 존재할때 에러발생)
limit : url-loader를 사용할 파일 크기. limit을 너무 높게 잡아도 좋지 않다. (단위는 byte)
유의적 버전이란 버전을 통해서 API의 변경을 표현하는 명세이다. 버전은 X.Y.Z(주.부.수)로 표현한다.
유의적 버전을 사용하는 이유
시스템 규모가 커질수록 더 많은 API를 사용하게 된다. 이에 따라 소프트웨어의 의존성이 점점 더 높아지고 있다. 이러한 상황에서 API의 버전이 올라가는 경우 의존성이 깨지는지 확인을 해 주어야 하는데 직접 하나하나 확인을 하기에는 힘들다. 그래서 버전만 보고도 의존성이 깨지는지 아닌지를 판단 할수 있도록 하기 위해서 사용하게 되었다.
유의적 버전
버전은 3부분으로 나뉘어 진다.
주버전(MAJOR) : 기존 버전과 호환되지 않게 변경되는 경우
부버전(MINOR) : 기존 버전과 호환되면서 기능이 추가된 경우
수버전(PATCH) : 기존 버전과 호환되면서 버그를 수정한 경우
유의적 버전 사용 방법
유의적 버전을 쓰는 소프트웨어는 반드시 공개 API를 선언한다.
버전 번호는 반드시 X.Y.Z의 형태로 하고, X, Y, Z는 각각 자연수이고, 절대로 0이 앞에 붙어서는 안 된다. 그리고 반드시 증가하는 수여야 한다.
한번 배포가 되면 그 버전의 내용은 변경이 되어서는 안된다. 변경사항 있으면 새로운 버전으로 배포되어야 한다.
주부전이 0인 경우는 초기 개발을 위해서 사용한다. 아무때나 바뀔수 있다. 이 버전은 안전판으로 보지 않는게 좋다.
1.0.0 버전은 공개 API를 제공한다.
수(PATCH)버전은 반드시 그 이전 버전 API와 호환되는 버그 수정의 경우에만 버전을 올린다. 버그 수정이란 잘못된 내부기능을 수정하는 것을 말한다.
공개 API에 기존과 호환되는 기능을 추가하는 경우에는 반드시 부(MINOR)버전을 올린다.
공개 API에 기존과 호환되지 않는 기능을 추가하는 경우에는 주(MAJOR)버전을 올린다.
npm이란 Node Package Manager의 약자이다. 이름에서 유추 할수 있는지 Node로 만들어진 모듈을 패키지화하여 관리하는 해주는 프로그램이다.
npm 명령어
package.json 생성
npm init 명령어를 실행하면 package.json 파일을 생성해준다. package.json 파일은 프로젝트 의존모듈 관리 및 프로젝트 정보를 관리한다. npm init 명령어를 입력하면 package.json에 들어갈 메타정보를 입력할수 있는 화면을 제공한다.
1
$ npm init
옵션으로 -y으로 설정 할 경우 메타 정보의 입력 없이 모두 default 값으로 package.json을 생성해 준다.
1
$ npm init -y
아래는 생성된 package.json의 내용이다.
1 2 3 4 5 6 7 8 9 10 11
{ "name": "sample", // 프로젝트 명 "version": "1.0.0", // 프로젝트 버전 "description": "", // 프로젝트 설명 "main": "index.js", // node.js에서 사용 되는 것 "scripts": { // 프로젝트를 자동화 할수 있는 쉘 스크립트 입력 "test": "echo \"Error: no test specified\" && exit 1" }, "author": "", // 프로젝트 작성자 "license": "ISC"// 라이센스 정보 }
패키지 설치
npm install(npm i) 명령어는 package.json 파일의 dependency에 있는 모듈을 모두 설치해 준다.
1 2
$ npm install <package> $ npm i <package>
npm install의 옵션으로 –save 사용한 경우 package.json의 dependency에 추가시켜 준다. 하지만 npm 버전 5 이상부터는 –save 옵션을 사용하지 않아도 자동으로 dependency에 추가해 준다.
–save-dev 옵션을 사용하는 경우에는 devDependency에 추가해준다. devDependency란 개발시에만 사용하는 개발용 의존 패키지를 작성할때 사용한다. 축양형은 -D를 사용한다.
package.json의 scripts에서 작성했었던 스크립트를 실행할수 있다. npm에서는 수많은 명령어를 제공해주는데 이것 이외에 스크립트를 통해서 추가한 명령을 실행할때 사용한다.
1
$ npm run <script-name>
패키지 설치 방법
1. CDN 방식(컨텐츠 전송 방식)
콘텐츠 전송 네트워크(이하 CDN)는 콘텐츠를 효율적으로 전달하기 위해 여러 노드를 가진 네트워크에 데이터를 저장하여 제공하는 시스템을 말한다. 인터넷 서비스 제공자에 직접 연결되어 데이터를 전송하므로, 콘텐츠 병목을 피할 수 있는 장점이 있다. 하지만 이 방식의 단점으로는 서버장애시 사용이 불가능 하다는 단점이 있다. 그리고 네트워크의 속도에 영향을 받기가 쉽다.
2. 직접 다운 받아 사용하기
해당 방법은 패키지를 제공하는 곳에서 직접 다운 받아서 사용하는 방법 이다. 이렇게 사용하면 서버의 장애와 무관하게 사용이 가능하다. 하지만 패키지가 업데이트 될 경우 직접 수동으로 다시 다운 받아서 관리를 해야하는 번걸움이 존재한다.
3. npm 이용하기
npm install 패키지명으로 손쉽게 설치가 가능하다. 직접 다운 받는 것보다 훨씐 편하게 버전 관리가 가능하다.
유의적 버전 범위
npm은 API의 버전을 관리 할때 유의적 범위를 사용한다. 아래의 버전 범위 표기법을 이용하여 업데이트 될 버전의 범위를 지정할수 있다.
표기법
설명
version
명시된 version과 일치
>version
명시된 version보다 높은 버전
>=version
명시된 version보다 높거나 같은 버전
<version
명시된 version보다 낮은 버전
<=version
명시된 version보다 낮거나 같은 버전
~version
패치버전을 변경하는 버전
^version
마이너버전을 변경하는 버전
여기에서 주목해야 할 것은 ~(틸드)와 ^(캐럿)이다.
~(틸드)
~(틸드)는 마이너 버전이 명시되어 있으면 패치버전을 업데이트 하고, 마이너 버전이 없으면 마이너 버전을 업데이트 한다.
최근 자바스크립트에서는 모듈을 이용하여 주로 작성이 되고 있다. 번들러는 모듈의 의존 관계를 분석하여 브라우저가 인식할 수 있는 자바스크립트 코드로 변환 후 하나 또는 여러개의 파일로 만들어 주는 도구이다. 번들러를 통해서 소스코드를 모듈별로 작성 할수 있고 모듈간의 의존성을 쉽게 관리할수 있다. 자바스크립트에서 많이 사용되고 있는 모듈 번들러 중에 하나가 웹팩이다. 웹팩을 사용하면 자바스크립트 뿐 아니라 HTML, CSS, Image 파일의 리소스까지 의존성 관리를 할수 있게 해준다.
웹팩 설치
옵션을 -D(–save-dev) 옵션을 줄 경우에는 devDependencies에 들어가는데 이는 개발용 패키지이다. webpack-cli를 설치하면 터미널에서 webpack 커맨드를 사용할수 있다.
1
npm install webpack webpack-cli -D
설치가 완료되면 아래와 같이 실행할수 있다.
1 2
node_modules/.bin/webpack --mode development npx webpack --mode development
웹팩 옵션
웹팩을 사용할 때 여러가지 옵션을 줄수 있다. 아래는 - 하나로 보이지만 실제로는 -를 2개 써주어야 한다.
–mode
development : 개발용으로 번들링된다.
production : 배포용으로 번들링된다.
none
–entry 모듈의 의존성 그래프를 만드는 시작점을 지정 해주는 것이다. 모든 모듈의 시작 파일을 지정해준다고 생각하면 쉽다.
–output 번들링된 파일의 위치와 이름을 지정할때 사용한다.
–config config 파일의 위치를 지정할때 사용한다. 기본값으로는 webpack.config.js 또는 webpackfile.js이다.
–progress 웹팩이 빌드되는 것을 커맨드라인으로 볼수 있게 해준다.
1
npx webpack --mode development --entry ./src/app.js --output dist/main.js
설정 파일 webpack.config.js
매번 위처럼 cli 명령어를 통해서 작업하기는 힘들다. config 파일을 통해서 작성 후에 webpack만 실행하면 편하게 작업할수 있다.
설정 파일 만들기
프로젝트 폴더의 루트에서 webpack.config.js 파일을 생성한다(package.json 파일과 동일한 위치).
before와 after를 테스트 파일에서 오직 한번 만 사용하기 위해서는 beforeAll와 afterAll를 사용하면 된다.
1 2 3 4 5 6 7
beforeAll(() => { console.log('테스트 전 오직 한번만 실행된다.'); });
afterAll(() => { console.log('테스트 후 한번만 호출된다.'); });
describe 내부에서의 before, after 사용하기
describe 내부에서 before와 after를 사용하는 경우에는 describe 내부의 테스트가 호출 될 경우에만 호출된다. 하지만 describe 외부의 before와 after는 describe 내부의 test를 포함한 테스트 파일 전체의 test가 호출 될때 호출이 된다.
test.only 사용하기
테스트가 실패할때 가장 먼저 확인 해봐야 할것은 테스트 케이스가 오직 실패하는 케이스만 실행 했을때에도 실패하는지 이다. 이를 위해서 test.only를 사용하면 다른 테스트는 스킵하고 해당 테스트만 실행된다. 이때 스킵되는 테스트는 test.only가 존재하는 테스트 파일에 한해서이다.
일반적인 상황에서 비동기를 사용하는 보편적인 방법 중 하나는 콜백을 사용하는 것이다. 하지만 Jest에서 테스트 할때는 의도대로 작동 하지 않는다. Jest 테스트는 콜백을 호출할때까지 기다려주지 않는다. 테스트 함수 내에서 마지막 코드까지 실행을 하게되면 테스트를 완료하게 된다. 그래서 항상 테스트가 통과하게 된다. 테스트 실패하도록 값을 변경하여도 통과하는 것을 확인 할수있다.
promise의 reject 또한 테스트 할수 있다. 이경우에는 then 대신에 catch를 활용한다. catch 내부에서 테스트 할 코드를 작성한다. 이때 expect.assertions(에러 발생한 횟수)를 테스트 위에 적어주지 않으면 테스트는 정상적으로 실행되지 못하고 완료되어 버린다.