· Özgür Vurgun · NestJS · 2 min read
4. NestJS Mimarisi: Modüller Arası İletişim (2. Bölüm)

Modüller Arası İletişim Neden Önemlidir?
Modülleri ayırdık ama gerçek hayatta işler böyle izole ilerlemez.
Örneğin:
- Kullanıcı kaydı yapılınca log’a bir şey yazmak isteyebilirsin.
- Bir ödeme alınınca stok sistemini bilgilendirmek isteyebilirsin.
Yani modüllerin birbiriyle konuşması gerekir. NestJS bunu imports, exports ve dependency injection sistemleriyle sağlar.
Temel Kurgu: Service Kullanmak
Senaryomuz şu:
UserServiceadında bir servisimiz var (UserModuleiçinde)AuthModulebu servisi kullanmak istiyor (örneğin kullanıcıyı veritabanında sorgulamak için)
Şöyle bir şey yapmak istiyoruz:
// auth.service.ts
constructor(private userService: UserService) {}Ama bu çalışmaz. Çünkü NestJS, bir modülde tanımlı provider’ı başka modüllere otomatik olarak açmaz.
Ne Yapmam Lazım?
Adım adım gidelim:
- Kullanmak istediğin servisi export et:
// user.module.ts
@Module({
providers: [UserService],
exports: [UserService], // dışa açıyoruz
})
export class UserModule {}- Kullanan modülde, ilgili modülü import et:
// auth.module.ts
@Module({
imports: [UserModule], // içeri alıyoruz
providers: [AuthService],
})
export class AuthModule {}- Artık kullanabilirsin:
// auth.service.ts
@Injectable()
export class AuthService {
constructor(private userService: UserService) {}
}Bitti.
Analoji
Bunu bir ofis binası gibi düşün:
- Her modül bir departman
UserService-> İnsan Kaynakları’nda çalışan biriAuthModule-> Güvenlik departmanı
Eğer HR’dan bir personeli kullanmak istiyorsan:
- HR onu dış dünyaya “tanıtmalı” (export)
- Güvenlik birimi HR ile “protokol imzalamalı” (import)
- Ancak o zaman o kişiyi çağırıp iş yaptırabilirsin
Circular Dependency Sorunu (Kabus)
Şimdi işler karışıyor. Diyelim ki hem AuthService, UserService’i kullanıyor… Hem de UserService, AuthService’i çağırmak istiyor.
Yani:
UserService → AuthService
AuthService → UserServiceBu bir circular dependency’dir. NestJS bunu görünce error verir:
Cannot resolve dependencies of the UserService
Çözüm: forwardRef
Bu durumda forwardRef kullanmamız gerekir. Bu, Nest’e “şimdilik tanımadığın ama sonra tanıyacağın bir şeyi kullan” demektir.
- Import ederken:
// user.module.ts
@Module({
imports: [forwardRef(() => AuthModule)],
providers: [UserService],
exports: [UserService],
})
export class UserModule {}// auth.module.ts
@Module({
imports: [forwardRef(() => UserModule)],
providers: [AuthService],
})
export class AuthModule {}- Inject ederken de
@Inject(forwardRef(...)):
@Injectable()
export class UserService {
constructor(
@Inject(forwardRef(() => AuthService))
private authService: AuthService,
) {}
}Bu yapı ilk bakışta karışık gibi ama büyük projelerde olmazsa olmaz bir tekniktir.
İpucu: exports sadece provider’lar içindir
exports: [X] dediğinde sadece servisleri (provider) paylaşabilirsin. Controller’lar dışa açılmaz, onlar sadece istek karşılar. Ayrıca controllers: [] ve providers: [] bir yere export edilmezse sadece o modülde erişilebilir olur.
Eksik/Kritik Nokta: Karmaşık Yapılarda İz Sürmek Zorlaşabilir
Evet, bu sistem sağlam. Ama şunu da kabul edelim:
- Bir modül birden fazla yere import/export edilince neyin nereden geldiğini takip etmek zorlaşabiliyor.
- Circular dependency durumları projeyi kırabilir.
- forwardRef, çözüm getiriyor ama yapıyı daha karmaşıklaştırıyor.
- Export ettiğin bir servisi iki farklı modülde override etmeye çalışırsan kontrol sende olmayabilir.
Yani bu güçlü yapı, “iyi bir mimari disiplin” ile desteklenmezse başına bela olabilir.



