JiwonDev

#11 ๋นˆ ์Šค์ฝ”ํ”„(+Provider, ํ”„๋ก์‹œ ๋ชจ๋“œ)

by JiwonDev

์•ž์—์„œ ์šฐ๋ฆฌ๋Š” ์Šคํ”„๋ง ๋นˆ์€ ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ์˜ ์‹œ์ž‘๊ณผ ํ•จ๊ป˜ ์ƒ์„ฑ๋˜๊ณ , ์ปจํ…Œ์ด๋„ˆ๊ฐ€ ์ข…๋ฃŒ๋  ๋•Œ ๊นŒ์ง€ ์œ ์ง€๋œ๋‹ค๊ณ  ํ•™์Šตํ–ˆ๋‹ค. ์ด๋Š” ์Šคํ”„๋ง ๋นˆ์ด ๊ธฐ๋ณธ์ ์œผ๋กœ '์‹ฑ๊ธ€ํ†ค ์Šค์ฝ”ํ”„'๋กœ ์ƒ์„ฑ๋˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ์—ฌ๊ธฐ์—์„œ ์Šค์ฝ”ํ”„๋Š” ๋ง ๊ทธ๋Œ€๋กœ ๋นˆ์ด ์กด์žฌํ•  ์ˆ˜ ์žˆ๋Š” ์ƒ๋ช…์ฃผ๊ธฐ ๋ฒ”์œ„๋ฅผ ์˜๋ฏธํ•œ๋‹ค.

 


# ์Šคํ”„๋ง์ด ์ง€์›ํ•˜๋Š” ๋‹ค์–‘ํ•œ ์Šค์ฝ”ํ”„

ํ•˜์ง€๋งŒ ํ•„์š”์— ๋”ฐ๋ผ ์Šคํ”„๋ง ๋นˆ์˜ ์ƒ๋ช…์ฃผ๊ธฐ, ์ฆ‰ ์Šค์ฝ”ํ”„๋ฅผ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๋‹ค. ์Šคํ”„๋ง์€ ๋‹ค์–‘ํ•œ ์Šค์ฝ”ํ”„๋ฅผ ์ง€์›ํ•œ๋‹ค.

  • ์‹ฑ๊ธ€ํ†ค(๊ธฐ๋ณธ) : ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ์˜ ์‹œ์ž‘๊ณผ ์ข…๋ฃŒ๊นŒ์ง€ ์œ ์ง€๋˜๋Š” ๊ฐ€์žฅ ๋„“์€ ๋ฒ”์œ„์˜ ์Šค์ฝ”ํ”„์ด๋‹ค.
  • ํ”„๋กœํ† ํƒ€์ž… : ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๋Š” ํ”„๋กœํ† ํƒ€์ž… ๋นˆ์˜ ์ƒ์„ฑ๊ณผ ์˜์กด๊ด€๊ณ„ ์ฃผ์ž…๊นŒ์ง€๋งŒ ๊ด€์—ฌํ•˜๊ณ , ์ดํ›„ ๋”ฐ๋กœ ๊ด€๋ฆฌํ•˜์ง€ ์•Š๋Š”๋‹ค. ์ฆ‰ ์Šคํ”„๋ง์—์„œ ๋งค์šฐ ์งง์€ ๋ฒ”์œ„์˜ ์Šค์ฝ”ํ”„์ด๋‹ค. (= ์ข…๋ฃŒ ์ฝœ๋ฐฑ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ์ด ๋˜์ง€ ์•Š๋Š”๋‹ค.)
  • ์›น ๊ด€๋ จ ์Šค์ฝ”ํ”„๋“ค
    - request : ์›น ์š”์ฒญ์ด ๋“ค์–ด์˜ค๊ณ  ๋‚˜๊ฐˆ๋•Œ ๊นŒ์ง€ ์œ ์ง€๋˜๋Š” ์Šค์ฝ”ํ”„์ด๋‹ค.
    - session: ์›น ์„ธ์…˜์ด ์ƒ์„ฑ๋˜๊ณ  ์ข…๋ฃŒ๋  ๋•Œ ๊นŒ์ง€ ์œ ์ง€๋˜๋Š” ์Šค์ฝ”ํ”„์ด๋‹ค.
    - application: ์›น์˜ ์„œ๋ธ”๋ฆฟ ์ปจํ…์ŠคํŠธ์™€ ๊ฐ™์€ ๋ฒ”์œ„๋กœ ์œ ์ง€๋˜๋Š” ์Šค์ฝ”ํ”„์ด๋‹ค

๋ฌผ๋ก  ์•„์ง ์ƒ์„ฑ๋˜์ง€ ์•Š์€ ์Šคํ”„๋ง๋นˆ (ex request๋นˆ์„ ์‹ฑ๊ธ€ํ†ค์— ์ฃผ์ž…ํ•˜๋ ค๊ณ ํ•˜๋Š”๊ฒฝ์šฐ)์„ ์‚ฌ์šฉํ•˜๋ฉด ์Šคํ”„๋ง์•ฑ์ด ์•ˆ๋œฌ๋‹ค. ์˜ค๋ฅ˜๋ฐœ์ƒ.
๋งŒ์•ฝ ํ•„์š”ํ•˜๋‹ค๋ฉด DL(Dependcy Lookup) ๊ธฐ๋Šฅ์ธ ObjectProvider ๋“ฑ์„ ์‚ฌ์šฉํ•˜๋ฉด๋œ๋‹ค. ์ด๋Š” ์•„๋ž˜์—์„œ ์„ค๋ช….

 

 

# ์Šคํ”„๋ง ๋นˆ ์Šค์ฝ”ํ”„ ์„ค์ • ๋ฐฉ๋ฒ•

@Scope("prototype")
@Component // ์ปดํฌ๋„ŒํŠธ ์Šค์บ”์„ ์ด์šฉํ•œ ์ž๋™ ๋“ฑ๋ก
public class HelloBean {}
@Scope("prototype")
@Bean // ์Šคํ”„๋ง ๋นˆ ์ˆ˜๋™ ๋“ฑ๋ก.
PrototypeBean HelloBean() {
    return new HelloBean();
}

 


# ํ”„๋กœํ† ํƒ€์ž… ์Šค์ฝ”ํ”„๋ž€

๊ธฐ์กด์˜ ์‹ฑ๊ธ€ํ†ค ์Šค์ฝ”ํ”„ ๋นˆ์„ ์กฐํšŒํ•˜๋ฉด, ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๋Š” ํ•ญ์ƒ ๊ฐ™์€ ์ธ์Šคํ„ด์Šค์˜ ์Šคํ”„๋ง ๋นˆ์„ ๋ฐ˜ํ™˜ํ–ˆ๋‹ค. ์ด๋Š” ์‹ฑ๊ธ€ํ†ค ์Šค์ฝ”ํ”„์˜ ๋นˆ์ด ์ปจํ…Œ์ด๋„ˆ์˜ ์ƒ์„ฑ๋ถ€ํ„ฐ ์ข…๋ฃŒ๊นŒ์ง€ ํ•จ๊ป˜ํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

 

์‹ฑ๊ธ€ํ†ค ๋นˆ์€ ์˜์กด์„ฑ ์ฃผ์ž…(DI)์„ ํ•˜๋“ ์ง€ ApplicationContext๋ฅผ ์ด์šฉํ•ด์„œ ๋นˆ์„ ๋ถˆ๋Ÿฌ์˜ค๋˜์ง€ ๋งค๋ฒˆ ๊ฐ™์€ ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค. ๊ทธ๋Ÿฐ๋ฐ ๋•Œ๋กœ๋Š” ๋นˆ์„ ์‹ฑ๊ธ€ํ†ค์ด ์•„๋‹Œ ํ•˜๋‚˜์˜ ๋นˆ์œผ๋กœ ์—ฌ๋Ÿฌ๊ฐœ์˜ ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค์–ด ์‚ฌ์šฉํ•ด์•ผ ํ•  ๋•Œ๊ฐ€ ์žˆ๋‹ค.

๊ทธ๋Ÿด ๋•Œ ํ”„๋กœํ†  ํƒ€์ž… ๋นˆ์„ ์‚ฌ์šฉํ•˜๋Š”๋ฐ ํ”„๋กœํ† ํƒ€์ž… ๋นˆ์€ ์ปจํ…Œ์ด๋„ˆ์—๊ฒŒ ๋นˆ์„ ์š”์ฒญํ•  ๋•Œ๋งˆ๋‹ค ๋งค๋ฒˆ ์ƒˆ๋กœ์šด ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ๋ฐ˜ํ™˜ํ•ด์ค€๋‹ค.

 

ํ”„๋กœํ† ํƒ€์ž… ๋นˆ์˜ ๊ฒฝ์šฐ ์ƒ์„ฑ, ์˜์กด์„ฑ์ฃผ์ž…+์ดˆ๊ธฐํ™” ์ดํ›„ ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ์—์„œ ๊ด€๋ฆฌํ•˜์ง€ ์•Š๋Š”๋‹ค. ์ฆ‰ ํ˜ธ์ถœํ•  ๋•Œ ๋งˆ๋‹ค ์ƒˆ๋กœ์šด ๋นˆ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๋ฉฐ ์ข…๋ฃŒํ•  ๋•Œ๋„ ๋”ฐ๋กœ ์ปจํ…Œ์ด๋„ˆ๊ฐ€ ๊ด€๋ฆฌํ•ด์ฃผ๋Š” ์ฝœ๋ฐฑ ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋‹ค. ๋งŒ์•ฝ @PreDestory ๊ฐ™์€ ์ข…๋ฃŒ ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ์ด ํ•„์š”ํ•˜๋‹ค๋ฉด, ํ•ด๋‹น ๋นˆ์„ ์กฐํšŒํ•œ ํด๋ผ์ด์–ธํŠธ์—์„œ ๋”ฐ๋กœ ๊ด€๋ฆฌํ•ด์ฃผ์–ด์•ผ ํ•œ๋‹ค.

 


@ ์‹ฑ๊ธ€ํ†ค๊ณผ ํ”„๋กœํ† ํƒ€์ž…์„ ํ•จ๊ป˜ ์‚ฌ์šฉํ•  ๋•Œ ๋ฌธ์ œ์ 

์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ์— ํ”„๋กœํ† ํƒ€์ž… ์Šค์ฝ”ํ”„ ๋นˆ์„ ์š”์ฒญํ•˜๋ฉด ํ•ญ์ƒ ์ƒˆ๋กœ์šด ๊ฐ์ฒด ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

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

๊ฐ๊ฐ ๋‹ค๋ฅธ ์ธ์Šคํ„ด์Šค ๊ฐ์ฒด๋ฅผ ๊ฐ€์ง€๊ธฐ ๋•Œ๋ฌธ์— addCount()๋กœ ์นด์šดํŠธ๋ฅผ ์ฆ๊ฐ€์‹œ์ผœ๋„ ๊ฐ๊ฐ ๊ณ ์œ ํ•œ count๋ฅผ ๊ฐ€์ง„๋‹ค.

๋งŒ์•ฝ ์‹ฑ๊ธ€ํ†ค ๋นˆ(clientBean)์ด ์˜์กด๊ด€๊ณ„ ์ฃผ์ž…์„ ํ†ตํ•ด์„œ ํ”„๋กœํ† ํƒ€์ž… ๋นˆ(PrototypeBean)์„ ์ฃผ์ž…๋ฐ›์œผ๋ฉด ์–ด๋–ป๊ฒŒ ๋ ๊นŒ?

์ปจํ…Œ์ด๋„ˆ์—์„œ ๊ด€๋ฆฌ๋˜๋Š” ์‹ฑ๊ธ€ํ†ค ๋นˆ์—์„œ, ํ”„๋กœํ† ํƒ€์ž… ๋นˆ์„ ์ฃผ์ž…๋ฐ›์œผ๋ฉด?

  • clientBean์€ ์‹ฑ๊ธ€ํ†ค์ด๋ฏ€๋กœ, ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ ์ƒ์„ฑ ์‹œ์ ์— ํ•จ๊ป˜ ์ƒ์„ฑ๋˜๊ณ  ์˜์กด๊ด€๊ณ„ ์ฃผ์ž…๋„ ๋ฐœ์ƒํ•œ๋‹ค.
  • clientBean์€ ์˜์กด๊ด€๊ณ„ ์ž๋™ ์ฃผ์ž…์„ ์‚ฌ์šฉํ•œ๋‹ค. ์ฆ‰ ์ฃผ์ž… ์‹œ์ ์— ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ์—์„œ ํ”„๋กœํ† ํƒ€์ž… ๋นˆ์„ ์š”์ฒญํ•˜๊ฒŒ ๋œ๋‹ค.
  • ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๋Š” ํ”„๋กœํ† ํƒ€์ž… ๋นˆ์„ ์ƒ์„ฑํ•˜์—ฌ clientBean์— ๋ฐ˜ํ™˜ํ•œ๋‹ค.
  • clientBean์€ ํ”„๋กœํ† ํƒ€์ž… ๋นˆ์„ ๋‚ด๋ถ€ ํ•„๋“œ์— ๋ณด๊ด€ํ•œ๋‹ค. (์ •ํ™•ํžˆ๋Š” ์ธ์Šคํ„ด์Šค๊ฐ€ ์•„๋‹Œ ์ฐธ์กฐ๊ฐ’์„ ๋ณด๊ด€ํ•œ๋‹ค.)

์ด ์ƒํ™ฉ์—์„œ addCount()๋ฅผ ํด๋ผ์ด์–ธํŠธ๋งˆ๋‹ค ํ˜ธ์ถœํ•˜๊ฒŒ ๋˜๋ฉด ์–ด๋–ป๊ฒŒ ๋ ๊นŒ? ๊ธฐ์กด์˜ ํ”„๋กœํ† ํƒ€์ž… ๋นˆ์ฒ˜๋Ÿผ ๊ฐ๊ฐ ๊ณ ์œ ํ•œ count๊ฐ’์„ ๊ฐ€์งˆ๊นŒ?

 count ๊ฐ’์„ ํ”„๋กœํ† ํƒ€์ž… ๊ฐ์ฒด๊ฐ€ ๊ณต์œ ํ•ด์„œ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋‹ค. ์ฆ‰ ํด๋ผ์ด์–ธํŠธ๋งˆ๋‹ค ์ƒˆ๋กœ์šด ๊ฐ์ฒด๊ฐ€ ๋งŒ๋“ค์–ด์ง€์ง€ ์•Š๋Š”๋‹ค.

์•„๋‹ˆ๋‹ค. ํด๋ผ์ด์–ธํŠธ๋Š” clientBean์„ ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ์— ์š”์ฒญํ•ด์„œ ๋ฐ›๋Š”๋‹ค. ์‹ฑ๊ธ€ํ†ค ๊ฐ์ฒด์ด๋ฏ€๋กœ ํ•ญ์ƒ ๊ฐ™์€ clientBean์ด ๋ฐ˜ํ™˜๋œ๋‹ค. ์—ฌ๊ธฐ์„œ ์ค‘์š”ํ•œ ๊ฒƒ์€, clientBean์ด ๋‚ด๋ถ€์— ๊ฐ€์ง€๊ณ ์žˆ๋Š” ํ”„๋กœํ† ํƒ€์ž… ๋นˆ์€, ์ด๋ฏธ ๊ณผ๊ฑฐ์— ์ฃผ์ž…์ด ๋๋‚œ ๋นˆ์ด๋‹ค. ์ฆ‰ ์‚ฌ์šฉํ•  ๋•Œ ๋งˆ๋‹ค ์ƒˆ๋กœ ์ƒ์„ฑ๋˜์ง€ ์•Š๋Š”๋‹ค. (* ํ”„๋กœํ† ํƒ€์ž… ๋นˆ์€ ์ฃผ์ž… ์‹œ์ ์—์„œ๋งŒ ์ƒˆ๋กญ๊ฒŒ ์ƒ์„ฑ๋œ๋‹ค.)

 

์Šคํ”„๋ง์€ ์ผ๋ฐ˜์ ์œผ๋กœ ์‹ฑ๊ธ€ํ†ค ๋นˆ์„ ์‚ฌ์šฉํ•˜๋ฏ€๋กœ, ๋ณดํ†ต ์‹ฑ๊ธ€ํ†ค ๋นˆ์ด ํ”„๋กœํ† ํƒ€์ž… ๋นˆ์„ ์ฃผ์ž…๋ฐ›๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ๋‹ค. ํ•˜์ง€๋งŒ ์‹ฑ๊ธ€ํ†ค๋นˆ์€ ์ƒ์„ฑ ์‹œ์ ์—๋งŒ ์˜์กด๊ด€๊ณ„ ์ฃผ์ž…์„ ๋ฐ›๊ธฐ ๋•Œ๋ฌธ์— ์ฃผ์ž…๋ฐ›์€ ํ”„๋กœํ† ํƒ€์ž… ๋นˆ์ด ์‹ฑ๊ธ€ํ†ค ๋นˆ๊ณผ ํ•จ๊ป˜ ์œ ์ง€๋˜๋Š” ๋ฌธ์ œ๊ฐ€ ์žˆ๋‹ค.

 

ํ”„๋กœํ† ํƒ€์ž… ๋นˆ์€ ์ฃผ์ž…์‹œ์ ์—๋งŒ ์ƒˆ๋กœ ์ƒ์„ฑํ•˜๊ณ  ์‹ถ์€๊ฒŒ ์•„๋‹ˆ๋ผ, ์‚ฌ์šฉํ•  ๋•Œ ๋งˆ๋‹ค ์ƒˆ๋กœ์šด ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•ด ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฒƒ์„ ์˜๋„ํ•˜๊ณ  ๋งŒ๋“ค์—ˆ์„ ๊ฒƒ์ด๋‹ค. ์ด๋ฅผ ์–ด๋–ป๊ฒŒ ํ•˜๋ฉด ์›ํ•˜๋Š”๋Œ€๋กœ ๋™์ž‘ํ•˜๊ฒŒ ๋ฐ”๊ฟ€ ์ˆ˜ ์žˆ์„๊นŒ?

 


@ ํ•ด๊ฒฐ์ฑ…

์‚ฌ์‹ค ๊ฐ€์žฅ ๊ฐ„๋‹จํ•œ ํ•ด๊ฒฐ์ฑ…์€ ์‹ฑ๊ธ€ํ†ค ๊ฐ์ฒด์—์„œ ํ”„๋กœํ† ํƒ€์ž… ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ ๋งˆ๋‹ค ์ƒˆ๋กญ๊ฒŒ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๋ฉด ๋œ๋‹ค. ์ฐธ๊ณ ๋กœ ์ด๋ ‡๊ฒŒ ์˜์กด๊ด€๊ณ„๋ฅผ ์™ธ๋ถ€์—์„œ ์ฃผ์ž…(DI)๋ฐ›๋Š”๊ฒŒ ์•„๋‹ˆ๋ผ ๊ฐ์ฒด ๋‚ด๋ถ€์—์„œ ์ปจํ…Œ์ด๋„ˆ(App..Context)์— ์žˆ๋Š” ์˜์กด๊ด€๊ณ„๋ฅผ ์ฐพ๋Š” ๊ฒƒ์„ Dependency Lookup(DL, ์˜์กด๊ด€๊ณ„ ํƒ์ƒ‰)๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค.

class ClientBean {
    @Autowired
    private ApplicationContext ac;

    public int logic() {
    	// ๋กœ์ง์„ ์‹คํ–‰ํ•  ๋•Œ ๋งˆ๋‹ค ์ƒˆ๋กœ์šด ๊ฐ์ฒด ์ƒ์„ฑ
        PrototypeBean prototypeBean = ac.getBean(PrototypeBean.class);
        prototypeBean.addCount();
        int count = prototypeBean.getCount();
        return count;
    }
}
  • ์‹คํ–‰ํ•ด๋ณด๋ฉด logic()์„ ์‹คํ–‰ ํ•  ๋•Œ ๋งˆ๋‹ค ac.getBean()์„ ํ†ตํ•ด ์ƒˆ๋กœ์šด ํ”„๋กœํ† ํƒ€์ž… ๋นˆ์ด ์ƒ์„ฑ๋œ๋‹ค.
  • ๊ทธ๋Ÿฐ๋ฐ ์ด๋ ‡๊ฒŒ ์Šคํ”„๋ง ์•ฑ ์ปจํ…์ŠคํŠธ๋ฅผ ์ฃผ์ž…๋ฐ›๊ฒŒ ๋˜๋ฉด, ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ(App..Context)์— ์ข…์†์ ์ธ ์ฝ”๋“œ๊ฐ€ ๋งŒ๋“ค์–ด์ ธ ์œ ์ง€๋ณด์ˆ˜๊ฐ€ ์–ด๋ ต๊ณ  ๋‹จ์œ„ํ…Œ์ŠคํŠธ๋„ ๋งค์šฐ ๊นŒ๋‹ค๋กœ์›Œ์ง„๋‹ค.
  • ๊ทธ๋ ‡๋‹ค๋ฉด ์Šคํ”„๋ง์—์„œ Denpendency Lookup์„ ํ•ด์ฃผ๋Š” ๊ธฐ๋Šฅ์€ ์—†์„๊นŒ?

 


@ ObjectFactory, ObjectProvider

์ง€์ •ํ•œ ๋นˆ์„ ์ปจํ…Œ์ด๋„ˆ์—์„œ ๋Œ€์‹  ์ฐพ์•„์ฃผ๋Š” DL์„œ๋น„์Šค๋ฅผ ์ œ๊ณตํ•ด์ฃผ๋Š” ๊ฒƒ์ด ๋ฐ”๋กœ ObjectProvider ์ด๋‹ค. ๊ณผ๊ฑฐ์—๋Š” ObjectFactory๋ฅผ ์‚ฌ์šฉํ–ˆ๋Š”๋ฐ, ์—ฌ๊ธฐ์— ์—ฌ๋Ÿฌ ํŽธ์˜ ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•˜์—ฌ ๋งŒ๋“  ๊ฒƒ์ด ObjectProvider์ด๋‹ค. ์ด๋Š” ์Šคํ”„๋ง์—์„œ ์ œ๊ณตํ•˜๋Š” ๊ธฐ๋Šฅ์ด๋ผ ๋ณ„๋„์˜ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ํ•„์š”ํ•˜์ง€ ์•Š๊ณ , ๋ฐ”๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. (๋Œ€์‹  ์Šคํ”„๋ง์— ์˜์กด์ ์ด๋‹ค. ๋‹ค๋ฅธ๊ณณ์—์„œ ์‚ฌ์šฉX)

  • ObjectProvider : ObjectFactory๋ฅผ ์ƒ์†, ์˜ต์…˜์ด๋‚˜ ์ŠคํŠธ๋ฆผ ์ฒ˜๋ฆฌ๋“ฑ ํŽธ์˜๊ธฐ๋Šฅ ์ œ๊ณต. ๋ณ„๋„์˜ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ํ•„์š”์—†์Œ. 
static class ClientBean {
  @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)
  • ์Šคํ”„๋ง์ด ์ œ๊ณตํ•˜๋Š” ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜์ง€๋งŒ, ๊ธฐ๋Šฅ์ด ๋‹จ์ˆœํ•ด์„œ ๋‹จ์œ„ํ…Œ์ŠคํŠธ๋ฅผ ๋งŒ๋“ค๊ฑฐ๋‚˜ mock ์ฝ”๋“œ(๊ฐ€์งœ ๊ฐ์ฒด๋ฅผ ์ด์šฉํ•œ ํ…Œ์ŠคํŠธ)๋ฅผ ๋งŒ๋“ค๊ธฐ ์‰ฝ๋‹ค.

* ApplicationContext๋ฅผ mock์œผ๋กœ ๋งŒ๋“ค๋ ค๋ฉด ๊ทธ๊ณณ์— ์žˆ๋Š” ์ˆ˜ ๋งŽ์€ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋ชจ๋‘ ๊ตฌํ˜„ํ•ด์•ผ ํ•œ๋‹ค. ๋ฐ˜๋ฉด์— ObjectProvider๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๊ทธ ๊ณณ์—์„œ ์ œ๊ณตํ•˜๋Š” ๋งค์šฐ ์ ์€ ์ธํ„ฐํŽ˜์ด์Šค๋งŒ ๊ตฌํ˜„ํ•ด๋„ ๋˜๋ฏ€๋กœ ํ…Œ์ŠคํŠธ๋‚˜ mock์„ ์ƒ๋Œ€์ ์œผ๋กœ ์‰ฝ๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.

 


@ JSR-330 Provider (JSR-330 ์ž๋ฐ” ํ‘œ์ค€)

๋‹ค๋งŒ ์œ„์˜ ObjectProvider๋Š” ์Šคํ”„๋ง ํ”„๋ ˆ์ž„์›Œํฌ์—์„œ๋งŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š”, ์Šคํ”„๋ง์— ์˜์กด์ ์ธ ๋ฐฉ๋ฒ•์ด์—ˆ๋‹ค. ์˜์กด์ ์ด์ง€ ์•Š๊ฒŒ ์ž๋ฐ” ํ‘œ์ค€(javax.inject.Provider)์„ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ์•„๋ณด์ž.

 

์ฐธ๊ณ ๋กœ ์Šคํ”„๋ง ํ”„๋ ˆ์ž„์›Œํฌ์—์„œ ํ•ด๋‹น ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜๋ ค๋ฉด build.gradle์— ์•„๋ž˜์™€ ๊ฐ™์€ ์„ค์ •์„ ์ถ”๊ฐ€ํ•ด์ฃผ๋ฉด ๋œ๋‹ค.

implementation 'javax.inject:javax.inject:1'
  • ์•„๋ž˜ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•ด๋ณด๋ฉด provider.get()์„ ํ†ตํ•ด ํ•ญ์ƒ ์ƒˆ๋กœ์šด ํ”„ํ† ํ† ํƒ€์ž… ๋นˆ์ด ์ƒ์„ฑ๋œ๋‹ค.
  • ObjectProvider์™€ ๋น„์Šทํ•˜๊ฒŒ provider์˜ get()์„ ํ˜ธ์ถœํ•˜๋ฉด ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ์—์„œ ํ•ด๋‹น ๋นˆ์„ ์ฐพ์•„ ๋ฐ˜ํ™˜ํ•œ๋‹ค(DL)
  • ์ด๋Š” ์Šคํ”„๋ง์˜ ๊ธฐ๋Šฅ์ด ์•„๋‹Œ ์ž๋ฐ” ํ‘œ์ค€์ด๊ธฐ์— ๋‹จ์œ„ํ…Œ์ŠคํŠธ๋‚˜ ์ฝ”๋“œ์˜ ์œ ์—ฐ์„ฑ์ด ํ›จ์”ฌ ์ข‹๋‹ค.
  • get() ๋ฉ”์„œ๋“œ ํ•˜๋‚˜๋กœ ๊ธฐ๋Šฅ์ด ๋งค์šฐ ๋‹จ์ˆœํ•˜๋ฉฐ, ์ž๋ฐ” ํ‘œ์ค€์ด๋ฏ€๋กœ ์Šคํ”„๋ง์ด ์•„๋‹Œ ๋‹ค๋ฅธ ์ปจํ…Œ์ด๋„ˆ์—์„œ๋„ ์‚ฌ์šฉ๊ฐ€๋Šฅํ•˜๋‹ค.
  • ๋‹ค๋งŒ ๋ณ„๋„์˜ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ (javax.inject)๊ฐ€ ํ•„์š”ํ•˜๋‹ค.
package javax.inject;
public interface Provider<T> {
 T get();
}
//implementation 'javax.inject:javax.inject:1' gradle ์ถ”๊ฐ€ ํ•„์ˆ˜
static class ClientBean {

    @Autowired
    private Provider<PrototypeBean> provider;

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

 


@ ์ •๋ฆฌ

์‚ฌ์‹ค ์‹ค๋ฌด์—์„œ ์›น ์•ฑ์„ ๊ฐœ๋ฐœํ•˜๋‹ค๋ณด๋ฉด, ๋Œ€๋ถ€๋ถ„ ์‹ฑ๊ธ€ํ†ค ๋นˆ์œผ๋กœ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๊ธฐ์— ํ”„๋กœํ† ํƒ€์ž… ๋นˆ์„ ์‚ฌ์šฉํ•˜๋Š” ์ผ์€ ๋“œ๋ฌผ๋‹ค. ํ•˜์ง€๋งŒ ์œ„์—์„œ ๋ฐฐ์šด ObjectProvider, javax.inject.Provider๋Š” ํ”„๋กœํ† ํƒ€์ž… ๋นˆ ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ์œ„์™€ ๊ฐ™์ด ์ปจํ…Œ์ด๋„ˆ์—์„œ ํ•„์š”ํ•œ ์˜์กด์„ฑ์„ ์ฐพ์•„ ์ง์ ‘ ์ฃผ์ž…ํ•˜๋Š” DL(Dependency Lookup)์ด ํ•„์š”ํ•œ ๊ฒฝ์šฐ ์–ธ์ œ๋“ ์ง€ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋Šฅ์ด๋‹ค.

 

๋˜ํ•œ Provider๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ์‹œ์ ๊นŒ์ง€ ๋นˆ ์ƒ์„ฑ์„ ์ง€์—ฐ์‹œํ‚ฌ ์ˆ˜ ์žˆ์–ด์„œ, ์•„๋ž˜์˜ ์›น ์Šค์ฝ”ํ”„์—์„œ ์‚ฌ์šฉํ•˜๊ธฐ ์ข‹๋‹ค. (๋นˆ ์Šค์ฝ”ํ”„๊ฐ€ ์ปจํ…Œ์ด๋„ˆ์™€ ํ•จ๊ป˜ ๋นˆ์„  ์ƒ์„ฑํ•˜์ง€ ์•Š๊ณ  ๊ณ ๊ฐ์˜ ์š”์ฒญ์ด ๋“ค์–ด์™€์•ผ ์‹œ์ž‘ํ•˜๊ธฐ ๋•Œ๋ฌธ.)

 

* ObjectProvider๋Š” DL์„ ์œ„ํ•œ ํŽธ์˜ ๊ธฐ๋Šฅ์„ ๋งŽ์ด ์ œ๊ณตํ•ด์ฃผ๊ณ , ์Šคํ”„๋ง์„ ์‚ฌ์šฉํ•˜๋ฉด ๋ณ„๋„์˜ ์„ค์ •์—†์ด ๋ฐ”๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์–ด ํ›จ์”ฌ ํŽธ๋ฆฌํ•˜๋‹ค. ๋งŒ์•ฝ ๋‹ค๋ฅธ ์ปจํ…Œ์ด๋„ˆ์—๋„ ์‚ฌ์šฉ ํ•  ์ˆ˜ ์žˆ๊ฒŒ ์„ค๊ณ„ํ•ด์•ผํ•œ๋‹ค๋ฉด ์ž๋ฐ” ํ‘œ์ค€ Provider๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค. ๊ทผ๋ฐ ๋ณดํ†ต ๊ทธ๋Ÿฐ ์ผ์€ ์ž˜ ์—†๊ธดํ•˜๋‹ค.


* ์ฐธ๊ณ ๋กœ ์Šคํ”„๋ง์ด ์ œ๊ณตํ•˜๋Š” ๋ฉ”์„œ๋“œ์— @Lookup ์–ด๋…ธํ…Œ์ด์…˜์ด ์žˆ๊ธด ํ•˜์ง€๋งŒ, ์ด์ „ ๋ฐฉ๋ฒ•๋“ค๋กœ ์ถฉ๋ถ„ํ•˜๊ธฐ๋„ ํ•˜๊ณ  ํ•ด๋‹น ์–ด๋…ธํ…Œ์ด์…˜์€ ์‚ฌ์šฉ์‹œ ์กฐ์‹ฌํ•ด์•ผ ๋  ๋ถ€๋ถ„์ด ๋งŽ์•„์„œ ๊ตณ์ด ์„ค๋ช…ํ•˜์ง€๋Š” ์•Š๊ฒ ๋‹ค. ์“ฐ์ง€๋ง์ž.

@Component
@Scope("prototype")
public class SchoolNotification {
    // ... prototype-scoped state
}

// @Lookup์„ ๋‹ฌ๋ฉด, ๋งค๋ฒˆ ์ƒˆ๋กญ๊ฒŒ ์ƒ์„ฑํ•ด์ค€๋‹ค.
@Component
public class StudentServices {

    // ... member variables, etc.

    @Lookup
    public SchoolNotification getNotification() {
        return null;
    }

    // ... getters and setters
}

์ฐธ๊ณ ๋กœ ์ด๋ ‡๊ฒŒ @Lookup๋“ฑ์„ ์‚ฌ์šฉํ•˜๋ฉด, ์‹ฑ๊ธ€ํ†ค ๊ฐ์ฒด์—๋Š” ํ”„๋ก์‹œ๊ฐ€ ์‚ฝ์ž…๋˜์–ด ์žˆ๋‹ค.
๊ทธ๋ฆฌ๊ณ  ์•„๋ž˜์™€ ๊ฐ™์ด ์‚ฌ์šฉํ•  ๋•Œ ๋งˆ๋‹ค ํ•ด๋‹น ํ”„๋ก์‹œ์—์„œ new Prototype ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•ด์ฃผ๋Š” ํ˜•์‹.

 


# ์›น ์Šค์ฝ”ํ”„

์›น ์Šค์ฝ”ํ”„๋Š” ์›น ํ™˜๊ฒฝ์—์„œ๋งŒ ๋™์ž‘ํ•œ๋‹ค. ์›น ์Šค์ฝ”ํ”„๋Š” ํ”„๋กœํ† ํƒ€์ž…๊ณผ๋Š” ๋‹ค๋ฅด๊ฒŒ ์Šคํ”„๋ง์ด ํ•ด๋‹น ์Šค์ฝ”ํ”„์˜ ์ข…๋ฃŒ์‹œ์ ๊นŒ์ง€ ๊ด€๋ฆฌํ•œ๋‹ค. (=์ข…๋ฃŒ ๋ฉ”์„œ๋“œ๊ฐ€ ํ˜ธ์ถœ๋œ๋‹ค.) ๊ธฐ์กด์— ์‚ฌ์šฉํ•˜๋˜ ์‹ฑ๊ธ€ํ†ค ๋นˆ์€ ์Šคํ”„๋ง ์•ฑ์ด ์‹คํ–‰ํ•˜๋Š” ์‹œ์ ์— ์ƒ์„ฑํ•ด์„œ ์ฃผ์ž…์ด ๊ฐ€๋Šฅํ•˜์ง€๋งŒ, ์›น ์Šค์ฝ”ํ”„ ๋นˆ์€ ์‹ค์ œ ์š”์ฒญ์ด ๋“ค์–ด์™€์•ผ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.

 

์ฐธ๊ณ ๋กœ ์Šคํ”„๋ง ๋ถ€ํŠธ์—์„œ๋Š” ์•„๋ž˜์™€ ๊ฐ™์ด ์›น ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‰ฝ๊ฒŒ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ๋‹ค. ์›น ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ์ถ”๊ฐ€๋˜๋ฉด ๊ธฐ์กด์— ์‚ฌ์šฉํ•˜๋˜ ์ปจํ…Œ์ด๋„ˆ ๊ตฌํ˜„์ฒด(AnnotationConfigApp..Context) ๋Œ€์‹ ์— AnnotationConfigServletWebServerApplicationContext๋ฅผ ์‚ฌ์šฉํ•˜๋„๋ก ๋ฐ”๋€๋‹ค. ์ด๋Š” ์›น๊ณผ ๊ด€๋ จ๋œ ์ถ”๊ฐ€ ์„ค์ •๋“ค๊ณผ ํ™˜๊ฒฝ์„ ์ œ๊ณตํ•ด์ค€๋‹ค.

//web ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ถ”๊ฐ€
implementation 'org.springframework.boot:spring-boot-starter-web'

์ด๋Š” ์›น MVC๋ฅผ ๊ณต๋ถ€ํ•˜๊ฒŒ๋˜๋ฉด ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ์ดํ•ด๊ฐ€ ๋œ๋‹ค.

@Component
@Scope(value = "request") // ์›น request ์Šค์ฝ”ํ”„
public class MyLogger {
	public void setRequestURL(String requestURL) {
        this.requestURL = requestURL; // ๊ฐ์ฒด ์ƒ์„ฑ ์ดํ›„ ์™ธ๋ถ€์—์„œ setter๋กœ ์ฃผ์ž…๋ฐ›๋Š”๋‹ค.
    }

	... ์ƒ๋žต ...
    
    @PostConstruct // request ์š”์ฒญ์ด ๋“ค์–ด์˜ฌ ๋•Œ, ๋นˆ ์ƒ์„ฑ
    public void init() {
        uuid = UUID.randomUUID().toString(); // UUID๋ฅผ ์ด์šฉํ•ด ๊ฐ ์š”์ฒญ์„ ๊ตฌ๋ถ„
        System.out.println("[" + uuid + "] request scope bean create:" + this);
    }

    @PreDestroy // ์ž‘์—… ์ข…๋ฃŒ. ๋นˆ ์†Œ๋ฉธ
    public void close() {
        System.out.println("[" + uuid + "] request scope bean close:" + this);
    }
}

 

์œ„ ์ฝ”๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด HTTP Request ์š”์ฒญ์ด ์˜ฌ ๋•Œ ๋งˆ๋‹ค ์•„๋ž˜์™€ ๊ฐ™์€ ์ฝ˜์†” ๋กœ๊ทธ๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ๋‹ค. 

[d06b992f...] request scope bean create
// ์ž‘์—… ์‹œ์ž‘
[d06b992f...][http:\\localhost:8080\log-demo] controller test
[d06b992f...][http:\\localhost:8080\log-demo] service id = testId
// ์ž‘์—… ๋
[d06b992f...] request scope bean close

 


@ ์›น ์Šค์ฝ”ํ”„ ์ข…๋ฅ˜

์„ธ์…˜, ์„œ๋ธ”๋ฆฟ ์ปจํ…์ŠคํŠธ, ์›น ์†Œ์ผ“ ๊ฐ™์€ ์šฉ์–ด๋ฅผ ์•ˆ๋‹ค๋ฉด ์‰ฝ๊ฒŒ ์ดํ•ดํ•  ์ˆ˜ ์žˆ๋‹ค. ์•„๋ž˜์˜ ์Šค์ฝ”ํ”„๋“ค๋„ ๊ฒฐ๊ตญ ์ ์šฉ๋ฒ”์œ„๋งŒ ๋‹ค๋ฅผ ๋ฟ, ์œ„ ์˜ˆ์ œ์˜ requset์™€ ํฌ๊ฒŒ ๋‹ค๋ฅด์ง€์•Š๋‹ค.

@Component
@Scope(value = "request") // ์›น request ์Šค์ฝ”ํ”„
public class MyLogger {...}
  • request : HTTP ์š”์ฒญ ํ•˜๋‚˜๊ฐ€ ๋“ค์–ด์˜ค๊ณ  ๋‚˜๊ฐˆ ๋•Œ ๊นŒ์ง€ ์œ ์ง€๋˜๋Š” ์Šค์ฝ”ํ”„, ๊ฐ๊ฐ์˜ 'HTTP ์š”์ฒญ๋งˆ๋‹ค' ๋ณ„๋„์˜ ๋นˆ
    ์ธ์Šคํ„ด์Šค๊ฐ€ ์ƒ์„ฑ๋˜๊ณ , ๊ด€๋ฆฌ๋œ๋‹ค. ์ฆ‰ ๊ฐ™์€ ์š”์ฒญ์ด๋ฉด ๊ฐ™์€ ์ธ์Šคํ„ด์Šค๊ฐ€ ๋‹ด๋‹นํ•˜๊ฒŒ ๋งŒ๋“ค์–ด์ค€๋‹ค.
  • session : HTTP Session๊ณผ ๋™์ผํ•œ ์ƒ๋ช…์ฃผ๊ธฐ๋ฅผ ๊ฐ€์ง€๋Š” ์Šค์ฝ”ํ”„
  • application : ์„œ๋ธ”๋ฆฟ ์ปจํ…์ŠคํŠธ( ServletContext )์™€ ๋™์ผํ•œ ์ƒ๋ช…์ฃผ๊ธฐ๋ฅผ ๊ฐ€์ง€๋Š” ์Šค์ฝ”ํ”„
  • websocket : ์›น ์†Œ์ผ“๊ณผ ๋™์ผํ•œ ์ƒ๋ช…์ฃผ๊ธฐ๋ฅผ ๊ฐ€์ง€๋Š” ์Šค์ฝ”ํ”„

์‚ฌ์‹ค ์Šค์ฝ”ํ”„๋ฅผ ์ง€์ •ํ•˜์ง€ ์•Š๊ณ  ์‚ฌ์šฉํ•œ๋‹ค๊ณ  ํ•ด์„œ, ๊ฐ‘์ž๊ธฐ ๋ฌธ์ œ๊ฐ€ ์ƒ๊ธฐ์ง€๋Š” ์•Š๋Š”๋‹ค. ํ•˜์ง€๋งŒ request scope๋“ฑ์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  ํŒŒ๋ผ๋ฉ”ํƒ€๋กœ ๋ชจ๋“  ์ •๋ณด๋ฅผ ์„œ๋น„์Šค ๊ณ„์ธต(๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์ด ์žˆ๋Š” ๊ณณ)์— ๋„˜๊ธด๋‹ค๋ฉด ๊ด€๋ฆฌํ•˜๋Š” ํŒŒ๋ผ๋ฉ”ํƒ€๊ฐ€ ๋งŽ์•„ ์ง€์ €๋ถ„ํ•ด์ง„๋‹ค.

 

๋” ๋ฌธ์ œ๋Š” requestURL ๊ฐ™์€ ์›น๊ณผ ๊ด€๋ จ๋œ ์ •๋ณด๊ฐ€, ์ „ํ˜€ ๊ด€๋ จ์—†๋Š” ๋น„์ฆˆ๋‹ˆ์Šค ์„œ๋น„์Šค ๊ณ„์ธต๊นŒ์ง€ ๋„˜์–ด๊ฐ„๋‹ค๋Š” ๊ฒƒ์ด๋‹ค. ์›น๊ณผ ๊ด€๋ จ๋œ ๋ถ€๋ถ„์€ ์ปจํŠธ๋กค๋Ÿฌ๊นŒ์ง€๋งŒ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค. ์„œ๋น„์Šค ๊ณ„์ธต์€ ์›น ๊ธฐ์ˆ ์— ์ข…์†๋˜์ง€์•Š๊ณ  ๊ณ„์ธต์„ ๋ถ„๋ฆฌํ•ด์„œ ๋งŒ๋“œ๋Š” ๊ฒƒ์ด ์œ ์ง€๋ณด์ˆ˜๋‚˜ ํ™•์žฅ์— ์ข‹๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

 


# ์Šค์ฝ”ํ”„์™€ ํ”„๋ก์‹œ

๋˜ํ•œ Provider๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ์‹œ์ ๊นŒ์ง€ ๋นˆ ์ƒ์„ฑ์„ ์ง€์—ฐ์‹œํ‚ฌ ์ˆ˜ ์žˆ์–ด์„œ, ์•„๋ž˜์˜ ์›น ์Šค์ฝ”ํ”„์—์„œ ์‚ฌ์šฉํ•˜๊ธฐ ์ข‹๋‹ค. (๋นˆ ์Šค์ฝ”ํ”„๊ฐ€ ์ปจํ…Œ์ด๋„ˆ์™€ ํ•จ๊ป˜ ๋นˆ์„  ์ƒ์„ฑํ•˜์ง€ ์•Š๊ณ  ๊ณ ๊ฐ์˜ ์š”์ฒญ์ด ๋“ค์–ด์™€์•ผ ์‹œ์ž‘ํ•˜๊ธฐ ๋•Œ๋ฌธ.)

์‚ฌ์‹ค ์ด๋Š” Provider ๋Œ€์‹  ํ”„๋ก์‹œ๋ฅผ ์ด์šฉํ•ด์„œ ๋” ๊ฐ„๋‹จํ•˜๊ฒŒ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.

ํ”„๋ก์‹œ ์ž์ฒด๋ฅผ ์ž˜ ๋ชจ๋ฅธ๋‹ค๋ฉด, ๋‚˜์ค‘์— ๋‹ค์‹œ ์•Œ์•„๋ณด๋„๋กํ•˜๊ณ  ์ด๋Ÿฐ ๋ฐฉ๋ฒ•์ด ์žˆ๋‹ค๋Š” ๊ฒƒ๋งŒ ๊ธฐ์–ตํ•˜๊ณ  ์žˆ์ž. ํ”„๋ก์‹œ๋Š” ์•„๋ž˜์™€ ๊ฐ™์ด proxyMode๋ฅผ ์ด์šฉํ•ด์„œ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋‹ค. 

@Component
@Scope(value = "request", proxyMode = ScopedProxyMode.TARGET_CLASS)
    public class MyLogger {
}
  • ์ ์šฉ ๋Œ€์ƒ์ด ์ธํ„ฐํŽ˜์ด์Šค๋ฉด .INTERFACES ๋ฅผ ์„ ํƒํ•˜๋ฉด ๋œ๋‹ค.
  • ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด MyLogger์˜ ๊ฐ€์งœ ํ”„๋ก์‹œ ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค์–ด๋‘๊ณ  HTTP request์™€ ์ƒ๊ด€ ์—†์ด ๊ฐ€์งœ ํ”„๋ก์‹œ ํด๋ž˜์Šค๋ฅผ ๋‹ค๋ฅธ ๋นˆ์— ๋ฏธ๋ฆฌ ์ฃผ์ž…ํ•ด ๋‘˜ ์ˆ˜ ์žˆ๋‹ค. ์šฐ๋ฆฌ๋Š” Provider๋ฅผ ์‹ ๊ฒฝ์“ฐ์ง€ ์•Š๊ณ , ํด๋ž˜์Šค ์‚ฌ์šฉํ•˜๋“ฏ์ด ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค.
  • ์˜์กด๊ด€๊ณ„ ์ฃผ์ž…๋„ ๊ฐ€์งœ ํ”„๋ก์‹œ ๊ฐ์ฒด๊ฐ€ ์ฃผ์ž…๋˜๊ฒŒ ๋œ๋‹ค.

 


@ Provider๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•

@Controller
@RequiredArgsConstructor
public class LogDemoController {
    private final LogDemoService logDemoService;
    private final ObjectProvider<MyLogger> myLoggerProvider;

    @RequestMapping("log-demo")
    @ResponseBody
    public String logDemo(HttpServletRequest request) {
        String requestURL = request.getRequestURL().toString();
        MyLogger myLogger = myLoggerProvider.getObject();
        myLogger.setRequestURL(requestURL);
        myLogger.log("controller test");
        logDemoService.logic("testId");
        return "OK";
    }
}
@Service
@RequiredArgsConstructor
public class LogDemoService {
    private final ObjectProvider<MyLogger> myLoggerProvider;

    public void logic(String id) {
        MyLogger myLogger = myLoggerProvider.getObject();
        myLogger.log("service id = " + id);
    }
}

 


@ ํ”„๋ก์‹œ(MyLogger์˜ ๊ฐ€์งœ ํ”„๋ก์‹œ ํด๋ž˜์Šค)๋ฅผ ์ด์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•

@Controller
@RequiredArgsConstructor
public class LogDemoController {
    private final LogDemoService logDemoService;
    private final MyLogger myLogger; // myLogger๋ฅผ ๋งˆ์น˜ ํด๋ž˜์Šค์ฒ˜๋Ÿผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋‹ค.

    @RequestMapping("log-demo")
    @ResponseBody
    public String logDemo(HttpServletRequest request) {
        String requestURL = request.getRequestURL().toString();
        myLogger.setRequestURL(requestURL); // ๋ฐ”๋กœ ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
        myLogger.log("controller test");
        logDemoService.logic("testId");
        return "OK";
    }
}
@Service
@RequiredArgsConstructor
public class LogDemoService {
    private final MyLogger myLogger;

    public void logic(String id) { // Provider๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ ๋„ ๋™์ผํ•˜๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
        myLogger.log("service id = " + id);
    }
}

 


@ ์ด๊ฒŒ ์–ด๋–ป๊ฒŒ ๊ฐ€๋Šฅํ•œ๊ฑธ๊นŒ?

์ด๋Š” ๊ฐ€์งœ ํ”„๋ก์‹œ ๊ฐ์ฒด(myLogger)๋ฅผ ์ฝ˜์†”์ฐฝ์— ์ฐ์–ด๋ณด๋ฉด ์–ด๋–ป๊ฒŒ ๊ฐ€๋Šฅํ•œ์ง€ ์•Œ ์ˆ˜ ์žˆ๋‹ค.

System.out.println("myLogger = " + myLogger.getClass());
// myLogger = class hello.core.common.MyLogger$$EnhancerBySpringCGLIB$$b68b726d

CGLIB๋ผ๋Š” ๋ฐ”์ดํŠธ์ฝ”๋“œ ์กฐ์ž‘ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋กœ ๋‚ด ํด๋ž˜์Šค๋ฅผ ์ƒ์†๋ฐ›์€ "๊ฐ€์งœ ํ”„๋ก์‹œ ๊ฐ์ฒด"๋ฅผ ๋งŒ๋“ค์–ด์„œ ๋Œ€์‹  ์ฃผ์ž…ํ•œ๋‹ค.

  • @Scope ์˜ proxyMode = ScopedProxyMode.TARGET_CLASS) ๋ฅผ ์„ค์ •ํ•˜๋ฉด ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๋Š” CGLIB ๋ผ๋Š” ๋ฐ”์ดํŠธ์ฝ”๋“œ๋ฅผ ์กฐ์ž‘ํ•˜๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•ด์„œ, MyLogger๋ฅผ ์ƒ์†๋ฐ›์€ ๊ฐ€์งœ ํ”„๋ก์‹œ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•œ๋‹ค
  • ๋กœ๊ทธ๋ฅผ ์ฐ์–ด๋ณด๋ฉด MyLogger๋ฅผ ์ƒ์†๋ฐ›์€ MyLogger$$EnhancerBySpringCGLIB๊ฐ€ ์ƒ์„ฑ๋จ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค.
  • ๊ทธ๋ฆฌ๊ณ  ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ์— "MyLogger"๋ผ๋Š” ์ด๋ฆ„์œผ๋กœ ์ง„์งœ ๋Œ€์‹ ์— ์ด ๊ฐ€์งœ ํ”„๋ก์‹œ ๊ฐ์ฒด๋ฅผ ๋“ฑ๋กํ•œ๋‹ค.
  • ac.getBean("myLogger", MyLogger.class)๋กœ ์กฐํšŒํ•ด๋„ ์ด ๊ฐ€์งœ ํ”„๋ก์‹œ ๊ฐ์ฒด๊ฐ€ ์กฐํšŒ๋˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ์ฆ‰ ์˜์กด๊ด€๊ณ„ ์ฃผ์ž… ๋˜ํ•œ ์ด ๊ฐ€์งœ ๊ฐ์ฒด๊ฐ€ ์ฃผ์ž…๋œ๋‹ค.

๋‹ค์‹œ ์•„๋ž˜ ๊ทธ๋ฆผ์„ ์‚ดํŽด๋ณด์ž.

๊ฐ€์งœ ํ”„๋ก์‹œ ๊ฐ์ฒด๋Š” ์š”์ฒญ์ด ์˜ค๋ฉด ๊ทธ๋–„ ๋‚ด๋ถ€์—์„œ ์ง„์งœ ๋นˆ์„ ์š”์ฒญํ•˜๋Š” ์œ„์ž„๋กœ์ง์ด ๋“ค์–ด์žˆ๋‹ค.

  • ํด๋ผ์ด์–ธํŠธ๊ฐ€ myLogger.logic()์„ ํ˜ธ์ถœํ•˜๋ฉด ์ค‘๊ฐ„์— ์žˆ๋Š” ๊ฐ€์งœ ํ”„๋ก์‹œ ๊ฐ์ฒด์˜ logic()์ด ํ˜ธ์ถœ๋œ๋‹ค.
  • ๊ฐ€์งœ ํ”„๋ก์‹œ ๊ฐ์ฒด๋Š” request ์Šค์ฝ”ํ”„์˜ ์ง„์งœ myLogger.logic()์„ ํ˜ธ์ถœํ•œ๋‹ค.
  • ๊ฐ€์งœ ํ”„๋ก์‹œ ๊ฐ์ฒด๋Š” ์›๋ณธ์„ ์ƒ์†๋ฐ›์•„ ๋งŒ๋“ค์—ˆ๊ธฐ์—, ํด๋ผ์ด์–ธํŠธ ์ž…์žฅ์—์„œ ํ”„๋ก์‹œ์˜ ์กด์žฌ๋ฅผ ๋ชฐ๋ผ๋„ ๋™์ผํ•˜๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. (๋‹คํ˜•์„ฑ)
  • ๊ฐ€์งœ ํ”„๋ก์‹œ ๊ฐ์ฒด๋Š” ์›๋ณธ์ด requset ์Šค์ฝ”ํ”„๋˜ ๋ง๋˜ ์ „ํ˜€ ์ƒ๊ด€์—†๋‹ค. ๋‚ด๋ถ€์—๋Š” ๋‹จ์ˆœํ•œ ์œ„์ž„ ๋กœ์ง๋งŒ ์žˆ๊ณ , ์‹ฑ๊ธ€ํ†ค์ฒ˜๋Ÿผ ๋™์ž‘ํ•œ๋‹ค.

@ ํ”„๋ก์‹œ์˜ ์žฅ์ 

Scope์— ํ”„๋ก์‹œ ๋ชจ๋“œ๋ฅผ ์ง€์ •ํ•ด์ฃผ๋ฉด, ์•„๋ž˜์™€ ๊ฐ™์€ ๋™์ž‘์ด ์ผ์–ด๋‚œ๋‹ค.

  • CGLIB๋ผ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋กœ ๋ฐ”์ดํŠธ์ฝ”๋“œ๋ฅผ ์กฐ์ž‘ํ•ด, ๋‚ด ํด๋ž˜์Šค๋ฅผ ์ƒ์†๋ฐ›์€ ๊ฐ€์งœ ํ”„๋ก์‹œ ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค์–ด ์ฃผ์ž…ํ•œ๋‹ค.
  • ์ด ๊ฐ€์งœ ํ”„๋ก์‹œ ๊ฐ์ฒด๋Š” ์‹ค์ œ ์š”์ฒญ์ด ์˜ค๋ฉด ๊ทธ๋•Œ ๋‚ด๋ถ€์—์„œ ์‹ค์ œ ๋นˆ์„ ์š”์ฒญํ•˜๋Š” ์œ„์ž„ ๋กœ์ง์ด ๋“ค์–ด๊ฐ€์žˆ๋‹ค.
  • ๊ฐ€์งœ ํ”„๋ก์‹œ ๊ฐ์ฒด๋Š” ๋ง ๊ทธ๋Œ€๋กœ ๊ฐ€์งœ์ด๊ธฐ์— ์‹ค์ œ ๊ฐ์ฒด์˜ scope์™€๋Š” ์ „ํ˜€ ์ƒ๊ด€์—†๋‹ค. ์‹ฑ๊ธ€ํ†ค ์Šค์ฝ”ํ”„๋กœ ์‚ฌ์šฉ๋œ๋‹ค.

 

์ด๋ ‡๊ฒŒ ํ”„๋ก์‹œ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด์„œ ์•„๋ž˜์™€ ๊ฐ™์€ ์žฅ์ ์„ ์–ป์„ ์ˆ˜ ์žˆ๋‹ค.

  • ํ”„๋ก์‹œ ๊ฐ์ฒด ๋•๋ถ„์— ํด๋ผ์ด์–ธํŠธ๋Š” ๋งˆ์น˜ ์‹ฑ๊ธ€ํ†ค ๋นˆ์„ ์‚ฌ์šฉํ•˜๋“ฏ requset scope๋ฅผ ์ด์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ์–ด๋…ธํ…Œ์ด์…˜ ์„ค์ • ๋ณ€๊ฒฝ๋งŒ์œผ๋กœ ์›๋ณธ ๊ฐ์ฒด๋ฅผ ํ”„๋ก์‹œ ๊ฐ์ฒด๋กœ ๋Œ€์ฒดํ•  ์ˆ˜ ์žˆ๋‹ค. (๋‹คํ˜•์„ฑ๊ณผ DI ์ปจํ…Œ์ด๋„ˆ์˜ ์žฅ์ )
  • ์›น ์Šค์ฝ”ํ”„๊ฐ€ ์•„๋‹ˆ๋”๋ผ๋„, ํ”„๋ก์‹œ๊ฐ€ ํ•„์š”ํ•œ ๊ฒฝ์šฐ ์‰ฝ๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

 

์‚ฌ์‹ค Provider๋ฅผ ์‚ฌ์šฉํ•˜๋“ , ํ”„๋ก์‹œ๋ฅผ ์‚ฌ์šฉํ•˜๋“  ํ•„์š”ํ•œ ๊ฒƒ์€ ์ง„์งœ ๊ฐ์ฒด ์กฐํšŒ๋ฅผ ๊ผญ ํ•„์š”ํ•œ ์‹œ์ ๊นŒ์ง€ ์ง€์—ฐ์ฒ˜๋ฆฌ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•œ๋‹ค๋Š” ์ ์ด๋‹ค. ์ด๋Š” ์š”์ฒญ์ด ๋“ค์–ด์˜ฌ ๋•Œ ๋นˆ์„ ์ƒ์„ฑํ•˜๋Š” ์›น ์Šค์ฝ”ํ”„๋ฅผ ๋งˆ์น˜ '์‹ฑ๊ธ€ํ†ค์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ' ์ฒ˜๋Ÿผ ๋งŒ๋“ค์–ด ์ฃผ๋Š” ๊ฒƒ์ด์ง€, ๊ฒฐ๊ตญ์—๋Š” ๋‹ค๋ฅด๊ฒŒ ๋™์ž‘ํ•œ๋‹ค๋Š” ๊ฑธ ์œ ์˜ํ•˜์ž.

 

๋˜ํ•œ ํ”„๋ก์‹œ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์ด๋ ‡๊ฒŒ ํŠน์ˆ˜ํ•œ Scope๋ฅผ ๋„ˆ๋ฌด ๋งŽ์ด ๋งŒ๋“ค๊ฒŒ ๋˜๋ฉด ์œ ์ง€๋ณด์ˆ˜๊ฐ€ ์–ด๋ ค์›Œ์ง„๋‹ค๋Š” ๊ฑธ ๋ช…์‹ฌํ•˜์ž.

๋ธ”๋กœ๊ทธ์˜ ์ •๋ณด

JiwonDev

JiwonDev

ํ™œ๋™ํ•˜๊ธฐ