서버 구동시 버전 체크

배경

코드 저장소에서 노드 프로젝트를 다운받아 개발환경을 구성할때 버전 문제가 발생하는 경우가 있다.

  • 서버를 이관할때 모듈간 버전충돌 문제, 혹은 노드 버전 문제로 고생. 별다른 오류 메세지도 없어서 원인도 못찾음.
  • 몽고 디비 최신버전을 설치하니 안되는 경우도 발생함. 2.4로 고정 했어야함.

위 경험으로 볼때 서버 구동시 모듈 버전 체크 로직을 사전에 넣어두면 프로젝트 관리시 편리할 것 같다.

시멘틱 버전

한글로 유의적 버전. 1.2.3 이라고 할때 각 자리수를 어떻게 매기는지 정의한 개념이다.

semver

node-semver: 시멘틱 버전 체크를 위한 노드 모듈이다.

  • valid(): 유효한 버전 형식인지 체크
  • satisfies(target, required): target 버전이 required 조건에 맞는지 체크

샘플코드

semver 모듈을 이용해 서버 초기화 작업시 버전 체크하는 로직을 추가할 수 있다.

노드 버전 체크

package.json 파일에서 노드 버전과 실제 설치된 노드버전을 체크한다. satisfies() 함수 호출후 올바른 버전이 아닐경우 에러 메세지를 출력한다.

var semver = require('semver'),
    packages = require('./package.json');

function checkNodeVersion() {
  // Tell users if their node version is not supported, and exit
  try {
    if (!semver.satisfies(process.versions.node, packages.engines.node)) {
        console.error('\x1B[31mERROR: Unsupported version of Node');
        console.error('\x1B[31mThis app needs Node version ' + packages.engines.node +
                      ' you are using version ' + process.versions.node + '\033[0m\n');

        process.exit(0);
    }
  } catch (e) {
    return;
  }
},

패키지 버전 체크

package.json 에 패키지 목록과 각 버전 정보(a)를 가져온다. 그리고 node_moudles 폴더에 설치된 각 모듈의 package.json 파일에서 설치된 모듈의 버전 정보(b)를 가져온다. a와 b를 satisfies() 함수로 비교하면서 올바른 버전의 모듈 설치를 확인한다.

var semver = require("semver"),
  packages = require("./package.json")

function checkPackagesVersion() {
  _.forEach(packages.dependencies, packageVersion)
}

function checkPackageVersion(version, packageName) {
  var reqVer = packages.dependencies[packageName],
    instVer
  try {
    instVer = require("./node_modules/" + packageName + "/package.json").version
    if (!semver.satisfies(instVer, reqVer)) {
      console.error(
        "\x1B[31mERROR: Unsupported version of " + packageName + " package"
      )
      console.error(
        "\x1B[31mSenty needs " +
          packageName +
          " package version " +
          reqVer +
          " you are using version " +
          instVer +
          "\033[0m\n"
      )

      process.exit(0)
    }
  } catch (e) {
    return
  }
}

패키지 설치 여부

패키지 설치 여부만 확인할 경우 require.resolve() 함수를 사용할 수 있다. 이 함수에 모듈명을 파라매터로 넘겨주면 설치된 모듈의 경로를 반환하는 기능을 한다.

function checkPackages() {
  var errors = [];
  Object.keys(packages.dependencies).forEach(function (p) {
    try {
      require.resolve(p);
    } catch (e) {
      errors.push(e.message);
    }
  });

  if (!errors.length) {
    return;
  }

  errors = errors.join('\n  ');

  console.error('\x1B[31mERROR: This app is unable to start due to missing dependencies:\033[0m\n  ' + errors);
  console.error('\x1B[32m\nPlease run `npm install --production`.');

  process.exit(0);
},

코드 참고: Ghost