본문 바로가기

카테고리 없음

자바스크립트 완벽 가이드 | 모듈

모듈화 프로그래밍의 목표는 큰 프로그램을 코드 모듈로 분리해서 모듈 개발자가 예측하지 못한 상황에서도 코드 전체가 정확히 실행하도록 하는 것입니다. 최근까지 자바스크립트는 모듈을 지원하지 않았고 큰 프로젝트 단위로 일하는 프로그래머는 클래스, 객체, 클로저에서 파생된 미약한 모듈성을 최대한 이용해야 했습니다. 클로저 기반 모듈성이 코드 번들링 도구의 지원에 힘입어 require 함수 형태로 실용화됐으며, 노드에서 이 시스템을 도입했습니다. 

 

require()에 기반한 모듈은 노드 프르고르매이 환경에서 필수적인 부분으로 정착했지만 자바스크립트 언어에서 공식적으로 받아들이지는 않았습니다. ES6는 require() 대신 import와 export 키워드를 사용하는 모듈 시스템을 도입했습니다. 

 

클래스, 객체, 클로저를 사용하는 모듈

클래스 메서드가 다른 클래스 메서드와 독립적인 이유는 각 클래스 메서드가 독립적인 프로토타입 객체의 프로퍼티로 정의됐기 때문입니다. 객체가 모듈의 성격을 가지므로 클래스 역시 모듈의 성격을 띱니다. 

 

노드 모듈

노드 프로그래밍에서는 일반적으로 프로그램을 여러개의 파일로 나눕니다. 이 파일은 빠른 파일 시스템에 존재한다고 가정하므로, 비교적 느린 네트워크 연결을 통해 자바스크립트 파일을 불러오는 웹 브라우저와 달리 노드 프로그램을 파일 하나로 모을 필요가 없습니다. 노드에서 각 파일은 비공개 네임스페이스를 가진 독립적 모듈입니다. 파일에서 정의한 상수,변수, 함수, 클래스는 모두 파일에서 내보내지 않는 한 비공개입니다. 모듈에서 명시적으로 내보내야만 다른 모듈에서 그 값을 가져올 수 있습니다. 노드 모듈은 require() 함수를 통해 다른 모듈을 가져오고, Exports 객체의 프로퍼티를 수정하거나 module.exports 객체 자체를 바꾸는 방법으로 공개 API를 내보냅니다.

 

노드의 전역 객체 exports는 항상 정의되어있습니다. 여러가지 값을 내보내는 노드 모듈을 만들 때 다음과 같이 이 객체의 프로퍼티로 할당하면 됩니다. 

 

const sum = (x, y) => x + y;
const square = x => x * x

exports.mean = data => data.reduce(sum) / data.length;
exports.stddev = function(d) {
	let m = exports.mean(d);
	return Math.sqrt(d.map(x => x - m).map(square).reduce(sum) / (d.length - 1)
}

 

함수와 클래스로 구성된 객체를 내보내지 않고 함수나 클래스 하나만 내보낼 때도 만습니다. 이럴 때는 내보낼 값을 module.exports에 할당합니다. 

 

module.exports = class BitSet extends AbstractWritableSet {}

 

module.exports의 기본 값은 exports가 참조하는 것과 같은 객체입니다. 앞에서 사용한 통계 모듈에서도 평균을 계산하는 함수를 exports.mean 대신 module.exports.mean에 할당할 수 있습니다. 

 

노드 모듈은 require() 함수를 호출해 다른 모듈을 가져옵니다. 이 함수의 인자는 가져올 모듈 이름이며 반환 값은 모듈이 내보내는 값(일반적으로 함수, 클래스, 객체)입니다. 

 

Exports 객체와 require() 함수는 노드 모듈에서 사용합니다. 웹팩 같은 번들링 도구로 코드를 처리한다면 웹 브라우저에서도 이런 스타일의 모듈을 사용할 수 있습니다. 

 

ES6 모듈

ES6에서 import와 export 키워드를 자바스크립트에 추가하면서 마침내 언어 코어에서 모듈을 지원하기 시작했습니다. ES6의 모듈성은 노드의 모듈성과 같은 개념입니다. 각 파일이 하나의 모듈이며 파일에서 정의한 상수,변수,함수,클래스는 명시적으로 내보내지 않는 한 해당 모듈에서만 사용됩니다. 모듈에서 값을 내보내면 다른 모듈에서 명시적으로 가져와 사용할 수 있습니다. ES6 모듈의 문법은 노드 모듈과 내보내기/가져오기 문법에 차이가 있고 웹 브라우저에서 모듈을 정의하는 방법도 다릅니다. 

 

ES6 모듈은 일반적인 자바스크립트의 ‘스크립트’와 중요한 차이가 있습니다. 가장 명백한 차이는 모듈성 자체입니다. 일반적인 스크립트에서는 최상위에서 선언한 변수, 함수, 클래스는 모두 모든 스크립트가 공유하는 전역 컨텍스트에 들어갑니다. 모듈에서는 각 파일에 비공개 컨텍스트가 있으며 import와 export문을 사용할 수 있습니다. 모듈에서는 최상위 코드에서도 this가 undefined입니다. 웹 브라우저와 노드의 스크립트에서 this가 전역 객체인 것과는 다릅니다. 

 

함수 선언과 마찬가지로 가져오기는 모듈 맨 위로 끌어올려지므로 가져온 값은 모듈 어디에서든 사용할 수 있습니다.