브라우저에 크롬의 V8 엔진이라는 것이 있는데, 이 엔진과 다른 코드들을 결합하여 원래는 브라우저에서만 사용했던 자바스크립트를 브라우저 밖에서 사용할 수 있게 되었다. 그래서 브라우저 바깥에서 애플리케이션을 만들 수 있는 환경을 제공하게 되었는데, 이것이 Node.js이다.
Node.js는 각각의 파일을 모듈이라고 한다. 이 각각의 파일들의 코드들을 실행하기 전 우리가 보이지 않는 곳에서 Node.js가 코드를 자동으로 함수로 감싸준다. 이것을 Module Wrapper이라고 한다. Module Wrapper는 다음과 같은 형태를 가지고 있다.
(function (exports, require, module, __filename, __dirname) {
console.log('Hello from IIFE')
})()
이런 함수의 형식을 IIFE라고 한다. 이 코드에서 매개변수들은 Node.js가 제공하는 내장 객체들이다.
exports: 다른 파일에서 사용할 수 있도록 현재 모듈에서 외부로 내보내는 역할
require: 다른 모듈 불러오는데 사용
module: 현재 모듈에 대한 정보를 가지고 있음
__filename: 현재 실행중인 파일의 절대 경로
__dirname: 현재 실행중인 파일이 위치한 디렉터리의 경로 제공
이러한 연유로 우리가 따로 저렇게 IIFE 형식으로 직접 쓰지 않아도 예를 들어 이런식으로 코드를 쓰면
console.log(__filename);
console.log(__dirname);
현재 실행중인 파일의 절대 경로와 현재 실행중인 파일이 위치한 디렉토리의 경로가 나오게 되는것이다.
다음으로 다른 파일에 써있는 코드를 어떻게 가져올 수 있는지에 대해 알아보겠다.
예를 들어 이렇게 greet함수를 포함한 greet.js 파일이 있다고 해보자
function greet(username) {
console.log('hello',username);
}
// Tell other file you can use this same function
module.exports = greet;
이 greet 함수를 다른 파일에 내보내기 위해서는 module.exports를 사용해야 한다. 앞에서 말한 module wrapper에서의 매개변수를 활용했다는 것을 알 수 있다.
그리고 나서 다른 파일인 index.js에서는 다음과 같이 해당 함수를 가져올 수 있다.
const greet = require('./greet');
greet('Yuuka')
이렇게 하면 greet 함수를 index.js 파일 내에서 직접 정의하지 않고도 사용할 수 있게 된다.
다른 예시로 여러 변수들이 정의되어 있는 people.js 파일을 살펴보자.
let person1 = 'Yuuka';
let person2 = 'Yurika';
let person3 = 'Greta';
//We have to tell other files you can use these
// variables
// module.exports = person1;
module.exports = {person1, person2, person3}
이 파일에서는 여러 변수들을 객체 안에 담아 module.exports로 다른 파일에 내보낸다.index.js 파일에서 이 변수들을 가져와 사용할 수 있게 해주는 코드는 다음과 같다.
const {person1,person2, person3} = require('./people');
console.log(person1);
console.log(person2);
console.log(person3);
위에서 다른 파일에 써 있는 코드를 가져올 때 require를 사용했었다. 그런데 더 최신 버전으로 import를 이용하는 방법도 있다. 그 방법을 한 번 알아보자. 위와 똑같이 greet 함수를 포함한 아래의 greet.js의 함수를 내보낸다고 해보자.
function greet(username) {
console.log('Hello',username)
}
//Tell other files you can use this function
export default greet;
이렇게 export default를 붙여서 내보낼 수 있다. index.js에서 이 함수를 어떻게 불러오는지도 보자.
import greet from "./greet.js";
greet('Yuuka');
이렇게 require 대신 import를 써주면 된다. 그런데 여기서 주의해야 할 점은 from 후에 불러오는 파일 경로를 써줄 때 js를 꼭 붙여줘야 한다는 것이다. require를 사용할 때는 js를 붙여주지 않아도 된다는 점이 다르다.
그럼 import를 사용할 때 여러 가지를 내보내고 불러오는 것은 어떻게 할까? people.js 파일에 이런 코드가 있다고 해보자.
let p1 = 'Yurika'
let p2 = 'Angel'
let p3 = 'Zzong'
export { p1, p2, p3 };
위의 코드처럼 export하고 객체에 보낼 것들을 적어주면 된다. 불러오는 것은 index.js 파일에 이렇게 써주면 된다.
import {p1, p2, p3} from './people.js'
console.log(p1, p2, p3)
여기서 기억해야 할 점은 이렇게 import를 이용할 때는 package.json에서 타입을 추가해 줘야 한다는 것이다. (참고로 package.json은 npm init -y을 해줘야 생김)

위의 캡쳐에서 "type":"module", 이라고 적어준 부분이 보일것이다. 이렇게 써줘야지만 import를 사용할 수 있다.
또, import쓰게 되면 require 을 썼을 때와 다르게 __filename 과 __dirname에 접근할수가 없다. 따라서 아래와 같이 콘솔로그에 출력해보려고 해도 되지 않는다.
console.log(__filename);
console.log(__dirname);
그렇기 때문에 import를 쓸때는 따로 path module이라는걸 써준다. path module은 다음 포스트에서 정리해보도록 하겠다.