O
OpenLog
Search
Log in
Back to Suggestions
New Suggest
Suggest edit for "NestJS의 커스텀 프로바이더 선언 (Class Provider)"
Suggestion title
Description
</>
Edit
Preview
## Summary ## Reason
</>
Edit
Preview
```ts // logs/logs.module.ts @Module({ providers: [ { provide: LogsRepository, useClass: InMemoryLogsRepository }, ], exports: [LogsRepository], }) export class LogsModule {} ``` 위와 같은 문법은 NestJS나 Angular와 같은 의존성 주입 프레임워크에서 사용하는 커스텀 프로바이더 선언 방식으로 구체적으로는 Class Provider라고 불리는 형태다. NestJS의 `module.ts`파일에서 `providers: [LogsRepository]` 라고만 적는 것은 사실 `providers: [{ provide: LogsRepository, useClass: LogsRepository }]`를 축약한 형태다. `provide`는 DI 컨테이너에서 인스턴스를 찾기 위한 Key 역할을 한다. 클래스 생성자에서 `@Inject(LogsRepository)`나 `constructor(private readonly logsRepository: LogsRepository)`처럼 타입 힌트를 통해 이 식별자를 요청하면, 시스템은 이 키에 연결된 인스턴스를 찾게 된다. `useClass`는 실제 구현체로 위에서 설명한 `provide`식별자가 호출되었을 때, 실제로 인스턴스화할 클래스를 지정하는 역할을 한다. 처음 예시로 작성한 코드에서는 `LogsRepository`라는 이름으로 객체를 요청받으면 실제로는 `InMemoryLogsRepository`클래스를 설계도 삼아 객체를 생성하여 반환하게 된다. #### 그래서 이걸 왜 씀? 이 방식은 인터페이스나 추상클래스를 실제 구현과 분리할 때 유용하다. 애플리케이션의 다른 서비스들은 `LogsRepository`라는 추상적인 개념에 의존하고 데이터가 DB에 저장되는지 메모리에 저장되는지 상관하지 않도록 추상화를 유지할 수 있다. 또 테스트 환경에서는 메모리 DB를 사용하는 `InMemoryLogsRepository`를 주입하고, 실제 운영 환경에서는 `DatabaseLogsRepository`로 바꾸는 등 유연하게 구현체를 교체할 수 있다는 장점이 있다. 마지막으로 주입받는 쪽의 코드는 전혀 수정하지 않고 `providers`설정 파일 한 곳만 수정함으로써 전체 로직의 데이터 저장 방식을 변경할 수 있게된다. ```ts // logs.repository.ts (추상 클래스 또는 인터페이스) export abstract class LogsRepository { abstract save(log: string): void; } // in-memory-logs.repository.ts (실제 구현체) export class InMemoryLogsRepository implements LogsRepository { save(log: string) { console.log(`Memory Storage: ${log}`); } } // app.module.ts import { Module } from '@nestjs/common'; import { LogsRepository } from './logs.repository'; import { InMemoryLogsRepository } from './in-memory-logs.repository'; @Module({ providers: [ { provide: LogsRepository, // "LogsRepository를 달라고 하면" useClass: InMemoryLogsRepository, // "InMemoryLogsRepository를 줘라" }, ], }) export class AppModule {} // logs.service.ts (사용부) import { Injectable } from '@nestjs/common'; import { LogsRepository } from './logs.repository'; @Injectable() export class LogsService { // 생성자에서 LogsRepository 타입으로 주입받음 // 실제로는 InMemoryLogsRepository의 인스턴스가 들어옴 constructor(private readonly logsRepository: LogsRepository) {} logData(data: string) { this.logsRepository.save(data); } } ``` 만약 이 프로바이더를 여러 모듈에서 사용하려면 모듈화를 시켜줘야하므로 `log.module.ts`파일을 만들어 다음과 같이 작성해주어야한다. ```ts // log.module.ts import { Module } from '@nestjs/common'; import { LogRepository } from './repository/log.repository'; import { InMemoryLogRepository } from './repository/in-memory-log.repository'; @Module({ providers: [{ provide: LogRepository, useClass: InMemoryLogRepository }], exports: [LogRepository], }) export class LogModule {} ```
Files changed
No changes yet.
Cancel
Submit suggestion