상세 컨텐츠

본문 제목

[노드 1팀] 3장. 노드 기능 알아보기 (1)

24-25/Node.js 1

by gooroominuna 2024. 10. 11. 10:03

본문

728x90

3.1. REPL 사용하기 

REPL(Read Eval Print Loop)

  • REPL은 노드에서 제공하는 콘솔이다.
  • 입력한 코드를 읽고(Read), 해석하여(Eval), 결과를 출력하고(Print),
    종료할 때까지 반복(Loop)한다. 
  • REPL을 이용하면 JavaScript 코드를 미리 컴파일하지 않고, 바로 실행할 수 있다. 

REPL 사용법

  1. 콘솔 (Windows의 cmd, Mac/Linux/VS Code의 터미널)을 열고 node를 입력한다.
  2. > 모양이 나오면 JavaScript 코드를 입력할 수 있다.
  3. Ctrl + C를 두 번 누르거나 .exit을 입력하여 REPL을 종료할 수 있다.

 

3.2. JS 파일 실행하기 

  • 긴 코드를 실행할 때는 REPL 대신, 
    코드를 자바스크립트 파일로 만든 후 한 번에 실행하는 것이 편리하다. 
  • 파일을 생성한 후, 콘솔에서 node [파일 경로]를 입력하여 실행한다.
  • 이때 확장자(.js)는 생략 가능하다.

 

3.3. 모듈로 만들기  

Module (모듈) 

① 모듈

  • 모듈은 특정한 기능을 하는 함수나 변수들의 집합이다.
  • 여러 파일에서 재사용되는 함수나 변수를 모듈로 만들어두면 편리하다. 

② 노드는 코드를 모듈로 만들 수 있다.

  • 보통 파일 하나가 모듈 하나가 되며,
    노드에서는 대부분의 파일이 다른 파일을 모듈로 사용한다. 
  • 노드에서는 CommonJS와 ECMAScript, 두 가지 형식의 모듈을 사용한다. 

CommonJS 

  CommonJS 모듈

  • 표준 자바스크립트 모듈이 나오기 이전부터 쓰였던 것으로, 가장 널리 쓰이는 모듈이다.

② CommonJS 형식으로 모듈 만들기

  1. module.exports 객체 함수, 변수를 대입하면, 이 파일은 모듈로서 기능한다.

    var.js
    const odd = 'CJS 홀수입니다';
    const even = 'CJS 짝수입니다';
    
    module.exports = {
      odd,
      even,
    };
    

    다른 파일에서 var.js 파일을 불러오면 module.exports에 대입된 값을 사용할 수 있다.

  2. require 함수로 모듈을 불러올 수 있다.

    func.js
    const { odd, even } = require('./var');
    
    function checkOddOrEven(num) {
      if (num % 2) { 
        return odd;
      }
      return even;
    }
    
    module.exports = checkOddOrEven;

    require 함수 안에 불러올 모듈의 경로를 적는다. 이때 확장자와 index.js는 생략 가능하다.   
    require 함수를 통해 var.js module.exports에 담겨 있던 객체를 불러와 func.js에서 사용할 수 있게 된다.

    ** require가 반드시 파일 최상단에, module.exports가 최하단에 위치할 필요가 없다. 
    ** require 함수는 require.cache require.main 속성을 갖는다.  
       한번 require 한 파일은 require.cache에 저장되어 재사용할 수 있고,
       require.main은 노드 실행 시 첫 모듈을 가리킨다.


  3. 모듈 하나가 여러 개의 모듈을 사용할 수 있고,
    모듈 하나가 여러 개의 모듈에 사용될 수도 있다.

    index.js
    const { odd, even } = require('./var');
    const checkNumber = require('./func');
    
    function checkStringOddOrEven(str) {
      if (str.length % 2) { // 홀수이면
        return odd;
      }
      return even;
    }
    
    console.log(checkNumber(10));
    console.log(checkStringOddOrEven('hello'));
    

    index.jsvar.js func.js를 모두 참조하고, var.jsfunc.jsindex.js에 두 번 쓰일 수 있다. 


  4. exports 객체로도 모듈을 만들 수 있다.

    var.js
    exports.odd = 'CJS 홀수입니다';
    exports.even = 'CJS 짝수입니다';

    module.exports로 한 번에 대입하는 대신, 각각의 변수를 exports 객체에 넣는다. 
    module.exports와 exports가 같은 객체를 참조하기 때문에 동일하게 동작한다.

    ** exports에는 반드시 속성명과 속성값을 대입하여,
        module.exports와의 참조 관계가 깨지지 않도록 주의해야 한다.
    ** 참조 관계가 있으므로
        한 모듈에 exports 객체와 module.exports를 동시에 사용하지 않는 것이 좋다.
    **  노드에서 this
         최상위 스코프에 존재하는 this는 module.exports를 가리킨다.
         함수 선언문 내부의 this는 global 객체를 가리킨다.

 
③ 순환 참조(circular dependency) 

 

  • dep1.js
    const dep2 = require('./dep2');
    console.log('require dep2', dep2);
    module.exports = () => {
      console.log('dep2', dep2);
    };
     
  •  dep2.js
    const dep1 = require('./dep1');
    console.log('require dep1', dep1);
    module.exports = () => {
      console.log('dep1', dep1);
    };
     
  •  dep-run.js
    const dep1 = require('./dep1');
    console.log('require dep1', dep1);
    module.exports = () => {
      console.log('dep1', dep1);
    };
     
  •  dep-run.js를 실행하

    1) require('./dep1')이 실행된다.
    2) dep1.js에서 require('./dep2')가 실행된다.
    3) dep2.js에서는 require('./dep1')이 실행된다.

    이 과정이 계속 반복되어 dep1의 module.exports가 함수가 아니라 빈 객체로 표시된다.
    이러한 현상을 순환 참조(circular dependency)라고 한다.
    순환 참조되는 대상은 에러 없이 빈 객체로 변경되므로 주의한다. 

ECMAScript 

 ECMAScript 모듈(ES 모듈)

  • 표준 자바스크립트 모듈 형식으로, 사용 비율이 늘어나고 있다.
  • 브라우저에서도 사용할 수 있어 브라우저와 노드에 같은 모듈 형식을 사용할 수 있다는 것이 장점이다.

  ECMAScript 모듈 사용법 

  • CommonJS의 require, exports, module.exports가 각각 import, export, export default로 바뀐다.
  • 확장자는 js에서 mjs로 변경되고, 생략이 불가능하다.  

    var.mjs 
    export const odd = 'MJS 홀수입니다';
    export const even = 'MJS 짝수입니다';

    func.mjs
    import { odd, even } from './var.mjs';
    
    function checkOddOrEven(num) {
      if (num % 2) { // 홀수이면
        return odd;
      }
      return even;
    }
    
    export default checkOddOrEven;

    index.mjs 
    import { odd, even } from './var.mjs';
    import checkNumber from './func.mjs';
    
    function checkStringOddOrEven(str) {
      if (str.length % 2) { // 홀수이면
        return odd;
      }
      return even;
    }
    
    console.log(checkNumber(10));
    console.log(checkStringOddOrEven('hello'));

 CommonJS vs ES 모듈 

  CommonJS 모듈 ECMAScript 모듈
문법 require('./a');

module.exports = A;

const A = require('./a');

exports.C = D;

const E = F; exports.E = E;

const { C, E } = require ('./b');
import './a.mjs';

export default A;

import A from './a.mjs';

export const C = D;

const E = F; export { E };

import { C, E } from './b.mjs';
확장자 js

cjs
mjs

js(package.json - type: "module")
확장자 생략 가능 불가능
다이내믹 임포트 가능 불가능
인덱스(index) 생략 가능

ex) require('./folder'))
불가능

ex) import './folder/index.mjs')
top level await 불가능 가능
__filename, __dirname,
require, module.exports, exports
사용 가능 사용 불가능
(import.meta.url 사용)
서로 간 호출 가능  

 

** 서로 간에 호환되지 않는 경우가 많으므로 한 가지 형식만 사용하는 것을 권장한다.

 

Dynamic Import (동적 불러오기) 

  • ES 모듈은 if문 안에서 import 하는 것이 불가능하므로,
    import 함수로 모듈을 동적으로 불러온다. 이를 Dynamic Import라고 한다.  

    dynamic.mjs
    const a = true;
    if (a) {
        const m1 = await import('./func.mjs');
        console.log(m1);
        const m2 = await import('./var.mjs');
        console.log(m2);
    }

    ** ES 모듈의 최상위 스코프에서는 async 함수 없이도 await 할 수 있다. 

__filename, __dirname 

  • __filename __dirname 키워드를 통해 현재 파일명 현재 파일 경로를 확인할 수 있다. 
     
    filename.js
    console.log(__filename); // C:\Users\user_name\Desktop\filename.js
    console.log(__dirname);  // C:\Users\user_name\Desktop
     
  • ES 모듈에서는 __filename과 __dirname을 사용할 수 없다.
    대신 import.meta.url로 경로를 가져올 수 있다.

    filename.mjs
    console.log(import.meta.url); // file:///C:/Users/user_name/Desktop/filename.mjs
    
    console.log(__filename); // ReferenceError: __filename is not defined in ES module scope



Quiz

  1.  콘솔에서 REPL로 들어가는 명령어는 (     ),
    노드를 통해 파일을 실행하는 명령어는 (     )이다.
  2. 노드에서는  (     )와  (     ) , 두 가지 형식의 모듈을 사용한다. 
  3. CommonJS 형식에서 (     ) 함수로 모듈을 불러올 수 있다.
  4. ES 모듈에서는 __filename과 __dirname을 사용할 수 없는 대신 (     )로 경로를 가져온다.

Programming Quiz

1. CommonJS 형식으로 작성된 코드를 ECMAScript 모듈 형식으로 변경하시오.

const { name, number } = require('./var');

function getInfo() {
  return `${name} ${number} Team`;
}

module.exports = getInfo;

정답

 

1. node, node [파일 경로] 
2. CommonJS, ECMAScript
3. require 
4. import.meta.url

 

1번

import { name, number } from './var.mjs';

function getInfo() {
  return `${name} ${number} Team`;
}

export default getInfo;

출처 :  조현영,  Node.js 교과서 개정 3판, 길벗(2022)
 

Corner Node.js 1
Editor : Snoopy

728x90

관련글 더보기