이 글은 Modules, a Future Approach to JavaScript Libraries – Tuts+ Code Article의 글을 한국어로 옮긴 것입니다. (참고로, 지금까지 이곳에 올린 글 중에 가장 긴 게 아닌가 생각되네요.)

jQuery와 같은 JavaScript 라이브러리는 거의 지난 10여 년 동안 웹 브라우저에서 실행될 JavaScript를 작정할 때마다 당연히 가장 먼저 추가해야만 되는 것으로 여겨지고 있습니다. 이러한 현상은 각종 브라우저 간 차이와 구현 문제로 어쩔 수 없었으며, 그래서 지금까지 그 임무를 훌륭히 수행하고 있습니다. jQuery는 이러한 브라우저 버그와 각자 기괴하게 꼬인 것들을 알아서 말끔하게 덮어주면서 가령 이벤트 처리나 Ajax 그리고 DOM 조작과 같은 작업을 손쉽게 만들어 주었습니다.

이땐, jQuery가 거의 모든 문제를 해결해 주었기에, 자연스레 추가해서 얻은 막강한 힘을 빌려 그냥 작업에만 바로 집중할 수 있었지요. 이것은 마치 브라우저가 제대로 작동하려면 있어야 하는 블랙박스와 같았습니다.

하지만 지금, 웹은 진보하였고, API도 많이 개선되었으며 마찬가지로 웹 표준도 그만큼 더 많이 구현되기 시작하면서 아주 빠르게 변화하는 환경이 되었습니다. 그래서 과연 미래의 브라우저에도 이런 거대한 라이브러리들이 필요로 할지 의문을 가질 수밖에 없게 되었습니다. 결국 모듈(Module)에 적합한 환경으로 변화하고 있는 것입니다.

모듈 소개

모듈은 어떤 하나의 특화된 기능을 아주 잘 수행하는 어떤 독립된 집합체라 할 수 있습니다. 예를 들어, 모듈은 어떤 특정 엘르먼트에 클래스를 추가하는 기능을 수행하거나, 혹은 Ajax를 이용한 HTTP 통신을 하는 등 그 가능성은 무한합니다.

모듈은 그 모양과 크기가 여러 가지 있는데, 일반적인 목적은 하나같이 작업 환경에 불러오기만 하면 알아서 원래 가지고 있는 기능을 잘 수행하는 데 있습니다. 보통 모듈은 기본적으로 각각의 개발자 문서와 설치 과정 그리고 브라우저나 서버와 같은 실행 환경의 정보를 제공하고 있습니다.

이러한 모듈은 프로젝트에 필요한 기능을 메꿔주면서 나중에 추가와 제거와 같은 의존성 관리가 훨씬 간편해지는 효과가 있습니다. 모듈이 제공하는 장점과 유연성을 생각해보면, 이젠 어떤 덩치 큰 라이브러리를 단순하게 추가하는 일은 점점 줄어들 것입니다. 다행스럽게도 jQuery와 같은 라이브러리들도 이점을 인식해서 필요한 기능만 내려받을 수 있는 온라인 도구를 제공하기 시작했습니다.

최근에 소개된 API들은 모듈로 작성될 수도 있는 영감을 북돋게 하는 커다란 촉진제 역할을 하였고, 이젠 브라우저의 구현 상황도 상당히 좋아져서, 대부분의 일상적 작업은 작은 기능의 모듈을 작성해서 대신 처리해 줄 수도 있게 되었습니다.

모듈의 시대는 이미 도래했으며, 앞으로도 오랫동안 그 소임을 계속 맡아주리라 기대되고 있습니다.
Modules, 앞으로 JavaScript 라이브러리가 나아갈 길 제목의 글 마저 읽기 »

node module을 처음 접해서 사용하다 보면 많은 사람이 갖게 되는 질문인데, 다음 글에 간단명료하게 정의되어 있다.

Difference between “module.exports” and “exports” in the CommonJs Module System – Stack Overflow

결국, 다음 코드로 간단히 설명된다.

var module = { exports: {} };
var exports = module.exports;

// your code

return module.exports;

exports의 property에 설정된 것은 문제없지만, exports 자체를 다른 것으로 설정해서 바꿔버리면 module.exports와의 연결고리가 끊어지게 되므로 이점 주의해야 한다.

좀 더 자세히 설명해놓은 글: Node.js Module – exports vs module.exports

module.exports.*exports.* 모두 다 함께 쓸 수 있다고 해서 번갈아 혼합해서 쓸 필요는 없고, module.exports.*의 존재 자체는 이해하되 일관성 있게 exports.*를 애용해서 사용해 줄 것을 권장한다.

꼬리표:
Function.prototype.throttle = function(n) {
  var fn = this;
  var throttled = false;
  return function() {
    if (throttled) return;
    throttled = true;
    fn.apply(null, arguments);
    setTimeout(function() {
      throttled = false;
    }, n);
  };
};

가령 window.onscroll event에 심어놓은 function이 불필요하게 너무 자주 실행되는 것을 방지하려는 목적으로 사용될 수 있는데, 간단한 사용법으로 다음과 같이 적용할 수 있다.

var logTest = function() {
  console.log('test');
};

window.onscroll = logTest.throttle(1000);

이렇게 해놓으면, 최대 1초에 한 번씩만 등록된 함수가 실행되면서 콘솔에 해당 메시지가 찍히는 것을 볼 수 있다. 비슷한 함수로 Underscore.jsLo-Dash에서도 모두 throttle이란 이름의 함수를 함께 제공하고 있음.

따온 곳: Functional Javascript Tools & Tricks – Tim Ruffles on Vimeo

가끔 웹페이지에 걸려있는 링크를 타고 들어가 보면 타이머를 걸어 놓고서 일정 시간이 지난 후에야, 가령 특정 form의 자료 입력과 같은, 작업을 진행할 수 있게 해 놓은 곳과 마주치곤 한다. 보통 링크 클릭을 통한 광고와 수익의 창출을 목적으로 이런 현상이 퍼지는데, 이럴 때마다 불편함과 함께 은근 짜증을 일으키게 한다.

그래서 이런 때를 대비해서 아래와 같은 JavaScript timers의 지연 시간을 아주 짧게 써는 실험 목적의 주문을 만들어 봤다. 주문이 잘 먹히면 더딤 없는 쾌속 진행의 길을 뚫을 수 있다. (물론, 사이트에서 어떤 추가 확인장치를 해 놓은 곳이라면 이것도 별 소용이 없겠지만.)

var originalInterval = this.setInterval, originalTimeout = this.setTimeout;
this.setInterval = function(func, delay) {
  originalInterval(func, 10);
};
this.setTimeout = function(func, delay) {
  originalTimeout(func, 10);
};

이를 이용한 간편 사용 목적의 bookmarklet: fastTimer – 가속기가 달린 고장난(?) Timer.

꼬리표:

CSS3에서 새로 소개된 rem(root em) unit은 em unit과 마찬가지로 상대성을 띤 Relative length units 중 하나지만, 기존 부모 요소를 기준으로 한 em unit과 달리 root element, 그러니까 html element를 기준으로 그 크기 값이 정해지면서 부모 요소의 중첩으로 생기는 뻥튀기의 부작용을 걱정할 필요가 없다는 것이 장점이다.

그래서, 어느 하나의 요소를 기준으로 또 다른 요소의 상대적 크기를 정해주고 싶을 때 많이 사용되는데, 문젠 언제나 그렇듯 IE < 9을 포함해서 아직 만족스럽지 못한 rem unit의 브라우저 지원 상황을 고려해서, 미지원 브라우저에서도 인식되도록 적절한 대응 값을 함께 정의해 줘야 하는 성가심이 있다.

이런 상황에서 SaasLESS 혹은 Stylus와 같은 CSS pre-processor의 힘을 빌린다면 효율적인 CSS 작성에 큰 도움이 된다는 것은 이미 잘 알려져 있다. 하나의 좋은 본보기로, CSS pre-processor를 써서 rem unit의 fallback을 구현한 예.

한편 아래는 실험 삼아 지금 한창 논의되고 있는 CSS VariablesCalc() function만을 써서 rem unit의 fallback을 구현해 보았는데, 여기에 꼭 안성맞춤으로 CSS polyfill임을 자처하면서 지금 한창 개발중인 또 하나의 CSS preprocessor인 Myth의 힘을 빌려서 바로 적용해 보았다.

:root {
  var-base-font-size: 10;
  var-body-font-size: 14;
  var-heading1-font-size: 18;
}

html {
  font-size: calc(var(base-font-size) / 16 * 100%);
}

body {
  font-size: calc(0px + var(body-font-size));
  font-size: calc(0rem + var(body-font-size) / var(base-font-size));
}

h1 {
  font-size: calc(0px + var(heading1-font-size));
  font-size: calc(0rem + var(heading1-font-size) / var(base-font-size));
}

이렇게 작성된 CSS는 Myth를 통해 다음과 같이 변환된다.
CSS Variables와 Calc() function을 써서 rem unit의 fallback 구현하기 제목의 글 마저 읽기 »