우리는 프로그램을 개발할 때 일일히 CPU 명령어를 입력하지는 않는다. 작성하기 편리하고 이해하기 쉬운 프로그래밍 언어를 사용해 프로그래밍하고, 그 후에 컴파일러라는 프로그램을 이용해 작성한 코드를 CPU가 실행할 수 있는 기계어 명령어로 번역한다.
우리가 쓰는 범용 프로그래밍 언어는 튜링 완전하다.
위의 기능을 갖추고 범용적인 계산 능력이 있다면 이걸 튜링 완전하다고 한다. 따라서, 하나의 프로그램을 어떤 프로그래밍언어로 작성할 수 있다면 다른 프로그래밍 언어로도 작성할 수 있다는 뜻이 된다 ! 너무 신기 ~
컴파일러는 복잡하고 고수준 프로그래밍 언얼 작성된 프로그램을 단순한 저수준 프로그래밍 언어(기계어)로 번역해주는 역할을 한다.
컴파일된 프로그램은 결국 일련의 CPU 명령어 모음인데, 서로 다른 CPU 아키텍쳐에서는 실행되지 않을 수 있다. (데스크탑용, 스마트폰용) 프로그램 동작을 위해서는 CPU뿐 아니라 운영체제와도 소통해야하기 때문이다.
프로그램은 내부 계산 뿐 아니라, 파일을 열고, 화면을 띄우고, 네트워크 접속을 하는 등의 입력/출력을 해야 한다. 컴퓨터마다 다른 하드웨어로 구성되어있고, 그만큼 다양한 하드웨어 제어 방법이 있는데, 이 모든 종류의 장치들을 직접 지원하기란 불가능하다.
이를 위해 필요한 것이 운영체제이고, 프로그램이 운영체제에 시스템콜 요청을 보내면 특정 입출력 연산을 처리해준다. 이때, 개발자가 직접 시스템콜을 위한 코드를 작성하는 경우는 거의 없는데, 이것을 바로 컴파일러가 해주기 때문이다! 프로그래밍 언어를 운영체제에 알맞은 시스템콜로 번역해주는 것이다.
프로그래밍 언어 - 컴파일 - 시스템콜 - CPU/운영체제 - 하드웨어
번들링이란 말그대로 어떤 것들을 묶는다는 뜻이다. JS로 개발을 하다보면, 너무나 익숙하게도 여러 파일들로 모듈화(특정 기능별 코드 단위)해서 코드를 작성하게 된다. 또, npm으로 다양한 라이브러리, 의존성 모듈들을 인스톨해서 사용하게 되는 경우가 많이 생긴다.
이런 여러 모듈을 번들링을 해주는 대표적인 번들러로 웹팩이 있다.
일단 브라우저에서 서버로 요청하는 파일의 숫자를 줄이는 데에 목적이 있다.
모듈 단위 개발을 가능하게 하고, 모듈 단위 파일을 호출할 때 신경써야하는 변수들의 스코프 겹침 문제를 줄일 수 있다.
웹팩 4버전 이상부터는 Production(production build), Development(npm run start) 모드를 지원하게 되면서, 코드 난독화, 압축, 최적화(tree shaking) 작업이 가능하다.
웹팩의 Loader는 ES6 문법을 지원하지 않는 브라우저에서 구동될 수 있도록 ES5로 변환해준다.
웹팩이 모든 것을 translate 해준다면, 바벨은 자바스크립트만을 translate 한다.
브라우저에는 다양한 종류가 있고, 다양한 버전이 있다.
또, 다양한 자바스크립트 엔진이 있다.
게다가 모두가 최신 버전의 브라우저를 사용하지는 않고,
일괄 업데이트를 적용한다는 것도 불가능한 일이다.
구형 브라우저에서 구동이 되는 프로그램을 만들기 위해 지저분한 코드를 계속 쓸 수도 없고, 그렇다고 최신 기능을 포기하고 개발하는 것도 말이 안되는 일이다.
그래서 최신의 코드를 작성하면서도 최대한 많은 사람들이 사용하는데에 불편함이 없도록 만들어주는게 바벨이다.
위의 설명처럼, 바벨의 기능은 최신의 js 문법을 이전 세대의 코드로 호환시켜준다. 그 외의 다양한 기능 중에 하나는 바로 JSX 문법 변환인데, 리액트 개발을 할 때 자주 사용하게 되는 JSX문법을 브라우저가 읽기 쉬운 ES5 문법으로 변환해준다!
그동안 CRA로 프로젝트 구성을 하면서, 직접적으로 웹팩, 바벨을 건들일 일이 없었던 것 같은데, 나의 코드가 브라우저에서 동작하도록 어마어마한 일들을 리액트에 내장된 웹팩과 바벨이 다 해주고 있었던 것이다.
프로젝트에서 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로 할 수 있는 일은 다음과 같다.
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문법 트랜스파일링 ! 이런 식으로..
이들은 각각 목적에 따라 조금씩 비슷하면서 다른 것을 해주고, 역시 모든 것은 개발하는 과정을 더욱 효과적으로 만들 수 있도록 도와주는 도구이기 때문에 적절하게 다룰 수 있다면 정말 좋겠다고 생각했다.