πŸ“– [Spring] πŸ’» μŠ€ν”„λ§ 핡심원리 - 3. IoC, DI, 그리고 μ»¨ν…Œμ΄λ„ˆ

πŸ’» [Spring] μŠ€ν”„λ§ 핡심원리 - 3. IoC, DI, 그리고 μ»¨ν…Œμ΄λ„ˆ

μ•ˆλ…•ν•˜μ„Έμš”. πŸ‘‹

μŠ€ν”„λ§μœΌλ‘œ μ—¬λŸ¬ ν”„λ‘œμ νŠΈλ₯Ό κ°œλ°œν–ˆμ—ˆλŠ”λ° 

문득 μŠ€ν”„λ§ 자체 핡심 원리에 λŒ€ν•œ 볡슡이 ν•˜κ³  μ‹Άμ—ˆμŠ΅λ‹ˆλ‹€.

κ·Έλž˜μ„œ κΉ€μ˜ν•œλ‹˜μ˜ μŠ€ν”„λ§ 핡심원리 κ°•μ˜λ₯Ό λ“€μœΌλ©° 

μŠ€ν”„λ§μ„ μ™œ μ‚¬μš©ν•΄μ•Όν•˜λŠ”μ§€μ™€

μŠ€ν”„λ§ 핡심원리에 λŒ€ν•΄ ν•™μŠ΅ν•œ λ‚΄μš©μž…λ‹ˆλ‹€. 

μ„Έλ²ˆμ§Έ ν¬μŠ€νŠΈμž…λ‹ˆλ‹€.

이전 λ‘λ²ˆμ§Έ ν¬μŠ€νŠΈμ—μ„œ 직접 순수 μžλ°”λ§Œμ„ μ΄μš©ν•΄ 객체 지ν–₯ 원리λ₯Ό μ μš©ν•΄ ν”„λ‘œμ νŠΈλ₯Ό κ°œλ°œν•΄λ³΄μ•˜μŠ΅λ‹ˆλ‹€. 이 κ³Όμ •μ—μ„œ μ™œ IoC, DI, μ»¨ν…Œμ΄λ„ˆ 같은 κ°œλ…λ“€μ΄ ν•„μš”ν•΄μ§€κ³  λ“±μž₯ν•˜κ²Œ λ˜μ—ˆλŠ”μ§€λ₯Ό μ•Œ 수 μžˆμ—ˆμŠ΅λ‹ˆλ‹€. 이번 μ„Έλ²ˆμ§Έ ν¬μŠ€νŠΈμ—μ„œλŠ” μ•žμ„  κ³Όμ •μ—μ„œ λ“±μž₯ν•˜κ²Œ 된 IoC, DI, μ»¨ν…Œμ΄λ„ˆμ— λŒ€ν•΄ μ •λ¦¬ν•˜λŠ” μ‹œκ°„μž…λ‹ˆλ‹€.

λ‘λ²ˆμ§Έ 포슀트 와 ν•¨κ»˜ λ³΄μ‹œλ©΄ μ΄ν•΄ν•˜κΈ°κ°€ 더 μ‰¬μšΈ 것 μž…λ‹ˆλ‹€.

1. μ œμ–΄μ˜ μ—­μ „ IoC (Inversion of Control)

β€» ν”„λ‘œκ·Έλž¨μ˜ μ œμ–΄ 흐름을 직접 μ œμ–΄ν•˜λŠ” 것이 μ•„λ‹ˆλΌ μ™ΈλΆ€μ—μ„œ κ΄€λ¦¬ν•˜λŠ” 것 을 μ œμ–΄μ˜ μ—­μ „(IoC) 이라 ν•œλ‹€.

  • κΈ°μ‘΄ ν”„λ‘œκ·Έλž¨μ€ ν΄λΌμ΄μ–ΈνŠΈ κ΅¬ν˜„ 객체가 슀슀둜 ν•„μš”ν•œ μ„œλ²„ κ΅¬ν˜„ 객체λ₯Ό μƒμ„±ν•˜κ³ , μ—°κ²°ν•˜κ³ , μ‹€ν–‰ν–ˆλ‹€. ν•œ λ§ˆλ””λ‘œ κ΅¬ν˜„ 객체가 ν”„λ‘œκ·Έλž¨μ˜ μ œμ–΄ 흐름을 슀슀둜 μ‘°μ’…ν–ˆλ‹€. 개발자 μž…μž₯μ—μ„œλŠ” μžμ—°μŠ€λŸ¬μš΄ 흐름이닀.

  • λ°˜λ©΄μ— AppConfigκ°€ λ“±μž₯ν•œ 이후에 κ΅¬ν˜„ κ°μ²΄λŠ” μžμ‹ μ˜ λ‘œμ§μ„ μ‹€ν–‰ν•˜λŠ” μ—­ν• λ§Œ λ‹΄λ‹Ήν•œλ‹€. ν”„λ‘œκ·Έλž¨μ˜ 제 μ–΄ 흐름은 이제 AppConfigκ°€ κ°€μ Έκ°„λ‹€. 예λ₯Ό λ“€μ–΄μ„œ OrderServiceImpl 은 ν•„μš”ν•œ μΈν„°νŽ˜μ΄μŠ€λ“€μ„ 호 μΆœν•˜μ§€λ§Œ μ–΄λ–€ κ΅¬ν˜„ 객체듀이 싀행될지 λͺ¨λ₯Έλ‹€.

  • ν”„λ‘œκ·Έλž¨μ— λŒ€ν•œ μ œμ–΄ 흐름에 λŒ€ν•œ κΆŒν•œμ€ λͺ¨λ‘ AppConfigκ°€ 가지고 μžˆλ‹€. 심지어 OrderServiceImpl 도 AppConfigκ°€ μƒμ„±ν•œλ‹€. 그리고 AppConfigλŠ” OrderServiceImpl 이 μ•„λ‹Œ OrderService μΈν„°νŽ˜ 이슀의 λ‹€λ₯Έ κ΅¬ν˜„ 객체λ₯Ό μƒμ„±ν•˜κ³  μ‹€ν–‰ν•  수 도 μžˆλ‹€. 그런 사싀도 λͺ¨λ₯Έμ²΄ OrderServiceImpl 은 묡묡히 μžμ‹ μ˜ λ‘œμ§μ„ μ‹€ν–‰ν•  뿐이닀.

  • 이렇듯 ν”„λ‘œκ·Έλž¨μ˜ μ œμ–΄ 흐름을 직접 μ œμ–΄ν•˜λŠ” 것이 μ•„λ‹ˆλΌ μ™ΈλΆ€μ—μ„œ κ΄€λ¦¬ν•˜λŠ” 것을 μ œμ–΄μ˜ μ—­μ „(IoC)이라 ν•œλ‹€.

2. ν”„λ ˆμž„μ›Œν¬ vs 라이브러리

β€» μž‘μ„± λ˜μ–΄μžˆλŠ” μ½”λ“œλ₯Ό λ‚΄κ°€ 직접 ν˜ΈμΆœν•΄ κ°€μ Έλ‹€μ“°λ©΄ 라이브러리이고 λ°˜λŒ€λ‘œ λ‚΄κ°€ μž‘μ„±ν•œ μ½”λ“œλ₯Ό μ™ΈλΆ€μ—μ„œ μ œμ–΄ν•˜λ©΄ κ·Έ μ™ΈλΆ€κ°€ ν”„λ ˆμž„μ›Œν¬λ‹€.

ν”„λ ˆμž„μ›Œν¬κ°€ λ‚΄κ°€ μž‘μ„±ν•œ μ½”λ“œλ₯Ό μ œμ–΄ν•˜κ³ , λŒ€μ‹  μ‹€ν–‰ν•˜λ©΄ 그것은 ν”„λ ˆμž„μ›Œν¬κ°€ λ§žλ‹€. (JUnit) λ°˜λ©΄μ— λ‚΄κ°€ μž‘μ„±ν•œ μ½”λ“œκ°€ 직접 μ œμ–΄μ˜ 흐름을 λ‹΄λ‹Ήν•œλ‹€λ©΄ 그것은 ν”„λ ˆμž„μ›Œν¬κ°€ μ•„λ‹ˆλΌ λΌμ΄λΈŒλŸ¬λ¦¬λ‹€.

3. μ˜μ‘΄κ΄€κ³„ μ£Όμž… DI(Dependency Injection)

  • OrderServiceImpl 은 DiscountPolicy μΈν„°νŽ˜μ΄μŠ€μ— μ˜μ‘΄ν•œλ‹€. μ‹€μ œ μ–΄λ–€ κ΅¬ν˜„ 객체가 μ‚¬μš©λ μ§€λŠ” λͺ¨λ₯Έλ‹€.
  • μ˜μ‘΄κ΄€κ³„λŠ” 정적인 클래슀 의쑴 관계와, μ‹€ν–‰ μ‹œμ μ— κ²°μ •λ˜λŠ” 동적인 객체(μΈμŠ€ν„΄μŠ€) 의쑴 관계 λ‘˜μ„ 뢄리 ν•΄μ„œ 생각해야 ν•œλ‹€.

정적인 클래슀 μ˜μ‘΄κ΄€κ³„

ν΄λž˜μŠ€κ°€ μ‚¬μš©ν•˜λŠ” import μ½”λ“œλ§Œ 보고 μ˜μ‘΄κ΄€κ³„λ₯Ό μ‰½κ²Œ νŒλ‹¨ν•  수 μžˆλ‹€ (정적). 정적인 μ˜μ‘΄κ΄€κ³„λŠ” μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ„ μ‹€ν–‰ν•˜μ§€ μ•Šμ•„λ„ 뢄석할 수 μžˆλ‹€. 클래슀 λ‹€μ΄μ–΄κ·Έλž¨μ„ 보자. OrderServiceImpl 은 MemberRepository , DiscountPolicy 에 μ˜μ‘΄ν•œλ‹€λŠ” 것을 μ•Œ 수 μžˆλ‹€.

그런데 μ΄λŸ¬ν•œ 클래슀 μ˜μ‘΄κ΄€κ³„ λ§ŒμœΌλ‘œλŠ” μ‹€μ œ μ–΄λ–€ 객체가 OrderServiceImpl 에 μ£Όμž… 될지 μ•Œ 수 μ—†λ‹€.

클래슀 λ‹€μ΄μ–΄κ·Έλž¨

class diagram

동적인 객체 μΈμŠ€ν„΄μŠ€ 의쑴 관계

μ• ν”Œλ¦¬μΌ€μ΄μ…˜ μ‹€ν–‰ μ‹œμ μ— μ‹€μ œ μƒμ„±λœ 객체 μΈμŠ€ν„΄μŠ€μ˜ μ°Έμ‘°κ°€ μ—°κ²°λœ 의쑴 관계닀.

객체 λ‹€μ΄μ–΄κ·Έλž¨

object diagram

  • μ• ν”Œλ¦¬μΌ€μ΄μ…˜ μ‹€ν–‰ μ‹œμ (λŸ°νƒ€μž„)에 μ™ΈλΆ€μ—μ„œ μ‹€μ œ κ΅¬ν˜„ 객체λ₯Ό μƒμ„±ν•˜κ³  ν΄λΌμ΄μ–ΈνŠΈμ— μ „λ‹¬ν•΄μ„œ 클라이언 νŠΈμ™€ μ„œλ²„μ˜ μ‹€μ œ μ˜μ‘΄κ΄€κ³„κ°€ μ—°κ²° λ˜λŠ” 것을 μ˜μ‘΄κ΄€κ³„ μ£Όμž…μ΄λΌ ν•œλ‹€.

  • 객체 μΈμŠ€ν„΄μŠ€λ₯Ό μƒμ„±ν•˜κ³ , κ·Έ 참쑰값을 μ „λ‹¬ν•΄μ„œ μ—°κ²°λœλ‹€.

  • μ˜μ‘΄κ΄€κ³„ μ£Όμž…μ„ μ‚¬μš©ν•˜λ©΄ ν΄λΌμ΄μ–ΈνŠΈ μ½”λ“œλ₯Ό λ³€κ²½ν•˜μ§€ μ•Šκ³ , ν΄λΌμ΄μ–ΈνŠΈκ°€ ν˜ΈμΆœν•˜λŠ” λŒ€μƒμ˜ νƒ€μž… μΈμŠ€ν„΄μŠ€ λ₯Ό λ³€κ²½ν•  수 μžˆλ‹€.

  • μ˜μ‘΄κ΄€κ³„ μ£Όμž…μ„ μ‚¬μš©ν•˜λ©΄ 정적인 클래슀 μ˜μ‘΄κ΄€κ³„λ₯Ό λ³€κ²½ν•˜μ§€ μ•Šκ³ , 동적인 객체 μΈμŠ€ν„΄μŠ€ μ˜μ‘΄κ΄€κ³„λ₯Ό 쉽 게 λ³€κ²½ν•  수 μžˆλ‹€.

4. IoC μ»¨ν…Œμ΄λ„ˆ, DI μ»¨ν…Œμ΄λ„ˆ

  • AppConfig 처럼 객체λ₯Ό μƒμ„±ν•˜κ³  κ΄€λ¦¬ν•˜λ©΄μ„œ μ˜μ‘΄κ΄€κ³„λ₯Ό μ—°κ²°ν•΄ μ£ΌλŠ” 것을 IoC μ»¨ν…Œμ΄λ„ˆ λ˜λŠ” DI μ»¨ν…Œμ΄λ„ˆλΌ ν•œλ‹€.
  • μ˜μ‘΄κ΄€κ³„ μ£Όμž…μ— μ΄ˆμ μ„ λ§žμΆ”μ–΄ μ΅œκ·Όμ—λŠ” 주둜 DI μ»¨ν…Œμ΄λ„ˆλΌ ν•œλ‹€.
  • μ• ν”Œλ¦¬μΌ€μ΄μ…˜ 전체에 λŒ€ν•œ ꡬ성을 쑰립을 ν•œλ‹€κ³  ν•΄μ„œ μ–΄μƒ˜λΈ”λŸ¬λΌκ³ λ„ ν•œλ‹€.
  • 였브젝트λ₯Ό 생성해낸닀고 ν•΄μ„œ 였브젝트 νŒ©ν† λ¦¬ λ“±μœΌλ‘œ λΆˆλ¦¬κΈ°λ„ ν•œλ‹€.

5. μŠ€ν”„λ§ μ»¨ν…Œμ΄λ„ˆ

  • μŠ€ν”„λ§ μ»¨ν…Œμ΄λ„ˆλ₯Ό λΆ€λ₯Ό λ•Œ BeanFactory , ApplicationContext 둜 κ΅¬λΆ„ν•΄μ„œ 이야기 ν•œλ‹€. ν•˜μ§€λ§Œ BeanFactory λ₯Ό 직접 μ‚¬μš©ν•˜λŠ” κ²½μš°λŠ” 거의 μ—†μœΌλ―€λ‘œ 일반적으둜 ApplicationContext λ₯Ό μŠ€ν”„λ§ μ»¨ν…Œμ΄λ„ˆλΌ ν•œλ‹€.

  • κΈ°μ‘΄μ—λŠ” κ°œλ°œμžκ°€ AppConfig λ₯Ό μ‚¬μš©ν•΄μ„œ 직접 객체λ₯Ό μƒμ„±ν•˜κ³  DIλ₯Ό ν–ˆμ§€λ§Œ, μ΄μ œλΆ€ν„°λŠ” μŠ€ν”„λ§ μ»¨ν…Œμ΄ λ„ˆλ₯Ό ν†΅ν•΄μ„œ μ‚¬μš©ν•œλ‹€.

  • μŠ€ν”„λ§ μ»¨ν…Œμ΄λ„ˆλŠ” @Configuration 이 뢙은 AppConfig λ₯Ό μ„€μ •(ꡬ성) μ •λ³΄λ‘œ μ‚¬μš©ν•œλ‹€. μ—¬κΈ°μ„œ @Bean 이라 적힌 λ©”μ„œλ“œλ₯Ό λͺ¨λ‘ ν˜ΈμΆœν•΄μ„œ λ°˜ν™˜λœ 객체λ₯Ό μŠ€ν”„λ§ μ»¨ν…Œμ΄λ„ˆμ— λ“±λ‘ν•œλ‹€. μ΄λ ‡κ²Œ μŠ€ν”„λ§ μ»¨ν…Œμ΄λ„ˆμ— λ“±λ‘λœ 객체λ₯Ό μŠ€ν”„λ§ 빈이라 ν•œλ‹€.

  • μŠ€ν”„λ§ λΉˆμ€ @Bean 이 뢙은 λ©”μ„œλ“œμ˜ λͺ…을 μŠ€ν”„λ§ 빈의 μ΄λ¦„μœΌλ‘œ μ‚¬μš©ν•œλ‹€. ( memberService ,orderService )

  • μ΄μ „μ—λŠ” κ°œλ°œμžκ°€ ν•„μš”ν•œ 객체λ₯Ό AppConfig λ₯Ό μ‚¬μš©ν•΄μ„œ 직접 μ‘°νšŒν–ˆμ§€λ§Œ, μ΄μ œλΆ€ν„°λŠ” μŠ€ν”„λ§ μ»¨ν…Œμ΄λ„ˆ λ₯Ό ν†΅ν•΄μ„œ ν•„μš”ν•œ μŠ€ν”„λ§ 빈(객체)λ₯Ό μ°Ύμ•„μ•Ό ν•œλ‹€. μŠ€ν”„λ§ λΉˆμ€ applicationContext.getBean() λ©”μ„œλ“œ λ₯Ό μ‚¬μš©ν•΄μ„œ 찾을 수 μžˆλ‹€.

  • κΈ°μ‘΄μ—λŠ” κ°œλ°œμžκ°€ 직접 μžλ°”μ½”λ“œλ‘œ λͺ¨λ“  것을 ν–ˆλ‹€λ©΄ μ΄μ œλΆ€ν„°λŠ” μŠ€ν”„λ§ μ»¨ν…Œμ΄λ„ˆμ— 객체λ₯Ό μŠ€ν”„λ§ 빈으둜 λ“±λ‘ν•˜κ³ , μŠ€ν”„λ§ μ»¨ν…Œμ΄λ„ˆμ—μ„œ μŠ€ν”„λ§ λΉˆμ„ μ°Ύμ•„μ„œ μ‚¬μš©ν•˜λ„λ‘ λ³€κ²½λ˜μ—ˆλ‹€.

끝

μŠ€ν”„λ§μ„ 더 μ˜¬λ°”λ₯΄κ²Œ μ‚¬μš©ν•˜κΈ° μœ„ν•΄ κΉ€μ˜ν•œλ‹˜μ˜ μŠ€ν”„λ§ 핡심 원리 κ°•μ˜λ₯Ό λ“€μœΌλ©° μ •λ¦¬ν•œ
μ„Έλ²ˆμ§Έ ν¬μŠ€νŠΈμ˜€μŠ΅λ‹ˆλ‹€.
κ°μ‚¬ν•©λ‹ˆλ‹€. πŸ™

μŠ€ν”„λ§ 핡심원리 포슀트

1. 객체 지ν–₯ 섀계와 μŠ€ν”„λ§
2. μŠ€ν”„λ§ 핡심 원리 이해 1,2


Reference

κΉ€μ˜ν•œλ‹˜μ˜ μŠ€ν”„λ§ 핡심원리

Written on May 14, 2021