Spring

빈 μŠ€μ½”ν”„

쑰밈밍 2022. 4. 13. 15:38

πŸ’‘ 빈 μŠ€μ½”ν”„

* μŠ€ν”„λ§ λΉˆμ€ μŠ€ν”„λ§ μ»¨ν…Œμ΄λ„ˆμ˜ μ‹œμž‘κ³Ό ν•¨κ»˜ μƒμ„±λ˜μ–΄μ„œ μŠ€ν”„λ§ μ»¨ν…Œμ΄λ„ˆκ°€ μ’…λ£Œλ  λ•Œ κΉŒμ§€ μœ μ§€λœλ‹€

-> 이것은 μŠ€ν”„λ§ 빈이 기본적으둜 싱글톀 μŠ€μ½”ν”„λ‘œ μƒμ„±λ˜κΈ° λ•Œλ¬Έμ΄λ‹€

- μŠ€μ½”ν”„ : μŠ€ν”„λ§ 빈이 μ‘΄μž¬ν•  수 μžˆλŠ” λ²”μœ„λ₯Ό λ§ν•œλ‹€

1. 싱글톀 : κΈ°λ³Έ μŠ€μ½”ν”„, μŠ€ν”„λ§ μ»¨ν…Œμ΄λ„ˆμ˜ μ‹œμž‘κ³Ό μ’…λ£ŒκΉŒμ§€ μœ μ§€λ˜λŠ” κ°€μž₯ 넓은 λ²”μœ„μ˜ μŠ€μ½”ν”„μ΄λ‹€

2. ν”„λ‘œν† νƒ€μž… : μŠ€ν”„λ§ μ»¨ν…Œμ΄λ„ˆλŠ” ν”„λ‘œν† νƒ€μž… 빈의 생성과 μ˜μ‘΄κ΄€κ³„ μ£Όμž…κΉŒμ§€λ§Œ κ΄€μ—¬ν•˜κ³ 

                    λ”λŠ” κ΄€λ¦¬ν•˜μ§€ μ•ŠλŠ” 맀우 짧은 λ²”μœ„μ˜ μŠ€μ½”ν”„μ΄λ‹€

3. μ›Ή κ΄€λ ¨ μŠ€μ½”ν”„ 

 - request : μ›Ή μš”μ²­μ΄ λ“€μ–΄μ˜€κ³  λ‚˜κ°ˆλ•Œ κΉŒμ§€ μœ μ§€λ˜λŠ” μŠ€μ½”ν”„

 - session : μ›Ή μ„Έμ…˜μ΄ μƒμ„±λ˜κ³  μ’…λ£Œλ  λ•Œ κΉŒμ§€ μœ μ§€λ˜λŠ” μŠ€μ½”ν”„

 - application : μ›Ήμ˜ μ„œλΈ”λ¦Ώ μ»¨ν…μŠ€νŠΈμ™€ 같은 λ²”μœ„λ‘œ μœ μ§€λ˜λŠ” μŠ€μ½”ν”„

 

πŸ’‘ μŠ€μ½”ν”„ 지정

☞ μ»΄ν¬λ„ŒνŠΈ μŠ€μΊ” μžλ™ 등둝

@Scope("prototype")
@Component
public class HelloBean {}

☞ μˆ˜λ™ 등둝

@Scope("prototype")
@Bean
PrototypeBean HelloBean() {
	return new HelloBean();
}

 

 

πŸ’‘ ν”„λ‘œν† νƒ€μž… μŠ€μ½”ν”„

- 생성과 μ˜μ‘΄κ΄€κ³„ μ£Όμž…, 그리고 μ΄ˆκΈ°ν™”κΉŒμ§€λ§Œ μ§„ν–‰ν•˜λŠ” νŠΉλ³„ν•œ μŠ€μ½”ν”„

- 싱글톀 μŠ€μ½”ν”„μ˜ λΉˆκ³ΌλŠ” λ‹€λ₯΄κ²Œ ν”„λ‘œν† νƒ€μž… μŠ€μ½”ν”„λ₯Ό μŠ€ν”„λ§ μ»¨ν…Œμ΄λ„ˆμ— μ‘°νšŒν•˜λ©΄ μŠ€ν”„λ§ μ»¨ν…Œμ΄λ„ˆλŠ” 

 ν•­μƒ μƒˆλ‘œμš΄ μΈμŠ€ν„΄μŠ€λ₯Ό μƒμ„±ν•΄μ„œ λ°˜ν™˜ν•œλ‹€

* 싱글톀 μŠ€μ½”ν”„μ˜ λΉˆμ„ μ‘°νšŒν•˜λ©΄ μŠ€ν”„λ§ μ»¨ν…Œμ΄λ„ˆλŠ” 항상 같은 μΈμŠ€ν„΄μŠ€μ˜ μŠ€ν”„λ§ λΉˆμ„ λ°˜ν™˜ν•œλ‹€

 

1. ν”„λ‘œν† νƒ€μž… μŠ€μ½”ν”„μ˜ λΉˆμ„ μŠ€ν”„λ§ μ»¨ν…Œμ΄λ„ˆμ— μš”μ²­ν•œλ‹€

2. μŠ€ν”„λ§ μ»¨ν…Œμ΄λ„ˆλŠ” 이 μ‹œμ μ— ν”„λ‘œν† νƒ€μž… λΉˆμ„ μƒμ„±ν•˜κ³ , ν•„μš”ν•œ μ˜μ‘΄κ΄€κ³„λ₯Ό μ£Όμž…ν•œλ‹€.

3. μŠ€ν”„λ§ μ»¨ν…Œμ΄λ„ˆλŠ” μƒμ„±ν•œ ν”„λ‘œν† νƒ€μž… λΉˆμ„ ν΄λΌμ΄μ–ΈνŠΈμ— λ°˜ν™˜ν•œλ‹€.

4. 이후에 μŠ€ν”„λ§ μ»¨ν…Œμ΄λ„ˆμ— 같은 μš”μ²­μ΄ 였면 항상 μƒˆλ‘œμš΄ ν”„λ‘œν† νƒ€μž… λΉˆμ„ μƒμ„±ν•΄μ„œ λ°˜ν™˜ν•œλ‹€.

 

πŸ“Œ μŠ€ν”„λ§ μ»¨ν…Œμ΄λ„ˆλŠ” ν”„λ‘œν† νƒ€μž… λΉˆμ„ μƒμ„±ν•˜κ³ , μ˜μ‘΄κ΄€κ³„ μ£Όμž…, μ΄ˆκΈ°ν™”κΉŒμ§€λ§Œ μ²˜λ¦¬ν•œλ‹€

이후, μŠ€ν”„λ§ μ»¨ν…Œμ΄λ„ˆλŠ” μƒμ„±λœ ν”„λ‘œν† νƒ€μž… λΉˆμ„ κ΄€λ¦¬ν•˜μ§€ μ•ŠλŠ”λ‹€. <- λΉˆμ„ 받은 ν΄λΌμ΄μ–ΈνŠΈκ°€ κ΄€λ¦¬ν•œλ‹€

=> @PreDestroy같은 μ’…λ£Œ λ©”μ„œλ“œκ°€ ν˜ΈμΆœλ˜μ§€ μ•ŠλŠ”λ‹€

 

❗️ - 싱글톀 λΉˆμ€ μŠ€ν”„λ§ μ»¨ν…Œμ΄λ„ˆ 생성 μ‹œμ μ— μ΄ˆκΈ°ν™” λ©”μ„œλ“œ μ‹€ν–‰λ˜μ§€λ§Œ, 

    ν”„λ‘œν† νƒ€μž… μŠ€μ½”ν”„μ˜ λΉˆμ€ μŠ€ν”„λ§ μ»¨ν…Œμ΄λ„ˆμ—μ„œ λΉˆμ„ μ‘°νšŒν•  λ•Œ μƒμ„±λ˜κ³ , μ΄ˆκΈ°ν™” λ©”μ„œλ“œλ„ μ‹€ν–‰λœλ‹€

   - 싱글톀 λΉˆμ€ μŠ€ν”„λ§ μ»¨ν…Œμ΄λ„ˆκ°€ κ΄€λ¦¬ν•˜κΈ° λ•Œλ¬Έμ— μŠ€ν”„λ§ μ»¨ν…Œμ΄λ„ˆκ°€ μ’…λ£Œλ  λ•Œ 빈의 μ’…λ£Œ λ©”μ„œλ“œκ°€ μ‹€ν–‰λ˜μ§€λ§Œ,

     ν”„λ‘œν† νƒ€μž… μŠ€μ½”ν”„μ˜ λΉˆμ€ μŠ€ν”„λ§ μ»¨ν…Œμ΄λ„ˆκ°€ 생성과 μ˜μ‘΄κ΄€κ³„ μ£Όμž… 그리고 μ΄ˆκΈ°ν™” κΉŒμ§€λ§Œ κ΄€μ—¬ν•˜κ³ , κ΄€μ—¬X

     => ν”„λ‘œν† νƒ€μž… λΉˆμ€ μŠ€ν”„λ§ μ»¨ν…Œμ΄λ„ˆκ°€ μ’…λ£Œλ  λ•Œ @PreDestroy같은 μ’…λ£Œ λ©”μ„œλ“œκ°€ μ‹€ν–‰λ˜μ§€ μ•ŠλŠ”λ‹€

 

πŸ“Œ ν”„λ‘œν† νƒ€μž… 빈의 νŠΉμ§• 정리

- μŠ€ν”„λ§ μ»¨ν…Œμ΄λ„ˆμ— μš”μ²­ν•  λ•Œ λ§ˆλ‹€ μƒˆλ‘œ μƒμ„±λœλ‹€

- μŠ€ν”„λ§ μ»¨ν…Œμ΄λ„ˆλŠ” ν”„λ‘œν† νƒ€μž… 빈의 생성과 μ˜μ‘΄κ΄€κ³„ μ£Όμž… 그리고 μ΄ˆκΈ°ν™”κΉŒμ§€λ§Œ κ΄€μ—¬ν•œλ‹€

- μ’…λ£Œ λ©”μ„œλ“œκ°€ ν˜ΈμΆœλ˜μ§€ μ•ŠλŠ”λ‹€

- λ•Œλ¬Έμ— ν”„λ‘œν† νƒ€μž… λΉˆμ€ ν”„λ‘œν† νƒ€μž… λΉˆμ„ μ‘°νšŒν•œ ν΄λΌμ΄μ–ΈνŠΈκ°€ 관리해야 ν•œλ‹€ 

  + μ’…λ£Œ λ©”μ„œλ“œμ— λŒ€ν•œ ν˜ΈμΆœλ„ ν΄λΌμ΄μ–ΈνŠΈκ°€ 직접 ν•΄μ•Όν•œλ‹€.

 

πŸ’‘ ν”„λ‘œν† νƒ€μž… μŠ€μ½”ν”„ - 싱글톀 빈과 ν•¨κ»˜ μ‚¬μš©μ‹œ 문제점

- ν”„λ‘œν† νƒ€μž… λΉˆμ„ μš”μ²­ν•˜λ©΄ 항상 μƒˆλ‘œμš΄ 객체 μΈμŠ€ν„΄μŠ€λ₯Ό μƒμ„±ν•΄μ„œ λ°˜ν™˜ν•œλ‹€ ν•˜μ§€λ§Œ 싱글톀 빈과 ν•¨κ»˜ μ‚¬μš©ν•  λ•Œ

  문제점이 λ°œμƒν•  수 μžˆλ‹€

 

☞ 싱글톀 λΉˆμ—μ„œ ν”„λ‘œν† νƒ€μž… 빈 μ‚¬μš© 

- clientBeanμ΄λΌλŠ” 싱글톀 빈이 μ˜μ‘΄κ΄€κ³„ μ£Όμž…μ„ 톡해 ν”„λ‘œν† νƒ€μž… λΉˆμ„ μ£Όμž…λ°›μ•„μ„œ μ‚¬μš©ν•˜λŠ” 예

* clientBean은 μ‹±κΈ€ν†€μ΄λ―€λ‘œ, 보톡 μŠ€ν”„λ§ μ»¨ν…Œμ΄λ„ˆ 생성 μ‹œμ μ— ν•¨κ»˜ μƒμ„±λ˜κ³ , μ˜μ‘΄κ΄€κ³„ μ£Όμž…λ„ λ°œμƒν•œλ‹€

1. clientBean은 μ˜μ‘΄κ΄€κ³„ μžλ™ μ£Όμž…μ„ μ‚¬μš©ν•œλ‹€. μ£Όμž… μ‹œμ μ— μŠ€ν”„λ§ μ»¨ν…Œμ΄λ„ˆμ— ν”„λ‘œν† νƒ€μž… λΉˆμ„ μš”μ²­ν•œλ‹€

2. μŠ€ν”„λ§ μ»¨ν…Œμ΄λ„ˆλŠ” ν”„λ‘œν† νƒ€μž… λΉˆμ„ μƒμ„±ν•΄μ„œ clientBean에 λ°˜ν™˜ν•œλ‹€. ν”„λ‘œν† νƒ€μž… 빈의 count ν•„λ“œ 값은 0이닀

-> 이제 clientBean은 ν”„λ‘œν† νƒ€μž… λΉˆμ„ λ‚΄λΆ€ ν•„λ“œμ— λ³΄κ΄€ν•œλ‹€ (μ •ν™•νžˆλŠ” 참쑰값을 λ³΄κ΄€ν•œλ‹€)

- ν΄λΌμ΄μ–ΈνŠΈAλŠ” clientBean을 μŠ€ν”„λ§ μ»¨ν…Œμ΄λ„ˆμ— μš”μ²­ν•΄μ„œ λ°›λŠ”λ‹€. μ‹±κΈ€ν†€μ΄λ―€λ‘œ 항상 같은 clientBean이 λ°˜ν™˜λœλ‹€

3. ν΄λΌμ΄μ–ΈνŠΈAλŠ” clientBean.logic()을 ν˜ΈμΆœν•œλ‹€

4. clientBean은 prototypeBean의 addCount()λ₯Ό ν˜ΈμΆœν•΄μ„œ ν”„λ‘œν† νƒ€μž… 빈의 countλ₯Ό μ¦κ°€ν•œλ‹€ -> count값이 1이 λœλ‹€

- ν΄λΌμ΄μ–ΈνŠΈBλŠ” clientBean을 μŠ€ν”„λ§ μ»¨ν…Œμ΄λ„ˆμ— μš”μ²­ν•΄μ„œ λ°›λŠ”λ‹€ -> μ‹±κΈ€ν†€μ΄λ―€λ‘œ 항상 같은 clientBean이 λ°˜ν™˜λœλ‹€

❗️ clientBean이 내뢀에 가지고 μžˆλŠ” ν”„λ‘œν† νƒ€μž… λΉˆμ€ 이미 과거에 μ£Όμž…μ΄ λλ‚œ λΉˆμ΄λ‹€. 

  μ£Όμž… μ‹œμ μ— μŠ€ν”„λ§ μ»¨ν…Œμ΄λ„ˆμ— μš”μ²­ν•΄μ„œ ν”„λ‘œν† νƒ€μž… 빈이 μƒˆλ‘œ 생성이 된 것이지,

  μ‚¬μš© ν•  λ•Œλ§ˆλ‹€ μƒˆλ‘œ μƒμ„±λ˜λŠ” 것이 μ•„λ‹ˆλ‹€!

5. ν΄λΌμ΄μ–ΈνŠΈBλŠ” clientBean.logic()을 ν˜ΈμΆœν•œλ‹€

6. clientBean은 prototypeBean의 addCount()λ₯Ό ν˜ΈμΆœν•΄μ„œ ν”„λ‘œν† νƒ€μž… 빈의 countλ₯Ό μ¦κ°€ν•œλ‹€ 

  -> μ›λž˜ count 값이 1μ΄μ—ˆμœΌλ―€λ‘œ 2κ°€ λœλ‹€

 

* μŠ€ν”„λ§μ€ 일반적으둜 싱글톀 λΉˆμ„ μ‚¬μš©ν•˜λ―€λ‘œ, 싱글톀 빈이 ν”„λ‘œν† νƒ€μž… λΉˆμ„ μ‚¬μš©ν•˜κ²Œ λœλ‹€

  그런데 싱글톀 λΉˆμ€ 생성 μ‹œμ μ—λ§Œ μ˜μ‘΄κ΄€κ³„λ₯Ό μ£Όμž… λ°›κΈ° λ•Œλ¬Έμ—, ν”„λ‘œν† νƒ€μž… 빈이 μƒˆλ‘œ μƒμ„±λ˜κΈ°λŠ” ν•˜μ§€λ§Œ,  

  ν•¨κ»˜ 계속 μœ μ§€λ˜λŠ” 것이 λ¬Έμ œλ‹€

=> ν”„λ‘œν† νƒ€μž… λΉˆμ„ μ£Όμž… μ‹œμ μ—λ§Œ μƒˆλ‘œ μƒμ„±ν•˜λŠ”κ²Œ μ•„λ‹ˆλΌ, μ‚¬μš©ν•  λ•Œ λ§ˆλ‹€ μƒˆλ‘œ μƒμ„±ν•΄μ„œ μ‚¬μš©ν•˜λŠ” 것을 μ›ν•œλ‹€

 

❗️ μ—¬λŸ¬ λΉˆμ—μ„œ 같은 ν”„λ‘œν† νƒ€μž… λΉˆμ„ μ£Όμž… λ°›μœΌλ©΄, μ£Όμž… λ°›λŠ” μ‹œμ μ— 각각 μƒˆλ‘œμš΄ ν”„λ‘œν† νƒ€μž… 빈이 μƒμ„±λœλ‹€

 

πŸ’‘ Provider둜 문제 ν•΄κ²°

- 싱글톀 빈과 ν”„λ‘œν† νƒ€μž… λΉˆμ„ ν•¨κ»˜ μ‚¬μš©ν•  λ•Œ, μ‚¬μš©ν•  λ•Œ λ§ˆλ‹€ 항상 μƒˆλ‘œμš΄ ν”„λ‘œν† νƒ€μž… λΉˆμ„ μƒμ„±ν•˜λŠ” 방법

 

1. κ°€μž₯ κ°„λ‹¨ν•œ 방법은 싱글톀 빈이 ν”„λ‘œν† νƒ€μž…μ„ μ‚¬μš©ν•  λ•Œλ§ˆλ‹€ μŠ€ν”„λ§ μ»¨ν…Œμ΄λ„ˆμ— μƒˆλ‘œ μš”μ²­ν•˜λŠ” 것

 

* ClientBean 클래슀

@Autowired
private ApplicationContext ac;

public int logic() {
    PrototypeBean prototypeBean = ac.getBean(PrototypeBean.class);
    prototypeBean.addCount();
    int count = prototypeBean.getCount();
    return count;
}

- ac.getBean()을 톡해 항상 μƒˆλ‘œμš΄ ν”„λ‘œν† νƒ€μž… 빈이 μƒμ„±λœλ‹€

- μ˜μ‘΄κ΄€κ³„λ₯Ό μ™ΈλΆ€μ—μ„œ μ£Όμž…(DI) λ°›λŠ”κ²Œ μ•„λ‹ˆλΌ μ΄λ ‡κ²Œ

  직접 ν•„μš”ν•œ μ˜μ‘΄κ΄€κ³„λ₯Ό μ°ΎλŠ” 것을 Dependency Lookup (DL) μ˜μ‘΄κ΄€κ³„ 쑰회(탐색) μ΄λΌν•œλ‹€

- ν•˜μ§€λ§Œ μ΄λ ‡κ²Œ μŠ€ν”„λ§μ˜ μ• ν”Œλ¦¬μΌ€μ΄μ…˜ μ»¨ν…μŠ€νŠΈ 전체λ₯Ό μ£Όμž…λ°›κ²Œ 되면, μŠ€ν”„λ§ μ»¨ν…Œμ΄λ„ˆμ— 쒅속적인 μ½”λ“œκ°€ 되고,

  λ‹¨μœ„ ν…ŒμŠ€νŠΈλ„ μ–΄λ €μ›Œμ§„λ‹€

 

2. ObjectFactory, ObjectProvider

- μ§€μ •ν•œ λΉˆμ„ μ»¨ν…Œμ΄λ„ˆμ—μ„œ λŒ€μ‹  μ°Ύμ•„μ£ΌλŠ” DL μ„œλΉ„μŠ€λ₯Ό μ œκ³΅ν•˜λŠ” ObjectProvider

  κ³Όκ±° ObjectFactoryμ—μ„œ 편의기λŠ₯이 μΆ”κ°€λœ ObjectProvider이닀

- ObjectFactory : κΈ°λŠ₯이 λ‹¨μˆœ, λ³„λ„μ˜ 라이브러리 ν•„μš” μ—†μŒ, μŠ€ν”„λ§μ— 의쑴

- ObjectProvider : ObjectFactory 상속, μ˜΅μ…˜, 슀트림 μ²˜λ¦¬λ“± 편의 κΈ°λŠ₯이 많고, λ³„λ„μ˜ 라이브러리 ν•„μš”X, μŠ€ν”„λ§μ— 의쑴

@Autowired
private ObjectProvider<PrototypeBean> prototypeBeanProvider;

public int logic() {
    PrototypeBean prototypeBean = prototypeBeanProvider.getObject();
    prototypeBean.addCount();
    int count = prototypeBean.getCount();
    return count;
}

- prototypeBeanProvider.getObject() ν†΅ν•΄μ„œ 항상 μƒˆλ‘œμš΄ ν”„λ‘œν† νƒ€μž… 빈이 μƒμ„±λœλ‹€

- ObjectProvider의 getObject()λ₯Ό ν˜ΈμΆœν•˜λ©΄ λ‚΄λΆ€μ—μ„œλŠ” μŠ€ν”„λ§ μ»¨ν…Œμ΄λ„ˆλ₯Ό 톡해 ν•΄λ‹Ή λΉˆμ„ μ°Ύμ•„ λ°˜ν™˜ν•œλ‹€(DL)

- ObjectProviderλŠ” λ”± ν•„μš”ν•œ DL μ •λ„μ˜ κΈ°λŠ₯만 μ œκ³΅ν•œλ‹€

 

πŸ“Œ 정리

ν”„λ‘œν† νƒ€μž… λΉˆμ„ μ–Έμ œ μ‚¬μš©ν• κΉŒ -> 맀번 μ‚¬μš©ν•  λ•Œ λ§ˆλ‹€ μ˜μ‘΄κ΄€κ³„ μ£Όμž…μ΄ μ™„λ£Œλœ μƒˆλ‘œμš΄ 객체가 ν•„μš”ν•˜λ©΄ μ‚¬μš©ν•˜μž

그런데 보톡 싱글톀 빈으둜 λŒ€λΆ€λΆ„μ˜ 문제λ₯Ό ν•΄κ²°ν•  수 있기 λ•Œλ¬Έμ— ν”„λ‘œν† νƒ€μž… λΉˆμ„ μ§μ ‘μ μœΌλ‘œ μ‚¬μš©ν•˜λŠ” 일은 λ“œλ¬Όλ‹€

 

πŸ’‘ μ›Ή μŠ€μ½”ν”„

- μ›Ή ν™˜κ²½μ—μ„œλ§Œ λ™μž‘ν•œλ‹€

- ν”„λ‘œν† νƒ€μž…κ³Ό λ‹€λ₯΄κ²Œ μŠ€ν”„λ§μ΄ ν•΄λ‹Ή μŠ€μ½”ν”„μ˜ μ’…λ£Œμ‹œμ κΉŒμ§€ κ΄€λ¦¬ν•œλ‹€ -> μ’…λ£Œ λ©”μ„œλ“œκ°€ ν˜ΈμΆœλœλ‹€

- request : HTTP μš”μ²­ ν•˜λ‚˜κ°€ λ“€μ–΄μ˜€κ³  λ‚˜κ°ˆ λ•Œ κΉŒμ§€ μœ μ§€λ˜λŠ” μŠ€μ½”ν”„

             : 각각의 HTTP μš”μ²­λ§ˆλ‹€ λ³„λ„μ˜ 빈 μΈμŠ€ν„΄μŠ€κ°€ μƒμ„±λ˜κ³  κ΄€λ¦¬λœλ‹€

- session : HTTP Sessionκ³Ό λ™μΌν•œ 생λͺ…μ£ΌκΈ°λ₯Ό κ°€μ§€λŠ” μŠ€μ½”ν”„

- application : μ„œλΈ”λ¦Ώ μ»¨ν…μŠ€νŠΈ(ServletContext)와 λ™μΌν•œ 생λͺ…μ£ΌκΈ°λ₯Ό κ°€μ§€λŠ” μŠ€μ½”ν”„

- websocket : μ›Ή μ†ŒμΌ“κ³Ό λ™μΌν•œ 생λͺ…μ£ΌκΈ°λ₯Ό κ°€μ§€λŠ” μŠ€μ½”ν”„