TypeScript + Webpack + Babel 을 사용하는 이유
프런트엔드 개발을 하면 자연스럽게 따라오는 것들이 있다.
TypeScript, Webpack, Babel 이전 프로그래머스 교육을 받으며 사용했던 것들이다. (이것 말고도 많겠지만...)
그런 느낌이 있다 개발을 하다 보면 이래서 이걸 사용하는구나?라고 느낄 때가 있지만 누군가 물어본다면 속 시원하게 대답할 수 없을 것 같은 느낌적인 느낌 말이다.
다른 사람에게 설명을 하지 못하면 진짜 내 지식이 아니지 않을까 생각한다. 이 기회에 왜 이것들을 사용해야 하는지에 대한 이유를 나름 정리해보려 한다.
혹시라도 잘못된 내용이 있다면 가감 없이 피드백 해주시면 감사하겠습니다.
왜 TypeScript를 사용하는가?
JavaScript는 동적 타입의 인터프리터 언어이다.
동적 타입이라는 의미는 number, string과 같은 자료형의 타입을
소스 코드를 빌드하는 컴파일 환경이 아닌, 실행하는 런타임 환경에서 결정한다는 의미이다.
이는 편하고 빠르게 개발할 수 있는 장점이 있으나, 예기치 못한 에러를 발생하는 원인으로 작용하기도 한다.
여담이지만, 이 때문에 JAVA, C, C++과 같은 정적 타입의 언어와 달리 JavaScript, Python과 같은 동적 타입의 언어를 싫어하는 개발자도 있다고 알고 있다.
본론으로 그래서 왜 TypeScript를 사용하는 걸까?
TypeScript를 간단하게 설명하자면 타입이 적용된 JavaScript이다.
타입 스크립트 컴파일러 또는 바벨(Babel)을 통해 자바스크립트 코드로 변환하는 과정이 필요한 것이 특징이다.
1. 타입이 존재
타입이 존재함으로써 코드의 안전성이 높아지고, 실제로 코드를 테스트하기 이전 단계(컴파일 환경)에서 에러를 캐치할 수 있다.
또한, 타입을 통해 특정 로직이 어떤 역할을 수행하는지 등 가독성이 높아지는 효과도 있다.
2. JavaScript 100% 호환
앞서 말한 바와 같이 TypeScript는 타입이 적용된 JavaScript이다.
따라서 이전 JavaScript로 작성된 프로젝트를 TypeScript로 점진적 리팩토링에 있어 매우 큰 강점을 갖는다.
왜 Webpack을 사용하는가?
1. 빠른 로딩 속도와 높은 성능
웹사이트 진입 시 브라우저는 서버로부터 해당 애플리케이션의 자원(HTML, CSS, JS, Image)등을 다운로드한다.
이때 자바스크립트 번들러인 웹팩을 사용하여 여러 개의 자원을 하나의 이상의 파일로 병합시켜준다.
따라서 서버로부터 받아야 하는 자원이 줄어드는 효과가 있어, 네트워크의 부하를 줄일 수 있다.
즉, 네트워크 요청 자체가 줄어든다.
또한, 초기 진입 시 모든 리소스를 한 번에 다운로드하는 SPA의 단점을 보완하기 위해
필요한 리소스는 그때그때 받아오자는 원리로 Lazy-loading과 code splitting 기능을 함께 제공한다.
2. 웹 개발 작업 자동화 도구 (web task manager)
웹에서 가장 많이 하는 것 vscode 같이 편집기에서 코드 수정하고 저장하고 웹에서 확인 및 새로고침 하는 것
html,css,js 압축, 이미지 압축, scss->css 전처리 변환 와 같은 작업들을 웹팩이 자동으로 관리해준다.
3. 파일 단위의 자바스크립트 모듈 관리의 필요성
먼저, 해당 이유를 이해하기 위해선 웹팩의 등장 배경을 알아보는 것이 좋다. (가장 좋은 참고 자료- Inkyo 님의 블로그(링크))
ES6 이후부터 자바스크립트에서 표준 모듈 시스템을 제안하였고 이것이 export/import 방식이 등장하였다. 그러나 모든 모든 브라우저에서 ES6 방식의 모듈 시스템을 지원하지는 않았다. 따라서 개발자들은 브라우저와 버전에 상관없이 편리한 모듈 시스템을 사용하기를 원했고 이러한 배경에 의해 등장하게 된 툴이 웹팩이다.
왜 Babel을 사용하는가?
Babel은 JavaScript 컴파일러이다.
입력도 JavaScript, 출력도 JavaScript이다. (이 때문에 소스 대 소드 컴파일러 -> 트랜스파일러라고 불리기도 한다.)
Babel은 TypeScript와 JSX 또한 지원한다.
(JSX는 리액트(페이스북)에서 만든 HTML과 비슷하지만 동일하지 않은 언어로 이를 변환하는 과정 없이는 브라우저가 JSX를 인식할 수 없기 때문에 Babel의 JSX 지원은 React와 Babel을 함께 사용하는 이유이기도 하다.)
여기서 컴파일러와 트랜스파일러를 한번 정리해보고 넘어가자.
Compile
한 언어로 작성된 소스 코드를 다른 언어로 변환하는 것을 의미
Transplie
한 언어로 작성된 소스 코드를 비슷한 수준의 추상화를 가진 다른 언어로 변환하는 것을 말한다.
그럼 Babel은 트랜스파일러라고 불러야 하지 않을까? 하지만 공식문서에서 Babel은 컴파일러라고 말한다.
정확하게 말하자면 Babel은 트랜스파일러이자 컴파일러라고 한다.
컴파일은 작성된 코드를 컴퓨터의 저수준 실행 파일(일반적으로 기계어 코드)로 바꾸는 포괄적인 용어이며,
트랜스파일은 때때로 소스-투-소스 컴파일러라고도 하므로 트랜스파일러가 컴파일러의 한 유형 이기 때문에 babel이 컴파일러라고 주장할 수 있다고 한다.
https://stackoverflow.com/questions/43968748/is-babel-a-compiler-or-transpiler/
https://dev.to/kealanparr/compiling-vs-transpiling-3h9i/
모든 언어가 그렇듯 언어 기술은 발전한다. JavaScript 또한 계속 발전해왔다.
이 중 Babel을 잘 이해하는데 도움이 되는 것이라 한다면
ES5 -> ES6(ECMAScript2015)으로 넘어가는 시점을 들여다보면 좋을 것 같다.
ES6 이전까지는 변수 선언으로 var 키워드를 사용했었다.
ES6가 등장하면서 let, const 키워드가 var를 대체하기 시작했다.
대체된 배경을 잠시 짚어보고 넘어가자면
1. var는 중복 선언이 가능했다.
2. var는 블록 레벨 스코프를 지원하지 않고, 함수 레벨 스코프만 지원했다. (전역 변수 오염 문제)
3. var 키워드는 생략이 가능했다.
4. 호이스팅과 함께 초기화가 된다. ( 선언 및 할당하기 전 식별자에 접근이 가능했다.)
ES6 이후 let과 const가 등장하면서 var는 사용되면 안 되는 키워드로 전락하게 된다.
let과 const는
1. 중복 선언이 불가능하다.
2. 블록 레벨 스코프를 지원한다.
3. 키워드 생략이 불가능하다.
4. 호이 스팅은 그대로 일어나지만 바로 초기화가 이루어지지 않는다.
let, const를 통해 생성된 식별자가 TDZ에 안에 들어가게 됨으로써 식별자가 초기화되지 않은 상태에서 접근할 경우 에러가 발생된다.
TDZ(Temporal Dead Zone)
스코프의 시작 지점부터 초기화 시작 지점까지의 구간을 ‘일시적 사각지대(Temporal Dead Zone; TDZ)’라고 부른다.
출처 및 참고 : 링크
본론으로 다시 가서! 그래서 Babel을 왜 사용할까?
1. 크로스 브라우징.
babel은 JavaScript 컴파일러라고 했다.
즉, JavaScript (ES6) -> JavaScript(ES5)로 변환해준다.
JavaScript는 기본적으로 브라우저 내에서만 실행할 수 있고, 브라우저 환경에서만 사용할 수 있는 언어였다. 물론, Node.JS가 등장하기 전까지의 말이지만 말이다.
결국 JavaScript가 발전함에 따라 자연스럽게 브라우저 또한 발전했다.
하지만, 아직도 갤럭시 노트2를 사용하는 사람이 있는 것처럼 모든 사람들이 최신의 브라우저를 사용하는 것은 아니다.
결국 브라우저 하위 호환성을 생각하여 ES6로 코드를 작성하여도 구형 브라우저가 이를 인식할 수 있도록 ES5로 변환하는 과정이 필요했다.
또한, 각 브라우저마다 JavaScript 엔진이 다르며 (크롬, 사파리, 파이어폭스...) Babel 모든 브라우저에서 동작하도록 호환성을 지켜준다.
2. 폴리필(polyfill)
Babel을 사용한다고 해서 최신 함수를 사용할 수 있는 것은 아니다.
Babel은 "변환"만 해주기 때문이다.
즉 , 브라우저 엔진이 구현하지 않는 새로운 함수라면 이를 브라우저에서 실행할 수 없다는 의미이며, 이에 대한 방안이 폴리필이다.
폴리필은 개발자가 특정 기능이 지원되지 않는 브라우저를 위해 사용할 수 있는 코드 조각이나 플러그인을 의미한다.
폴리필은 프로그램이 처음에 시작될 때 현재 브라우저에서 지원하지 않는 함수를 검사해서 각 object의 prototype에 붙여주는 역할을 한다.
babel은 컴파일-타임에 실행되고 babel-polyfill은 런-타임에 실행된다고 한다.
참고