본문 바로가기

Front-end/JavaScript

러닝 자바스크립트 2장 : 자바스크립트 개발 도구

  • 실무에서 반드시 사용하게 될 자바 스크립트 도구는 다음과 같다.
    • Git 
    • Node : 브라우저 밖에서 자바스크립트를 실행할 수 있게 하는 도구이다. 노드와 함께 설치되는 npm은 이 리스트의 다른 도구를 설치할 때 필요하다.
    • Gulp : 반복적인 개발 작업을 자동화하는 빌드 도구이다. Grunt도 널리 쓰인다.
    • Babel : ES6 코드를 ES5로 변환하는 트랜스컴파일러이다.
    • ES린트 : 자주하는 실수를 피하고, 더 나은 프로그래머가 되도록 돕는 린트 프로그램이다.

 2.2.4 깃과 버전 컨트롤

 

  • 먼저 프로젝트 루트에서 저장소를 초기화한다. 아래의 명령은 저장소를 만드는 명령이다. 이제 프로젝트 루트에 숨김 디렉토리 .git이 생긴다.
  • 버전 컨트롤을 사용하다 보면 빌드 과정에서 생기는 파일, 임시 파일과 같이 깃에서 추적하지 않으면 하는 파일이 생긴다. .gitignore 파일을 만들어서 추적에서 제외할 파일을 정할 수 있다.

 2.2.5 npm 패키지 관리 

  • npm을 알아야만 자바스크립트 개발이 가능한 건 아니지만, 패키지 관리 도구로 npm을 사용하는 사람이 점점 늘어나고 있으며, 노드 개발에서는 npm이 필수라고 해도 과언이 아니다. 실제로 노드앱을 개발하든, 브라우저 앱만 개발하든, npm을 사용하면 일이 훨씬 쉬워진다.
  • npm을 통해 빌드 도구와 트랜스 컴파일러를 설치해보자. npm은 노드를 설치할 때 함께 설치된다. 
  • npm의 목적은 간단히 말해 패키지 관리이다. 패키지는 완전한 애플리케이션일 수도 있고, 코드 샘플일 수도, 혹은 프로젝트에서 사용할 모듈 또는 라이브러리일 수도 있다.
  • npm은 패키지를 설치할 때 전역으로 또는 로컬로 설치할 수 있다. 로컬 패키지는 각 프로젝트에 종속되는 패키지이다. 패키지를 설치할 때에는 npm install 명령어를 사용한다. 일단, 인기 있는 패키지 언더스코어(underscore)를 설치해보자.
npm install underscore
  • 이 모듈이 실제 설치된 위치는 프로젝트 루프 밑에 새로 생긴 node-modules 폴더이다. 일단 이 디렉토리를 삭제한다.
  • 설치하는 모듈이 늘어나면 모듈을 추적하고 관리할 방법이 필요해진다. 프로젝트에 설치하고 사용하는 모듈을 dependency라고 부른다. 프로젝트가 성장하면서 늘어날 패키지를 간결하게 정리하려면, npm에서 제공하는 package.json 파일을 통해 dependency를 관리할 수 있다.
  • package.json을 직접 만들 필요 없이 다음 명령을 내리고 몇가지 질문에 답하면 된다.
npm init
  • dependency는 일반 dependency와 개발 dependency로 나뉜다. 개발 의존성은 앱을 실행할 때는 필요 없지만, 프로젝트를 개발할 때 필요하거나, 도움이 되는 패키지를 말한다.
  • 지금부터 로컬 패키지를 설치할 때, --save 또는 --save-dev 플래그를 사용한다. 이 플래그를 쓰지 않아도 패키지가 설치되긴 하지만, package.json 파일에는 등록되지 않기 때문이다. 다시 프로젝트 루트에서 --save 플래그를 사용하여 언더스코어를 다시 설치해보자.
npm install --save underscore
  • 이 때 설치 과정에서 패키지 구성 요소가 빠져있다는 경고가 뜰 수 있는데, 이 책을 공부할 때에는 경고를 무시해도 되지만, npm을 통해 패키지를 배포하려 한다면 이 경고에 신경써야 한다.
  • package.json 파일을 보면 dependancy 리스트에 언더스코어가 있다. 이 관리가 가능한 것은 package.json 파일에서 패키지 이름과 버전 번호를 읽고 필요한 패키지를 다시 내려받아 설치할 수 있기 때문이다. node_modules 디렉토리를 다시 삭제하고, npm install 명령을 내려도 npm은 package.json 파일을 읽고 필요한 패키지를 자동으로 설치할 수 있다. 

 2.2.6 빌드 도구 : 걸프와 그런트 

 

  • 개발 과정에서 피할 수 없는 반복 작업을 자동화하는 빌드 도구가 필요하다. 현재 자바스크립트에서 널리 쓰이는 빌드 도구는 그런트와 걸프이다. 걸프를 전역으로 설치해보자.
npm install -g gulp
  • 리눅스나 macOS를 사용한다면, 전역에서 npm에서 플래그를 사용하기 위해 권리자 권한이 필요할 수도 있다. 그때는 다음과 같이 명령을 해야 한다.
sudo npm install -g gulp
  • 전역 설치는 컴퓨터에 한번만 하면 되지만, 프로젝트마다 로컬 걸프도 필요하므로 프로젝트 루트에서 다음과 같이 명령을 실행해야 한다.
npm install --save-dev gulp
  • 걸프는 최종 사용자에게는 필요 없지만 개발 과정에서 도움이 되는 개발 depency이다. 걸프가 없어도 앱은 잘 작동하나, 개발할 때 걸프가 있으면 작업이 편해진다.
  • 걸프가 설치되면 다음과 같이 gulpfile.js를 만든다.
const gulp = require('gulp');
// 걸프 dependency를 여기 씁니다.

gulp.task('default', function() {
    // 걸프 작업을 여기 씁니다.
});
  • 아직 걸프가 할 일을 지정하지 않았지만, 성공적으로 설치됐는지 확인하는 것은 가능하다. 콘솔에서 다음과 같이 명령을 한다.
gulp

 2.2.7 프로젝트 구조 

 

  • 걸프와 바벨을 써서 ES6 코드를 ES5 코드로 바꾸기 전에 코드를 어디에 저장할지 생각해야 한다. 
  • 소스코드를 src나 js 디렉토리에 저장하는 경우가 많지만 우리는 소스 코드를 es6 디렉토리에 저장할 것이다.
  • 서버 쪽(노드) 코드와 클라이언트 쪽(브라우저) 코드를 모두 포함하는 프로젝트가 많으므로 우리 코드도 양쪽 카테고리를 만든다. 서버쪽 코드는 프로젝트 루트의 es6 디렉토리에 저장하고, 브라우저 코드는 public/es6 디렉토리에 저장한다. 브라우저에 보내는 자바스크립트는 공개된 코드이기 때문이다.
  • ES6 코드를 변환한 ES5 코드를 저장할 장소는 distribution의 약자인 dist 디렉토리에 저장하는 경우가 많다. 따라서 서버쪽과 클라이언트쪽 es6 디렉토리가 있는 곳 옆에 dist 디렉토리를 만든다.

 2.3 트랜스 컴파일러 

 

  • 이 책을 쓰는 시점에서 가장 널리 쓰이는 트랜스 컴파일러는 바벨과 트레이서이다. 이 책에서는 트랜스 컴파일러로 바벨을 사용한다. 
  • 바벨은 ES5를 ES6으로 바꾸는 트랜스 컴파일러로 시작했고, 프로젝트가 성장하면서 ES6와 리액트, ES7 등 여러 가지를 지원하는 범용 트랜스컴파일러가 됐다. 바벨 버전 6부터는 ES5을 ES6로 변환하려면 ES6 변환 프리셋을 설치하고, 바벨이 해당 프리셋을 사용하게끔 설정해야 한다. 어떤 프로젝트에서는 ES6을, 어떤 프로젝트에서는 리액트를 쓰게 될 수도 있으므로 이번 설정은 이 프로젝트에만 적용해야 한다.
  • 먼저 ES6를 설치한다.
npm install --save-dev babel-preset-es2015
  • 프로젝트 루트에 .babelrc 파일을 만든다. 이 파일의 내용은 다음과 같다. 이 파일이 있으면 프로젝트에서 바벨을 사용할 때 ES6을 사용한다는 것을 인식한다.
{"presets": ["es2015"]}

 2.3.1. 바벨을 걸프와 함께 사용하기

 

  • 이제 걸프를 통해 우리가 작성할 ES6 코드를 ES5 코드로 바꿀 수가 있다. es6와 public/es6에 있는 코드를 ES5 코드로 변환하여 dist와 public/dist에 저장한다.
  • 다음 명령으로 gulp-babel 패키지를 설치한다.
npm install --save-dev gulp-babel
  • 그리고 gulpfile.js를 다음과 같이 수정한다.
const gulp = require('gulp');
const babel = require('gulp-babel');

gulp.task('default', function() {
    // 노드 소스
    gulp.src("es6/**/*.js")
    .pipe(babel())
    .pipe(gulp.dest("dist"));

    // 브라우저 소스
    gulp.src("public/es6/**/*.js")
    .pipe(babel())
    .pipe(gulp.dest("public/dist"));
});
  • 걸프는 파이프라인 개념으로 작업을 처리한다. 먼저 변환할 파일을 (src("es6/**/*.js))로 지정했다. **는 서브 디렉토리를 포함해 모든 디렉토리를 뜻하는 와일드 카드이다. 따라서 이 소스 필터는 서브디렉토리 깊이에 상관없이 es6에 있는 모든 .js 파일을 선택한다. 
  • 다음에는 이 소스 파일을 바벨에 파이프로 연결한다. 바벨은 ES6 코드를 ES5 코드로 변형한다. 마지막 단계에서는 컴파일된 ES5 코드를 dist 디렉토리에 저장한다. 걸프는 소스 파일 이름과 디렉토리 구조를 그대로 유지한다. 예를 들어 es6/a/b/c.js 파일은 dist/a/b/c.js로 컴파일되는 식이다.
  • 이제 ES6 샘플 파일을 만들어 걸프 설정이 제대로 동작하는지 확인해보자. ES6의 새기능을 사용하는 파일 es6/test.js를 다음과 같이 작성한다.
'use strict'
// es6 기능: 블록 스코프 변수 선언
const sentences = [
    {subject: 'JavaScript', verb: 'is', object: 'great'},
    {subject: 'Elephants', verb: 'are', object: 'large'},
];

// es6 기능: 객체 분해
function say({ subject, verb, object }) {
    // es6 기능: 템플릿 문자열
    console.log(`$(subject) $(verb) $(object)`);
}

// es6 기능: for..of
for (let s of sentences) {
    say(s);
}
  • 또, 이 파일을 public/es6에 복사해주고 gulp 명령을 내린다.
  • 이제 dist와 public/dist 디렉토리에 test.js 파일을 열어 ES6 파일과 다른 것을 확인해보자.
  • 그리고 ES6 파일을 실행해보자. 
$node es6/test.js
$(subject) $(verb) $(object)
$(subject) $(verb) $(object)
  • 그리고 ES5 파일을 실행하여 제대로 실행되는 것을 확인해보자
$node dist/test.js
JavaScript is greate
Elephants are large
  • 문제 없이 실행되는 것을 확인했다면, dist와 public/dist 디렉토리를 .gitignore 파일에 추가하자. 

 2.4 린트 

 

  • 린트 프로그램은 당신의 코드를 세심히 검토해서 자주 일어나는 실수를 알려준다. 따라서 초보자에게 린트 프로그램은 중요한 도구가 된다.
  • 자바 스크립트 린트 프로그램은 여러가지가 있으나, 이중에서 니콜라스 자카스의 ESLint를 설치해보자.
npm install -g eslint
  • ESLint를 사용하기 전에 프로젝트에 쓸 설정 파일, .eslintrc를 만들어야 한다. 프로젝트마다 다른 표준이나 규칙에 따라 작업해야 할 때, 그에 맞게 .eslintrc 파일을 만들어 ESLint의 린트 규칙을 적용할 수도 있다. 
  • eslint--init 명령을 내리고 몇 가지 질문에 답하면 기본 .eslintrc 파일이 만들어진다.
    • ESMAScript 6 기능을 사용합니까? YES
    • ES6 모듈을 사용합니까? YES
    • 어디에서 코드를 실행합니까(노드 또는 브라우저)? 노드
    • commonJS를 사용합니까? NO
    • JSX를 사용합니까? NO
    • 들여쓰기를 어떤 식으로 하겠습니까? 탭 혹은 스페이스
    • 문자열에 어떤 따옴표를 사용합니까? ' 혹은 "
    • 줄 끝 문자에 무엇을 사용합니까(유니스 또는 윈도우)? 리눅스나  macOS를 사용한다면 유닉스를 선택, 윈도우면 윈도우 선택
    • 세미콜론을 필수로 하길 원합니까? YES
    • 설정 파일 형식은 무엇으로 하시겠습니까(JavaScript, YAML, JSON)? JavaScript
  • 모든 질문에 답하면 .eslintrc 파일이 생성된다. 이제 ESLint를 사용할 수 있다.
  • ESLint를 사용하는 방법은 여러가지이다. eslint es6/test.js 명령을 실행하여 직접 실행할 수도 있고, 에디터에 통합할 수도 있고, Gulpfile에 추가해도 된다. 에디터에 통합되면 아주 편리하나 방법이 에디터와 운영체제마다 전부 다르다.
  • 에디터에 통합하더라도 Gulpfile에는 ESLint를 꼭 추가해라. 결국 빌드할 때마다 걸프를 실행하므로 여기서 코드를 체크하는 것이 좋다. 먼저 다음 명령을 실행한다.
npm install --save-dev gulp-eslint
  • 그리고 gulpfile.js를 다음과 같이 수정한다. 
const gulp = require('gulp');
const babel = require('gulp-babel');

gulp.task('default', function() {
    // ESLint를 실행합니다.
    gulp.src(["es6/**/(.js", "public/es6/**/*.js"])
    .pipe(eslint())
    .pipe(eslint.format());
    
    // 노드 소스
    gulp.src("es6/**/*.js")
    .pipe(babel())
    .pipe(gulp.dest("dist"));

    // 브라우저 소스
    gulp.src("public/es6/**/*.js")
    .pipe(babel())
    .pipe(gulp.dest("public/dist"));
});
  • 이제 ESLint에서 우리 코드 중 어떤 부분을 지적하는지 본다. Gulpfile의 기본 작업에 ESLint를 추가했으므로 걸프를 실행하기만 하면 된다.
  • ESLint는 무엇을 실수로 지적할지 정할 수 있다. comma-dangle 규칙의 기본 값은 never이고, 우리는 이 규칙을 아예 끄거나 always-multiline으로 정할 수 있다. .eslintrc 파일을 수정하여 이 설정을 바꿔보자.
  • .eslintrc의 각 규칙은 배열이다. 배열의 첫 번째 요소는 숫자이다. 0은 규칙을 적용하지 않은 것이고, 1은 실수라고 지적하며, 2는 에러로 간주한다.
{
  "rules": {
    /* 마지막 쉼표에 관한 규칙을 수정했습니다.
       하지만 이 파일은 JSON 파일이므로, 마지막 쉼표를 허용하는
       이 파일에는 마지막 쉽표를 쓸 수 없습니다.*/
    "comma-dangle": [
      2,
      "always-multiline"
    ],
    "indent":[
      2,
      4
    ],
    .
    .
    .
  • 이렇게 수정 후 걸프를 다시 실행하면, 끝 쉼표를 에러로 지적하지 않는다. 사실 test.js에서 줄 끝 쉽표를 제거하면 에러가 일어난다.
  • 두 번째 에러는 console.log에 관한 것으로 console.log를 실무 브라우저 코드에 남겨두는 것은 일반적으로 엉성한 습관이라 여기며, 구식 브라우저 대상일 경우 위험하기까지 하다. 하지만 공부 목적이라면 console.log에 대한 경고를 꺼도 된다. 이 책을 진행하는 동안 console.log를 많이 사용할 것이다.
  • quotes 규칙도 끄는 편이 낫다. 이 규칙을 비활성화시키는 방법은 직접 알아보자
  • ESLint에는 설정 옵션이 아주 많으며 이들은 모두 ESLint 웹사이트에 문서화되어 있다.