Spring Boot

[Spring] μŠ€ν”„λ§ IOC μ»¨ν…Œμ΄λ„ˆμ™€ Bean

hnev 2023. 1. 15. 00:50

🌈 Spring IOC, Container, DI, Bean?

μŠ€ν”„λ§μ„ μ‚¬μš©ν•˜λ‹€ 보면 κΎΈμ€€νžˆ λ“€μ–΄μ˜€λ˜ μš©μ–΄λ“€μ΄λ‹€. 이 μž₯μ—μ„œλŠ” κ·Έ κ°œλ…μ— λŒ€ν•΄μ„œ μ•Œμ•„λ³΄κ³  정리해 λ³Έλ‹€.

IOC (Inversion of Control)

μ œμ–΄μ˜ 역전이라 λΆ€λ₯Έλ‹€. μ•„λž˜μ—μ„œ μ»¨ν…Œμ΄λ„ˆμ™€ ν•¨κ»˜ μ„€λͺ…ν•œλ‹€.

Container (μ»¨ν…Œμ΄λ„ˆ)

μ»¨ν…Œμ΄λ„ˆλŠ” 보톡 객체의 생λͺ…μ£ΌκΈ°, μƒμ„±λœ μΈμŠ€ν„΄μŠ€λ“€μ—κ²Œ 좔가적인 κΈ°λŠ₯을 μ œκ³΅ν•œλ‹€. μŠ€ν”„λ§ μ»¨ν…Œμ΄λ„ˆλŠ” μ˜μ‘΄μ„±λ„ κ΄€λ¦¬ν•œλ‹€.

 

Spring IOC Container - μŠ€ν”„λ§ IOC μ»¨ν…Œμ΄λ„ˆ

μŠ€ν”„λ§μ€ μŠ€ν”„λ§ IOC μ»¨ν…Œμ΄λ„ˆμ—μ„œ 객체λ₯Ό κ΄€λ¦¬ν•˜λŠ”λ°, μ΄λ•Œ μŠ€ν”„λ§μ΄ μ œμ–΄ κΆŒν•œμ„ κ°€μ Έ 객체 생성, 관계, μ˜μ‘΄μ„±, 생λͺ…μ£ΌκΈ° 관리 ν•˜λŠ”데 μ΄λ•Œ μƒμ„±λœ 객체λ₯Ό Bean이라고 ν•œλ‹€. 이 Bean듀은 μ‹±κΈ€ν†€μœΌλ‘œ κ΄€λ¦¬λœλ‹€.

즉, κ°œλ°œμžλŠ” 이런 과정을 μŠ€ν‚΅ ν•¨μœΌλ‘œμ¨ λΉ„μ¦ˆλ‹ˆμŠ€ λ‘œμ§μ— 집쀑할 수 있게 λœλ‹€.

κ·Έλ ‡λ‹€λ©΄ μš°λ¦¬κ°€ λ§Œλ“  클래슀λ₯Ό μŠ€ν”„λ§ IOC μ»¨ν…Œμ΄λ„ˆκ°€ 관리할 수 있게 ν•˜λ €λ©΄ μ–΄λ–»κ²Œ ν• κΉŒ? λ°”λ‘œ Bean으둜 등둝해 μ£Όλ©΄ λœλ‹€. Bean으둜 λ“±λ‘ν•˜λŠ” 방법은 μ—¬λŸ¬ 가지 방법이 μžˆλŠ”λ° μ˜ˆμ „μ— μ‚¬μš©ν•˜λ˜ XML을 톡해 λ“±λ‘ν•˜λŠ” 방법을 μ œμ™Έν•˜κ³  μ–΄λ…Έν…Œμ΄μ…˜μ„ 톡해 λ“±λ‘ν•˜λŠ” 2가지 방법을 확인해 보자.

 

1. Bean으둜 λ“±λ‘ν•˜λŠ” 방법

1-1. Component Scan

Bean으둜 등둝될 μ€€λΉ„κ°€ 된 ν΄λž˜μŠ€λ“€μ„ μŠ€μΊ”ν•˜μ—¬ Bean으둜 등둝해 μ£ΌλŠ” 과정이닀.

 

μ€€λΉ„κ°€ 된 ν΄λž˜μŠ€λ“€μ΄λž€ @Component μ–΄λ…Έν…Œμ΄μ…˜μ„ ν΄λž˜μŠ€μ— μΆ”κ°€ν•œ 것을 λ§ν•œλ‹€. 많이 μ‚¬μš©ν•˜λŠ” @Controller, @Service, @Repository도 따라가 보면 @Componet이 μžˆλŠ” κ±Έ 확인할 수 μžˆλ‹€.

 

κ·Έλ ‡λ‹€λ©΄ 이제 ν•˜λ‚˜ 더 ꢁ금증이 생긴닀. λ‚˜λŠ” μ»΄ν¬λ„ŒνŠΈ μŠ€μΊ”μ„ ν•œ 적이 μ—†λŠ”λ° μ™œ μœ„μ˜ μ–΄λ…Έν…Œμ΄μ…˜λ§Œ λΆ™μ˜€μ„ 뿐인데 Bean으둜 λ“±λ‘λœ 걸까?

 

μŠ€ν”„λ§λΆ€νŠΈ ν”„λ‘œμ νŠΈλ₯Ό μƒμ„±ν•˜λ©΄ 기본적으둜 ~Application ν΄λž˜μŠ€κ°€ μƒμ„±λ˜λŠ”λ° 이 ν΄λž˜μŠ€μ—λŠ” @SpringBootApplication μ–΄λ…Έν…Œμ΄μ…˜μ΄ μžˆλŠ”λ° κ·Έ μ•ˆμ„ μ‚΄νŽ΄λ³΄λ©΄ @ComponentScan μ–΄λ…Έν…Œμ΄μ…˜μ„ ν†΅ν•΄μ„œ ν•΄λ‹Ή 클래슀λ₯Ό κΈ°μ€€μœΌλ‘œ ν•˜μœ„ νŒ¨ν‚€μ§€λ₯Ό μŠ€μΊ”ν•˜λŠ” κ±Έ μ•Œ 수 μžˆλ‹€.

 

1-2. Java config - @Configuration, @Bean

@Configuration ν΄λž˜μŠ€μ—μ„œ @Bean μ–΄λ…Έν…Œμ΄μ…˜μ„ μ‚¬μš©ν•΄ μˆ˜λ™μœΌλ‘œ μŠ€ν”„λ§ μ»¨ν…Œμ΄λ„ˆμ— λΉˆμ„ λ“±λ‘ν•˜λŠ” 방법이닀.

@Configuration
public class TestConfig {
    @Bean
    public OpenApi openApi() {
        return new OpenApi();
    }
}

μœ„μ™€ 같이 μˆ˜λ™μœΌλ‘œ Bean을 λ“±λ‘ν•˜λŠ” κ²½μš°μ—λŠ” 주둜 λ‹€μŒκ³Ό 같을 λ•Œ μ‚¬μš©ν•œλ‹€.

1. κ°œλ°œμžκ°€ 직접 μ œμ–΄κ°€ λΆˆκ°€λŠ₯ν•œ 라이브러리λ₯Ό 빈으둜 λ“±λ‘ν•˜μ—¬ μ‚¬μš©ν•  λ•Œ

2. μ „λ²”μœ„μ μœΌλ‘œ μ‚¬μš©λ˜λŠ” 클래슀λ₯Ό 등둝할 λ•Œ

3. λ‹€ν˜•μ„±μ„ ν™œμš©ν•˜μ—¬ μ—¬λŸ¬ κ΅¬ν˜„μ²΄λ₯Ό 등둝해주어야 ν•  λ•Œ

 

2. DI(Dependency Injection) - μ˜μ‘΄μ„± μ£Όμž…

Bean으둜 λ“±λ‘ν•˜κ³  μŠ€ν”„λ§ IOC μ»¨ν…Œμ΄λ„ˆμ— μ˜ν•΄ 생성도 λ˜μ—ˆλ‹€λ©΄, 이제 μ˜μ‘΄μ„± μ£Όμž…μ„ 톡해 μ‚¬μš©ν•  수 μžˆλŠ”λ° μ˜μ‘΄μ„± μ£Όμž…μ—λŠ” μ—¬λŸ¬ 가지 방법이 μžˆλ‹€. μ°¨λ‘€λŒ€λ‘œ 확인해 보자.

2-1. ν•„λ“œ μ£Όμž…

@Controller
public class TestController {
    @Autowired
    private TestService testService;
}

2-2. μˆ˜μ •μž(Setter) μ£Όμž…

@Controller
public class TestController {

    private TestService testService;

    @Autowired
    public void setTestService(TestService testService) {
        this.testService = testService;
    }
}

2-3. μƒμ„±μž μ£Όμž…

@Controller
public class TestController {

    private final TestService testService;

    public TestController(TestService testService) {
        this.testService = testService;
    }
}

λ‹€λ§Œ, ν•„λ“œλ‚˜ Setter λ©”μ„œλ“œμ—μ„œ μ£Όμž…μ„ μ‚¬μš©ν•˜λŠ” 것보닀 μƒμ„±μž μ£Όμž… 방법이 ꢌμž₯λœλ‹€. κ·Έ μ΄μœ λŠ” μ•„λž˜μ™€ κ°™λ‹€.

1. μˆœν™˜ μ°Έμ‘° 방지

Aκ°€ Bλ₯Ό μ°Έμ‘°ν•˜κ³ , Bκ°€ λ‹€μ‹œ Aλ₯Ό μ°Έμ‘°ν•˜λŠ” λ¬Έμ œ

2. λΆˆλ³€μ„±(Immutability)

μƒμ„±μžλ‘œ μ˜μ‘΄μ„±μ„ μ£Όμž…ν•  λ•Œ final둜 μ„ μ–Έν•  수 있고, λŸ°νƒ€μž„μ—μ„œ μ˜μ‘΄μ„±μ„ μ£Όμž…λ°›λŠ” 객체가 λ³€ν•  일이 μ—†μ–΄μ§€κ²Œ λœλ‹€. 또, ν•„λ“œ μ£Όμž… 방식은 null이 λ§Œλ“€μ–΄μ§ˆ κ°€λŠ₯성이 μžˆλŠ”λ° final둜 μ„ μ–Έν•œ μƒμ„±μž μ£Όμž… 방식은 null이 λΆˆκ°€λŠ₯ν•˜λ‹€.

Reference