DI (Dependency Injection)

๐Ÿ” ๊ฐœ์š”

  • DI๋Š” ํ•„์š”ํ•œ ์˜์กด ๊ฐ์ฒด๋ฅผ new๋กœ ์ง์ ‘ ๋งŒ๋“ค์ง€ ์•Š๊ณ  ์™ธ๋ถ€(์ปจํ…Œ์ด๋„ˆ) ์—์„œ ์ฃผ์ž…๋ฐ›์•„ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ์‹์ด๋‹ค.
  • Spring์—์„  IoC ์ปจํ…Œ์ด๋„ˆ(ApplicationContext) ๊ฐ€ ๋นˆ์„ ์ƒ์„ฑ/๊ด€๋ฆฌํ•˜๊ณ , ์ƒ์„ฑ์žยท์„ธํ„ฐยทํ•„๋“œ ๋“ฑ ๋‹ค์–‘ํ•œ ๋ฐฉ๋ฒ•์œผ๋กœ ์˜์กด์„ฑ์„ ์ฃผ์ž…ํ•œ๋‹ค.
  • IoC ๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ํ•ต์‹ฌ ๋ฉ”์ปค๋‹ˆ์ฆ˜์ด DI์ด๋ฉฐ, ๊ตฌ์„ฑ/ํ™˜๊ฒฝ์€ external-configuration/auto-configuration์œผ๋กœ ์œ ์—ฐํ•˜๊ฒŒ ๋ฐ”๊ฟ€ ์ˆ˜ ์žˆ๋‹ค.

โ˜๐Ÿป ํ•œ์ค„ ์š”์•ฝ

DI๋Š” ๊ฐ์ฒด ๊ฐ„ ์—ฐ๊ฒฐ ์ฑ…์ž„์„ ์ฝ”๋“œ์—์„œ ์ปจํ…Œ์ด๋„ˆ๋กœ ๋ถ„๋ฆฌํ•ด ๊ฒฐํ•ฉ๋„โ†“ยทํ…Œ์ŠคํŠธ ์šฉ์ด์„ฑโ†‘๋ฅผ ๋งŒ๋“œ๋Š” ์˜์กด์„ฑ ์—ฐ๊ฒฐ ๋ฐฉ์‹์ด๋‹ค.


๐Ÿค” ์™œ ํ•„์š”ํ•œ๊ฐ€?

  • ๊ตฌํ˜„ ๊ต์ฒด/ํ™•์žฅ ์šฉ์ด: ์ธํ„ฐํŽ˜์ด์Šค ๊ธฐ๋ฐ˜์œผ๋กœ ๊ตฌํ˜„ ๋ฐ”๊ฟ” ๋ผ์šฐ๊ธฐ ์‰ฌ์›€
  • ํ…Œ์ŠคํŠธ ์ƒ์‚ฐ์„ฑโ†‘: ๋ชฉ/์Šคํ… ๋“ฑ ํ…Œ์ŠคํŠธ ๋Œ€์—ญ ์ฃผ์ž…์ด ๊ฐ„๋‹จ
  • ํ™˜๊ฒฝ ๋ถ„๋ฆฌ ์šฉ์ด: ํ”„๋กœํ•„/์กฐ๊ฑด์— ๋”ฐ๋ผ ๋นˆ ์„ ํƒ ๊ฐ€๋Šฅ
  • ๊ด€์‹ฌ์‚ฌ ๋ถ„๋ฆฌ: ์™ธ๋ถ€ ๋ฐ ์ž๋™ ๊ตฌ์„ฑ์€ ์„ค์ •(properties), ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์€ ์ฝ”๋“œ

์ฃผ์ž… ๋ฐฉ์‹ & ์„ ํƒ

  • ์ƒ์„ฑ์ž ์ฃผ์ž…(๊ถŒ์žฅ): ๋ถˆ๋ณ€์„ฑ ์œ ์ง€, NPE ์˜ˆ๋ฐฉ, ํ…Œ์ŠคํŠธ/๋ฆฌํŒฉํ† ๋ง์— ์ตœ์ . ๋‹จ์ผ ์ƒ์„ฑ์ž๋ฉด @Autowired ์ƒ๋žต.
  • ์„ธํ„ฐ ์ฃผ์ž…: ์„ ํƒ์  ์˜์กด์„ฑ, ๋Ÿฐํƒ€์ž„ ๊ต์ฒด๊ฐ€ ํ•„์š”ํ•œ ๊ฒฝ์šฐ. (์„ธํ„ฐ๋ฅผ ๊ณต๊ฐœํ•ด์•ผ ํ•˜๋ฏ€๋กœ ๋‚จ์šฉ ๊ธˆ์ง€)
  • ํ•„๋“œ ์ฃผ์ž…(์ง€์–‘): ์บก์Аํ™”/๋ถˆ๋ณ€์„ฑ ์ €ํ•ด, ํ…Œ์ŠคํŠธ ์–ด๋ ค์›€(๋ฆฌํ”Œ๋ ‰์…˜ ํ•„์š”). ๋ ˆ๊ฑฐ์‹œ/์ƒ˜ํ”Œ ์™ธ ์‚ฌ์šฉ ๋น„๊ถŒ์žฅ.

๊ถŒ์žฅ ์ˆœ์„œ: ์ƒ์„ฑ์ž ์ฃผ์ž… > ์„ธํ„ฐ ์ฃผ์ž… > ํ•„๋“œ ์ฃผ์ž…(์ง€์–‘).


๐Ÿ”ง ์˜ˆ์‹œ

(A) ์ƒ์„ฑ์ž ์ฃผ์ž… - ๊ถŒ์žฅ โœ…

@Component
public class Communicator {
  private final Greeting greeting;
  private final Farewell farewell;
  private final Sender sender;
 
  // ๋‹จ์ผ ์ƒ์„ฑ์ž โ†’ @Autowired ์ƒ๋žต ๊ฐ€๋Šฅ
  public Communicator(Greeting greeting, Farewell farewell, Sender sender) {
    this.greeting = greeting;
    this.farewell = farewell;
    this.sender = sender;
  }
}

Lombok ์‚ฌ์šฉ

@RequiredArgsConstructor
@Component
public class Communicator {
  private final Greeting greeting;
  private final Farewell farewell;
  private final Sender sender;
}

(B) ์„ธํ„ฐ ์ฃผ์ž…

@Component
public class AppStartupRunner implements ApplicationRunner {
  private Greeting greeting;
 
  @Autowired
  public void setGreeting(Greeting greeting) { 
	  this.greeting = greeting; 
  }
 
  @Override 
  public void run(ApplicationArguments args) { 
	  greeting.sayHello(); 
  }
}

์ฃผ์ž… ๋ฐ›๊ณ  ์‹ถ์€ ๊ฐ์ฒด๋ฅผ ์„ ์–ธํ•˜๊ณ , Setter ๋ฅผ ์ด์šฉํ•ด ์˜์กด์„ฑ์„ ์ฃผ์ž…ํ•œ๋‹ค.

(C) ํ•„๋“œ ์ฃผ์ž… - ์ง€์–‘ โŒ

@Component
public class AppStartupRunner implements ApplicationRunner {
  @Autowired
  private Greeting greeting; // ์ง€์–‘
  
  @Override
  public void run(ApplicationArguments args) { 
	  greeting.sayHello(); 
  }
}

๐Ÿ”— ๊ด€๋ จ

  • IoC : DI๋Š” IoC๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ์ˆ˜๋‹จ
  • auto-configuration - ๊ธฐ๋ณธ ๋นˆ ์ž๋™ ๋“ฑ๋ก
  • external-configuration - ํ™˜๊ฒฝ/ํ”„๋กœํ•„ ๊ธฐ๋ฐ˜ ์„ค์ • ๋ถ„๋ฆฌ