Bean Scopes

Bean Scopes (๋นˆ ์Šค์ฝ”ํ”„)

Bean ์ •์˜๋ฅผ ์ƒ์„ฑํ•  ๋•Œ, ํ•ด๋‹น Bean ์ •์˜์— ์˜ํ•ด ์ •์˜๋œ ํด๋ž˜์Šค์˜ ์‹ค์ œ ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•˜๊ธฐ ์œ„ํ•œ "๋ ˆ์‹œํ”ผ"๋ฅผ ๋งŒ๋“œ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. Bean ์ •์˜๊ฐ€ ๋ ˆ์‹œํ”ผ๋ผ๋Š” ๊ฐœ๋…์€ ์ค‘์š”ํ•˜๋ฉฐ, ์ด๋Š” ํด๋ž˜์Šค์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ๋‹จ์ผ ๋ ˆ์‹œํ”ผ์—์„œ ์—ฌ๋Ÿฌ ๊ฐ์ฒด ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์Œ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

Bean ์ •์˜์—์„œ ํŠน์ • Bean ์ •์˜๋กœ ์ƒ์„ฑ๋œ ๊ฐ์ฒด์˜ ๋‹ค์–‘ํ•œ ์˜์กด์„ฑ๊ณผ ๊ตฌ์„ฑ ๊ฐ’์„ ์ œ์–ดํ•  ์ˆ˜ ์žˆ์„ ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ, ํŠน์ • Bean ์ •์˜๋กœ ์ƒ์„ฑ๋œ ๊ฐ์ฒด์˜ ๋ฒ”์œ„(scope)๋„ ์ œ์–ดํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ์ ‘๊ทผ ๋ฐฉ์‹์€ ๊ฐ์ฒด์˜ ๋ฒ”์œ„๋ฅผ Java ํด๋ž˜์Šค ์ˆ˜์ค€์—์„œ ๊ณ ์ •ํ•˜์ง€ ์•Š๊ณ  ๊ตฌ์„ฑ(configuration)์„ ํ†ตํ•ด ์„ ํƒํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๊ฐ•๋ ฅํ•˜๊ณ  ์œ ์—ฐํ•ฉ๋‹ˆ๋‹ค.

Spring Framework๋Š” ์—ฌ์„ฏ ๊ฐ€์ง€ ๋ฒ”์œ„๋ฅผ ์ง€์›ํ•˜๋ฉฐ, ๊ทธ ์ค‘ ๋„ค ๊ฐ€์ง€๋Š” ์›น ์ธ์‹(ApplicationContext) ํ™˜๊ฒฝ์—์„œ๋งŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ, ์‚ฌ์šฉ์ž ์ •์˜ ๋ฒ”์œ„๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

Bean Scopes

Scope

Description

singleton

(๊ธฐ๋ณธ๊ฐ’) ๊ฐ Spring IoC ์ปจํ…Œ์ด๋„ˆ๋‹น ๋‹จ์ผ ๊ฐ์ฒด ์ธ์Šคํ„ด์Šค๋กœ ์Šค์ฝ”ํ”„๋ฅผ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.

prototype

๋‹จ์ผ Bean ์ •์˜๋ฅผ ์—ฌ๋Ÿฌ ๊ฐ์ฒด ์ธ์Šคํ„ด์Šค๋กœ ์Šค์ฝ”ํ”„๋ฅผ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.

request

๋‹จ์ผ HTTP ์š”์ฒญ์˜ ์ƒ๋ช…์ฃผ๊ธฐ์— Bean์„ ์Šค์ฝ”ํ”„ํ•ฉ๋‹ˆ๋‹ค. ์ฆ‰, ๊ฐ HTTP ์š”์ฒญ๋งˆ๋‹ค ๋‹จ์ผ Bean ์ •์˜๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ์ƒˆ๋กœ์šด ์ธ์Šคํ„ด์Šค๊ฐ€ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค. ์ด๋Š” ์›น ์ธ์‹ Spring ApplicationContext ํ™˜๊ฒฝ์—์„œ๋งŒ ์œ ํšจํ•ฉ๋‹ˆ๋‹ค.

session

HTTP ์„ธ์…˜์˜ ์ƒ๋ช…์ฃผ๊ธฐ์— Bean์„ ์Šค์ฝ”ํ”„ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ์›น ์ธ์‹ Spring ApplicationContext ํ™˜๊ฒฝ์—์„œ๋งŒ ์œ ํšจํ•ฉ๋‹ˆ๋‹ค.

application

ServletContext์˜ ์ƒ๋ช…์ฃผ๊ธฐ์— Bean์„ ์Šค์ฝ”ํ”„ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ์›น ์ธ์‹ Spring ApplicationContext ํ™˜๊ฒฝ์—์„œ๋งŒ ์œ ํšจํ•ฉ๋‹ˆ๋‹ค.

websocket

WebSocket์˜ ์ƒ๋ช…์ฃผ๊ธฐ์— Bean์„ ์Šค์ฝ”ํ”„ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ์›น ์ธ์‹ Spring ApplicationContext ํ™˜๊ฒฝ์—์„œ๋งŒ ์œ ํšจํ•ฉ๋‹ˆ๋‹ค.

Thread scope๋Š” ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ๊ธฐ๋ณธ์ ์œผ๋กœ ๋“ฑ๋ก๋˜์–ด ์žˆ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ด ๋˜๋Š” ๊ธฐํƒ€ ์‚ฌ์šฉ์ž ์ •์˜ ์Šค์ฝ”ํ”„๋ฅผ ๋“ฑ๋กํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด์„œ๋Š” Custom Scope ์‚ฌ์šฉํ•˜๊ธฐ๋ฅผ ์ฐธ์กฐํ•˜์„ธ์š”.

Singleton Scope

์‹ฑ๊ธ€ํ†ค ๋ฒ”์œ„์˜ Bean์€ ๋‹จ์ผ ๊ณต์œ  ์ธ์Šคํ„ด์Šค๋งŒ ๊ด€๋ฆฌํ•˜๋ฉฐ, ํ•ด๋‹น Bean ์ •์˜์™€ ์ผ์น˜ํ•˜๋Š” ID๋ฅผ ๊ฐ€์ง„ ๋ชจ๋“  ์š”์ฒญ์— ๋Œ€ํ•ด Spring ์ปจํ…Œ์ด๋„ˆ๊ฐ€ ๋™์ผํ•œ Bean ์ธ์Šคํ„ด์Šค๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

๋‹ค์‹œ ๋งํ•ด, Bean ์ •์˜๋ฅผ ์‹ฑ๊ธ€ํ†ค์œผ๋กœ ์Šค์ฝ”ํ”„ํ•˜๋ฉด Spring IoC ์ปจํ…Œ์ด๋„ˆ๋Š” ํ•ด๋‹น Bean ์ •์˜์— ์˜ํ•ด ์ •์˜๋œ ๊ฐ์ฒด์˜ ์ •ํ™•ํžˆ ํ•˜๋‚˜์˜ ์ธ์Šคํ„ด์Šค๋งŒ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. ์ด ๋‹จ์ผ ์ธ์Šคํ„ด์Šค๋Š” ์‹ฑ๊ธ€ํ†ค Bean ์บ์‹œ์— ์ €์žฅ๋˜๋ฉฐ, ์ดํ›„์˜ ๋ชจ๋“  ์š”์ฒญ๊ณผ ์ฐธ์กฐ๋Š” ์บ์‹œ๋œ ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

Spring์˜ ์‹ฑ๊ธ€ํ†ค ๊ฐœ๋…์€ Gang of Four(GoF) ํŒจํ„ด ์ฑ…์—์„œ ์ •์˜๋œ ์‹ฑ๊ธ€ํ†ค ํŒจํ„ด๊ณผ ๋‹ค๋ฆ…๋‹ˆ๋‹ค. GoF ์‹ฑ๊ธ€ํ†ค์€ ClassLoader๋‹น ํ•˜๋‚˜์˜ ์ธ์Šคํ„ด์Šค๋งŒ ์ƒ์„ฑํ•˜๋„๋ก ๊ฐ์ฒด์˜ ๋ฒ”์œ„๋ฅผ ํ•˜๋“œ์ฝ”๋”ฉํ•ฉ๋‹ˆ๋‹ค. ๋ฐ˜๋ฉด Spring ์‹ฑ๊ธ€ํ†ค์˜ ๋ฒ”์œ„๋Š” ์ปจํ…Œ์ด๋„ˆ ๋ฐ Bean๋‹น ํ•˜๋‚˜๋กœ ์„ค๋ช…ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๋Š” ๋‹จ์ผ Spring ์ปจํ…Œ์ด๋„ˆ์— ํŠน์ • ํด๋ž˜์Šค์˜ Bean์„ ํ•˜๋‚˜ ์ •์˜ํ•˜๋ฉด, ๊ทธ Bean ์ •์˜์— ์˜ํ•ด ์ •์˜๋œ ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค๊ฐ€ ํ•˜๋‚˜๋งŒ ์ƒ์„ฑ๋จ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ์‹ฑ๊ธ€ํ†ค ์Šค์ฝ”ํ”„๋Š” Spring์—์„œ ๊ธฐ๋ณธ ์Šค์ฝ”ํ”„์ž…๋‹ˆ๋‹ค. XML์—์„œ ์‹ฑ๊ธ€ํ†ค์œผ๋กœ Bean์„ ์ •์˜ํ•˜๋Š” ์˜ˆ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค:

<bean id="accountService" class="com.something.DefaultAccountService"/>
<bean id="accountService" class="com.something.DefaultAccountService" scope="singleton"/>
@Component
class HomeController(
    var data: String = "hello spring"
) {
}
------------------------------------------------------------------
@ExtendWith(SpringExtension::class)
@ContextConfiguration("file:web/WEB-INF/spring/applicationContext.xml")
class BeanScopeTest {
    @Autowired
    lateinit var homeController: HomeController

    @Autowired
    lateinit var applicationContext:ApplicationContext

    @Test
    fun test() {
        homeController.data = "new one"

        val bean = applicationContext.getBean("homeController") as HomeController
        assertEquals("new one", bean.data) // ๋ณ€๊ฒฝ๋œ ๊ฐ’ ์œ ์ง€
    }
}

Prototype Scope

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

์ผ๋ฐ˜์ ์œผ๋กœ ์ƒํƒœ๋ฅผ ๊ฐ€์ง€๋Š”(Stateful) Bean์—๋Š” ํ”„๋กœํ† ํƒ€์ž… ์Šค์ฝ”ํ”„๋ฅผ, ๋ฌด์ƒํƒœ(Stateless) Bean์—๋Š” ์‹ฑ๊ธ€ํ†ค ์Šค์ฝ”ํ”„๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

XML์—์„œ ํ”„๋กœํ† ํƒ€์ž…์œผ๋กœ Bean์„ ์ •์˜ํ•˜๋Š” ์˜ˆ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค

<bean id="accountService" class="com.something.DefaultAccountService" scope="prototype"/>
@Component
class HomeController(
    var data: String = "hello spring"
) {
}
------------------------------------------------------------------
@ExtendWith(SpringExtension::class)
@ContextConfiguration("file:web/WEB-INF/spring/applicationContext.xml")
class BeanScopeTest {
    @Autowired
    lateinit var homeController: HomeController

    @Autowired
    lateinit var applicationContext:ApplicationContext

    @Test
    fun test() {
        homeController.data = "new one"

        val bean = applicationContext.getBean("homeController") as HomeController
        assertEquals("hello spring", bean.data) // ์ธ์Šคํ„ด์Šค ์žฌ์ƒ์„ฑ
    }
}

๋‹ค๋ฅธ ์Šค์ฝ”ํ”„์™€ ๋‹ฌ๋ฆฌ Spring์€ ํ”„๋กœํ† ํƒ€์ž… Bean์˜ ์ „์ฒด ์ƒ๋ช…์ฃผ๊ธฐ๋ฅผ ๊ด€๋ฆฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ปจํ…Œ์ด๋„ˆ๋Š” ํ”„๋กœํ† ํƒ€์ž… ๊ฐ์ฒด๋ฅผ ์ธ์Šคํ„ด์Šคํ™”, ์„ค์ • ๋ฐ ์กฐ๋ฆฝํ•œ ํ›„ ํด๋ผ์ด์–ธํŠธ์— ์ „๋‹ฌํ•˜๋ฉฐ, ๊ทธ ์ดํ›„๋กœ๋Š” ํ•ด๋‹น ํ”„๋กœํ† ํƒ€์ž… ์ธ์Šคํ„ด์Šค์— ๋Œ€ํ•œ ๊ธฐ๋ก์„ ์œ ์ง€ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ ์ดˆ๊ธฐํ™” ์ƒ๋ช…์ฃผ๊ธฐ ์ฝœ๋ฐฑ ๋ฉ”์„œ๋“œ๋Š” ๋ชจ๋“  ๊ฐ์ฒด์— ๋Œ€ํ•ด ํ˜ธ์ถœ๋˜์ง€๋งŒ, ์†Œ๋ฉธ ์ƒ๋ช…์ฃผ๊ธฐ ์ฝœ๋ฐฑ์€ ํ˜ธ์ถœ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ํด๋ผ์ด์–ธํŠธ ์ฝ”๋“œ๋Š” ํ”„๋กœํ† ํƒ€์ž… ์Šค์ฝ”ํ”„์˜ ๊ฐ์ฒด๋ฅผ ์ •๋ฆฌํ•˜๊ณ , ํ”„๋กœํ† ํƒ€์ž… Bean์ด ๋ณด์œ ํ•œ ๋น„์šฉ์ด ๋งŽ์ด ๋“œ๋Š” ๋ฆฌ์†Œ์Šค๋ฅผ ํ•ด์ œํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ํ”„๋กœํ† ํƒ€์ž… ์Šค์ฝ”ํ”„์˜ Bean์ด ๋ณด์œ ํ•œ ๋ฆฌ์†Œ์Šค๋ฅผ ํ•ด์ œํ•˜๋ ค๋ฉด, ์ฐธ์กฐ๋ฅผ ์œ ์ง€ํ•˜๊ณ  ์ •๋ฆฌํ•ด์•ผ ํ•˜๋Š” Bean์„ ๋ณด์œ ํ•˜๋Š” ์‚ฌ์šฉ์ž ์ •์˜ Bean Post-Processor๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

์–ด๋–ค ๋ฉด์—์„œ๋Š” Spring ์ปจํ…Œ์ด๋„ˆ๊ฐ€ ํ”„๋กœํ† ํƒ€์ž… ์Šค์ฝ”ํ”„ Bean์— ๋Œ€ํ•ด ์ˆ˜ํ–‰ํ•˜๋Š” ์—ญํ• ์ด Java์˜ new ์—ฐ์‚ฐ์ž๋ฅผ ๋Œ€์ฒดํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ ์ดํ›„์˜ ๋ชจ๋“  ์ƒ๋ช…์ฃผ๊ธฐ ๊ด€๋ฆฌ๋Š” ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์ฒ˜๋ฆฌํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

Singleton Beans with Prototype-bean Dependencies

์‹ฑ๊ธ€ํ†ค ์Šค์ฝ”ํ”„ Bean์ด ํ”„๋กœํ† ํƒ€์ž… ์Šค์ฝ”ํ”„ Bean์— ์˜์กด์„ฑ์„ ๊ฐ€์งˆ ๋•Œ, ์˜์กด์„ฑ์€ ์ธ์Šคํ„ด์Šคํ™” ์‹œ์ ์— ํ•ด๊ฒฐ๋ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์‹ฑ๊ธ€ํ†ค Bean์— ํ”„๋กœํ† ํƒ€์ž… ์Šค์ฝ”ํ”„ Bean์„ ์˜์กด์„ฑ ์ฃผ์ž…ํ•˜๋ฉด, ์ƒˆ๋กœ์šด ํ”„๋กœํ† ํƒ€์ž… Bean ์ธ์Šคํ„ด์Šค๊ฐ€ ์ƒ์„ฑ๋˜์–ด ์‹ฑ๊ธ€ํ†ค Bean์— ์ฃผ์ž…๋ฉ๋‹ˆ๋‹ค. ์ด ํ”„๋กœํ† ํƒ€์ž… ์ธ์Šคํ„ด์Šค๋Š” ์‹ฑ๊ธ€ํ†ค ์Šค์ฝ”ํ”„ Bean์— ์ œ๊ณต๋˜๋Š” ์œ ์ผํ•œ ์ธ์Šคํ„ด์Šค์ž…๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ ์‹ฑ๊ธ€ํ†ค ์Šค์ฝ”ํ”„ Bean์ด ๋Ÿฐํƒ€์ž„์— ํ”„๋กœํ† ํƒ€์ž… ์Šค์ฝ”ํ”„ Bean์˜ ์ƒˆ๋กœ์šด ์ธ์Šคํ„ด์Šค๋ฅผ ๋ฐ˜๋ณต์ ์œผ๋กœ ํš๋“ํ•˜๋ ค๋Š” ๊ฒฝ์šฐ, ํ”„๋กœํ† ํƒ€์ž… ์Šค์ฝ”ํ”„ Bean์„ ์‹ฑ๊ธ€ํ†ค Bean์— ์˜์กด์„ฑ ์ฃผ์ž…ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ์™œ๋ƒํ•˜๋ฉด ์ด๋Ÿฌํ•œ ์ฃผ์ž…์€ Spring ์ปจํ…Œ์ด๋„ˆ๊ฐ€ ์‹ฑ๊ธ€ํ†ค Bean์„ ์ธ์Šคํ„ด์Šคํ™”ํ•˜๊ณ  ์˜์กด์„ฑ์„ ํ•ด๊ฒฐํ•  ๋•Œ ๋‹จ ํ•œ ๋ฒˆ๋งŒ ๋ฐœ์ƒํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

Request, Session, Application, and WebSocket Scopes

request, session, application, websocket ์Šค์ฝ”ํ”„๋Š” ์›น ์ธ์‹ Spring ApplicationContext ๊ตฌํ˜„์ฒด(XmlWebApplicationContext ๋“ฑ)์—์„œ๋งŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ์Šค์ฝ”ํ”„๋ฅผ ์ผ๋ฐ˜ Spring IoC ์ปจํ…Œ์ด๋„ˆ(ClassPathXmlApplicationContext ๋“ฑ)์™€ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๋ฉด, ์•Œ ์ˆ˜ ์—†๋Š” Bean ์Šค์ฝ”ํ”„์— ๋Œ€ํ•œ IllegalStateException์ด ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

์ดˆ๊ธฐ ์›น ์„ค์ •

์š”์ฒญ, ์„ธ์…˜, ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜, ์›น์†Œ์ผ“ ์ˆ˜์ค€์—์„œ Bean์˜ ์Šค์ฝ”ํ•‘์„ ์ง€์›ํ•˜๊ธฐ ์œ„ํ•ด ์ผ๋ถ€ ์ดˆ๊ธฐ ์„ค์ •์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

์„ค์ • ๋ฐฉ๋ฒ•

Spring Web MVC ์‚ฌ์šฉ ์‹œ: DispatcherServlet์„ ํ†ตํ•ด ์ฒ˜๋ฆฌ๋˜๋Š” ์š”์ฒญ ๋‚ด์—์„œ ์Šค์ฝ”ํ”„๋œ Bean์„ ์ ‘๊ทผํ•˜๋ฉด ํŠน๋ณ„ํ•œ ์„ค์ •์ด ํ•„์š” ์—†์Šต๋‹ˆ๋‹ค. DispatcherServlet์ด ์ด๋ฏธ ๊ด€๋ จ ์ƒํƒœ๋ฅผ ๋…ธ์ถœํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

Servlet ์›น ์ปจํ…Œ์ด๋„ˆ ์‚ฌ์šฉ ์‹œ (JSF ๋“ฑ์—์„œ DispatcherServlet ์™ธ๋ถ€์—์„œ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•  ๋•Œ):

org.springframework.web.context.request.RequestContextListener ServletRequestListener๋ฅผ ๋“ฑ๋กํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” WebApplicationInitializer ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๋ฐฉ์‹์œผ๋กœ ์ˆ˜ํ–‰ํ•˜๊ฑฐ๋‚˜, ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ web.xml ํŒŒ์ผ์— ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์„ ์–ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

<web-app>
    ...
    <listener>
        <listener-class>
            org.springframework.web.context.request.RequestContextListener
        </listener-class>
    </listener>
    ...
</web-app>

๋˜๋Š” RequestContextFilter๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์„ ๊ณ ๋ คํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ•„ํ„ฐ ๋งคํ•‘์€ ์ฃผ๋ณ€ ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๊ตฌ์„ฑ์— ๋”ฐ๋ผ ๋‹ฌ๋ผ์ง€๋ฏ€๋กœ, ์ ์ ˆํ•˜๊ฒŒ ๋ณ€๊ฒฝํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ํ•„ํ„ฐ ๋ถ€๋ถ„ ์˜ˆ์‹œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค:

<web-app>
    ...
    <filter>
        <filter-name>requestContextFilter</filter-name>
        <filter-class>org.springframework.web.filter.RequestContextFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>requestContextFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    ...
</web-app>

DispatcherServlet, RequestContextListener, RequestContextFilter๋Š” ๋ชจ๋‘ ๋™์ผํ•œ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค. ์ฆ‰, HTTP ์š”์ฒญ ๊ฐ์ฒด๋ฅผ ํ•ด๋‹น ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ์Šค๋ ˆ๋“œ(Thread)์— ๋ฐ”์ธ๋”ฉํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ์š”์ฒญ ๋ฐ ์„ธ์…˜ ์Šค์ฝ”ํ”„์˜ Bean์ด ํ˜ธ์ถœ ์ฒด์ธ์˜ ๋” ์•„๋ž˜์—์„œ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•ด์ง‘๋‹ˆ๋‹ค.

์ดˆ๊ธฐ ์„ค์ • ๋ฐฉ๋ฒ•์€ ํŠน์ • Servlet ํ™˜๊ฒฝ์— ๋”ฐ๋ผ ๋‹ค๋ฆ…๋‹ˆ๋‹ค.

Request Scope

๋‹ค์Œ์€ Bean ์ •์˜๋ฅผ ์š”์ฒญ ์Šค์ฝ”ํ”„๋กœ ์„ค์ •ํ•œ XML ๊ตฌ์„ฑ ์˜ˆ์‹œ์ž…๋‹ˆ๋‹ค:

<bean id="loginAction" class="com.something.LoginAction" scope="request"/>

Spring ์ปจํ…Œ์ด๋„ˆ๋Š” ๊ฐ HTTP ์š”์ฒญ๋งˆ๋‹ค loginAction Bean ์ •์˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ƒˆ๋กœ์šด LoginAction Bean ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. ์ฆ‰, loginAction Bean์€ HTTP ์š”์ฒญ ์ˆ˜์ค€์—์„œ ์Šค์ฝ”ํ”„๋ฉ๋‹ˆ๋‹ค.

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

์• ๋…ธํ…Œ์ด์…˜ ๊ธฐ๋ฐ˜ ๊ตฌ์„ฑ์ด๋‚˜ Java ์„ค์ •์„ ์‚ฌ์šฉํ•  ๋•Œ๋Š” @RequestScope ์• ๋…ธํ…Œ์ด์…˜์„ ์‚ฌ์šฉํ•˜์—ฌ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์š”์ฒญ ์Šค์ฝ”ํ”„๋กœ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ์‹œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค:

@RequestScope
@Component
public class LoginAction {
    // ...
}

Session Scope

๋‹ค์Œ์€ Bean ์ •์˜๋ฅผ ์„ธ์…˜ ์Šค์ฝ”ํ”„๋กœ ์„ค์ •ํ•œ XML ๊ตฌ์„ฑ ์˜ˆ์‹œ์ž…๋‹ˆ๋‹ค:

<bean id="userPreferences" class="com.something.UserPreferences" scope="session"/>

Spring ์ปจํ…Œ์ด๋„ˆ๋Š” userPreferences Bean ์ •์˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋‹จ์ผ HTTP ์„ธ์…˜ ๋™์•ˆ ์ƒˆ๋กœ์šด UserPreferences Bean ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

๋‹ค์‹œ ๋งํ•ด, userPreferences Bean์€ HTTP ์„ธ์…˜ ์ˆ˜์ค€์—์„œ ์Šค์ฝ”ํ”„๋ฉ๋‹ˆ๋‹ค. ์š”์ฒญ ์Šค์ฝ”ํ”„์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ, ์ƒ์„ฑ๋œ ์ธ์Šคํ„ด์Šค์˜ ๋‚ด๋ถ€ ์ƒํƒœ๋ฅผ ๋ณ€๊ฒฝํ•ด๋„ ๋™์ผํ•œ userPreferences Bean ์ •์˜๋กœ๋ถ€ํ„ฐ ์ƒ์„ฑ๋œ ๋‹ค๋ฅธ ์„ธ์…˜ ์ธ์Šคํ„ด์Šค๋“ค์€ ์ด๋Ÿฌํ•œ ์ƒํƒœ ๋ณ€๊ฒฝ์„ ๋ณด์ง€ ๋ชปํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ๊ฐ ์„ธ์…˜ ์ธ์Šคํ„ด์Šค๊ฐ€ ๊ฐœ๋ณ„ ์„ธ์…˜์— ํŠนํ™”๋˜์–ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. HTTP ์„ธ์…˜์ด ์ตœ์ข…์ ์œผ๋กœ ํ๊ธฐ๋˜๋ฉด, ํ•ด๋‹น ์„ธ์…˜์— ์Šค์ฝ”ํ”„๋œ Bean๋„ ํ๊ธฐ๋ฉ๋‹ˆ๋‹ค.

์• ๋…ธํ…Œ์ด์…˜ ๊ธฐ๋ฐ˜ ๊ตฌ์„ฑ์ด๋‚˜ Java ์„ค์ •์„ ์‚ฌ์šฉํ•  ๋•Œ๋Š” @SessionScope ์• ๋…ธํ…Œ์ด์…˜์„ ์‚ฌ์šฉํ•˜์—ฌ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์„ธ์…˜ ์Šค์ฝ”ํ”„๋กœ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ์‹œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค:

@SessionScope
@Component
public class UserPreferences {
    // ...
}

Application Scope

๋‹ค์Œ์€ Bean ์ •์˜๋ฅผ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์Šค์ฝ”ํ”„๋กœ ์„ค์ •ํ•œ XML ๊ตฌ์„ฑ ์˜ˆ์‹œ์ž…๋‹ˆ๋‹ค:

<bean id="appPreferences" class="com.something.AppPreferences" scope="application"/>

Spring ์ปจํ…Œ์ด๋„ˆ๋Š” appPreferences Bean ์ •์˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ „์ฒด ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋™์•ˆ ํ•˜๋‚˜์˜ AppPreferences Bean ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

์ฆ‰, appPreferences Bean์€ ServletContext ์ˆ˜์ค€์—์„œ ์Šค์ฝ”ํ”„๋˜๋ฉฐ, ์ผ๋ฐ˜ ServletContext ์†์„ฑ์œผ๋กœ ์ €์žฅ๋ฉ๋‹ˆ๋‹ค. ์ด๋Š” Spring์˜ ์‹ฑ๊ธ€ํ†ค Bean๊ณผ ์œ ์‚ฌํ•˜์ง€๋งŒ ๋‘ ๊ฐ€์ง€ ์ค‘์š”ํ•œ ์ ์—์„œ ๋‹ค๋ฆ…๋‹ˆ๋‹ค

  1. ServletContext๋‹น ํ•˜๋‚˜์˜ ์‹ฑ๊ธ€ํ†ค์œผ๋กœ, Spring ApplicationContext๋‹น ํ•˜๋‚˜์˜ ์‹ฑ๊ธ€ํ†ค์ด ์•„๋‹™๋‹ˆ๋‹ค (ํ•˜๋‚˜์˜ ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ์—ฌ๋Ÿฌ ApplicationContext๊ฐ€ ์žˆ์„ ์ˆ˜ ์žˆ์Œ).

  2. ์‹ค์ œ๋กœ ServletContext ์†์„ฑ์œผ๋กœ ๋…ธ์ถœ๋˜์–ด ๋ณด์ด๋ฏ€๋กœ, ์™ธ๋ถ€์—์„œ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์• ๋…ธํ…Œ์ด์…˜ ๊ธฐ๋ฐ˜ ๊ตฌ์„ฑ์ด๋‚˜ Java ์„ค์ •์„ ์‚ฌ์šฉํ•  ๋•Œ๋Š” @ApplicationScope ์• ๋…ธํ…Œ์ด์…˜์„ ์‚ฌ์šฉํ•˜์—ฌ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์Šค์ฝ”ํ”„๋กœ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ์‹œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค:

@ApplicationScope
@Component
public class AppPreferences {
    // ...
}

WebSocket Scope

์›น์†Œ์ผ“ ์Šค์ฝ”ํ”„๋Š” WebSocket ์„ธ์…˜์˜ ์ƒ๋ช…์ฃผ๊ธฐ์™€ ์—ฐ๊ด€๋˜๋ฉฐ, STOMP over WebSocket ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ์ ์šฉ๋ฉ๋‹ˆ๋‹ค.

Scoped Beans as Dependencies

Spring IoC ์ปจํ…Œ์ด๋„ˆ๋Š” ๊ฐ์ฒด(Bean)์˜ ์ธ์Šคํ„ด์Šคํ™”๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ํ˜‘๋ ฅ์ž(๋˜๋Š” ์˜์กด์„ฑ)์˜ ์™€์ด์–ด๋ง๋„ ๊ด€๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด, HTTP ์š”์ฒญ ์Šค์ฝ”ํ”„ Bean์„ ๋” ๊ธด ์ƒ๋ช…์ฃผ๊ธฐ(scope)๋ฅผ ๊ฐ€์ง„ ๋‹ค๋ฅธ Bean์— ์ฃผ์ž…ํ•˜๋ ค๋Š” ๊ฒฝ์šฐ, ์Šค์ฝ”ํ”„๋œ Bean์„ ๋Œ€์ฒดํ•  AOP ํ”„๋ก์‹œ๋ฅผ ์ฃผ์ž…ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ฆ‰, ์Šค์ฝ”ํ”„๋œ ๊ฐ์ฒด์™€ ๋™์ผํ•œ ๊ณต๊ฐœ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋…ธ์ถœํ•˜์ง€๋งŒ, ๊ด€๋ จ ์Šค์ฝ”ํ”„(์˜ˆ: HTTP ์š”์ฒญ)์—์„œ ์‹ค์ œ ํƒ€๊ฒŸ ๊ฐ์ฒด๋ฅผ ๊ฒ€์ƒ‰ํ•˜๊ณ  ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ์„ ์œ„์ž„ํ•  ์ˆ˜ ์žˆ๋Š” ํ”„๋ก์‹œ ๊ฐ์ฒด๋ฅผ ์ฃผ์ž…ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๋˜ํ•œ, <aop:scoped-proxy/>๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์Šค์ฝ”ํ”„๊ฐ€ ์‹ฑ๊ธ€ํ†ค์ธ Bean๊ณผ ์Šค์ฝ”ํ”„๊ฐ€ ์„ธ์…˜์ด๋‚˜ ์š”์ฒญ์ธ Bean ์‚ฌ์ด์— ํ”„๋ก์‹œ๋ฅผ ์‚ฝ์ž…ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์Šค์ฝ”ํ”„๊ฐ€ ํ”„๋กœํ† ํƒ€์ž…์ธ Bean์˜ ๊ฒฝ์šฐ, ๊ณต์œ  ํ”„๋ก์‹œ์˜ ๋ชจ๋“  ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ์€ ์ƒˆ๋กœ์šด ํƒ€๊ฒŸ ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ํ•ด๋‹น ์ธ์Šคํ„ด์Šค๋กœ ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ์„ ์œ„์ž„ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

์Šค์ฝ”ํ”„๋œ ํ”„๋ก์‹œ๋Š” ์งง์€ ์Šค์ฝ”ํ”„์˜ Bean์„ ์ƒ๋ช…์ฃผ๊ธฐ ์•ˆ์ „ํ•˜๊ฒŒ ์ ‘๊ทผํ•˜๋Š” ์œ ์ผํ•œ ๋ฐฉ๋ฒ•์€ ์•„๋‹™๋‹ˆ๋‹ค. ๋˜ํ•œ ObjectFactory<MyTargetBean> ๋˜๋Š” ObjectProvider<MyTargetBean>์„ ์‚ฌ์šฉํ•˜์—ฌ ๋งค๋ฒˆ ํ•„์š”ํ•  ๋•Œ ํ˜„์žฌ ์ธ์Šคํ„ด์Šค๋ฅผ ๋™์ ์œผ๋กœ ๊ฐ€์ ธ์˜ฌ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. JSR-330์˜ Provider<MyTargetBean>๋„ ๋™์ผํ•œ ๋ชฉ์ ์„ ์œ„ํ•ด ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

ํ”„๋ก์‹œ ์œ ํ˜• ์„ ํƒ

Spring ์ปจํ…Œ์ด๋„ˆ๊ฐ€ <aop:scoped-proxy/> ์š”์†Œ๋กœ ํ‘œ์‹œ๋œ Bean์— ๋Œ€ํ•ด ํ”„๋ก์‹œ๋ฅผ ์ƒ์„ฑํ•  ๋•Œ, ๊ธฐ๋ณธ์ ์œผ๋กœ CGLIB ๊ธฐ๋ฐ˜์˜ ํด๋ž˜์Šค ํ”„๋ก์‹œ๊ฐ€ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค. CGLIB ํ”„๋ก์‹œ๋Š” ๋น„๊ณต๊ฐœ ๋ฉ”์„œ๋“œ๋ฅผ ์ธํ„ฐ์…‰ํŠธํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์ด๋Ÿฌํ•œ ํ”„๋ก์‹œ์—์„œ ๋น„๊ณต๊ฐœ ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด ์‹ค์ œ ์Šค์ฝ”ํ”„๋œ ํƒ€๊ฒŸ ๊ฐ์ฒด๋กœ ์œ„์ž„๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๋Œ€์•ˆ์œผ๋กœ, <aop:scoped-proxy/> ์š”์†Œ์˜ proxy-target-class ์†์„ฑ ๊ฐ’์„ false๋กœ ์„ค์ •ํ•˜์—ฌ ํ‘œ์ค€ JDK ์ธํ„ฐํŽ˜์ด์Šค ๊ธฐ๋ฐ˜ ํ”„๋ก์‹œ๋ฅผ ์ƒ์„ฑํ•˜๋„๋ก Spring ์ปจํ…Œ์ด๋„ˆ๋ฅผ ๊ตฌ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. JDK ์ธํ„ฐํŽ˜์ด์Šค ๊ธฐ๋ฐ˜ ํ”„๋ก์‹œ๋Š” ์ถ”๊ฐ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ํ•„์š” ์—†๋‹ค๋Š” ์žฅ์ ์ด ์žˆ์ง€๋งŒ, ์Šค์ฝ”ํ”„๋œ Bean ํด๋ž˜์Šค๊ฐ€ ์ ์–ด๋„ ํ•˜๋‚˜์˜ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•ด์•ผ ํ•˜๋ฉฐ, ์Šค์ฝ”ํ”„๋œ Bean์ด ์ฃผ์ž…๋˜๋Š” ๋ชจ๋“  ํ˜‘๋ ฅ์ž๋Š” ํ•ด๋‹น ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํ†ตํ•ด Bean์„ ์ฐธ์กฐํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋‹ค์Œ ์˜ˆ์‹œ๋Š” ์ธํ„ฐํŽ˜์ด์Šค ๊ธฐ๋ฐ˜ ํ”„๋ก์‹œ๋ฅผ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค:

<!-- DefaultUserPreferences๋Š” UserPreferences ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ -->
<bean id="userPreferences" class="com.stuff.DefaultUserPreferences" scope="session">
    <aop:scoped-proxy proxy-target-class="false"/>
</bean>

<bean id="userManager" class="com.stuff.UserManager">
    <property name="userPreferences" ref="userPreferences"/>
</bean>

Injecting Request/Session References Directly

ํŒฉํ† ๋ฆฌ ์Šค์ฝ”ํ”„์˜ ๋Œ€์•ˆ์œผ๋กœ, Spring WebApplicationContext๋Š” HttpServletRequest, HttpServletResponse, HttpSession, WebRequest ๋ฐ (JSF๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ) FacesContext์™€ ExternalContext๋ฅผ Spring ๊ด€๋ฆฌ Bean์— ํƒ€์ž… ๊ธฐ๋ฐ˜ ์ž๋™ ์ฃผ์ž…์„ ํ†ตํ•ด ์ง์ ‘ ์ฃผ์ž…ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Spring์€ ์ผ๋ฐ˜ Bean๊ณผ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ์ด๋Ÿฌํ•œ ์š”์ฒญ ๋ฐ ์„ธ์…˜ ๊ฐ์ฒด์˜ ํ”„๋ก์‹œ๋ฅผ ์ฃผ์ž…ํ•˜์—ฌ, ์‹ฑ๊ธ€ํ†ค Bean ๋ฐ ์ง๋ ฌํ™” ๊ฐ€๋Šฅํ•œ Bean์—์„œ๋„ ์•ˆ์ „ํ•˜๊ฒŒ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.

Creating a Custom Scope (์‚ฌ์šฉ์ž ์ •์˜ ์Šค์ฝ”ํ”„ ์ƒ์„ฑ)

์‚ฌ์šฉ์ž ์ •์˜ ์Šค์ฝ”ํ”„๋ฅผ Spring ์ปจํ…Œ์ด๋„ˆ์— ํ†ตํ•ฉํ•˜๋ ค๋ฉด, org.springframework.beans.factory.config.Scope ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. Spring Framework ์ž์ฒด์—์„œ ์ œ๊ณตํ•˜๋Š” Scope ๊ตฌํ˜„์ฒด์™€ Scope javadoc์„ ์ฐธ๊ณ ํ•˜์—ฌ ํ•„์š”ํ•œ ๋ฉ”์„œ๋“œ๋ฅผ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Scope ์ธํ„ฐํŽ˜์ด์Šค๋Š” ์Šค์ฝ”ํ”„์—์„œ ๊ฐ์ฒด๋ฅผ ๊ฐ€์ ธ์˜ค๊ณ , ์Šค์ฝ”ํ”„์—์„œ ์ œ๊ฑฐํ•˜๋ฉฐ, ํŒŒ๊ดดํ•  ์ˆ˜ ์žˆ๋Š” ๋„ค ๊ฐ€์ง€ ๋ฉ”์„œ๋“œ๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด, ์„ธ์…˜ ์Šค์ฝ”ํ”„ ๊ตฌํ˜„์€ ์„ธ์…˜์— ๋ฐ”์ธ๋”ฉ๋œ ์„ธ์…˜ ์Šค์ฝ”ํ”„ Bean์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ๋‹ค์Œ์€ ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋ฉ”์„œ๋“œ์˜ ์˜ˆ์‹œ์ž…๋‹ˆ๋‹ค:

Using a Custom Scope

์‚ฌ์šฉ์ž ์ •์˜ Scope ๊ตฌํ˜„์ฒด๋ฅผ ์ž‘์„ฑํ•˜๊ณ  ํ…Œ์ŠคํŠธํ•œ ํ›„, Spring ์ปจํ…Œ์ด๋„ˆ์— ๋“ฑ๋กํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋‹ค์Œ์€ ์Šค์ฝ”ํ”„๋ฅผ ๋“ฑ๋กํ•˜๋Š” ์ฃผ์š” ๋ฉ”์„œ๋“œ์ž…๋‹ˆ๋‹ค:

beanFactory.registerScope("thread", new SimpleThreadScope());

์œ„ ์˜ˆ์‹œ๋Š” SimpleThreadScope๋ฅผ ๋“ฑ๋กํ•˜๋Š” ์˜ˆ์‹œ์ด๋ฉฐ, ์‚ฌ์šฉ์ž ์ •์˜ ์Šค์ฝ”ํ”„ ๊ตฌํ˜„์ฒด๋„ ๋™์ผํ•œ ๋ฐฉ์‹์œผ๋กœ ๋“ฑ๋กํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

XML ์„ค์ •์„ ํ†ตํ•ด ์‚ฌ์šฉ์ž ์ •์˜ ์Šค์ฝ”ํ”„๋ฅผ ์„ ์–ธ์ ์œผ๋กœ ๋“ฑ๋กํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ๋‹ค์Œ์€ CustomScopeConfigurer๋ฅผ ์‚ฌ์šฉํ•œ ์˜ˆ์‹œ์ž…๋‹ˆ๋‹ค:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           https://www.springframework.org/schema/beans/spring-beans.xsd
                           http://www.springframework.org/schema/aop
                           https://www.springframework.org/schema/aop/spring-aop.xsd">

    <bean class="org.springframework.beans.factory.config.CustomScopeConfigurer">
        <property name="scopes">
            <map>
                <entry key="thread">
                    <bean class="org.springframework.context.support.SimpleThreadScope"/>
                </entry>
            </map>
        </property>
    </bean>

    <bean id="thing2" class="x.y.Thing2" scope="thread">
        <property name="name" value="Rick"/>
        <aop:scoped-proxy/>
    </bean>

    <bean id="thing1" class="x.y.Thing1">
        <property name="thing2" ref="thing2"/>
    </bean>

</beans>

์œ„ ์˜ˆ์‹œ์—์„œ <aop:scoped-proxy/>๋Š” thing2 Bean์ด thread ์Šค์ฝ”ํ”„๋ฅผ ๋”ฐ๋ฅด๋„๋ก ํ”„๋ก์‹œ๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. thing1 Bean์€ thing2 Bean์„ ์ฐธ์กฐํ•  ๋•Œ ํ”„๋ก์‹œ๋ฅผ ํ†ตํ•ด ์ ‘๊ทผํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

Last updated