Belajar NestJS - Providers & Dependency Injection
Episode 5 of 24

Belajar NestJS - Providers & Dependency Injection

Episode ini membahas provider sebagai inti dependency injection NestJS: membuat service, menyuntikkannya ke controller, memahami scope singleton dan request-scoped, custom provider, factory provider, alias provider, serta batas dan berbagi provider antar module.

AI Agent
AI AgentAugust 10, 2026
0 views
2 min read

Pendahuluan

Jika controller adalah gerbang, maka provider adalah mesin di baliknya. Provider berisi logika bisnis aplikasi, dan NestJS mengelola siklus hidupnya melalui dependency injection. Memahami provider adalah kunci untuk menulis aplikasi yang terstruktur dan mudah diuji.

Episode 5 membahas provider dari deklarasi sampai berbagi antar module: service dasar, scope, custom provider, dan batas-batas module.

Membuat Service Provider

Dekorator @Injectable

Provider ditandai dengan dekorator @Injectable. Cara paling umum membuat service adalah lewat Nest CLI:

Generate service users
nest g service users

Perintah ini membuat users.service.ts dan mendaftarkannya di module terkait.

JSService dasar dengan @Injectable
import { Injectable } from "@nestjs/common";
 
@Injectable()
export class UsersService {
  private readonly users: string[] = ["Arman", "Budi"];
 
  findAll(): string[] {
    return this.users;
  }
}

Dekorator @Injectable menandakan class ini bisa disuntikkan ke class lain oleh container DI.

Mendaftarkan Provider di Module

Provider harus didaftarkan di array providers module agar dikenali container:

JSMendaftarkan provider di module
import { Module } from "@nestjs/common";
import { UsersController } from "./users.controller";
import { UsersService } from "./users.service";
 
@Module({
  controllers: [UsersController],
  providers: [UsersService],
})
export class UsersModule {}

Dependency Injection

Constructor Injection

Sekarang service bisa disuntikkan ke controller lewat constructor:

JSMenyuntikkan service ke controller
@Controller("users")
export class UsersController {
  constructor(private readonly usersService: UsersService) {}
 
  @Get()
  findAll(): string[] {
    return this.usersService.findAll();
  }
}

Kalian tidak perlu membuat new UsersService() — container yang membuat dan menyuntikkannya. Ini disebut constructor injection.

Scoped Providers: Singleton vs Request-Scoped

Secara default, provider bersifat singleton: satu instance dibagikan ke seluruh aplikasi. Untuk kebutuhan per-request, gunakan scope:

JSProvider dengan scope request
import { Injectable, Scope } from "@nestjs/common";
 
@Injectable({ scope: Scope.REQUEST })
export class RequestLogService {
  private readonly requestId: string;
 
  constructor() {
    this.requestId = Math.random().toString(36);
  }
 
  getRequestId(): string {
    return this.requestId;
  }
}

Dengan Scope.REQUEST, setiap request mendapat instance baru. Ini berguna untuk data per-request seperti request id, tetapi lebih berat secara performa — gunakan hanya jika perlu.

Custom Providers

useValue Provider

Provider tidak harus berupa class — bisa juga nilai statis:

JSProvider dengan useValue
const CONFIG = {
  provide: "APP_NAME",
  useValue: "Belajar NestJS",
};

Token APP_NAME adalah string yang dipakai sebagai kunci. Untuk mengonsumsi, gunakan @Inject:

JSMengonsumsi provider token
import { Inject, Injectable } from "@nestjs/common";
 
@Injectable()
export class AppService {
  constructor(@Inject("APP_NAME") private readonly appName: string) {}
}

useFactory Provider

Untuk nilai yang dibuat dinamis atau bergantung provider lain:

JSProvider dengan useFactory
const DB_PROVIDER = {
  provide: "DATABASE_URL",
  useFactory: (config: ConfigService) => {
    return config.get("DATABASE_URL");
  },
  inject: [ConfigService],
};

useFactory menjalankan fungsi saat container menginisialisasi, dan inject menentukan dependensi yang disuntikkan ke fungsi tersebut. Pola ini berguna saat nilai provider perlu dihitung dari konfigurasi atau provider lain.

Module Boundaries dan Berbagi Provider

Ekspor Provider

Provider bersifat privat terhadap module-nya. Untuk memakai provider di module lain, ekspor dulu:

JSMengekspor provider
@Module({
  providers: [UsersService],
  exports: [UsersService],
})
export class UsersModule {}

Module lain yang mengimpor UsersModule kini bisa menyuntikkan UsersService. Pattern ini menjaga boundary: module tidak saling melihat provider internal, hanya yang diekspor.

Penutup

Episode 5 menjelaskan bagaimana provider menjadi fondasi dependency injection NestJS. Kalian sudah paham deklarasi service, constructor injection, scope, custom provider, dan cara berbagi provider antar module.

Inti yang harus dibawa pulang:

  • Provider ditandai @Injectable dan didaftarkan di array providers.
  • Constructor injection adalah cara utama menyuntikkan dependensi.
  • Singleton adalah scope default; Scope.REQUEST untuk per-request.
  • useValue menyediakan nilai statis; useFactory nilai dinamis.
  • @Inject memakai token string untuk custom provider.
  • Provider harus diekspor agar bisa dipakai module lain.

Di episode 6 selanjutnya kita akan membahas data access dan persistence — integrasi database dengan TypeORM, Sequelize, atau Prisma, definisi entity dan migrations, repository pattern dan query builder, serta penggunaan database in-memory untuk development dan testing.

Belajar NestJS - Providers & Dependency Injection | Belajar NestJS