toggle menu

[NodeJS] module.exports 와 exports 의 차이점

2014.12.01 15:52 Node.js
Express 에 대해서 분석하다보니, Router 부분에서 다소 익숙치 않은 부분을 발견했다.

아래와 같이 module.exports 에 객체를 직접 대입하는 부분이었는데, 항상 exports 아래에 프로퍼티로 값을 추가해주었던 기존 패턴과 달라서 어떤 효과를 갖는지 이해할 필요가 있었다.

var express = require('express');
var router = express.Router();

/* GET home page. */
router.get('/', function(req, res) {
  res.render('index', { title: 'Express' });
});

module.exports = router;

module.exports 와 exports, 서로 어떤 차이점이 있을까?



module.exports 와 exports 의 관계

CommonJS 방식으로 모듈을 선언하고 사용할 때 일반적으로 아래와 같은 방식으로 사용하게 된다.

exports.aaa = function ( a, b ) { return a + b; };

exports.bbb = function ( c, d ) { return c - d; };


이렇게 만들어진 모듈은 아래와 같이 require 로 로드하여 사용하게 된다.

var ddd = require('./module_name_without_extention');

var plus = ddd.aaa(1, 3);
var minus = ddd.bbb(5, 2);

모듈 객체의 프로퍼티 형태로 사용하는 매우 눈에 익은 패턴이다. 처음의 모듈은 아래와 같이 바꾸어 줄 수 있다.

module.exports.aaa = function ( a, b ) { return a + b; };

module.exports.bbb = function ( c, d ) { return c - d; };



그렇다면, module.exports 와 exports 는 서로 어떤 관계일까?

exports 가 call by reference 로 module.exports 를 바라보고 있고, 리턴되는 값은 항상 module.exports 이다. 이 관계를 굳이 코드로 표현해보면 아래와 같다.


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


기본적으로 module.exports, exports 모두 하나의 객체를 바라보고 있는데, 최종적으로 return 되는 것은 무조건 module.exports 라는 것이다. exports 에 멤버를 추가하면, 결국 module.exports 에도 같은 멤버가 추가되는 것이다.

하지만 결국 최종적으로 리턴되는 것은 module.exports 이다.  만약 exports 에 다른 객체를 할당하게 되면, module.exports 의 객체와 달라지게 되고, exports 에 어떤 변경을 해도 모듈에는 영향을 주지 못한다.



다시 맨 처음 소스로 돌아가보자.

var express = require('express');
var router = express.Router();

/* GET home page. */
router.get('/', function(req, res) {
  res.render('index', { title: 'Express' });
});

module.exports = router;

위의 소스를 다시 살펴보면, 이렇게 해석할 수 있다.

express.Router() 가 리턴한 "객체"에 일부 프로퍼티를 수정한 뒤, 이 객체 자체를 모듈로 리턴한 것이다.




결론

단순하게 CommonJS 방식의 모듈을 사용하다보면 놓칠 수 있는 몇가지 중요한 사실을 확인했다.

exports 가 module.exports 와 동일하며 동일한 객체를 call by reference 방식으로 바라보고 있다는 사실과, 최종적으로 리턴되는 값은 module.exports 라는 것이다.

이 두 가지 사실을 명확히 인지한다면, exports 와 module.exports 가 혼용되어 있다고 하더라도, 처음 의도된대로 소스를 해석하고 작성할 수 있을 것이다.


Node.js 관련 포스팅 더보기