[js/ts] require와 import

Aain·2024년 1월 5일

JS 백엔드

목록 보기
2/2

JS가 모듈을 불러오고 내보내는 2가지 방법

JavaScript에는 2가지 모듈 방식이 존재한다.
CommonJS방식과 ES방식이다.
CommonJS는 조금 더 전통적(?)이랄까 기존에 존재하던 방식이고 ES는 최신의 방식이다.

CommonJS방식은 node.js에서 돌아가고 ES 모듈 방식은 최신답게(?) node.js와 브라우저 모두에서 돌아간다.

둘은 문법과 방식에서 차이점이 있다.

2가지 모듈 방식

1. CommonJS 모듈 시스템

  • 불러오기
    const 변수명 = require('모듈명');
  • 내보내기
    module.exports 모듈

변수명에 아무거나 들어갈 수 있긴 하지만 다른 개발자나 본인을 위해서 관례적으로 대부분 해당 모듈 이름을 그대로 사용한다.

2. ES 모듈 시스템

  • 불러오기
    import path from 'path'
  • 내보내기
    export 모듈

어떤 모듈 방식인지 알 필요가 있을 때

Express.js나 NestJS등 JS로 서버 만드는 과정을 공부하면서 어느 파일에서 이 처리가 수행된건지 궁금할 때가 있다. 파일이 갈수록 많아지면서 디렉토리 및 파일의 구조가 머리속에 아직 완벽히 정리 되지 않았을 때 console.log로 해당 파일의 이름이 출력되게 하면 알아보기가 쉽다. 그래서 종종 이용하는데, 보통 아래와 같이 사용한다.

console.log(__filename);

그런데 이렇게 __filename만 사용하면 아래와 같이 전체 경로명이 다 나온다.

결과
/Users/leeaain/codes/node/book_backend/08_nestJs/blog/src/blog.service.ts

때문에 path 모듈을 불러들여 path.basename()으로 감싸줘서 파일 이름만 나오도록 한다.

const path = require('path');
console.log(path.basename(__filename) + ': 데이터를 가져옵니다.')

NestJS는 파일들을 타입스크립트로 작성하며. 최신 버전의 타입스크립트에서는 주로 import문(ES 모듈 스타일)을 사용한다. 그래서 import path from 'path';라고 작성해봤더니 path라는 게 없다고 에러가 난다. 왜지??

이유를 살펴보니 CommonJS 모듈 방식(require문)과 ES 모듈 방식(import문)이 내보내고 받아올 때 차이가 있어서다.

어떤 모듈방식인지 어떻게 알 수 있을까?

path 모듈의 기술문서를 찾아가 보자. (npm path module document 따위로 검색해보았다)

path 모듈 기술문서 -> https://nodejs.org/api/path.html


중간쯤에 Source Code: lib/path.js 라는 부분이 있다. 링크를 클릭하면 아래로 이동하게 되고 path 모듈의 내부 코드를 볼 수 있다. 이렇게 소스코드가 공개되어 있다.
https://github.com/nodejs/node/blob/v21.5.0/lib/path.js#L30

코드의 맨 마지막 줄을 보면 path 모듈이 자신을 어떤식으로 내보내고 있는지 확인할 수 있다.

module.exports = platformIsWin32 ? win32 : posix;

CommonJS 방식인 module.exports로 내보내고 있다.

A 모듈방식으로 만들어진 것을 B 모듈방식으로 불러들여 쓸 수 있을까?

이것을 다음과 같이 ES 모듈 방식으로 불러들이려면 에러가 난다.

import path from 'path';

왜냐하면 ES 모듈방식에서는 기본적으로 export default 땡땡땡형식으로 내보낸 것(이렇게 내보내면 모듈 전체가 한 덩어리가 된다)만 위와 같이 받아올 수 있기 때문이다.

앞에서 확인했듯이 path 모듈은 CommonJS 방식으로 작성되어 있다. 이것을 ES 방식 문법인 import로 불러오려면 중간에서 번역을 해주어야 한다. 이때 번역해주는 프로그램을 '번들러'라고 하는데 대표적으로 webpack이 있다.

ES 방식으로 번역된 path 모듈에는 export default 구문이 존재하지 않고 대신에 수십개의 메서드들이 조각조각 따로 내보내진다. 따라서 한덩어리로 불러들이는 import 모듈명 from '모듈' 형태로 불러올 수 없다.
(webpack이 번역해주는 과정에서 그렇게 되는것인지는 잘 모르겠다)

그래서 아래와 같이 수십개의 메서드 들 중 필요한 것들만을 따로따로 한개씩 받아들이던지

import { basename } from 'path';

아니면 아래처럼 해서 한덩어리로 전체를 받아오고 필요한 메서드를 닷 노테이션으로 사용할 수도 있다.

import * as path from 'path';

path.basename(파일경로명)

단순히 const path = require('path')를 어째서 import path from 'path'라고 바로 사용할 수가 없나 찾아보다가 알아낸 것들을 이렇게 기록으로 남긴다.

profile
{happiness: true}

0개의 댓글