framework/NextJS

๐Ÿ” NestJS ModuleRef – ๋™์  ๋ชจ๋“ˆ ์ธ์Šคํ„ด์Šค ์ฃผ์ž… ์™„์ „ ๊ฐ€์ด๋“œ

octo54 2025. 5. 12. 10:00
๋ฐ˜์‘ํ˜•

๐Ÿ” NestJS ModuleRef – ๋™์  ๋ชจ๋“ˆ ์ธ์Šคํ„ด์Šค ์ฃผ์ž… ์™„์ „ ๊ฐ€์ด๋“œ


NestJS์—์„œ ModuleRef๋Š” ๋™์ ์œผ๋กœ ๋ชจ๋“ˆ ์ธ์Šคํ„ด์Šค๋ฅผ ์ฃผ์ž…ํ•  ์ˆ˜ ์žˆ๋„๋ก ๋„์™€์ฃผ๋Š” ๋„๊ตฌ์ž…๋‹ˆ๋‹ค.
์ด๋ฒˆ ๊ธ€์€ NestJS ๊ณต์‹ ๋ฌธ์„œ ModuleRef๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ,
์‹ค๋ฌด์—์„œ ModuleRef๋ฅผ ํ™œ์šฉํ•˜์—ฌ ๋™์  ์ฃผ์ž… ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ’ก "ํŠน์ • ์ƒํ™ฉ์—์„œ๋งŒ ํ•„์š”ํ•œ ์„œ๋น„์Šค๋ฅผ ๋™์ ์œผ๋กœ ์ฃผ์ž…ํ•˜์—ฌ, ๋ฉ”๋ชจ๋ฆฌ์™€ ์„ฑ๋Šฅ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค."


โœ… ModuleRef๋ž€?

  • NestJS์˜ ๋ชจ๋“ˆ ์ธ์Šคํ„ด์Šค๋ฅผ ๋™์ ์œผ๋กœ ๊ฐ€์ ธ์˜ค๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•˜๋Š” ํด๋ž˜์Šค์ž…๋‹ˆ๋‹ค.
  • ์ˆœํ™˜ ์˜์กด์„ฑ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ฑฐ๋‚˜, ๋Ÿฐํƒ€์ž„์— ํŠน์ • ์„œ๋น„์Šค๋ฅผ ์ฃผ์ž…ํ•  ๋•Œ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ“ฆ ์„ค์น˜

ModuleRef๋Š” NestJS์˜ ๊ธฐ๋ณธ ๋ชจ๋“ˆ๋กœ ํฌํ•จ๋˜์–ด ์žˆ์–ด ๋ณ„๋„์˜ ์„ค์น˜๊ฐ€ ํ•„์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.


1๏ธโƒฃ ๊ธฐ๋ณธ ์‚ฌ์šฉ๋ฒ• – get() ๋ฉ”์„œ๋“œ

import { Injectable, ModuleRef } from '@nestjs/core';

@Injectable()
export class DynamicService {
  constructor(private moduleRef: ModuleRef) {}

  getService(serviceName: string) {
    return this.moduleRef.get(serviceName, { strict: false });
  }
}

์‚ฌ์šฉ ์˜ˆ์‹œ

const catsService = this.getService(CatsService);
catsService.getCats();
  • ๋™์ ์œผ๋กœ ์„œ๋น„์Šค ์ธ์Šคํ„ด์Šค๋ฅผ ๊ฐ€์ ธ์˜ด
  • strict: false ์˜ต์…˜์„ ํ†ตํ•ด ๋ชจ๋“ˆ ๊ฒฝ๋กœ๊ฐ€ ๋ช…์‹œ์ ์ด์ง€ ์•Š์•„๋„ ์ฃผ์ž… ๊ฐ€๋Šฅ

๋ฐ˜์‘ํ˜•

ModuleRef๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋™์  ์ฃผ์ž… ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ์ด ์ง€์ ์€
๋ธ”๋กœ๊ทธ ๋…์ž๋“ค์ด ์ฃผ๋ชฉํ•˜๋Š” ํ•ต์‹ฌ ๊ตฌ๊ฐ„์ž…๋‹ˆ๋‹ค.
์• ๋“œ์„ผ์Šค ๊ด‘๊ณ ๋ฅผ ์‚ฝ์ž…ํ•˜๋ฉด CTR์ด ๋†’๊ฒŒ ๋‚˜์˜ค๋Š” ๊ตฌ๊ฐ„์ž…๋‹ˆ๋‹ค.

<ins class="adsbygoogle"
     style="display:block"
     data-ad-client="ca-pub-XXXXXX"
     data-ad-slot="YYYYYY"
     data-ad-format="auto"
     data-full-width-responsive="true"></ins>

2๏ธโƒฃ ์ˆœํ™˜ ์˜์กด์„ฑ ๋ฌธ์ œ ํ•ด๊ฒฐ

โœ… Circular Dependency ํ•ด๊ฒฐ ์ฝ”๋“œ

@Injectable()
export class CatsService {
  private dogsService: DogsService;

  constructor(private moduleRef: ModuleRef) {}

  onModuleInit() {
    this.dogsService = this.moduleRef.get(DogsService, { strict: false });
  }

  getRelatedDogs() {
    return this.dogsService.getDogs();
  }
}
  • onModuleInit() ํ›„์— ๋ชจ๋“ˆ ์ธ์Šคํ„ด์Šค๋ฅผ ๊ฐ€์ ธ์™€์•ผ ์ˆœํ™˜ ์˜์กด์„ฑ ๋ฌธ์ œ๋ฅผ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

3๏ธโƒฃ Transient Scope์—์„œ ์‚ฌ์šฉ

  • Transient Scope์—์„œ๋Š” DI๊ฐ€ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์ฃผ์ž…๋˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์Šต๋‹ˆ๋‹ค.
  • ์ด๋Ÿด ๋•Œ ModuleRef๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋™์ ์œผ๋กœ ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

โœ… Transient Service ์ƒ์„ฑ

@Injectable({ scope: Scope.TRANSIENT })
export class TransientService {
  sayHello() {
    return 'Hello from Transient Service!';
  }
}

โœ… ๋™์  ํ˜ธ์ถœ

@Injectable()
export class MainService {
  constructor(private moduleRef: ModuleRef) {}

  async handle() {
    const transientService = await this.moduleRef.resolve(TransientService);
    console.log(transientService.sayHello());
  }
}

**moduleRef.resolve()**๋Š” ๋งค๋ฒˆ ์ƒˆ๋กœ์šด ์ธ์Šคํ„ด์Šค๋ฅผ ๋ฐ˜ํ™˜ํ•˜์—ฌ Transient Scope ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•ฉ๋‹ˆ๋‹ค.


4๏ธโƒฃ Lazy Loading์„ ํ†ตํ•œ ๋ฉ”๋ชจ๋ฆฌ ์ตœ์ ํ™”

  • ํŠน์ • ์„œ๋น„์Šค๊ฐ€ ํ•ญ์ƒ ์‚ฌ์šฉ๋˜์ง€ ์•Š๋Š”๋‹ค๋ฉด ์ดˆ๊ธฐํ™”ํ•˜์ง€ ์•Š๊ณ , ํ•„์š”ํ•  ๋•Œ ๋กœ๋“œํ•˜๋Š” ๊ฒƒ์ด ์œ ๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

โœ… Lazy Loading ์ฝ”๋“œ

@Injectable()
export class LazyService {
  constructor(private moduleRef: ModuleRef) {}

  private async getDynamicService(): Promise<DynamicService> {
    return this.moduleRef.resolve(DynamicService);
  }

  async executeTask() {
    const service = await this.getDynamicService();
    return service.runTask();
  }
}

๐Ÿง  ์‹ค๋ฌด ํ™œ์šฉ ์ „๋žต

์ƒํ™ฉ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•

์ˆœํ™˜ ์˜์กด์„ฑ ๋ฐœ์ƒ ModuleRef๋กœ ๋™์  ์ฃผ์ž…
Transient Scope ๋ฌธ์ œ moduleRef.resolve()๋กœ ์ƒˆ๋กœ์šด ์ธ์Šคํ„ด์Šค ์‚ฌ์šฉ
๋Ÿฐํƒ€์ž„์— ์„œ๋น„์Šค ์„ ํƒ ํ•„์š” moduleRef.get()๋กœ ์กฐ๊ฑด๋ถ€ ์ธ์Šคํ„ด์Šค ์ฃผ์ž…
๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ ์ตœ์ ํ™” Lazy Loading ๊ธฐ๋ฒ• ์ ์šฉ

๐Ÿšง ์ฃผ์˜์‚ฌํ•ญ

  • Singleton ๋ชจ๋“ˆ์—์„œ Transient ๋ชจ๋“ˆ ์ฃผ์ž… ์‹œ ๋งค๋ฒˆ ๋™์ผ ์ธ์Šคํ„ด์Šค๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
    → ์ด ๊ฒฝ์šฐ moduleRef.resolve()๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ•ญ์ƒ ์ƒˆ๋กœ์šด ์ธ์Šคํ„ด์Šค๋ฅผ ๋ฐ›์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • strict: false ์‚ฌ์šฉ ์‹œ, ์ž˜๋ชป๋œ ๋ชจ๋“ˆ์„ ๊ฐ€์ ธ์˜ฌ ์œ„ํ—˜์ด ์žˆ์Šต๋‹ˆ๋‹ค.
    → ๊ตฌ์กฐ๋ฅผ ๋ช…ํ™•ํžˆ ํ•˜๊ณ  ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๋ฐ”๋žŒ์งํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ”š ๋งˆ๋ฌด๋ฆฌ ์š”์•ฝ

๊ธฐ๋Šฅ ์„ค๋ช…

get() ๋ชจ๋“ˆ ์ธ์Šคํ„ด์Šค๋ฅผ ๊ฐ€์ ธ์˜ด (๊ธฐ๋ณธ์ ์œผ๋กœ Singleton)
resolve() ํ•ญ์ƒ ์ƒˆ๋กœ์šด ์ธ์Šคํ„ด์Šค๋ฅผ ๊ฐ€์ ธ์˜ด (Transient ์ง€์›)
Circular Dependency ํ•ด๊ฒฐ onModuleInit() ํ›„์— ๋ชจ๋“ˆ ์ธ์Šคํ„ด์Šค ํ• ๋‹น
Lazy Loading ํ•„์š”ํ•œ ์‹œ์ ์— ๋ชจ๋“ˆ์„ ๊ฐ€์ ธ์™€ ๋ฉ”๋ชจ๋ฆฌ ์ตœ์ ํ™”

 

NestJS ModuleRef,NestJS Circular Dependency,NestJS Transient Scope ํ•ด๊ฒฐ,NestJS ๋™์  ์ฃผ์ž…,NestJS Lazy Loading,NestJS Module ์ธ์Šคํ„ด์Šค,NestJS DI ์ตœ์ ํ™”,NestJS resolve ์‚ฌ์šฉ๋ฒ•,NestJS ๋ชจ๋“ˆ ๊ด€๋ฆฌ,NestJS ์‹ค๋ฌด ํŒจํ„ด