exports 와 module.exports 를 좀 더 생각해보기

이상문
3 min readApr 19, 2020

자바스크립트를 처음 접하게 된 것은 node.js를 프로젝트를 위해서 사용하기 시작하면서였다. 모듈이라는 개념이 node.js 자체에서 지원됨으로써 재사용성과 확장성이 아주 높은 언어로 인상이 남아있다.

그런데, 어떤 곳에서는 모듈로 내보내기 위해서 exports로 사용하고, 또 다른 곳에서는 module.exports 로 사용하는 것으로 나온다. 대체 어떤 장단에 맞춰서 사용해야 하는 것일까.

결론은 둘은 하나인 것이고, module.exports 는 좀 더 넓은 범위의 경우에 대해서 사용할 수 있다.

Node.js By Example이라는 책에서는 exports 와 module.exports 와의 관계를 다음과 같이 표현했다.

var module = { exports: {} };
var exports = module.exports;
// our code
return module.exports;

즉, module.exports 가 exports라는 의미가 된다.

그래서, 다음과 같이 코드를 작성하면 재미있는 결과를 얻을 수 있다.

// in test-module.js
exports.name = "test module";
module.exports.name = "test overriding";

test-module.js 라는 모듈을 하나 작성했고, 이 모듈을 사용하는 코드를 다음과 같이 작성했다.

const test-module = require("./test-module");
console.log(test-module.name);

결과는 다음과 같이 출력된다.

"test overriding"

즉, test-module.js 파일에서 작성했던, exports.name과 module.exports.name 이 같은 것이기 때문에 앞서 대입했던 “test module” 이 뒤에 대입한 “test overriding” 으로 대체되어 버리는 것이다.

그렇다면, 굳이 module.exports와 exports를 구분해 뒀을까. 개인적인 추론이긴하지만, 우선 첫번째로는 앞서 예를 통해서 충분히 예상할 수 있듯이, 편의성 때문이다. module.exports라고 길게 쓰는 것보다 exports만 써도 앞선 예는 충분히 사용할 수 있다.

두번째로 exports를 사용할 수 없는 경우가 있다. 다음과 같은 경우를 생각해보자.

// in test-module2.js
module.exports = {
print: () => {console.log("This is test-module2");}
}

즉, module.exports 자체가 오브젝트로 대체되는 경우이다. 그런데, 이러한 경우에 대해서 exports를 사용한다고 가정해보자.

// in test-module3.js
exports = {
print: () => {console.log("This is test-module3");}
}

앞선 예제에서는 module 이 살아있기 때문에 module이 모듈 처리하기 위한 작업들을 할 수 있겠지만, 뒤의 예제에서는 exports가 새롭게 정의하는 오브젝트로 대체되어버리기 때문에 모듈 처리하기 위한 아무런 작업을 할 수 없게 될 것이다. 바로 이것이 module.exports와 exports의 사용하는 경우를 구분해야 하는 이유가 될 것이다.

결론

module.exports와 exports는 결론적으로 같은 것이다. exports는 더 간략히 표현할 수 있기 때문에 편의성이 있다. 그러나, 오브젝트 자체를 내보내기하기 위해서는 exports는 대체가 되는 문제가 있기 때문에 module.exports 를 사용해야 한다.

--

--

이상문

software developer working mainly in field of streaming, using C++, javascript