2023-06-07 수요일
NestJS 프로젝트에 버전을 적용하려고 했다.
v1, v2 이런 API Versioning 말고 package.json에 version을 작성해서 그 값을 프론트엔드에서 확인할 수 있게 하자는 취지였다.
version용 module을 만들었고, package.json에 버전 쓰는 것까지는 좋았는데 version을 반환해주는 API를 만들면서 문제가 생겼다.
version.service.ts에서 package.json을 import 해서 쓰기 때문에 build할 때 dist 디렉터리의 구조가 바뀌어버린다.
자세하게 말하면 원래는 dist 아래에 module들이 나열되어 있었는데 version.service.ts에서 src 바깥에 있는 package.json을 참조하게 되면서 src 디렉터리까지 빌드에 포함되어서 dist 디렉터리 아래에 src 디렉터리가 생기고 그 안에 모듈들이 나열되는 구조로 바뀌었다.
// version.service.ts
import { Injectable } from '@nestjs/common';
import { version } from '../../package.json';
@Injectable()
export class VersionService {
async getVersion() {
return { version };
}
}version module 없을 때 dist 구조
version module을 사용할 때 dist 구조
이 것만으로는 별 문제가 생기진 않는다.
하지만 npm script로 start 명령어를 구성해 놓은게 node dist/main 으로 해놨기 때문에 start할 때 문제가 발생한다.
dist/main 경로가 아닌 dist/src/main으로 바뀌기 때문이다.
물론 그냥 script의 내용을 바꾸면 간단한 일이지만 그렇게 하기는 싫었기 때문에 현재 구조에서 바뀌지 않고 package.json의 version도 참조할 수 있는 방법을 찾고 싶었다.
이 문제점을 해결하기 위해서 package.json을 직접 import 하지 않고 fs 모듈을 써서 동적으로 파일의 내용을 가져오도록 변경하였다.
예외처리는 덤으로.
import { Injectable, InternalServerErrorException } from '@nestjs/common';
import * as fs from 'fs';
import * as path from 'path';
@Injectable()
export class VersionService {
async getVersion() {
const packageJsonFilePath = path.join(
__dirname,
'..',
'..',
'package.json'
);
const rawData = fs.readFileSync(packageJsonFilePath);
const packageJson = JSON.parse(rawData.toString());
if (!('version' in packageJson)) {
throw new InternalServerErrorException(
'can not found version in package.json'
);
}
const { version } = packageJson;
return { version };
}
}Cannot find module '../../package.json'. Consider using '--resolveJsonModule' to import module with '.json' extension.