ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • NodeJS - 내장 객체 알아보기(this, require)
    개발언어/Node.js 2023. 2. 20. 09:51
    const checkNumber = require("./func");
    const { odd, even } = require("./var");
    
    function checkStringOddEven(str) {
      if (str.length % 2) {
        return odd;
      } else {
        return even;
      }
    }
    
    console.log(checkNumber(10));
    console.log(checkStringOddEven("hello"));

    this

    노드에서 this를 사용할 때 주의점이 존재한다.

    • 최상위 Scope의 this는 module.exports를 가르킨다.
    • 그 외에는 브라우저의 자바스크립트와 동일하다.
    • 함수 선언문 내부의 this는 global(전역) 객체를 가리킨다.

    노드에서의 this는 브라우저의 JavaScript와 다르게 특별한게 하나 추가되었다고 생각하면 좋다.

     

    this.js

     // nodeJS에서 전역객체인 global을 가르킬까?
    console.log(this); //{}
    console.log(this === module.exports); //true
    console.log(module.exports === exports); //true
    
    function a(){
      console.log(this === global);
    }
    a(); //true

    nodeJS에서 위와 같은 전역 Scope는 anonymous this는 global(X)객체가 아니다. 

    다만, function Scope에 들어간 anonymous this는 global(O)객체를 가르킨다.

     

    전역 Scope의 anonymous this는 빈 객체를 반환하는 것을 확인할 수 있는다. 이 외에는 브라우저의 JavaScript 동작과 동일하다. function마다 this가 생기는 것, 화살표 함수를 쓰면 부모의 this를 공유한다.

     

    var.js

    const odd = '홀수입니다.';
    const even = '짝수입니다.';
    
    //exports.odd;
    //exports.even;
    
    //다음과 같이 적는 것도 가능하다.
    //하지만 거의 쓰이지는 않는다.
    this.odd = odd;
    this.even = even;

     

    require의 특성

    • require가 제일 위에 올 필요는 없다.
    • require.cache에 한 번 require한 모듈에 대한 캐싱 정보가 들어있다.
    • require.main은 노드 실행 시 첫 모듈을 가르킨다.

    require.js

    console.log("require가 가장 위에 오지 않아도 된다.");
    //하지만 최신문법에서 자주 사용하는 import문은 파일의 최상단에 있어야 한다.
    
    module.exports = "저를 찾아보세요";
    
    require("./var");
    console.log(require); //require() 함수에대한 로그들이 나온다.
    
    console.log("require.cache입니다.");
    console.log(require.cache);
    console.log("require.main입니다.");
    console.log(require.main === module);
    console.log(require.main.filename);

    require()를 변수에 대입하지 않으면 var.js가 실행은 된다. 모듈로 나온것을 require.js에서 사용하지 않는것이다. 즉 다른 파일을 실행만 하고 싶고 거기있는 변수를 가져오고 싶지 않다면 require로 가져온 파일은 변수에 대입하지 않아도 된다.

     

    require()도 하나의 모듈이다. JavaScript를 Node로 실행하면 파일들은 거의 모듈이된다. 기본적으로 module.exports는     '{ }'빈 객체다. 모듈은 해당 파일에서 빈 객체 안에 들어간 속성 들을 다른 파일에서 쓸수 있게 해준 것이다.

     

    require.main

     

    node require

    터미널에서 위와 같은 명령어를 실행하면 실행한 파일인 require가 main이 된다. 역으로 require.main으로 어떤 파일을 실행한건지 알아 낼 수도 있다.

     

    require.js가 mian이 된다면, var.js는 서브같은 개념으로 분류가 된다. 왜냐하면 require.js에서 var.js를 불러오기 때문이다.

     

    require.cache

     

    index.js

    const checkNumber = require("./func");
    const { odd, even } = require("./var");
    
    function checkStringOddEven(str) {
      if (str.length % 2) {
        return odd;
      } else {
        return even;
      }
    }
    
    console.log(checkNumber(10));
    console.log(checkStringOddEven("hello"));
    node index

    위 명령어를 실행했을때 

    다음과 같은 메시지들이 console을 통해 출력된다.

     

    코드는 항상 위쪽에서 아래쪽 왼쪽에서 아래쪽으로 실행이 된다고 가정하면 index.js에서는 require('/var')가 먼저 실행되서 const { odd, even }에 구조분해되어 할당 된다. 그리고 한 번 require했던 것은 캐싱이된다. 

     

    즉 require('./var')를 읽을 때 require()메서드는 require.cache라는 곳에 저장을 해둔다. 그리고 index.js에 있는 require('./func')도 require.cahe에 저장을 해둔다. 이때 require.cache의 저장 공간은 메모리이다.

     

    근데 func.js에서도 require('./var')를 하고 있다. 이때는 또 다시 var.js를 읽는 것이 아니라. require.cache에서 저장해둔 var.js를 불러온다. 특정 파일이 처음 require되었을때 해당 파일을 읽지만 최초에 읽었을때 require.cahe에 저장해두고 또다시 해당 파일을 불러와야 하는 일이 생기면 require.cahe(메모리)에 저장된 파일 내용을 활용한다.

     

     원래 특정 파일을 읽는 것이 오래걸리는 작업이다. 근데 파일은 한번 읽어서 메모리에 저장해두고 다시 메모리에서 읽어 오는 것은 빠르다. 왜냐면 하드디스크에서 특정파일을 읽는 작업이 시간이 오래 걸리는데, 최초의 파일을 읽는 것은 하드디스트에서 읽어오는 작업이기 때문이다. 하드디스크에 있는 정보를 읽어와서 메모리에 저장해두는 것을 캐싱이라고한다.

     

    근데 require.cache를 delete해서 초기화하는 것도 가능하긴 하지만 내장된 객체를 직접조작하는건 권장되는 사용방식은 아니다.

     

    console.log(require)를 찍어보면 require.main에 속성에도 exports가 있고 require.cache에도 속성에도 exports가 있는 것을 확인할 수 있는데 그때의 exports는 module.exports와 동일하다.

     

    순환참조

    두 개의 모듈이 서로를 require하는 상황을 조심해야 한다.

    • Dep1이 dep2를 require하고, dep2가 dep1를 require함
    • Dep1의 module.exports가 함수가 아니라 빈 객체가 됨(무한 반복을 막기위해 의도되었다.)
    • 순환참조하는 상황이 나오지 않도록 하는 것이 좋다.   

    dep1.js

    const dep2 = require("./dep2"); //{}
    console("require dep2", dep2);
    module.exports = () => {
      console.log("dep2", dep2);
    };

     

    dep2.js

    const dep1 = require("./dep1");
    console("require dep1", dep1);
    module.exports = () => {
      console.log("dep1", dep1);
    };

     

    dep-run.js

    const dep1 = require("./dep1");
    const dep2 = require("./dep2");
    
    dep1();
    dep2();

     

    dep1.js와 dep2.js는 require를 사용해서 서로를 호출하고 있다. 이때 해당파일 중 하나를 실행한 시에 서로를 호출하고 있음으로 무한 호출 루프에 빠진다. 이런 상황을 순환참조라고 한다.

     

    만약 순환 참조가 발견되면 dep1.js 파일에 module.export = { hello : 'hi' } 같은 객체를 넣어 놨어도 dep2.js파일에서 노드에서 알아서 require('./dep1')은 빈객체로 바꿔버린다. 그렇지 않으면 무한 순환참조가 일어나기 때문이다. 

     

    출처 

     

    https://www.inflearn.com/course/%EB%85%B8%EB%93%9C-js-%EA%B5%90%EA%B3%BC%EC%84%9C/dashboard

     

    [개정3판] Node.js 교과서 - 기본부터 프로젝트 실습까지 - 인프런 | 강의

    노드가 무엇인지부터, 자바스크립트 최신 문법, 노드의 API, npm, 모듈 시스템, 데이터베이스, 테스팅 등을 배우고 5가지 실전 예제로 프로젝트를 만들어 나갑니다. 클라우드에 서비스를 배포해보

    www.inflearn.com

     

    댓글

Designed by Tistory.