Files
2nd/10_Wiki/Topics/Architecture/Dependency Injection (의존성 주입).md
T
2026-05-10 22:08:15 +09:00

5.0 KiB

id, title, category, status, canonical_id, aliases, duplicate_of, source_trust_level, confidence_score, verification_status, tags, raw_sources, last_reinforced, github_commit, tech_stack
id title category status canonical_id aliases duplicate_of source_trust_level confidence_score verification_status tags raw_sources last_reinforced github_commit tech_stack
wiki-2026-0508-dependency-injection-의존성-주입 Dependency Injection (의존성 주입) 10_Wiki/Topics verified self
DI
Dependency Injection
IoC
Inversion of Control
none A 0.93 applied
di
ioc
design-pattern
spring
nestjs
2026-05-10 pending
language framework
typescript nestjs

Dependency Injection (의존성 주입)

매 한 줄

"매 의존성 매 외부 주입, 직접 생성 X". IoC 의 가장 흔한 구현. Martin Fowler (2004) 가 명명. 2026 현재 Spring (Java), NestJS (Node), Angular, dagger (Android), wire (Go) 매 mainstream; testability + decoupling 의 backbone.

매 핵심

매 형태 (3 종류)

  • Constructor injection — 생성자 매 dependency 받음. 매 immutable, 매 권장.
  • Setter injection — setter 매 dependency 받음. optional dep 에 적합.
  • Field injection — 매 framework 의 reflection. simple 하지만 testability ↓.

매 benefit

  • Testability — mock 매 쉽게 inject.
  • Decoupling — concrete impl 의 unaware.
  • Lifecycle 관리 — singleton, request-scoped, transient.
  • Configuration centralization — DI container 의 wiring.

매 응용

  1. Spring @Autowired, @Component.
  2. NestJS @Injectable() + module providers.
  3. Angular providedIn: 'root'.
  4. Go: 매 manual 또는 google/wire codegen.

💻 패턴

NestJS — constructor injection

@Injectable()
export class UserService {
  constructor(
    private readonly repo: UserRepository,
    private readonly logger: Logger,
  ) {}

  async find(id: string) {
    this.logger.log(`finding ${id}`);
    return this.repo.findById(id);
  }
}

@Module({
  providers: [UserService, UserRepository, Logger],
  exports: [UserService],
})
export class UserModule {}

Spring Boot — constructor injection (no @Autowired needed)

@Service
public class OrderService {
    private final PaymentGateway gateway;
    private final OrderRepository repo;

    public OrderService(PaymentGateway gateway, OrderRepository repo) {
        this.gateway = gateway;
        this.repo = repo;
    }
}

Token / interface binding (NestJS)

export const PAYMENT_GATEWAY = Symbol('PAYMENT_GATEWAY');

@Module({
  providers: [
    { provide: PAYMENT_GATEWAY, useClass: StripeGateway },
  ],
  exports: [PAYMENT_GATEWAY],
})
export class PaymentModule {}

@Injectable()
class CheckoutService {
  constructor(@Inject(PAYMENT_GATEWAY) private gw: PaymentGateway) {}
}

Factory provider (async, e.g. DB connection)

{
  provide: 'DATABASE_CONNECTION',
  useFactory: async (config: ConfigService) => {
    return await createPool({ url: config.get('DB_URL') });
  },
  inject: [ConfigService],
}

Manual DI (Go, wire-style)

// wire.go (codegen)
func InitializeApp() *App {
    repo := NewUserRepo(NewDB())
    svc  := NewUserService(repo)
    return NewApp(svc)
}

Test with mock (vitest)

const mockRepo: UserRepository = {
  findById: vi.fn().mockResolvedValue({ id: '1', name: 'A' }),
};
const service = new UserService(mockRepo, mockLogger);
expect(await service.find('1')).toEqual({ id: '1', name: 'A' });

Modern: TC39 decorators + Reflect.metadata (2026)

@injectable()
class EmailService {
  @inject(SMTP_CLIENT) private smtp!: SmtpClient;
}

매 결정 기준

상황 Approach
Spring/Java @Component + constructor injection
Node.js/TS, full framework NestJS module providers
Frontend (Angular) providedIn: 'root'
Go manual or google/wire
Tiny app, no framework manual constructor — DI 불필요

기본값: constructor injection, framework-managed singleton. Field injection 매 피하기.

🔗 Graph

🤖 LLM 활용

언제: provider wiring 생성, mock 매 test 자동 생성, refactor field→constructor injection. 언제 X: lifecycle / scope decision 매 architectural taste 필요.

안티패턴

  • Service Locator — DI 와 혼동, dep 매 hidden.
  • Field injection 남용 — test 시 reflection 필요, 매 fragile.
  • Circular dep — A→B→A. forwardRef 로 hack 보다 redesign.
  • God container — singleton 매 200개. module boundary 무시.
  • new in business logic — DI 의 의미 없음.

🧪 검증 / 중복

  • Verified (Fowler 2004 Inversion of Control Containers and the Dependency Injection Pattern, NestJS docs 2026).
  • 신뢰도 A.

🕓 Changelog

날짜 변경
2026-05-08 Phase 1
2026-05-10 Manual cleanup — full content with NestJS/Spring/Go patterns