레이블이 CoffeeScript인 게시물을 표시합니다. 모든 게시물 표시
레이블이 CoffeeScript인 게시물을 표시합니다. 모든 게시물 표시

2018-02-09

[CoffeeScript] 왜 커피스크립트를 사용하지 않는가

 아랫글은 2016년에 썼던 글인데 왜인지 모르게 아직 publish 안 하고 있었다.
 그 사이에 ES2015(ES6)의 변경을 추가 한 커피스크립트2가 나왔다. 하지만 이미 ES2015를 넘어 ES2017도 나왔고, 브라우저들도 ES2016는 네이티브로 지원하고 있기 때문에 앞으로도 커피스크립트를 쓸 일은 없을 것 같아 발견한 김에 publish 한다.


 커피스크립트는 자바스크립트 코드를 간결하게 만드는 것을 목표로 만들어진 언어다. 2009년 첫 버젼을 릴리즈 하였고, 2010년 12월 1.0이 릴리즈 되었다.
 내가 커피스크립트를 처음 썼던 것은 1.0이 릴리즈 된 지 조금 뒤인 2011년 경이었던 것 같다. 지금도 자바스크립트 코드가 다른 언어에 비해 간결하지는 않지만, 당시 자바스크립트 코드는 지금보다도 verbose 하였기 때문에 꽤 애용하였었다. 그러다가 웹 말고 다른 일을 하다 보니 자바스크립트를 사용하지 않게 되었고 자연스럽게 커피스크립트도 안 쓰게 되었다. 그러다가 2014년경 잠시 웹 개발을 하게 되었는데 이때 습관적으로 다시 커피스크립트를 사용하였었다. 하지만 그것도 잠시였고, 그 뒤로는 사용하지 않게 되었다. 더 이상 커피스크립트를 쓰지 않게 된 이유는 크게 2가지였다.

 일단 커피스크립트의 문법은 너무 애매했다. 커피스크립트가 가장 중요하게 생각하는 요소 중 하나는 자바스크립트로 일대일로 매칭되는 것이다. 하지만 처음 커피 스크립트를 보면 자바스크립트 같은 느낌이 전혀 들지 않는다. 이는 커피스크립트 코드에서는 괄호를 거의 사용하지 않기 때문이다. 사실 일부 기능을 제외하고 대부분의 커피스크립트 코드는 적절한 위치에 괄호를 추가하는 것으로 자바스크립트 코드로 변환할 수 있다. 이는 커피스크립트의 설계자가 자바스크립트의 괄호가 자바스크립트 코드를 복잡하게 만든다고 생각했기 때문이다.
 하지만 실제로 사용해보면 이는 딱히 편하지 않다. 물론 괄호가 없기 때문에 타이핑은 많이 줄어든다. 하지만 코드를 작성해본 사람은 알겠지만 적은 타이핑은 딱히 간결한 코드를 만드는데 중요한 요소가 아니다. 게다가 이 정도 타이핑은 사실 좋은 에디터를 쓰면 해결될 문제다. 실제로 커피스크립트를 사용하면 타이핑이 줄어서 드는 이득보다 코드를 읽기 힘들어져서 생기는 문제가 더 크다. 물론 익숙해지면 어느 정도 해결되는 문제지만, 엣지 케이스에 대해서는 꾸준히 밟는 지뢰가 생긴다. 게다가 문제가 발생했을 때 컴파일 에러가 발생하는 것이 아니라 예상치 못했던 방식으로 컴파일돼서 실행되는 것이 더 큰 문제다.

 또한 당시에는 ECMAScript 6(a.k.a. ES6)를 ECMAScript 5로 변환시켜주는 babel이라는 기술이 나오고 있었다. ES6를 사용하면 커피스크립트만큼은 아니지만, 어느 정도 간결한 코드를 사용할 수 있었다. 그리고 ES6에는 이미 커피스크립트의 arrow 문법(-> 대신 =>를 사용하기는 한다)과 class가 추가됐다. 게다가 변수 선언이 암시적으로 이루어지는 커피스크립트의 특성상 ES6에 추가 된 let이나 const같은 장점을 전혀 사용할 수 없다.

 뭐 이런저런 이유로 더 이상 커피스크립트를 사용하지는 않을 것 같다. 하지만 커피스크립트의 노력이 헛되다고 생각하지는 않는다. arrow를 함수로 사용하기 시작한 것도, 자바스크립트에 class를 도입한 것도 내가 알기로는 커피스크립트가 처음이었고, 자바스크립트를 조금 더 쓰기 좋은 언어로 만드는데 커피스크립트가 기여한 바는 결코 작지 않다. 다만, 이미 커피스크립트가 해결하고자 하는 문제는 거의 다 자바스크립트에 반영됐고, 자바스크립트는 다음 문제로 넘어가고 있다. 따라서 앞으로 커피스크립트를 쓸 일은 없을 것 같다.

2014-03-01

[CoffeeScript] undefined를 void 0로 compile하는 이유는 무엇일까

 요새 재미삼아 만들고 있는 웹 프로그램이 있다.
 JavaScript를 약간 하드하게 사용하여야 하므로, pure한 JavaScript를 사용하지 않고, CoffeeScript를 이용하여 개발을 진행하고 있다.

 CoffeeScript 자체를 실행시키는 interpreter가 존재하지 않고, 언제나 JavaScript로 compile한 뒤 실행되어야 해서, 빠르게 코드 수정 내용을 테스트할 수 있다는 장점이 사라진다. 변환되는 과정에서 어떤 경우는 JavaScript로 직접 작성한 코드보다 비효율적인 코드가 나오기도 한다.
 게다가 CoffeeScript는 기본적으로 모든 JavaScript 코드는 CoffeeScript 코드로, CoffeeScript 코드는 JavaScript 코드로 1:1로 변환 가능하게 해주는 것을 목표로 삼고 있기 때문에, JavaScript보다 더 powerful한 것도 아니다.

 그럼에도 새 프로젝트에 JavaScript를 사용하지 않고 CoffeeScript를 사용하는 것은 다음의 두 가지 이유 때문이다.
 우선 내가 c-style의 코드보다 ruby-style의 코드를 더 좋아한다.
 별거 아니지만 오랜 시간 아무런 이득도 없이(쉽게 말해서 돈 받는 게 아니면서) 혼자서 쓸쓸히 작업하려면 내가 좋아하는 방식으로 작업하는 게 최고다.
 다음으로 compile과정을 거치기 때문에 실수를 한번 걸러줄 수 있다. compile 과정에서 엄격한 정적 분석을 거치는 것은 아니지만, 기본적인 실수를 막아주는 역할 정도는 할 수 있다.
  CoffeeScript가 undefined를 void 0로 compile하는 이유도 여기에 있다.


 위와 같이 undefined를 사용하는 CoffeeScript 코드를 컴파일하면, 아래와 같이 undefined를 void 0로 변환한 JavaScript 코드를 돌려준다.

 void 함수는 분명히 언제나 undefined를 return 하기는 하지만 굳이 멀쩡한 undefined를 놔두고 void 함수를 이용하는 이유는 무엇일까?

 결론부터 말하면 undefined가 멀쩡하지 않을 수도 있기 때문이다.
 기술적으로 말하면 undefined라는 variable에 undefined라는 value 이외의 다른 value가 있을 수 있다.
 JavaScript를 써본 사람 중 많은 사람이 어떤 경우에 이런 일이 있는지 궁금해할 것이다.

 undefined에 새로운 값을 할당해도 undefined가 여전히 undefined라는 것 정도는 이미 경험으로 알고 있을테니 말이다.

 하지만 다음의 예제를 한번 보자.

 someStrangeFunction은 인자를 2개 받아서 (그런데 두 번째 인자의 이름이 undefined라니) 첫 번째 인자가 undefined와 같은지 비교해준다.1)
 호출할 때 항상 두 번째 인자를 집어넣지 않으면 아무런 문제도 발생하지 않는다. 하지만 어떤 인자를 집어넣는다면 someStrangeFunction 안에서는 undefined는 더 이상 undefined를 의미하지 않고, 인자로 받은 값을 의미하게 된다.
 흔히 일어나지 않는 일이지만, 그런 만큼 디버깅이 쉽지 않은 버그다. 이런 일을 사전에 방지하고자 CoffeeScript에서는 undefined를 항상 void 0로 compile한다.

 그렇다면 함수의 인자를 undefined로 정하는 경우를 CoffeeScript에서는 어떻게 처리할까?
***: error: unexpected undefined
a = (undefined) ->
     ^^^^^^^^^
 그런 경우 그냥 compile 단계에서 깔끔하게 에러로 처리해버린다.

1) 일단 처음 이 코드를 본 사람은 이게 valid한 코드인지부터 의심될 것이다. undefined가 null처럼 value일 것으로 생각하기 때문에 그런 의심이 드는 것일 텐데, undefined는 variable이고, 위의 코드는 valid한 코드가 맞다.
 이에 대해서는 다른 글에서 자세하게 다루도록 하겠다.