Yarn Berry(v3) Workspace #2 - Nest 설정

projaguar·2023년 2월 3일
2

Yarn Berry Workspace

목록 보기
2/5
post-thumbnail

Intro

Yarn Berry(v3) Workspace #1 - workspace 설정 (node_modules 사용하는 방식)으로 먼저 워크스페이스를 준비하고, 이 워크스페이스에 Nest app을 생성하도록 하겠습니다.

목표

  • yarn berry workspace에서 최소한의 설정으로 Nest 앱을 관리한다.
  • typescript 라이브러리를 공유한다.
  • nest module을 라이브러리로 공유 한다.
  • 최소한의 설정으로 dockerizing을 위한 설정을 한다. (aws lambda Docker 배포 목적)

수정

  • 2023.05.23 - 앱 생성방식 변경, 라이브러리 참조 방식 변경
  • 2023.03.16 - 전반적인 변경
  • 2023.02.10 - 소스 공유방식 변경
  • 2023.02.10 - typescript 설정방법 변경

nest app 생성

nest 앱은 apps 폴더에 생성 합니다.

cd apps
yarn dlx @nestjs/cli@latest new nest-sample --package-manager yarn 

// 또는
yarn dlx -p @nestjs/schematics -p @nestjs/cli@latest nest new nest-sample --package-manager yarn

yarn dlx를 사용하여 앱을 생성 하였습니다. 글로벌로 nest cli을 설치 하셨다면 'nest new'로 앱을 생성 하면 됩니다.

생성된 앱의 package.json을 수정 합니다.
(아직 이 부분은 추가한것과 하지 않은것의 차이를 모르겠습니다만, 하라고 하니...)

// pacages/server-sample/package.json
{
  ...
  "packageManager": "yarn@3.4.1",  // 추가
  ...
}

(packageManager 버젼은 root의 package.json 을 참고 하여 같게 하여야 합니다)

패키지를 생성하고 yarn install을 해 주어야 합니다.
yarn install 을 실행 할 폴더 위치는 아무곳이나 상관 없습니다.

yarn install
yarn workspace nest-sample start:dev

정상적으로 실행되는것을 확인할 수 있습니다.

Nest 모듈의 공유

모듈의 생성은 각각의 파일을 생성해서 만드는 방법도 있지만, 저는 주로 nest cli를 사용하여 구성 합니다.

module 폴더 구성

cd packages/nest
mkdir -p module-hello/src
cd module-hello

yarn init -p -y
// packages/est/module-hello/package.json
{
  "name": "@pnds/nest-module-hello",
  "packageManager": "yarn@3.4.1",
  "private": true,
  "main": "dist/packages/nest/module-hello/src/index.js",
  "typings": "dist/packages/nest/module-hello/src/index.d.ts",
  "files": [
    "dist/**/*"
  ],
  "scripts": {
    "build": "tsc"
  },
  "dependencies": {
  },
  "devDependencies": {
    "@nestjs/testing": "^9.3.10",
    "@types/jest": "^29.4.4",
    "@types/node": "^18.15.3",
    "jest": "^29.5.0",
    "typescript": "^4.9.5",
    "@nestjs/common": "^9.3.10",
    "@nestjs/core": "^9.3.10",
    "@nestjs/mapped-types": "^1.2.2",
    "rxjs": "^7.2.0",
  },
   "peerDependencies": {
    "@nestjs/common": "^9.0.0",
    "@nestjs/core": "^9.0.0",
    "@nestjs/mapped-types": "^1.2.2",
	"reflect-metadata": "^0.1.13",
    "rxjs": "^7.2.0"
  }
}

소스에서 사용할 dependencies를 일괄적으로 포함 시켰습니다. 필요에 따라 가감하여 사용하시면 됩니다.
라이브러리에 @nestjs/* 를 사용 할 경우, 해당 라이브러리들은 peerDependencies에 정의해줍니다.

// packages/libs-nest/module-hello/tsconfig.json
{
  "extends": "../../../tsconfig.base.json",
  "compilerOptions": {
    "outDir": "./dist",
    "declaration": true,
    "experimentalDecorators": true // 중요
  },
  "include": ["./src/**/*"],
  "exclude": ["node_modules", "dist"]
}

module 소스코드 생성

cd packages/nest/module-hello
yarn dlx @nestjs/cli@latest g resource hello --flat

// 또는
yarn dlx -p @nestjs/schematics -p @nestjs/cli@latest nest g resource hello --flat

CRUD entry points 생성할것인가의 질문에는 No를 선택 합니다.

nest cli를 global로 설치 한 경우는 'nest g resource hello --flat' 를 사용합니다.

src 폴더에 5개의 파일이 생성됩니다.
index.ts를 만들어 생성된 파일을 export 합니다.

// packages/nest/module-hello/src/index.ts
export * from './hello.module';
export * from './hello.controller';
export * from './hello.service';

샘플코드를 작성 합니다.

// packages/nest/module-hello/src/hello.service.ts
import { Injectable } from '@nestjs/common';

@Injectable()
export class HelloService {
  getHello(): string {
    return 'Hello World! Hello Module!!';
  }
}
// packages/nest/module-hello/src/hello.controller.ts
import { Controller, Get } from '@nestjs/common';
import { HelloService } from './hello.service';

@Controller('hello')
export class HelloController {
  constructor(private readonly helloService: HelloService) {}

  @Get()
  getHello(): string {
    return this.helloService.getHello();
  }
}

모듈 설정이 완료되면 yarn install 을 실행 해 줍니다.

yarn insall

공유 설정

공유라이브러리를 사용하기 위해 라이브러리의 dependencies에 추가 합니다.

yarn workspace nest-sample add @pnds/nest-module-hello

nest-sample의 tsconfig.json 에 path 속성에, 사용할 라이브러리를 포함 합니다.

// packages/nest-sample/tsconfig.json
{
  "compilerOptions": {
    ...
    "paths": {
      "@pnds/nest-module-hello": ["../../packages/nest/module-hello/src"]
    }
    ...
  }
}

app 모듈에 hello 모듈을 임포트 합니다.

import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { HelloModule } from '@pnds/nest-module-hello'; // 추가

@Module({
  imports: [HelloModule], // 추가
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

모듈이 잘 적용되었는지 확인합니다.

yarn workspace nest-sample start:dev

main을 못찾는다는 오류가 발생합니다.
dist 폴더를 확인하고, main.js의 위치를 확인 한 후 nestjs-cli.json을 수정 합니다.

// nest-cli.json
{
  ...
  "entryFile": "apps/nest-sample/src/main"
}

다시 실행 합니다.

yarn workspace nest-sample start:dev
curl localhost:3000/hello


정상적으로 실행되는것을 확인할 수 있습니다.

참고
워크스페이스 내에서 공유라이브러리를 add 할때 위의 예에서는 package name 을 사용하였습니다.
예: 'yarn workspace nest-sample add @pnds/nest-module-hello'
하지만 워크스페이스 내에서 공유 라이브러리를 참고할 때는 상대경로방식으로 add 하는것이 잇점이 더 있다고 합니다.
예: 'yarn workspace nest-sample add ../../packages/nest/module-hello'
경로 방식이 상대적으로 디버깅이 용이하고, 라이브러리간의 의존성 버전 충돌을 방지할수 있고 등등..
취향에 따라 방법은 선택하면 될것 같습니다.

공통

공유 라이브러리를 사용하기전에 반드시 build를 하여야 합니다.
만약 라이브러리를 계속 수정하면서 작업하여야 한다면, yarn workspace @pnds/nest-module-hello build --watch (또는 라이브러리 폴더에서 tsc --watch 나 yarn build --watch) 명령을 실행하여, 변경된 사항이 있을때마다 자동으로 build 할수 있게 합니다.

Conculution

공유 모듈을 참조하는 방식은 package.json의 dependencies 에 정의하는 방법, tsconfig.json에 path alias를 설정하는 방법, 그리고 두가지 모두를 하는 방법이 있습니다. 이 세가지 모두 유효하지만 두가지 모두 하는 방법이 일반적이고, 안전하며, 각각의 역할이 있기에 두가지 모두 설정하는 방식을 선택 하였습니다.

이어갈 연재에서 Next, React Native도 같은 프로젝트로 포함시킬 예정입니다.

profile
아직도 개발하고 있는 개발자 입니다

2개의 댓글

comment-user-thumbnail
2023년 4월 18일

backend 코드를 git으로 관리할 때 서브모듈을 반드시 사용해야하나요??

1개의 답글