Javascript Runtime & Node.js

런타임이란 우리가 만든 코드가 실행되는 환경을 말한다. 다시 말해서, “어떤 프로그래밍 언어가 동작할 수 있는 프로그램" 이다. 자바스크립트로 만든 코드가 웹에서 돌아간다면, 이때 런타임은 브라우저다. Node.js도 마찬가지로 자바스크립트가 실행될 수 있는 런타임이다. 우리는 Node.js 덕분에 자바스크립트를 이용해 서버를 만들 수 있다.

NVM(Node Version Manager)

IT환경은 끊임없이 변한다. 언어, 프레임워크, 라이브러리 등 모든 것이 실시간으로 업데이트된다. Node.js도 마찬가지다. 업데이트는 좋은 것이지만, 우리는 항상 누군가와 함께 일하기 때문에 버전 충돌이라는 문제를 겪는다. 내가 만든 코드가 동료의 컴퓨터에서는 읽히지 않으면 큰 문제다. NVM은 내 컴퓨터에 여러가지 버전의 Node를 설치하고, 필요한 버전을 선택해서 사용할 수 있게 해주는 메니징 프로그램이다.

$ nvm ls
$ nvm install 10.13.0
$ nvm use (사용하고 싶은 node version)

Package.json & NPM(Node Package Module)

하나의 프로그램은 다양한 모듈이 합쳐져서 만들어진다. 하나의 코드에 몽땅 집어 넣을 수도 있지만, 그렇게 하면 인수인계, 유지보수할 때 후회한다. 그렇기 때문에 모듈 별로 개발을 하고, 모듈 별로 다운받을 수도 있다. 이때 필요한 것이 NPM 과 package.json이다.

NPM은 node모듈들을 다운로드할 수 있는 일종의 앱스토어이다. npm 명령어를 통해 앞으로 필요한 모듈들을 모두 다운로드할 수 있다.

package.json에는 이 프로그램을 실행시키기 위해 필요한 모듈이 무엇인지, 프로그램을 실행시키는 방법, 프로그램을 테스트하는 방법 등이 명시되어 있다. 일종의 전자제품 카탈로그다. 단, 여기는 필요한 모듈들이 명시만 되어있다. 실제 모듈들은 node_modules 폴더에 모두 들어가 있다.

1. dependencies : 필요한 모듈 목록
“dependencies”:{
   "react":"16.9.5"
}
2. devDependencies : 개발하는 환경에서 필요한 모듈 목록
"devDependencies":{
   "jest": "2.0",
   "eslint": "3.0'
}
3. scripts : npm으로 실행시킬 수 있는 명령어 정의
"scripts":{
   "start": "node app.js",
   "test":  "node test.js"
}
=> npm run start 혹은 npm run test 명령어 사용 가능

Scope & Closure, Hoisting

Scope(스코프)는 변수의 접근 유효 범위이다. 스코프는 계속해서 변한다. 두가지 스코프, Lexical scope 와 Dynamic scope로 나눌 수 있다. Lexical scope는 유효범위가 코드를 작성할 때 결정된다. 반면, Dynamic scope는 함수가 실행될 때 결정된다(this 키워드).

변수를 선언하는 방법에 따라 스코프가 달라지기도 한다. Block level 과 function level 로 나눌 수 있다. var 의 경우 함수를 스코프로 가지며(function level), let과 const는 block을 스코프로 가진다(block level). let을 사용해서 변수를 사용하는 편이 혼돈을 줄일 수는 있지만, 어떤 상황에서는 var이 필요하기도 하다.

Closure는 외부 함수의 변수에 접근할 수 있는 내부함수로, 함수를 리턴함으로써 주로 구현된다. 함수형 프로그래밍에 필수적인 스킬이다

this

자바스크립트에서의 this 는 C++에서의 this와 약간 다르다. C++ 에서 this는 클래스 내에서 사용되는 포인터로, 현재 멤버 함수(메소드)가 호출된 인스턴스의 주소를 가리킨다. 자바스크립트에서 this 는 좀 더 복잡하다. 잘 이해하기 위해서는 실행 컨텍스트(나중에 따로 정리)를 보자.

나름대로의 정의를 하자면 this 는 메소드나 프로퍼티가 호출하는 객체 를 기리킨다. 어떻게 호출됐는지에 따라 달라질 수 있다는 것이다. this가 binding 바인딩 되는 규칙은 다섯가지가 있다.

5 this binding patterns
Global reference : log(this)
Free Function Invocation : 함수의 호출이 전역에서 이루어 질 때 this 는 window 를 가리킨다.
.call or .apply invocation : fun.call(obj)
Construction Mode : new fun();
Method Invocation : 닷 노테이션을 통해서 함수가 호출될 경우 호출한 객체가 this가 된다. Obj.method()

아래 소스들의 결과값이 어떻게 될지 생각해보자.

var x = 10;
var strangeAdd = function(y){
    var x = 20;
    return this.x+y;
};
var result = strangeAdd(10);
var obj = {
  foo: function(){
    console.log(this);
  }
}
var obj2 = {
  foo: obj.foo
}
obj.foo.call(obj2);

Testing & Linting(+Prettier)

Testing(테스팅)은 우리가 작성한 코드가 의도대로 동작하는지, 문제가 없는지를 확인하기 위한 툴이다. 테스팅 방법에 따라 End to End test, Integration test, Unit test세가지가 있다. 이번 프로젝트에서는 Unit Test의 기능을 하는 Jest를 사용했다.

Linting(린팅)은 지정한 코드스타일을 지키는지의 여부를 체크해주는 툴이다. 이를 통해 일관된 코드 스타일 유지가 가능해진다. 린터를 이용해 체크를 할 수 있는 시점도 정할 수 있는데, 크게 1. 코드 작성 중(에디터에 플러그인 설치) 2. Commit 시 3. Test를 돌릴 때(Cl)가능하다. 다양한 종류의 린터가 있지만, 이번 프로젝트에는 ESlint를 사용했다.

린팅에 대해 조사하다 보면, Prettier(프리티어)도 자연스럽게 접할 수 있다. 이 둘을 비슷하면서도 다르다. 린팅은 코드의 규칙을 잡고, 프리티어는 코드의 모양을 잡는다. 린터와 프리티어를 연결하여 우리가 설정한 규칙대로 프리티어가 코드를 수정할 수 있다. 참고할 점은, 기본적으로 유명한 lint rule에 대해서는 프린티어가 이미 설정되어 있기 때문에 린터와 프리티어가 언뜻 저절로 연동이 되는 것 같지만, 아니다. 직접 연결해줘야 한다.

Git flow

깃을 통한 버전 관리는 매우 중요하다. 아무 생각 없이 사용했던 아래 세가지 깃 명령어를 remote 와 origin의 이해를 통해 확실하게 알고 넘어가자

remote?
remote는 내 컴퓨터가 아닌 모든 곳을 가리킨다. 깃헙의 내 repo, 페어의 repo 등 모든 것이 해당된다.
origin?
origin은 어떤 repo를 local(내 컴퓨터)로 clone해왔을 때 받아온 repo를 가리킨다.

1. git remote add pair (원격 repo 주소)
2. git push origin master
3. git pull pair master

1. git remote add pair (원격 repo의 주소)
(원격 repo의 주소)를 git에 알려주고, 이름은 pair로 설정한다.

2. git push origin master
origin에 현재 작성중인 master 를 push 한다. origin의 위치에는 remote의 이름을 적을 수 있다.

3. git pull pair master
pair라는 이름의 원격 repo를 현재 작성중인 master로 가져온다. 이때 같을 파일을 변경 했을 때 충돌이 일어날 수 있다.