컴파일?번들링?(Webpack, Babel, Gulp)

Jiwoo Joy Kim (zuzokim)·2021년 8월 25일
1

컴파일이 뭐냐?

우리는 프로그램을 개발할 때 일일히 CPU 명령어를 입력하지는 않는다. 작성하기 편리하고 이해하기 쉬운 프로그래밍 언어를 사용해 프로그래밍하고, 그 후에 컴파일러라는 프로그램을 이용해 작성한 코드를 CPU가 실행할 수 있는 기계어 명령어로 번역한다.


우리가 쓰는 범용 프로그래밍 언어는 튜링 완전하다.

  • 메모리에서 데이터 읽고, 쓰기
  • 조건에 따라 분기를 수행하기 (메모리 주소에 값이 주어지면 프로그램의 다른 지점으로 건너뛰기)

위의 기능을 갖추고 범용적인 계산 능력이 있다면 이걸 튜링 완전하다고 한다. 따라서, 하나의 프로그램을 어떤 프로그래밍언어로 작성할 수 있다면 다른 프로그래밍 언어로도 작성할 수 있다는 뜻이 된다 ! 너무 신기 ~


컴파일러

컴파일러는 복잡하고 고수준 프로그래밍 언얼 작성된 프로그램을 단순한 저수준 프로그래밍 언어(기계어)로 번역해주는 역할을 한다.

컴파일된 프로그램은 결국 일련의 CPU 명령어 모음인데, 서로 다른 CPU 아키텍쳐에서는 실행되지 않을 수 있다. (데스크탑용, 스마트폰용) 프로그램 동작을 위해서는 CPU뿐 아니라 운영체제와도 소통해야하기 때문이다.

프로그램은 내부 계산 뿐 아니라, 파일을 열고, 화면을 띄우고, 네트워크 접속을 하는 등의 입력/출력을 해야 한다. 컴퓨터마다 다른 하드웨어로 구성되어있고, 그만큼 다양한 하드웨어 제어 방법이 있는데, 이 모든 종류의 장치들을 직접 지원하기란 불가능하다.

이를 위해 필요한 것이 운영체제이고, 프로그램이 운영체제에 시스템콜 요청을 보내면 특정 입출력 연산을 처리해준다. 이때, 개발자가 직접 시스템콜을 위한 코드를 작성하는 경우는 거의 없는데, 이것을 바로 컴파일러가 해주기 때문이다! 프로그래밍 언어를 운영체제에 알맞은 시스템콜로 번역해주는 것이다.

프로그래밍 언어 - 컴파일 - 시스템콜 - CPU/운영체제 - 하드웨어

번들러가 뭐냐?

번들링이란 말그대로 어떤 것들을 묶는다는 뜻이다. JS로 개발을 하다보면, 너무나 익숙하게도 여러 파일들로 모듈화(특정 기능별 코드 단위)해서 코드를 작성하게 된다. 또, npm으로 다양한 라이브러리, 의존성 모듈들을 인스톨해서 사용하게 되는 경우가 많이 생긴다.

이런 여러 모듈을 번들링을 해주는 대표적인 번들러로 웹팩이 있다.

웹팩은 웹 애플리케이션을 위한 정적 모듈 번들러다. js, 스타일시트, 이미지, 폰트 등을 모두 모듈로 보고 번들링해준다. 웹팩이 바벨을 사용하기도 하고, js안의 css를 수집해서 번들링해주기도 한다.

그럼 왜 번들링을 해줘야하나? 장점은?

일단 브라우저에서 서버로 요청하는 파일의 숫자를 줄이는 데에 목적이 있다.

  • 웹페이지에서 모듈을 사용하려면 해당 모듈과 사용되는 라이브러리를 모두 로드해야하는데, 선후 관계를 따져서 순서대로 로드해야하고, 이렇게 많은 양의 파일을 한 번에 로드할 경우(파일마다 서버에 요청을 보내는 것이기 때문에) 네트워크 병목 현상이 발생한다. 하나의 파일에 작성하면 해결할 수도 있겠지만, 가독성이 떨어질 것이다. 유지보수? 당연히 불가.
  • 그래서 번들링한 파일을 로드하면 선후관계를 따질 필요가 없고, 파일의 수도 줄어들기 때문에 병목현상도 예방할 수 있다.
  • 번들링을 하면 같은 타입별로 html, css, js 파일을 묶어서 요청/응답을 할 수 있다.

모듈 단위 개발을 가능하게 하고, 모듈 단위 파일을 호출할 때 신경써야하는 변수들의 스코프 겹침 문제를 줄일 수 있다.

  • 위에서 언급했던 로드 선후관계가 중요한 이유가 이런 스코프 겹칩 문제에 있다고 볼 수 있다. 먼저 로드한 파일에서 전역에 선언된 변수가 다음에 로드된 파일의 같은 변수명을 가진 변수의 값으로 재할당, 덮어씌워질 수 있는 것이다. 어플리케이션이 복잡해지면 복잡해질수록 이런 스코프 관리가 어려워질것이고, 에러가 생길 것이다.
  • 또한, 기본적으로 모듈은 모듈 단위안에서 스코프를 가지는데, 여러 모듈들의 의존성을 번들러가 분석하고 이를 한 데 모아주는 역할을 한다.

웹팩 4버전 이상부터는 Production(production build), Development(npm run start) 모드를 지원하게 되면서, 코드 난독화, 압축, 최적화(tree shaking) 작업이 가능하다.

  • 쓰임이 없는 모듈을 지워준다.
  • 도달 불가한 코드를 지워준다.
  • 개발관련 코드를 지워준다.
  • 공백제거, 변수 이름 줄이기로 산출물 사이즈를 줄인다.
  • 작성된 코드를 더 효율적으로 실행한다.(개발과정의 불필요한 최적화 과정을 줄일 수도 있다.)

웹팩의 Loader는 ES6 문법을 지원하지 않는 브라우저에서 구동될 수 있도록 ES5로 변환해준다.

그럼 웹팩과 바벨은 어떻게 다른가?

웹팩이 모든 것을 translate 해준다면, 바벨은 자바스크립트만을 translate 한다.

Babel is a toolchain that is mainly used to convert ECMAScript 2015+(ES6) code into a backwards compatible version of JavaScript in current and older browsers or environments.

브라우저에는 다양한 종류가 있고, 다양한 버전이 있다.
또, 다양한 자바스크립트 엔진이 있다.

게다가 모두가 최신 버전의 브라우저를 사용하지는 않고,
일괄 업데이트를 적용한다는 것도 불가능한 일이다.

구형 브라우저에서 구동이 되는 프로그램을 만들기 위해 지저분한 코드를 계속 쓸 수도 없고, 그렇다고 최신 기능을 포기하고 개발하는 것도 말이 안되는 일이다.

그래서 최신의 코드를 작성하면서도 최대한 많은 사람들이 사용하는데에 불편함이 없도록 만들어주는게 바벨이다.

위의 설명처럼, 바벨의 기능은 최신의 js 문법을 이전 세대의 코드로 호환시켜준다. 그 외의 다양한 기능 중에 하나는 바로 JSX 문법 변환인데, 리액트 개발을 할 때 자주 사용하게 되는 JSX문법을 브라우저가 읽기 쉬운 ES5 문법으로 변환해준다!

CRA(create-react-app)이 다 해주고 있었어...

그동안 CRA로 프로젝트 구성을 하면서, 직접적으로 웹팩, 바벨을 건들일 일이 없었던 것 같은데, 나의 코드가 브라우저에서 동작하도록 어마어마한 일들을 리액트에 내장된 웹팩과 바벨이 다 해주고 있었던 것이다.

scss 컴파일을 위한 Gulp 사용기

프로젝트에서 css 전처리기인 scss를 사용했었는데, scss는 브라우저에서 바로 동작하지 않기 때문에, css로 한 번 컴파일이 필요하다. 그래서 사용하게 된 것이 Gulp 였다.

일단 공식문서를 읽어보면,

A toolkit to automate & enhance your workflow
Leverage gulp and the flexibility of JavaScript to automate slow, repetitive workflows and compose them into efficient build pipelines.

자바스크립트에서 반복적이고 자주 사용되는 일을 자동화해주는 툴 ! 워크플로우 자동화 툴이라고 소개가 되어있다. 즉, scss를 컴파일해주는 컴파일러의 기능은 Gulp의 일부 기능이었던 것이다.

Gulp로 할 수 있는 일은 다음과 같다.

  • Js 라이브러리, 서드파티 앱을 축소, 압축
  • 유닛 테스트 수행
  • LESS / SCSS 컴파일
  • 브라우저 refresh

Gulp를 사용하려면,

Gulp 설치와 함께 필요한 플러그인을 함께 설치해 gulpfile.js 안에 원하는 동작들을 설정해주면 된다.

gulp.task // 반복 수행할 태스크 지정
gulp.pipe // 태스크 연결
gulp.src //어떤 파일을 읽을 것인지 지정
gulp.dest //최종 저장되는 경로 지정
gulp.watch //파일 변경,업데이트 감지

등의 다양한 메소드?와 옵션이 있어서 원하는 작업을 태스크단위로 쉽게 작성할 수 있다는 편리함이 있다. 솔직히 웹팩 커스터마이징하는 것에 지식이 없던 터라, 가볍고 쉽게 작성할 수 있는 툴인 Gulp를 선택했었다.

scss 디렉토리 안에 scss 파일들을 작성하고, 루트 css 파일인 App.css 로 concat하는 파이프라인을 구성했다.

또, sourcemap을 이용해서 브라우저 개발자도구에서 바로 디버깅을 할 수 있도록 했다. (scss를 css로 컴파일하고 나면 브라우저에서 css로만 확인이 되고, 어떤 scss 출처파일에 해당 코드가 있는지 찾기 어려운 문제가 있는데, sourcemap이 이 문제를 해결해준다.)

또, watch 설정을 통해서 코드를 수정하면 자동으로 감지해 바로바로 브라우저에서 업데이트되는 것을 볼 수 있도록 defualt 설정을 해줬다.

그런데 !

cra로 프로젝트 구성을 하면, 내장된 기능으로 자동으로 scss 확장자 파일을 css 컴파일을 해준다는 것을.. 뒤늦게 알아버렸고,

로컬 프로젝트 파일에서 scss 파일들과 동일한 내용이 담긴 App.css 파일을 중복으로 가지고 있다는 비효율성이 있다고 느껴져서 gulp를 덜어내고, cra의 내장기능으로 전환을 했다. 웹팩 설정을 직접 만지지 않고도 scss를 사용할 수 있다니 !!!

참고로 node-sass 는 더이상 개발이 진행되지 않기 때문에, 아래 공식 cra 깃헙 안내에 따라 npm sass로 설치를 해주고, 깔끔한 전환을 해주었다.
https://github.com/facebook/create-react-app/blob/main/docusaurus/docs/adding-a-sass-stylesheet.md

결국에는..

리액트 프로젝트를 하면서 돌고 돌아서 컴파일러의 개념, 번들링이 뭐고 왜 필요한지 !! 알게 되었다고 할 수 있겠다. 또, 아직까지 직접 웹팩 설정을 자세히 건드려 보지는 않았지만, 웹팩의 강력함과 편리함에 대해 알 수 있었다.

그리고 마지막으로 어떤 도구에 대해서 알고 싶다면, 공식문서에서 해당 도구가 어떤 것을 지향하는지 설명된 소개글을 읽어보면 어느정도 파악이 가능하다는 것도 배우게 되었다.

예를 들면, Gulp는 워크플로우 자동화를 내세우고 있고, 웹팩은 모듈 번들링, 바벨은 js문법 트랜스파일링 ! 이런 식으로..

이들은 각각 목적에 따라 조금씩 비슷하면서 다른 것을 해주고, 역시 모든 것은 개발하는 과정을 더욱 효과적으로 만들 수 있도록 도와주는 도구이기 때문에 적절하게 다룰 수 있다면 정말 좋겠다고 생각했다.

profile
- I make something! ✍🏽👩🏻‍💻🎬🎨💖🪑🔨🔜

0개의 댓글