--- id: wiki-2026-0508-dependency-injection-의존성-주입 title: Dependency Injection (의존성 주입) category: 10_Wiki/Topics status: verified canonical_id: self aliases: [DI, Dependency Injection, IoC, Inversion of Control] duplicate_of: none source_trust_level: A confidence_score: 0.93 verification_status: applied tags: [di, ioc, design-pattern, spring, nestjs] raw_sources: [] last_reinforced: 2026-05-10 github_commit: pending tech_stack: language: typescript framework: 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 ```typescript @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) ```java @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) ```typescript 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) ```typescript { provide: 'DATABASE_CONNECTION', useFactory: async (config: ConfigService) => { return await createPool({ url: config.get('DB_URL') }); }, inject: [ConfigService], } ``` ### Manual DI (Go, wire-style) ```go // wire.go (codegen) func InitializeApp() *App { repo := NewUserRepo(NewDB()) svc := NewUserService(repo) return NewApp(svc) } ``` ### Test with mock (vitest) ```typescript 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) ```typescript @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 - 부모: [[Inversion of Control]] · [[SOLID]] (D) - 변형: [[Service Locator]] · [[Factory Pattern]] - 응용: [[Spring Framework]] · [[NestJS]] · [[Angular]] - Adjacent: [[Cross-Cutting Concerns]] · [[Aspect-Oriented Programming (AOP)]] ## 🤖 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 |