[Nest.js] Nest 공통 모듈 Library로 분리하기 (cannot find dist/main 오류)

2025. 2. 15. 21:58카테고리 없음

728x90

개요

저희 프로젝트에서는 Nest 프레임워크를 사용 중이고 서버의 역할을 분리하기 위해 monorepo를 사용하여 여러 개의 workspace로 나누었습니다.

 

API를 담당하는 backend 서버와 실시간 통신을 담당하는 websocket 서버가 독립적인 workspace로 존재하는 상황입니다.

 

 

이렇게 독립적인 workspace로 분리하고 나서 조금 불편한 점을 발견했습니다.

 

바로 중복되는 모듈이 존재한다는 점이었습니다.

 

역할이 분리되었기 때문에 대부분의 소스 코드가 독립적이지만 redis에 관련된 모듈의 경우 backend 서버와 websocket 서버가 동일하게 사용하고 있었습니다.

 

저희 프로젝트는 아래처럼 websocket에 들어오는 변경 사항들을 redis에 저장해두었다가 스케줄러로 주기적으로 데이터베이스에 반영하고 있습니다.

즉, websocket 서버와 backend 서버는 동일한 redis에 접근해야 했고 이 redis에 관련된 모듈은 각 workspace에 존재했습니다.

 

그러다보니 redis 모듈의 변경 사항이 발생했다면 수작업으로 다른 workspace의 redis 모듈도 변경해줘야 했습니다.

 

지금은 단순히 두 개의 workspace만 있기 때문에 수작업으로 진행할 수 있지만 redis에 접근해야 하는 workspace가 늘어난다면 수작업에는 한계가 있을 것입니다.

 

그래서 redis 모듈 하나를 여러 workspace에서 공유할 수 있도록 redis 모듈을 분리하기로 결정했습니다.

 

Nest 공통 모듈 Library로 분리하기

어떻게 redis 모듈을 공유할 수 있을지 고민하다가 Nest의 Library 기능에 대해 알게 되었습니다.

 

Nest의 라이브러리 기능을 사용하면 nest cli 명령어로 쉽게 모듈을 분리할 수 있습니다.

 

그러면 redis 모듈을 별도의 라이브러리로 분리하기 앞서 기존 프로젝트 구조를 살짝 변경하겠습니다.

 

우선 저희 프로젝트의 경우 root에 tsconfig.json 파일이 존재하지 않았고 각 workspace 별로 tsconfig.json을 독립적으로 관리하고 있었습니다.

 

저희 프로젝트와 같은 구조를 하고 있다면 root에 tsconfig.json에 공통 설정들을 모아두고 각 workspace에서 extends 한 뒤 추가 설정을 적용하는 것을 추천드립니다.

 

nest cli로 라이브러리를 생성할 때 root의 tsconfig.json에 자동으로 alias를 넣어주는데 root에 tsconfig.json이 없다면 각 workspace에 수작업으로 alias를 넣어줘야 하기 때문입니다.

 

root에 tsconfig.json을 생성하고나서 공통 설정들을 적어둔 뒤에 nest cli로 라이브러리를 분리하면 자동으로 alias 설정을 작성해줍니다.

nest g library redis

 

cli를 통해 라이브러리를 생성하면 아래처럼 자동으로 alias를 만들어줍니다.

 

</tsconfig.json>

{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@app/redis": [
        "libs/redis/src"
      ],
      "@app/redis/*": [
        "libs/redis/src/*"
      ]
    }
  }
}

 

라이브러리를 생성한 뒤 프로젝트 구조가 변경되었습니다.

 

기존 root에 apps 디렉토리 이외에 libs 디렉토리가 추가되었습니다.

 

libs 내부를 보면 분리한 라이브러리 이름 아래 모듈과 서비스가 생성된 모습을 확인할 수 있습니다.

 

이렇게 생성한 library는 기본 설정 값만 들어있기 때문에 원래 redis 모듈과 redis 서비스를 그대로 복사합니다.

 

참고로 라이브러리를 분리할 때 의존성을 갖는 모듈도 함께 분리하는 것을 추천드립니다.

 

redis 모듈을 성공적으로 분리했다면 이제 각 workspace 내부에서는 alias를 사용할 수 있습니다.

 

import { RedisModule } from '../redis/redis.module';
import { RedisModule } from '@app/redis/redis.module';

 

만약 분리한 라이브러리를 찾을 수 없다면 baseUrl을 잘 설정하시길 바랍니다.

 

entryFile 설정

library 분리에 성공했다면 이제 dist 디렉토리에도 변화가 생깁니다.

 

우선 library 분리 전 dist 디렉토리는 다음과 같습니다.

 

다들 library가 분리되면서 apps 디렉토리와 같은 디렉토리에 libs 디렉토리가 생기는 것을 확인하셨을 겁니다.

 

그래서 workspace와 libs의 빌드 파일 또한 dist 디렉토리 내부에서 분리되어야 합니다.

 

기존에 dist 디렉토리 하위에 존재하던 빌드 파일들은 apps/workspace이름/src 내부로 변경되고 역시 apps 디렉토리와 같은 디렉토리에 libs 디렉토리가 생성됩니다.

 

여기서 typescript의 동작 방식을 짚고 갑시다.

 

typescript는 그 자체로 실행하지 못 하고 javascript로 변환된 뒤 실행할 수 있습니다.

 

nest도 typescript로 개발을 하지만 개발 서버를 실행할 때 우선 빌드 파일을 생성한 뒤 만들어진 main.js 파일을 실행하는 방식입니다.

 

기존에는 dist 디렉토리 하위에 바로 main.js가 존재했습니다.

 

하지만 library를 생성하면서 libs와 apps가 분리되었고 main.js의 위치가 dist에서 dist/apps/workspace/src로 변경되었습니다.

 

그래서 이 상태로 서버를 실행하면 아래와 같은 오류가 발생합니다.

node:internal/modules/cjs/loader:1228
  throw err;
  ^

Error: Cannot find module '/app/apps/websocket/dist/main'     
    at Module._resolveFilename (node:internal/modules/cjs/loader:1225:15)
    at Module._load (node:internal/modules/cjs/loader:1051:27)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:173:12)
    at node:internal/main/run_main_module:28:49 {
  code: 'MODULE_NOT_FOUND',
  requireStack: []
}
 
Node.js v20.18.3

 

dist 하위 main.js를 찾을 수 없다는 오류입니다.

 

당연합니다. main.js의 위치가 바뀌었으니까요.

 

그래서 tsconfig.json 설정을 통해 entryFile의 위치를 바꿔줘야 합니다.

 

이제 각 workspace의 nest-cli.json 설정에서 entryFile의 위치를 바꿔줍니다.

 

websocket workspace의 경우 아래와 같이 nest-cli.json에 entryFile을 추가해주었습니다.

 

</apps/websocket/nest-cli.json>

{
  "$schema": "https://json.schemastore.org/nest-cli",
  "collection": "@nestjs/schematics",
  "sourceRoot": "src",
  "compilerOptions": {
    "deleteOutDir": true
  },
  "entryFile": "./apps/websocket/src/main.js"
}

 

이제 library 모듈을 성공적으로 분리했고 기존 workspace 내부에 있던 해당 모듈들을 제거하고 libs 내부 모듈을 사용할 수 있게 되었습니다.

 

지금까지 Nest library 기능으로 공통 모듈을 분리하는 방법과 주의 사항에 대해 알아보았습니다.

 

감사합니다.

참고

https://stackoverflow.com/questions/77420116/nestjs-cannot-find-module-dist-main

https://docs.nestjs.com/cli/libraries

728x90