Node.js 를 배워보자

Node.js Express에서는 모듈을 동적으로 호출

_Blue_Sky_ 2024. 12. 5. 22:42
728x90

  Node.js Express에서는 모듈을 동적으로 호출할 수 있습니다. 이를 위해 require를 사용하여 필요할 때마다 모듈을 로드할 수 있습니다. 동적 로딩은 주로 경로 또는 파일 이름이 런타임에 결정될 때 유용합니다.

예를 들어, 특정 조건에 따라 모듈을 동적으로 로드하고 싶다면, require를 함수 안에서 호출할 수 있습니다:

A와 B가 각각 독립적으로 개발하고 있고, 두 사람이 개발한 모듈을 동적으로 로드하는 예시를 들어보겠습니다. 예를 들어, A는 moduleA라는 모듈을 개발하고, B는 moduleB라는 모듈을 개발한다고 가정해봅니다.

 

728x90

동적 모듈 로딩이란?

Node.js에서 동적 모듈 로딩이란, 코드 실행 중에 require 함수를 사용하여 모듈을 동적으로 불러오는 것을 의미합니다. 이는 미리 정의된 모든 모듈을 한꺼번에 로드하는 정적 로딩과 대비되는 개념입니다.

동적 모듈 로딩의 장점

  • 유연성: 실행 환경이나 사용자의 요청에 따라 필요한 모듈만 로드하여 메모리 사용량을 줄이고 시스템 성능을 향상시킬 수 있습니다.
  • 확장성: 새로운 기능을 추가하거나 기존 기능을 변경할 때, 서버를 재시작하지 않고도 모듈만 교체하면 됩니다.
  • 플러그인 시스템 구현: 다양한 플러그인을 동적으로 로드하여 애플리케이션 기능을 확장할 수 있습니다.
  • 마이크로서비스 아키텍처: 각 모듈을 독립적인 서비스로 만들어 마이크로서비스 아키텍처를 구현할 수 있습니다.

1. 디렉토리 구조

/project
  /modules
    /moduleA.js
    /moduleB.js
  server.js
  • moduleA.js: A가 개발한 모듈
  • moduleB.js: B가 개발한 모듈
  • server.js: Express 서버가 실행되는 파일

2. moduleA.js와 moduleB.js

modules/moduleA.js

module.exports = {
  greet: () => "Hello from module A!"
};

modules/moduleB.js

module.exports = {
  greet: () => "Hello from module B!"
};

3. Express 서버 (동적 모듈 로딩)

server.js 파일에서, A와 B가 개발한 모듈을 동적으로 로드하는 예시입니다.

server.js

const express = require('express');
const app = express();

app.get('/:moduleName', (req, res) => {
  const { moduleName } = req.params;
  
  try {
    // 동적으로 모듈을 로드
    const module = require(`./modules/${moduleName}`);
    res.send(module.greet()); // 해당 모듈의 greet 함수 실행
  } catch (error) {
    res.status(404).send('Module not found');
  }
});

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

4. 서버 실행 및 모듈 호출

서버가 실행되고 나면, A와 B는 각자의 모듈을 아래와 같이 호출할 수 있습니다:

  • 모듈 A 호출: http://localhost:3000/moduleA
    • 응답: Hello from module A!
  • 모듈 B 호출: http://localhost:3000/moduleB
    • 응답: Hello from module B!
  •  

5. 동적 로딩의 활용

이 방식은 A와 B가 독립적으로 각자의 모듈을 개발하고, server.js에서 동적으로 해당 모듈을 호출하여 결과를 제공하는 방식입니다. 이렇게 하면 A와 B는 자신이 개발한 모듈을 서버에 통합하거나 수정할 때 서버를 재시작할 필요 없이, 모듈 이름만 변경하여 새로운 기능을 추가할 수 있습니다.

6. 캐시 문제 해결

만약 동적으로 로드된 모듈을 자주 갱신해야 한다면, 캐시 문제를 피하기 위해 다음과 같이 require.cache를 사용하여 모듈 캐시를 삭제할 수 있습니다.

delete require.cache[require.resolve(`./modules/${moduleName}`)];
const module = require(`./modules/${moduleName}`);

이렇게 하면, 모듈을 변경한 후에도 최신 버전의 모듈을 동적으로 로드할 수 있습니다.

 

728x90

 

그럼 개발자가 여러명이고 만든 파일만큼 리스팅하여 차례대로 호출하게 하려면?

여러 개발자가 만든 파일을 차례대로 호출하는 방식으로 리스팅하여 자동으로 호출하고자 할 때는, 해당 디렉토리 내의 파일 목록을 동적으로 가져와서 이를 처리할 수 있습니다. 예를 들어, 개발자들이 각각의 모듈을 modules 디렉토리에 두고, 이 파일들을 동적으로 로드하고 호출하는 방법을 설명하겠습니다.

1. 디렉토리 구조

/project
  /modules
    /moduleA.js
    /moduleB.js
    /moduleC.js
  server.js

2. 모듈 예시

모듈은 각기 다른 파일에 정의된 여러 개의 파일로 존재한다고 가정합니다. 예를 들어:

modules/moduleA.js

module.exports = {
  greet: () => "Hello from module A!"
};

modules/moduleB.js

module.exports = {
  greet: () => "Hello from module B!"
};

modules/moduleC.js

module.exports = {
  greet: () => "Hello from module C!"
};

3. 동적으로 모듈을 로드하고 호출하는 서버 구현

서버에서는 fs 모듈을 사용하여 modules 디렉토리 내의 모든 파일을 읽어들인 후, 해당 파일들을 순차적으로 로드하여 호출할 수 있습니다.

server.js

const express = require('express');
const fs = require('fs');
const path = require('path');
const app = express();

// 모듈 디렉토리 경로
const modulesDir = path.join(__dirname, 'modules');

// 모듈 디렉토리 내의 모든 파일 읽기
fs.readdir(modulesDir, (err, files) => {
  if (err) {
    console.error('Failed to read modules directory:', err);
    return;
  }

  // .js 파일만 필터링하여 모듈을 차례대로 로드
  files.filter(file => file.endsWith('.js')).forEach(file => {
    const moduleName = path.basename(file, '.js'); // 파일 이름에서 확장자 제거
    const modulePath = path.join(modulesDir, file);

    // 동적으로 모듈 로드
    const module = require(modulePath);

    // 각 모듈에 대해 특정 작업 수행 (예: greet 함수 실행)
    app.get(`/call/${moduleName}`, (req, res) => {
      res.send(module.greet());
    });

    console.log(`Module loaded: ${moduleName}`);
  });
});

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

4. 동작 설명

  1. fs.readdir: modules 디렉토리 내의 모든 파일을 읽습니다.
  2. 파일 필터링: .js 확장자를 가진 파일만 필터링하여 처리합니다.
  3. 동적 로딩: 각 파일을 동적으로 require하여 모듈을 로드합니다.
  4. 자동 라우팅: 모듈의 greet 함수가 호출될 수 있도록 라우팅을 동적으로 설정합니다. 예를 들어, moduleA.js 파일은 http://localhost:3000/call/moduleA에서 접근할 수 있습니다.

5. 서버 실행 및 테스트

서버를 실행하고, 브라우저에서 다음 URL을 통해 각 모듈을 차례대로 호출할 수 있습니다.

  • 모듈 A 호출: http://localhost:3000/call/moduleA
    응답: Hello from module A!
  • 모듈 B 호출: http://localhost:3000/call/moduleB
    응답: Hello from module B!
  • 모듈 C 호출: http://localhost:3000/call/moduleC
    응답: Hello from module C!

6. 자동화된 관리

이 방식은 새로운 모듈이 추가되거나 기존 모듈이 삭제될 때마다 서버 코드 수정 없이 자동으로 해당 모듈을 불러오고 호출할 수 있습니다. 즉, 개발자들이 모듈을 추가하면 자동으로 호출할 수 있는 라우터가 생성되므로 관리가 간편해집니다.

이 방식의 장점은 개발자들이 모듈을 추가할 때마다 서버를 재시작하거나 별도로 설정을 수정할 필요 없이, 모듈 파일만 추가하면 자동으로 반영된다는 점입니다.

728x90