Goal
- Spring Bean
- Spring IoC Container
- Dependency Injection (DI)
- Constructor Injection
- Method Injection
- Setter Injectio
Spring Bean
Spring Bean ์ผ๋ก ๋ฑ๋ก๋ ํด๋์ค๋ IoC Contrainer ์ ์ํด ์์ฑ๋ Singleton ๊ฐ์ฒด๋ฅผ ์๋ฏธํ๋ฉฐ, Bean ์ผ๋ก ๋ฑ๋ก๋ ํด๋์ค๋ง ์ปจํ
์ด๋๋ฅผ ํตํด ์์กด์ฑ์ด ์ฃผ์
(Dependency Injection)๋์ด ๊ฐ์ฒด์ ์๋ช
์ฃผ๊ธฐ๋ฅผ ๊ฐ๋ฐ์๊ฐ ์๋ ์ปจํ
์ด๋๊ฐ ๊ด๋ฆฌํ๋๋ก ํ๋ค.
Register Bean
- @Bean
- @Bean ์ @Configuration ์ด ๋ถ์ DI ์ค์ ์ฉ ํด๋์ค์์ ์ฌ์ฉ๋๋ ์ด๋
ธํ
์ด์
์ผ๋ก, ๋ฉ์๋๋ฅผ ์ด์ฉํด Bean Object ์ ์์ฑ๊ณผ ์์กด ๊ด๊ณ ์ฃผ์
์ ์ํํ๋ค.
@Configuration
class DataSourceConfig {
@Bean
fun dataSource(): DataSource {
val dataSource = SimpleDriverDataSource()
dataSource.setDriverClass(Driver::class.java)
dataSource.url = "jdbc:mysql://localhost/springbook?characterEncoding=UTF-8"
dataSource.username = "user"
dataSource.password = "password"
return dataSource
}
}
- @Autowired
- Spring Framework ๋ @Autowired ๊ฐ ๋ถ์ ์์ ์ ๋ฉ์๋(Setter) ๊ฐ ์์ผ๋ฉด ํ๋ผ๋ฏธํฐ ํ์
์ ๋ณด๊ณ ์ฃผ์
๊ฐ๋ฅํ ํ์
์ Bean ์ ๋ชจ๋ ๊ฒ์ํ์ฌ ์ฃผ์
ํ๋ค.
- ์ด๊ฐ์ @Autowired ์ด๋
ธํ
์ด์
์ ์ด์ฉํ๋ฉด ์์ฝ๊ฒ ์์กด์ฑ์ ์ฃผ์
ํ ์ ์์ด DI ๊ด๋ จ ์ฝ๋๋ฅผ ๋ํญ ์ค์ผ ์ ์์ด์ ์ฝ๋๋ฅผ ๊ฐ๊ฒฐํ ์์ฑํ ์ ์๋ ์ฅ์ ์ด ์์ง๋ง, Bean ์ค์ ์ ๋ณด๋ฅผ ๋ณด๊ณ ๋ค๋ฅธ ๋น๊ณผ์ ์์กด ๊ด๊ณ๊ฐ ์ด๋ค์ง ํ์
ํ๊ธฐ ํ๋ค๋ค๋ ๋จ์ ์ด ์๋ค.
- ๋จ, ์์กด ๊ฐ์ฒด์ ๊ตฌํ์ฒด๊ฐ ๋ ๊ฐ ์ด์์ธ ๊ฒฝ์ฐ ๊ตฌํ์ฒด ๋ณ๋ก ๋ค๋ฅธ Bean ์ด๋ฆ์ ์ค์ ํ์ฌ ์ต์ข
ํ๋ณด๋ฅผ ์ ํํ๋๋ก ๋ง๋ค์ด์ผ ํ๋ค.
- @Component("AComponentImpl") ์ ๊ฐ์ด Bean ๊ฐ์ฒด์ ์ด๋ฆ์ ์ง์ ํ๋ค.
@Configuration
class ProductServiceConfig(
@Autowired
private val productRepository: ProductRepository
) {
@Bean
fun productService(): ProductService = ProductService(productRepository)
}
@Configuration
class ProductRepositoryConfig() {
@Bean
fun productRepository(): ProductRepository = ProductRepository()
}
- @Component
- ํด๋น ์ด๋
ธํ
์ด์
์ ํด๋์ค์์ ์ฌ์ฉ ๊ฐ๋ฅํ๋ฉฐ Bean Scanner ๋ฅผ ํตํด ์๋์ผ๋ก Bean ๊ฐ์ฒด๋ก ๋ฑ๋ก๋๋ค.
- @Componenet ์ด๋
ธํ
์ด์
์ ์ฌ์ฉํด Bean ์ผ๋ก ๋ฑ๋กํ๋ ค๋ฉด @ComponentScan ๊ณผ ๊ฐ์ ์ด๋
ธํ
์ด์
์ ์ถ๊ฐ์ ์ผ๋ก ์ฌ์ฉํ์ฌ ์ด๋ค ๋ฒ์๊น์ง ์ค์บํ ๊ฒ์ธ์ง ์ค์ ํ๋ ๊ณผ์ ์ด ํ์ํ๋ค.
- @ComponentScan @Component ๋ฐ ํ์ ์ด๋
ธํ
์ด์
์ด ๋ถ์ ํด๋์ค๋ฅผ ์ด๋ ๋ฒ์๊น์ง ๊ฒ์ํ ์ ์์์ง ์ค์ ํ๊ธฐ ์ํด ์ฌ์ฉ๋๋ค. ํจํค์ง๋ฅผ ๊ธฐ์ค์ผ๋ก ํ๋ฉฐ ์ค์ ๊ฐ๋ฅํ ํจํค์ง๋ ๋ค์ค ์ ํ์ด ๊ฐ๋ฅํ๋ค.
- @Controller, @Service, @Repository ๋ฑ
@Target(AnnotationTarget.CLASS)
@Retention(AnnotationRetention.RUNTIME)
@MustBeDocumented
@Component
annotation class WebAdapter(
@get:AliasFor(annotation = Component::class)
val value: String = ""
)
Spring IoC Container
Spring IoC Container() ๋ DI(Dependency Injection) ๊ณผ ๋ฐ์ ํ ๊ด๊ณ๋ฅผ ๋งบ๊ณ ์๋ค. ์ด๋ฌํ Spring Container ๋ ๋ค์๊ณผ ๊ฐ์ ๊ฒฝ์ฐ์ ๊ฐ์ฒด๋ฅผ ์ ์ํ๋๋ก ํ๋ ํ๋ก์ธ์ค๋ฅผ ๊ฑฐ์น๋ค.
ApplicationContext ๋ Spring IoC Container ์ Bean ํด๋์ค์ ์ธ์คํด์คํ, ๊ตฌ์ฑ ๋ฐ ์กฐ๋ฆฝ ๋ฑ์ ๋ด๋นํ๋ ์ญํ ์ด๋ค. ์ด๋ก ์ธํด ์ปจํ
์ด๋๋ ์ค์ ๋ฉํ๋ฐ์ดํฐ ๋ฅผ ํตํด Bean ์ธ์คํด์ค ์์ฑ ์ค์ ์ ์ฝ์ด ๋ค์ธ๋ค. ์ค์ ๋ฉํ๋ฐ์ดํฐ๋ XML ์ด๋ Java Annotation, Java Code ๋ฑ์ผ๋ก ์ค์ ๊ฐ๋ฅํ๋ค.
Spring Framework ๋ ApplicationContext ์ธํฐํ์ด์ค์ ์ฌ๋ฌ ๊ตฌํ์ฒด๋ฅผ ์ ๊ณตํ๋๋ฐ, ClassPathxmlApplicationContext, FileSystemXmlApplicationContext ํด๋์ค์ ์ธ์คํด์ค๊ฐ ์ฌ์ฉ๋๋ ๊ฒ์ด ์ผ๋ฐ์ ์ด๋ค. ๊ธฐ์กด์๋ XML ์ ํตํด ์ค์ ๋ฉํ๋ฐ์ดํฐ๋ฅผ ์ ์ ํ์ผ๋ ์ด๋ฌํ ํ์์ Java Annotation ์ด๋ Code ๋ฅผ ์ด์ฉํด ์ ์ธ์ ์ผ๋ก ์์ฑํ ์ ์๋๋ก ์ปจํ
์ด๋์์ ์กฐ์ ๊ฐ๋ฅํ๋ค.
Config Metadata Annotation
- @Import
- @Configuration์ผ๋ก ์ค์ ํ ํ์ผ์ ๋ ๊ฐ ์ด์ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ
@Import(QueryFactoryConfig::class)
@Configuration
class JpaQueryFactoryConfig {
@PersistenceContext
private lateinit var entityManager: EntityManager
@Bean
fun queryFactory() = JPAQueryFactory(this.entityManager)
}
- @DependsOn
- ๋น์ด ๋ฑ๋ก๋๋ ์์๋ฅผ ์ง์ ํ๋ ์ด๋
ธํ
์ด์
@Component("calculator-2")
@DependsOn(value = ["calculator-1"])
class Calculator(
var number: Int
)
Dependency Injection
Dependency Injection(DI)๋ Bean ๊ฐ์ฒด์์ ํ์ํ ์ธ๋ถ์ Bean ๊ฐ์ฒด๋ฅผ ์ฃผ์
ํ๋๋ก ํ๋ ํ๋ก์ธ์ค์ด๋ค. ์ด๋ฌํ DI ์์น์ ์ํด ์ฝ๋๋ฅผ ๊น๋ํ๊ฒ ์์ฑํ ์ ์์ด๋ฉฐ, ๊ฐ์ฒด ๊ฐ ์ข
์์ฑ์ ๋ํ Decoupling ์ ํจ๊ณผ์ ์ผ๋ก ๋ค๋ฃฐ ์ ์๋ค. ๋ํ, ์์กด์ด ํ์ํ Bean ๊ฐ์ฒด๋ ์ธ๋ถ์์ ์ฃผ์
๋ฐ๋ Bean ๊ฐ์ฒด์ ์์น๋ ๊ตฌํ์ฒด๋ฅผ ์ ์ ์๋ค. ์ฆ, ์ธํฐํ์ด์ค๋ ์ถ์ ํด๋์ค๋ฅผ ์ฃผ์
๋ฐ์์ผ๋ก์จ ํ
์คํธ ์งํ์ด ์ฉ์ดํด์ง๋๋ก ํ๋ฉฐ ์ ์ฐํ ํ์ฅ์ด ๊ฐ๋ฅํ๋๋ก ํ๋ค. ์ด๋ฌํ DI ๋ ๊ฐ๋ฐฉ ํ์ ์์น์ ๊ด์ ์์ ํ์์ ๊ด์ ์์ ๋ณผ ๋ ์ฌ์ฌ์ฉ์ด ๊ฐ๋ฅํ๋ค๋ ์ ์ ์ฒ ์ ํ ํด๋น ์์น์ ์ค์ํ๊ณ ์๋ค๊ณ ๋ณผ ์ ์๋ค.
DI ํ์ฉ ๋ฐฉ๋ฒ
- ํต์ฌ ๊ธฐ๋ฅ ๋ณ๊ฒฝ
- ์์กด ๋์์ ๊ตฌํ์ ๋ฐ๊ฟ ํต์ฌ ๊ธฐ๋ฅ์ ๋์ ๋ฐฉ์์ ๋ค๋ฅธ ๊ตฌํ์ฒด๋ก ๋ณ๊ฒฝ ํ ์ ์๋ค. ์ด๋ฌํ ํน์ง์ ๊ธฐ์กด JDBC ๋ฅผ ์ฌ์ฉํ๋ค๊ฐ JPA ๋ MyBatis ๋ฑ์ผ๋ก ๊ตฌํ์ฒด๋ฅผ ํต์งธ๋ก ๋ณ๊ฒฝํ๋ ๊ฒ์ผ๋ก ์์๋ฅผ ๋ค ์ ์๋ค.
- ํต์ฌ ๊ธฐ๋ฅ์ ๋์ ์ธ ๋ณ๊ฒฝ
- DI ๋ ๊ธฐ๋ณธ์ ์ผ๋ก ๋ฐํ์ ์ ๋์ ์ผ๋ก ์์กด ์ค๋ธ์ ํธ๋ฅผ ์ฐ๊ฒฐํด์ฃผ์ง๋ง, ํ ๋ฒ ์์กด์ฑ์ด ์ฃผ์
๋๊ณ ๋๋ฉด ๊ทธ ํ๋ก๋ ๊ตฌํ์ฒด๊ฐ ๋ณ๊ฒฝ๋์ง ์๋๋ค. ์ฆ, ์ ์ ์ธ ๊ด๊ณ๋ก ์๊ณค๊ด๊ณ๋ฅผ ๋งบ์ด์ฃผ๋ ๊ฒ์ด๋ค. ํ์ง๋ง DI ๋ฅผ ์ ํ์ฉํ๋ฉด ์ ํ๋ฆฌ์ผ์ด์
์ด ๋์ํ๋ ์ค๊ฐ์ ์์กดํ๋ ๊ตฌํ์ฒด๋ฅผ ๋์ ์ผ๋ก ๋ณ๊ฒฝํ ์ ์๋ค. ์ด๋ Dynamic Routing Proxy / Proxy Object ๊ธฐ๋ฒ์ ํ์ฉํ์ฌ ์์ฉํ ์ ์๋ค.
- ํ์์ ๋ฑ๊ธ์ ๋ฐ๋ผ ๋ค๋ฅธ ๊ตฌํ์ฒด๋ฅผ ์ฌ์ฉํ๋๋ก ํ๊ฑฐ๋ ์ฌ์ฉ์๋ณ๋ก ๋
๋ฆฝ์ ์ธ ์์กด ์ค๋ธ์ ํธ๋ฅผ ์ฌ์ฉํ๊ฒ๋ ํ๋ค.
- ๋ถ๊ฐ ๊ธฐ๋ฅ ์ถ๊ฐ
- ๊ธฐ์กด ๊ตฌํ๋ ํต์ฌ ๊ธฐ๋ฅ์ ๊ทธ๋๋ก ๋์ฑ ์ถ๊ฐ์ ์ผ๋ก ๋ถ๊ฐ ๊ธฐ๋ฅ์ ๊ตฌํ ํ ์ ์๋ค. ๊ทธ ์์๋ก Decorator ํจํด์ด ์๋ค. ์์กด ์ค๋ธ์ ํธ๋ ์ธํฐํ์ด์ค๋ฅผ ์ฌ์ฉํ๊ฒ ํ๋๋ก ํ๊ณ , ์ค์ ์ฌ์ฉํ ์ค๋ธ์ ํธ๋ DI ๋ฅผ ์ ์ฉํ๋๋ก ํ๋ฉด Decorator ํจํด์ ์ฝ๊ฒ ์ ์ฉํ ์ ์๋ค.
- ์ธํฐํ์ด์ค ๋ณ๊ฒฝ
- Proxy
- ํ์ํ ์์ ์์ ์ค์ ์ฌ์ฉํ ์ค๋ธ์ ํธ๋ฅผ ์ด๊ธฐํํ๊ณ ๋ฆฌ์์ค๋ฅผ ์ค๋นํ๊ฒ ํด์ฃผ๋ Lazy Loading ์ ์ฉ ์ Proxy ๊ฐ์ฒด๋ฅผ ์ด์ฉํ๋๋ก ํ๋ค.
- Template / Callback
- ๋ฐ๋ณต์ ์ผ๋ก ๋ฑ์ฅํ์ง๋ง ํญ์ ๊ณ ์ ์ ์ธ ์์
ํ๋ฆ๊ณผ ๊ทธ ์ฌ์ด์์ ์์ฃผ ๋ฐ๋๋ ๋ถ๋ถ์ ๋ถ๋ฆฌํด์ Template ๊ณผ Callbak ์ผ๋ก ๋ง๋ค์ด DI ์๋ฆฌ๋ฅผ ์์ํด ์ ์ฉํ๋ฉด ๋ฐ๋ณต์ ์ผ๋ก ์์ฑ๋ ์ง์ ๋ถํ ์ฝ๋๋ฅผ ๊ฐ๊ฒฐํ๊ฒ ๋ง๋ค ์ ์๋ค.
- Singleton / Object Scope
- Spring DI ๋ ๊ธฐ๋ณธ์ ์ผ๋ก Singleton ์ผ๋ก Bean ๊ฐ์ฒด๋ฅผ ๋ง๋ค์ด ์ฌ์ฉํ๋๋ก ํ๋ค. ์ด ๋๋ถ์ IoC Container ๋ Bean ์ผ๋ก ๋ฑ๋ก๋ Singleton ๊ฐ์ฒด์ ์๋ช
์ฃผ๊ธฐ๋ฅผ ์ง์ ์ ์ดํ๊ฒ ๋์ด ๊ฐ๋ฐ์๋ ์ด๋ฅผ ํ์ฉํด ์์ ๋กญ๊ฒ ์ค๊ณํ ์ ์๋ค๋ ์ฅ์ ์ ๊ฐ์ง๋ค.
- ๋๋ก๋ Singleton ์๋ช
์ฃผ๊ธฐ ๋ฟ๋ง ์๋๋ผ ์์์ ์๋ช
์ฃผ๊ธฐ๋ฅผ ๊ฐ๋ ๊ฐ์ฒด๊ฐ ํ์ํ ๋๋ ์๋ค. HTTP ์์ฒญ ๋น ํ๋์ ๊ฐ์ฒด๊ฐ ๋ง๋ค์ด์ง๊ฑฐ๋, HTTP Session ํ๋ ๋น ์๋ก์ด ๊ฐ์ฒด๊ฐ ๋ง๋ค์ด์ง๊ฒ๋ ํ ์ ์๋ค.
- Test
- ์์กด ๊ฐ์ฒด๋ฅผ ๋์ ํด์ ๋์ํ Stub / Mock ๊ฐ์ฒด๋ฅผ ์ด์ฉํด ํ
์คํธ์ ์ฌ์ฉํ ์ ์๋ค. DI ๋ฅผ ์ํด ๋ง๋ ์์ ์ ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ฉด ํ
์คํธ ์ฝ๋ ์์์ ์๋์ผ๋ก Mock ๊ฐ์ฒด๋ฅผ ์ฃผ์
ํ ์ ์๋ค.
์์กด์ฑ ์ฃผ์
๋ฐฉ์
- Constructor Inject
- ์์ฑ์ ๊ธฐ๋ฐ DI ๋ ์ปจํ
์ด๋๊ฐ ์์ฑ์๋ฅผ ํตํด ์ฌ๋ฌ ์ธ์๋ฅผ ํธ์ถํ์ฌ ์์กด์ฑ์ ์ฃผ์
ํ๊ฒ ๋๋ค. ์ด๋ ์ ์ ํฉํ ๋ฆฌ ๋ฉ์๋๋ฅผ ํธ์ถํ๋ ๊ฒ์ ๋๋ฑํ๋ฉฐ, ์์กด ์ธ์๋ฅผ ์ ์ฌํ๊ฒ ๋ค๋ฃฌ๋ค.
@RestController
class ProductController(
private val getProductsUseCase: GetProductsUseCase
)
@RestController
class ProductController(
lateinit var getProductsUseCase: GetProductUseCase
)
@RestController
class ProductController(
@Autowired
private val getProductUseCase: GetProductUseCase
)