거의 모든 Node.js 개발자가 require() 함수의 기능을 알려줄 수 있지만 실제로 작동 방식을 아는 사람은 몇 명이나 될까요? 우리는 라이브러리와 모듈을 로드하기 위해 매일 이를 사용하지만 그 동작은 우리에게 미스터리입니다.
호기심에서 내부적으로 무슨 일이 벌어지고 있는지 알아보기 위해 node의 핵심 코드를 파헤쳐봤습니다. 하지만 이것은 단일 기능이 아닙니다. node의 모듈 시스템에서 module.js를 찾았습니다. 이 파일에는 각 파일의 로드, 컴파일 및 캐싱을 제어하는 놀랍도록 강력하고 상대적으로 익숙하지 않은 핵심 모듈이 포함되어 있습니다. `require()`의 출현은 빙산의 일각에 불과합니다.
module.js
이 모듈의 두 번째 주요 작업은 노드의 모듈 로딩 메커니즘을 처리하는 것입니다. 우리가 사용하는 독립적인 작업 "require" 함수는 실제로 module.require의 추상 개념이며, 그 자체는 단지 Module._load 함수의 간단한 캡슐화일 뿐입니다. 이 로드 메소드는 각 파일의 실제 로드를 처리하고 그곳에서 여정을 시작합니다.
모듈._로드
Module._load는 새 모듈을 로드하고 모듈 캐시를 관리하는 역할을 담당합니다. 로드된 각 모듈을 캐싱하면 중복된 파일 읽기 수가 줄어들고 애플리케이션 속도가 크게 향상될 수 있습니다. 또한 공유 모듈 인스턴스를 사용하면 모듈의 싱글톤 기능을 프로젝트 상태로 유지할 수 있습니다.
캐시에 모듈이 없으면 Module._load는 해당 파일의 새 기본 모듈을 생성합니다. 그런 다음 새 파일의 내용을 module._compile로 보내기 전에 읽도록 모듈에 지시합니다. [1]
위의 6단계를 확인하면 module.exports가 사용자에게 반환된 것을 볼 수 있습니다. 이것이 사용할 공용 인터페이스를 정의할 때 내보내기 및 module.exports를 사용하는 이유입니다. 그 이유는 Module._load가 다음에 필요한 콘텐츠를 반환하기 때문입니다. 여기에 더 많은 기능이 없다는 것에 놀랐습니다. 그러나 있었다면 좋을 것입니다.
module._compile
· 여기가 진짜 마법이 일어나는 곳입니다. 먼저, 이 모듈에 대해 특별한 독립형 require 함수가 생성됩니다. 이는 우리 모두에게 필요하고 친숙한 기능입니다. 함수 자체는 단지 Module.require의 패키지일 뿐이며 사용하기 쉬운 잘 알려지지 않은 몇 가지 보조 메서드도 포함되어 있습니다.
· require(): 외부 모듈 로드
· require.resolve(): 모듈 이름을 절대 경로로 확인합니다.
· require.main:메인 모듈
· require.cache: 캐시된 모든 모듈
· ·require.extensions: 확장자에 따라 유효한 각 파일 유형에 대해 사용 가능한 컴파일 방법
require가 준비되면 로드된 전체 소스 코드는 require, 모듈, 내보내기 및 기타 모든 노출된 변수를 매개변수로 받아들일 수 있는 새로운 함수로 캡슐화됩니다. Node.js 환경과의 충돌을 방지하기 위해 모듈을 캡슐화하기 위해서만 만들어진 기능입니다.
결론
그래서 우리는 require의 전체 코드를 이해했고 그것이 어떻게 작동하는지 미리 이해했습니다.
이 모든 내용을 따랐다면 마지막 비밀인 require('모듈')을 사용할 준비가 된 것입니다. 맞습니다. 모듈 시스템 자체는 모듈 시스템을 통해서 로딩이 가능합니다. 처음. 이상하게 들릴 수도 있지만 이를 통해 사용자 공간은 Node.js 코어를 자세히 조사하지 않고도 모듈 로딩 시스템과 상호 작용할 수 있습니다. 인기 있는 모듈은 이렇게 만들어졌습니다. [2]
자세한 내용은 module.js 소스코드를 직접 확인해보세요. 한동안 머리를 아프게 할 일들이 충분히 있습니다. 첫 번째 사람은 NODE_MODULE_CONTEXTS"가 무엇인지, 왜 추가되었는지, 추가하는 사람은 보너스 포인트를 얻을 수 있는지 알려줄 수 있나요?
[1] module._compile 메소드는 JavaScript 파일을 실행하는 데에만 사용됩니다. JSON 파일은 JSON.parse()를 통해 구문 분석하고 반환해야 합니다.
[2] 그러나 두 모듈 모두 Module._resolveLookupPaths 및 Module._findPath와 같은 비공개 모듈 메서드를 기반으로 구축되었습니다. 별로 좋지 않다고 생각하시면 됩니다...