Injection scopes

Injection scopes

λ‹€λ₯Έ μ–Έμ–΄λ₯Ό μ‚¬μš©ν•˜λŠ” μ‚¬λžŒλ“€μ—κ²ŒλŠ” Nestμ—μ„œ 거의 λͺ¨λ“  것이 λ“€μ–΄μ˜€λŠ” μš”μ²­μ—μ„œ κ³΅μœ λ˜λŠ” 것이 어색할 수 μžˆμŠ΅λ‹ˆλ‹€. μš°λ¦¬λŠ” λ°μ΄ν„°λ² μ΄μŠ€μ— λŒ€ν•œ μ—°κ²° ν’€, μ „μ—­ μƒνƒœλ“±μ˜ μ‹±κΈ€ 톀 μ„œλΉ„μŠ€λ₯Ό 가지고 μžˆμŠ΅λ‹ˆλ‹€. 일반적으둜 Node.jsλŠ” λͺ¨λ“  μš”μ²­μ΄ λ³„λ„μ˜ μŠ€λ ˆλ“œμ— μ˜ν•΄ μ²˜λ¦¬λ˜λŠ” μš”μ²­/응닡 닀쀑 μŠ€λ ˆλ“œ μƒνƒœ λΉ„ μ €μž₯ λͺ¨λΈμ„ λ”°λ₯΄μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. λ”°λΌμ„œ μ‹±κΈ€ 톀 μΈμŠ€ν„΄μŠ€λ₯Ό μ‚¬μš©ν•˜λŠ” 것은 μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ— μ•ˆμ „ν•©λ‹ˆλ‹€.

κ·ΈλŸ¬λ‚˜ 컨트둀러의 μš”μ²­ 기반 수λͺ…이 μ˜λ„μ μΈ λ™μž‘ (예: GraphQL μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ˜ μš”μ²­λ³„ μΊμ‹œ, μš”μ²­ 좔적 λ˜λŠ” 닀쀑 ν…Œλ„Œμ‹œ) 일 수 μžˆλŠ” κ²½μš°κ°€ μžˆμŠ΅λ‹ˆλ‹€. μ–΄λ–»κ²Œ 처리 ν•  수 μžˆμŠ΅λ‹ˆκΉŒ?

Scopes

기본적으둜 λͺ¨λ“  κ³΅κΈ‰μžλŠ” μ‹±κΈ€ ν†€μœΌλ‘œ μž‘λ™ν•˜κ³  μš”μ²­ λ²”μœ„λ₯Ό μ„€μ •ν•˜λ©° μž„μ‹œ λͺ¨λ“œλ‘œ μ „ν™˜ ν•  수 μžˆμŠ΅λ‹ˆλ‹€. 차이점을 μ΄ν•΄ν•˜λ €λ©΄ λ‹€μŒ ν‘œλ₯Ό μ°Έμ‘°ν•˜μ‹­μ‹œμ˜€.

SINGLETON

각 κ³΅κΈ‰μžλŠ” μ—¬λŸ¬ ν΄λž˜μŠ€μ—μ„œ κ³΅μœ ν•  수 μžˆμŠ΅λ‹ˆλ‹€. κ³΅κΈ‰μž 수λͺ…은 μ‘μš© ν”„λ‘œκ·Έλž¨ 수λͺ…주기와 λ°€μ ‘ν•œ 관련이 μžˆμŠ΅λ‹ˆλ‹€. μ‘μš© ν”„λ‘œκ·Έλž¨μ΄ λΆ€νŠΈ 슀트랩되면 λͺ¨λ“  κ³΅κΈ‰μžκ°€ 이미 μΈμŠ€ν„΄μŠ€ν™”λ©λ‹ˆλ‹€. μ‹±κΈ€ 톀 λ²”μœ„κ°€ 기본적으둜 μ‚¬μš©λ©λ‹ˆλ‹€.

REQUEST

μš”μ²­ μ²˜λ¦¬κ°€ μ™„λ£Œλœ ν›„ μˆ˜μ‹ λ˜λŠ” λͺ¨λ“  μš”μ²­λ° 가비지에 λŒ€ν•΄ 제곡자의 μƒˆ μΈμŠ€ν„΄μŠ€κ°€ λ…μ μ μœΌλ‘œ μž‘μ„±λ©λ‹ˆλ‹€.

TRANSIENT

μΌμ‹œμ μΈ μ œκ³΅μžλŠ” μ œκ³΅μžκ°„μ— 곡유 ν•  수 μ—†μŠ΅λ‹ˆλ‹€. λ‹€λ₯Έ κ³΅κΈ‰μžκ°€ Nest μ»¨ν…Œμ΄λ„ˆμ— νŠΉμ • μž„μ‹œ κ³΅κΈ‰μžλ₯Ό μš”μ²­ν•  λ•Œλ§ˆλ‹€ μ»¨ν…Œμ΄λ„ˆλŠ” μƒˆλ‘œμš΄ μ „μš© μΈμŠ€ν„΄μŠ€λ₯Ό λ§Œλ“­λ‹ˆλ‹€.

info 힌트 μ‹±κΈ€ 톀 μŠ€μ½”ν”„λ₯Ό μ‚¬μš©ν•˜λŠ” 것이 항상 ꢌμž₯λ˜λŠ” λ°©λ²•μž…λ‹ˆλ‹€. μš”μ²­κ°„μ— κ³΅κΈ‰μžλ₯Ό κ³΅μœ ν•˜λ©΄ λ©”λͺ¨λ¦¬ μ†ŒλΉ„κ°€ 쀄어듀어 μ• ν”Œλ¦¬μΌ€μ΄μ…˜ μ„±λŠ₯이 ν–₯μƒλ©λ‹ˆλ‹€ (맀번 클래슀λ₯Ό μΈμŠ€ν„΄μŠ€ν™”ν•˜μ§€ μ•Šμ•„λ„ 됨).

Usage

λ‹€λ₯Έ μ£Όμž… λ²”μœ„λ‘œ μ „ν™˜ν•˜λ €λ©΄@Injectable()λ°μ½”λ ˆμ΄ν„°μ— 인수λ₯Ό 전달해야 ν•©λ‹ˆλ‹€.

import { Injectable, Scope } from '@nestjs/common';

@Injectable({ scope: Scope.REQUEST })
export class CatsService {}

custom provider의 경우 μΆ”κ°€scope 속성을 μ„€μ •ν•΄μ•Όν•©λ‹ˆλ‹€.

{
  provide: 'CACHE_MANAGER',
  useClass: CacheManager,
  scope: Scope.TRANSIENT,
}

μ»¨νŠΈλ‘€λŸ¬μ— κ΄€ν•΄μ„œλŠ” ControllerOptions 객체λ₯Ό μ „λ‹¬ν•˜μ‹­μ‹œμ˜€ :

@Controller({
  path: 'cats',
  scope: Scope.REQUEST,
})
export class CatsController {}

warning μ•Œλ¦Ό κ²Œμ΄νŠΈμ›¨μ΄λŠ” 단일 λ²”μœ„ 역할을 ν•˜λ―€λ‘œ μš”μ²­ λ²”μœ„ κ³΅κΈ‰μžμ— μ˜μ‘΄ν•΄μ„œλŠ” μ•ˆλ©λ‹ˆλ‹€. ν•˜λ‚˜μ˜ κ²Œμ΄νŠΈμ›¨μ΄λŠ” λ‚΄λΆ€μ˜ μ‹€μ œ μ†ŒμΌ“μ„ μΊ‘μŠν™”ν•˜λ©° μ—¬λŸ¬λ²ˆ μΈμŠ€ν„΄μŠ€ν™” ν•  수 μ—†μŠ΅λ‹ˆλ‹€.

Per-request injection

μš”μ²­ λ²”μœ„μ˜ κ³΅κΈ‰μžλŠ” 맀우 μ‹ μ€‘ν•˜κ²Œ μ‚¬μš©ν•΄μ•Όν•©λ‹ˆλ‹€. μŠ€μ½”ν”„λŠ” μΈμ μ…˜ μ²΄μΈμ—μ„œ μ‹€μ œλ‘œ 버블링됨을 λͺ…μ‹¬ν•˜μ‹­μ‹œμ˜€. μ»¨νŠΈλ‘€λŸ¬κ°€ μš”μ²­ λ²”μœ„μ˜ κ³΅κΈ‰μžμ— μ˜μ‘΄ν•˜λŠ” 경우 μ»¨νŠΈλ‘€λŸ¬λ„ μ‹€μ œλ‘œ μš”μ²­ λ²”μœ„μž…λ‹ˆλ‹€.

CatsController<-CatsService<-CatsRepository 체인을 상상해 λ³΄μ‹­μ‹œμ˜€. CatsServiceκ°€ μš”μ²­ λ²”μœ„ (및 λ‚˜λ¨Έμ§€λŠ” 이둠적으둜 μ‹±κΈ€ 톀) 인 경우, CatsController도 μš”μ²­ λ²”μœ„κ°€ λ©λ‹ˆλ‹€ (μš”μ²­ λ²”μœ„κ°€ μ§€μ •λœ μΈμŠ€ν„΄μŠ€λŠ” μƒˆλ‘œ μž‘μ„±λœ μ»¨νŠΈλ‘€λŸ¬μ— μ‚½μž…λ˜μ–΄μ•Όν•˜κΈ° λ•Œλ¬Έμ—). λ°˜λ©΄μ— CatsRepositoryλŠ” μ‹±κΈ€ ν†€μœΌλ‘œ 남아 μžˆμ„ κ²ƒμž…λ‹ˆλ‹€.

κ²½κ³  이 경우 μˆœν™˜ 쒅속성은 맀우 κ³ ν†΅μŠ€λŸ¬μš΄ λΆ€μž‘μš©μœΌλ‘œ μ΄μ–΄μ§ˆ 수 μžˆμœΌλ―€λ‘œ λΆ€μž‘μš©μ„ μΌμœΌν‚€μ§€ μ•Šμ•„μ•Ό ν•©λ‹ˆλ‹€.

Request provider

HTTP μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ—μ„œ μš”μ²­ λ²”μœ„ 제곡자λ₯Ό μ‚¬μš©ν•˜λ©΄ μ›λž˜ μš”μ²­ μ°Έμ‘°λ₯Ό μ‚½μž… ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

import { Injectable, Scope, Inject } from '@nestjs/common';
import { REQUEST } from '@nestjs/core';
import { Request } from 'express';

@Injectable({ scope: Scope.REQUEST })
export class CatsService {
  constructor(@Inject(REQUEST) private readonly request: Request) {}
}

κ·ΈλŸ¬λ‚˜ 이 κΈ°λŠ₯은 마이크둜 μ„œλΉ„μŠ€ λ˜λŠ” GraphQL μ‘μš© ν”„λ‘œκ·Έλž¨μ—μ„œλŠ” μž‘λ™ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. GraphQL μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ—μ„œ λŒ€μ‹  CONTEXTλ₯Ό μ‚½μž… ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

import { Injectable, Scope, Inject } from '@nestjs/common';
import { CONTEXT } from '@nestjs/graphql';

@Injectable({ scope: Scope.REQUEST })
export class CatsService {
  constructor(@Inject(CONTEXT) private readonly context) {}
}

그런 λ‹€μŒ context κ°’ (GraphQLModule)을 κ΅¬μ„±ν•˜μ—¬ requestλ₯Ό νŠΉμ„±μœΌλ‘œ 포함할 수 μžˆμŠ΅λ‹ˆλ‹€.

Performance

μš”μ²­ λ²”μœ„ κ³΅κΈ‰μžλ₯Ό μ‚¬μš©ν•˜λ©΄ λΆ„λͺ…νžˆ μ‘μš© ν”„λ‘œκ·Έλž¨ μ„±λŠ₯에 영ν–₯을 λ―ΈμΉ©λ‹ˆλ‹€. Nestκ°€ κ°€λŠ₯ν•œ ν•œ λ§Žμ€ 메타 데이터λ₯Ό μΊμ‹œν•˜λ €κ³  μ‹œλ„ν•˜λ”λΌλ„ 각 μš”μ²­λ§ˆλ‹€ 클래슀의 μΈμŠ€ν„΄μŠ€λ₯Ό μž‘μ„±ν•΄μ•Ό ν•©λ‹ˆλ‹€. λ”°λΌμ„œ 평균 응닡 μ‹œκ°„κ³Ό μ „λ°˜μ μΈ λ²€μΉ˜λ§ˆν‚Ή κ²°κ³Όκ°€ λŠλ €μ§‘λ‹ˆλ‹€. κ³΅κΈ‰μžκ°€ λ°˜λ“œμ‹œ μš”μ²­ λ²”μœ„λ₯Ό 지정할 ν•„μš”κ°€ μ—†λ‹€λ©΄ μ‹±κΈ€ 톀 λ²”μœ„λ₯Ό κ³ μˆ˜ν•΄μ•Όν•©λ‹ˆλ‹€.

Last updated