๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
๐Ÿ•Š๏ธ ํ”„๋กœ๊ทธ๋ž˜๋จธ์Šค ๋ฐ๋ธŒ์ฝ”์Šค

SpringBoot Part1-3

by hyeon-z 2023. 6. 22.

 

1. Circular Dependency (์›ํ˜• ์˜์กด์„ฑ)

 

- ๋‘ ๊ฐœ ์ด์ƒ์˜ ๊ฐ์ฒด ๊ฐ„์— ์„œ๋กœ๊ฐ€ ์„œ๋กœ์— ๋Œ€ํ•ด ์˜์กดํ•˜๋Š” ์ƒํ™ฉ

- A -> B๋ฅผ ์ฐธ์กฐํ•˜๋Š” ๋™์‹œ์—  B -> A๋ฅผ ์ฐธ์กฐ

- BeanCurrentlyInCreationException ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค.

 

Circular Dependency์˜ ๋ฌธ์ œ์ 

 

@Configuration
class CircularConfig{
    @Bean
    public A a (B b) {
        return new A(b);
    }

    @Bean
    public B b(A a) {
        return new B(a);
    }
}

- ์–ด๋А ๋นˆ์„ ๋จผ์ € ์ƒ์„ฑํ•˜๊ณ  ์ฃผ์ž…ํ•ด์•ผ ํ•˜๋Š”์ง€ ํŒ๋‹จํ•˜๊ธฐ ์–ด๋ ต๋‹ค. -> BeanCurrentlyInCreationException ๋ฐœ์ƒ

- ์˜์กด์„ฑ ์ฃผ์ž…์ด ์ˆœํ™˜์ ์œผ๋กœ ๊ณ„์†๋˜๋Š” ๊ฒฝ์šฐ, ๋ฌดํ•œ ๋ฃจํ”„๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

 

ํ•ด๋‹น ๋ฌธ์ œ์ ์„ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•œ ๋ฐฉ๋ฒ•์€ ํ•˜๋‹จ ๋ธ”๋กœ๊ทธ ์ฐธ๊ณ !

https://www.baeldung.com/circular-dependencies-in-spring


2. Component Scan

 

์Šคํ”„๋ง์ด ์ง์ ‘ ํด๋ž˜์Šค๋ฅผ ๊ฒ€์ƒ‰ํ•ด์„œ ๋นˆ์œผ๋กœ ๋“ฑ๋กํ•ด ์ฃผ๋Š” ๊ธฐ๋Šฅ

=> ์„ค์ • ํด๋ž˜์Šค์— ๋นˆ์œผ๋กœ ์ง์ ‘ ๋“ฑ๋กํ•˜์ง€ ์•Š์•„๋„ ์›ํ•˜๋Š” ํด๋ž˜์Šค๋ฅผ ๋นˆ์œผ๋กœ ๋“ฑ๋กํ•  ์ˆ˜ ์žˆ๋‹ค.

 

@ComponentScan

 

์ปดํฌ๋„ŒํŠธ ์Šค์บ๋‹์„ ์ˆ˜ํ–‰ํ•œ๋‹ค.

 

๐Ÿ‘† ์ปดํฌ๋„ŒํŠธ ์Šค์บ๋‹

- ํ˜„์žฌ ์‹คํ–‰ ์ค‘์ธ ์„ค์ • ํด๋ž˜์Šค๊ฐ€ ์†ํ•œ ํŒจํ‚ค์ง€์™€ ๊ทธ ํ•˜์œ„ ํŒจํ‚ค์ง€์—์„œ ์ปดํฌ๋„ŒํŠธ๋“ค์„ ์Šค์บ๋‹ํ•œ๋‹ค.

- ์ปดํฌ๋„ŒํŠธ๋Š” @Component, @Controller, @Service, @Repository ๋“ฑ์˜ ์Šคํ”„๋ง ๊ด€๋ จ ์• ๋…ธํ…Œ์ด์…˜์ด ๋ถ€์—ฌ๋œ ํด๋ž˜์Šค๋ฅผ ์˜๋ฏธํ•œ๋‹ค.

๐Ÿ‘† ์ž๋™ ๋นˆ ๋“ฑ๋ก

- ์ปดํฌ๋„ŒํŠธ ์Šค์บ๋‹์„ ํ†ตํ•ด ์ฐพ์•„์ง„ ํด๋ž˜์Šค๋“ค์€ ์ž๋™์œผ๋กœ ์Šคํ”„๋ง ๋นˆ์œผ๋กœ ๋“ฑ๋ก๋œ๋‹ค.

- ๊ฐœ๋ฐœ์ž๋Š” ๋นˆ ๋“ฑ๋ก์— ๋Œ€ํ•œ ๋ช…์‹œ์ ์ธ ์„ค์ •์„ ์ค„์ผ ์ˆ˜ ์žˆ๋‹ค.

๐Ÿ‘† ํŒจํ‚ค์ง€ ๋ฐ ํ•„ํ„ฐ๋ง ์„ค์ •

- ์Šค์บ๋‹ํ•  ํŒจํ‚ค์ง€๋ฅผ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, includeFilters์™€ excludeFilters๋ฅผ ํ†ตํ•ด ํŠน์ • ์กฐ๊ฑด์— ๋”ฐ๋ผ ์Šค์บ๋‹ํ•  ํด๋ž˜์Šค๋ฅผ ํ•„ํ„ฐ๋งํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

- ์Šค์บ๋‹ ๋ฒ”์œ„๋ฅผ ์„ธ๋ฐ€ํ•˜๊ฒŒ ์ œ์–ดํ•  ์ˆ˜ ์žˆ๋‹ค.

๐Ÿ‘† ๋‹ค์ค‘ @ComponentScan

- ์—ฌ๋Ÿฌ ๊ฐœ์˜ @ComponentScan ์• ๋…ธํ…Œ์ด์…˜์„ ์‚ฌ์šฉํ•˜์—ฌ ๋‹ค๋ฅธ ํŒจํ‚ค์ง€๋ฅผ ๋Œ€์ƒ์œผ๋กœ ์Šค์บ๋‹ํ•  ์ˆ˜ ์žˆ๋‹ค.

- ์—ฌ๋Ÿฌ ํŒจํ‚ค์ง€์— ๊ฑธ์ณ ์žˆ๋Š” ์ปดํฌ๋„ŒํŠธ๋“ค์„ ํ•œ ๋ฒˆ์— ๋“ฑ๋กํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

 

๐Ÿค” ์Šคํ”„๋ง์€ ์ž๋™์œผ๋กœ ๋“ฑ๋ก๋  Bean์„ ์–ด๋–ป๊ฒŒ ์ฐพ์„๊นŒ?

Stereotype ์• ๋…ธํ…Œ์ด์…˜์„ ์ด์šฉํ•ด์„œ ์ฐพ๋Š”๋‹ค.

 

Stereotype

 

- ์Šคํ”„๋ง ํ”„๋ ˆ์ž„์›Œํฌ์—์„œ ์ œ๊ณตํ•˜๋Š” ์• ๋…ธํ…Œ์ด์…˜๋“ค์˜ ๊ทธ๋ฃน์œผ๋กœ, ํŠน์ •ํ•œ ์˜๋ฏธ์™€ ์—ญํ• ์„ ๊ฐ€์ง„ ์• ๋…ธํ…Œ์ด์…˜๋“ค์„ ์ง€์นญํ•œ๋‹ค.

- ์ปดํฌ๋„ŒํŠธ ์Šค์บ”(ComponentScan)๊ณผ ํ•จ๊ป˜ ์‚ฌ์šฉ๋˜์–ด ํŠน์ • ์• ๋…ธํ…Œ์ด์…˜์ด ๋ถ™์€ ํด๋ž˜์Šค๋“ค์„ ์Šค์บ”ํ•˜์—ฌ ์Šคํ”„๋ง ๋นˆ์œผ๋กœ ๋“ฑ๋กํ•˜๋Š” ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•œ๋‹ค.

https://incheol-jung.gitbook.io/docs/q-and-a/spring/stereo-type

 

๐Ÿ‘† @Component

ํ•ด๋‹น ํด๋ž˜์Šค๋ฅผ ์Šคํ”„๋ง ๋นˆ์œผ๋กœ ๋“ฑ๋กํ•œ๋‹ค.

 

๐Ÿ“ข @Bean์™€ @Component์˜ ์ฐจ์ด์ 

@Component
- ํด๋ž˜์Šค ์ƒ๋‹จ์— ์ ์œผ๋ฉฐ, default๋กœ ํด๋ž˜์Šค ์ด๋ฆ„์ด Bean์˜ ์ด๋ฆ„์ด ๋œ๋‹ค.

- ์Šคํ”„๋ง์—์„œ @ComponentScan์„ ์‚ฌ์šฉํ•ด์„œ ์ž๋™์œผ๋กœ ์ฐพ์•„์ฃผ๊ณ  ๊ด€๋ฆฌํ•ด ์ค€๋‹ค.

@Bean
- @Configuration์œผ๋กœ ์„ ์–ธ๋œ ํด๋ž˜์Šค ๋‚ด์— ์žˆ๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ์ •์˜ํ•  ๋•Œ ์‚ฌ์šฉํ•œ๋‹ค.
- ์ด ๋ฉ”์„œ๋“œ๊ฐ€ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฐ์ฒด๊ฐ€ Bean์ด ๋˜๋ฉฐ, default๋กœ ๋ฉ”์„œ๋“œ ์ด๋ฆ„์ด Bean์˜ ์ด๋ฆ„์ด ๋œ๋‹ค.

 

๐Ÿ‘† @Configuration

- ํ•œ ๊ฐœ ์ด์ƒ์˜ @Bean ์• ๋…ธํ…Œ์ด์…˜์œผ๋กœ ์ •์˜ํ•œ bean ๋“ค์„ ์ƒ์„ฑํ•˜๋ ค ํ•  ๋•Œ ํด๋ž˜์Šค์— ์ •์˜ํ•˜๋Š” ์–ด๋…ธํ…Œ์ด์…˜

- ์„ค์ • ํด๋ž˜์Šค๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ์• ๋…ธํ…Œ์ด์…˜์œผ๋กœ ์Šคํ”„๋ง ๋นˆ์„ ์ •์˜ํ•˜๊ณ  ์„ค์ • ์ •๋ณด๋ฅผ ์ œ๊ณตํ•œ๋‹ค.

 

๐Ÿ‘† @Repository

- ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์™€์˜ ์ƒํ˜ธ์ž‘์šฉ์„ ๋‹ด๋‹นํ•˜๋Š” ๋ฆฌํฌ์ง€ํ† ๋ฆฌ(๋ฐ์ดํ„ฐ ์ ‘๊ทผ ๊ณ„์ธต) ํด๋ž˜์Šค๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ์• ๋…ธํ…Œ์ด์…˜

- ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค CRUD ์ž‘์—…์ด๋‚˜ ๋ฐ์ดํ„ฐ ์กฐ์ž‘๊ณผ ๊ด€๋ จ๋œ ๋กœ์ง์„ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋œ๋‹ค.

 

๐Ÿ‘† @Service

- ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ ์ฒ˜๋ฆฌํ•˜๋Š” ์„œ๋น„์Šค ํด๋ž˜์Šค๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ์• ๋…ธํ…Œ์ด์…˜

- ์ฃผ๋กœ ์ปจํŠธ๋กค๋Ÿฌ์™€ ๋ฆฌํฌ์ง€ํ† ๋ฆฌ ์‚ฌ์ด์—์„œ ๋ฐ์ดํ„ฐ ์กฐ์ž‘์ด๋‚˜ ๋น„์ฆˆ๋‹ˆ์Šค ๊ทœ์น™์„ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋œ๋‹ค.

 

๐Ÿ‘† @Controller

- ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ์ปจํŠธ๋กค๋Ÿฌ ์—ญํ• ์„ ์ˆ˜ํ–‰ํ•˜๋Š” ํด๋ž˜์Šค๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ์• ๋…ธํ…Œ์ด์…˜

- MVC ์•„ํ‚คํ…์ฒ˜์—์„œ ์‚ฌ์šฉ๋˜๋ฉฐ, ํด๋ผ์ด์–ธํŠธ์˜ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๊ณ  ์ ์ ˆํ•œ ์‘๋‹ต์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ์—ญํ• ์„ ๋‹ด๋‹นํ•ฉ๋‹ˆ๋‹ค


3. Component Scan ์‹ค์Šต

 

Repository ๊ตฌํ˜„์ฒด ๋งŒ๋“ค๊ธฐ

 

@Repository
public class MemoryVoucherRepository implements VoucherRepository {
    private final Map<UUID, Voucher> storage = new ConcurrentHashMap<>();

    @Override
    public Voucher insert(Voucher voucher) {
        storage.put(voucher.getVoucherId(), voucher);
        return voucher;
    }
}

@Repository ์• ๋…ธํ…Œ์ด์…˜์„ ํ†ตํ•ด์„œ VoucherRespository์˜ ๊ตฌํ˜„์ฒด์ธ MemoryVoucherRepository๋ฅผ ์Šค์บ”ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•œ๋‹ค.

 

๐Ÿค” interface์ธ VoucherRepository์—๋Š” ์•ˆ ๋ถ™์—ฌ๋„ ๋˜๋‚˜?

 

๋ถ™์—ฌ๋„ ๋˜๊ณ  ์•ˆ ๋ถ™์—ฌ๋„ ๋˜์ง€๋งŒ ๋ณดํ†ต์˜ ๊ฒฝ์šฐ ๊ตฌํ˜„์ฒด์—๋งŒ ๋ถ™์ธ๋‹ค.

 

Spring์€ @Repository ์• ๋…ธํ…Œ์ด์…˜์ด ๋ถ™์€ ํด๋ž˜์Šค๋ฅผ ์Šค์บ”ํ•˜์—ฌ Repository ์ธํ„ฐํŽ˜์ด์Šค์™€ ๋งคํ•‘ํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ๋™์ž‘ํ•œ๋‹ค.

=> MemoryVoucherRepository๋ฅผ VoucherRepository ์ธํ„ฐํŽ˜์ด์Šค์˜ ๋นˆ์œผ๋กœ ๋“ฑ๋ก

 

+) interface์ธ VoucherRepository์—๋งŒ @Repository ์• ๋…ธํ…Œ์ด์…˜์„ ๋ถ™์ด๋ฉด ๊ตฌํ˜„์ฒด๋ฅผ Bean์œผ๋กœ ๋“ฑ๋กํ•˜๊ฑฐ๋‚˜ ๊ด€๋ฆฌํ•  ์ˆ˜ ์—†๋‹ค.

 

๐Ÿ’ก  ConcurrentHashmap์ด๋ž€?

Hashtable ํด๋ž˜์Šค์˜ ๋‹จ์ ์„ ๋ณด์™„ํ•˜๋ฉด์„œ Multi-Thread ํ™˜๊ฒฝ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ๋‚˜์˜จ ํด๋ž˜์Šค

- Thread-Safe ํ•˜๋‹ค
- ์–ด๋–ค Entry๋ฅผ ์กฐ์ž‘ํ•˜๋Š” ๊ฒฝ์šฐ์— ํ•ด๋‹น Entry์— ๋Œ€ํ•ด์„œ๋งŒ ๋ฝ์„ ๊ฑด๋‹ค.
- HashTable๋ณด๋‹ค ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ค๋ฃจ๋Š” ์†๋„๊ฐ€ ๋น ๋ฅด๋‹ค.

=> Entry ์•„์ดํ…œ๋ณ„๋กœ ๋ฝ์„ ๊ฑธ์–ด ๋ฉ€ํ‹ฐ ์Šค๋ ˆ๋“œ ํ™˜๊ฒฝ์—์„œ์˜ ์„ฑ๋Šฅ์„ ํ–ฅ์ƒ์‹œํ‚จ๋‹ค.

๋™์ž‘์›๋ฆฌ๊ฐ€ ๊ถ๊ธˆํ•˜๋‹ค๋ฉด ์ถ”๊ฐ€๋กœ ๋ณด๋ฉด ์ข‹์„ ๋“ฏ!
[Java] ConcurrentHashMap๋Š” ์–ด๋–ป๊ฒŒ Thread-safe ํ•œ๊ฐ€?

 

Service์—์„œ Repository ์˜์กด์„ฑ ์ฃผ์ž…๋ฐ›๊ธฐ

 

@Service
public class VoucherService {
    private final VoucherRepository voucherRepository;

    public VoucherService(VoucherRepository voucherRepository) {
        this.voucherRepository = voucherRepository;
    }
}

VoucherService์—์„œ ์ƒ์„ฑ์ž๋ฅผ ํ†ตํ•œ ์˜์กด์„ฑ ์ฃผ์ž…์„ ํ†ตํ•ด ์Šคํ”„๋ง์€ ์ž๋™์œผ๋กœ MemoryVoucherRepository ๋นˆ์„ ์ฃผ์ž…ํ•˜์—ฌ ์‚ฌ์šฉํ•œ๋‹ค.

+) MemoryVoucherRepository ํด๋ž˜์Šค๊ฐ€ VoucherRepository ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•˜๊ณ  ์žˆ์œผ๋ฉฐ @Repository ์• ๋…ธํ…Œ์ด์…˜์ด ๋ถ™์–ด์žˆ๊ธฐ ๋•Œ๋ฌธ์—, ํ•ด๋‹น ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค๊ฐ€ VoucherRepository ํƒ€์ž…์˜ ๋นˆ์œผ๋กœ ๋“ฑ๋ก๋˜์–ด ์žˆ์œผ๋ฉด ์ฃผ์ž…๋œ๋‹ค.

 

๐Ÿค”VoucherRepository์˜ ๊ตฌํ˜„์ฒด๊ฐ€ ์—ฌ๋Ÿฌ ๊ฐœ์ธ ๊ฒฝ์šฐ์—๋Š” ์–ด๋–ป๊ฒŒ ๋™์ž‘ํ• ๊นŒ?

 

1. @Qualifier์„ ์‚ฌ์šฉํ•œ ๋ช…์‹œ์ ์ธ ๋นˆ ์ฃผ์ž…

 

@Service
public class VoucherService {
    private final VoucherRepository voucherRepository;

    @Autowired
    public VoucherService(@Qualifier("memoryVoucherRepository") VoucherRepository voucherRepository) {
        this.voucherRepository = voucherRepository;
    }

    // ...
}

VoucherService ํด๋ž˜์Šค์˜ ์ƒ์„ฑ์ž์— @Qualifier ์• ๋…ธํ…Œ์ด์…˜์„ ์‚ฌ์šฉํ•˜์—ฌ "memoryVoucherRepository"๋ผ๋Š” ์ด๋ฆ„์˜ ๋นˆ์„ ์ฃผ์ž…ํ•˜๋„๋ก ๋ช…์‹œ์ ์œผ๋กœ ์ง€์ •ํ•˜๊ณ  ์žˆ๋‹ค. ์Šคํ”„๋ง์€ ํ•ด๋‹น ์ด๋ฆ„์„ ๊ฐ€์ง„ ๋นˆ์„ ์ฐพ์•„์„œ ์ฃผ์ž…ํ•œ๋‹ค.

 

2. @Primary๋ฅผ ์‚ฌ์šฉํ•œ ์šฐ์„ ์ ์ธ ๋นˆ ์ฃผ์ž…

 

@Repository
@Primary
public class MemoryVoucherRepository implements VoucherRepository {
    // ...
}

@Primary ์• ๋…ธํ…Œ์ด์…˜์„ ์‚ฌ์šฉํ•˜์—ฌ MemoryVoucherRepository ํด๋ž˜์Šค๋ฅผ ์ฃผ ์šฉ๋„๋กœ ์‚ฌ์šฉํ•˜๋Š” ๊ธฐ๋ณธ ๋นˆ์œผ๋กœ ์ง€์ •ํ•˜๊ณ  ์žˆ๋‹ค.

VoucherService ํด๋ž˜์Šค์—์„œ VoucherRepository๋ฅผ ์ฃผ์ž…๋ฐ›์„ ๋•Œ ๋ช…์‹œ์ ์œผ๋กœ ์–ด๋–ค ๋นˆ์„ ์ฃผ์ž…ํ• ์ง€ ์ง€์ •ํ•˜์ง€ ์•Š์•˜๋‹ค๋ฉด, ์Šคํ”„๋ง์€ @Primary ์• ๋…ธํ…Œ์ด์…˜์ด ๋ถ™์€ MemoryVoucherRepository ๋นˆ์„ ์šฐ์„ ์ ์œผ๋กœ ์ฃผ์ž…ํ•œ๋‹ค.

+) ๋ฐ˜๋“œ์‹œ ํ•˜๋‚˜์˜ ๋นˆ์—๋งŒ ์ ์šฉํ•ด์•ผ ํ•œ๋‹ค. 

 

๐Ÿ’ก@Qualifier์™€ @Primary์˜ ์šฐ์„ ์ˆœ์œ„

1. @Qualifier๋กœ ๋ช…์‹œํ•œ ๋นˆ์ด ์šฐ์„ ์ ์œผ๋กœ ์ฃผ์ž…๋œ๋‹ค.
2. @Qualifier๋กœ ๋ช…์‹œํ•œ ๋นˆ์ด ์—†๋Š” ๊ฒฝ์šฐ, @Primary ์• ๋…ธํ…Œ์ด์…˜์ด ๋ถ™์€ ๋นˆ์ด ์ฃผ์ž…๋œ๋‹ค.
3. @Qualifier๋กœ ๋ช…์‹œํ•œ ๋นˆ์ด ์—†๊ณ , @Primary ์• ๋…ธํ…Œ์ด์…˜์ด ๋ถ™์€ ๋นˆ๋„ ์—†๋Š” ๊ฒฝ์šฐ์—๋Š” NoSuchBeanDefinitionException ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

 

ComponentScan์‹œ ํŠน์ • ํŒจํ‚ค์ง€ ์ง€์ •ํ•˜๊ธฐ

 

1. @ComponentScan(basePackages = {})

 

ํŒจํ‚ค์ง€์˜ ์ด๋ฆ„์„ ์ง์ ‘ ์ง€์ •ํ•˜๋Š” ๋ฐฉ๋ฒ•

 

๋ฌธ์ž์—ด ๋ฐฐ์—ด์„ ์ „๋‹ฌํ•˜์—ฌ ์Šค์บ”ํ•œ ํŒจํ‚ค์ง€๋ฅผ ๋ช…์‹œํ•œ๋‹ค.

@ComponentScan(basePackages = {"org.prgms.kdt.springorder.order", "org.prgms.kdt.springorder.voucher"})

์„ค์ • ํŒŒ์ผ๊ณผ ๊ฐ™์€ ํŒจํ‚ค์ง€์— ์žˆ์–ด๋„ ํ•ด๋‹น ๋ฐฐ์—ด์— ํฌํ•จ๋˜์ง€ ์•Š์œผ๋ฉด ์Šค์บ”ํ•˜์ง€ ์•Š๋Š”๋‹ค.

 

2. @ComponentScan(basePackageClasses = {})

 

ํด๋ž˜์Šค๋ฅผ ๊ธฐ์ค€์œผ๋กœ ํŒจํ‚ค์ง€๋ฅผ ์ง€์ •ํ•˜๋Š” ๋ฐฉ๋ฒ•

 

ํด๋ž˜์Šค ๋ฐฐ์—ด์„ ์ „๋‹ฌํ•˜์—ฌ, ํ•ด๋‹น ํด๋ž˜์Šค๊ฐ€ ์กด์žฌํ•˜๋Š” ํŒจํ‚ค์ง€๊ฐ€ ์Šค์บ” ๋Œ€์ƒ์ด ๋œ๋‹ค.

@ComponentScan(basePackageClasses = {Order.class, Voucher.class})

Order.class์™€ Voucher.class๊ฐ€ ์žˆ๋Š” ํŒจํ‚ค์ง€๋งŒ ์Šค์บ”ํ•œ๋‹ค.

 

๐Ÿ’กexcludeFilters, includeFilters

excludeFilters
์Šค์บ” ๋Œ€์ƒ์—์„œ ์ œ์™ธํ•  ํ•„ํ„ฐ๋ฅผ ์ง€์ •ํ•œ๋‹ค.
์ฆ‰, ํ•ด๋‹น ํ•„ํ„ฐ์˜ ์กฐ๊ฑด์„ ๋งŒ์กฑํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ๋Š” ์Šค์บ” ๋Œ€์ƒ์—์„œ ์ œ์™ธ๋ฉ๋‹ˆ๋‹ค.

includeFilters
์Šค์บ” ๋Œ€์ƒ์— ํฌํ•จํ•  ํ•„ํ„ฐ๋ฅผ ์ง€์ •ํ•œ๋‹ค.
์ฆ‰, ํ•ด๋‹น ํ•„ํ„ฐ์˜ ์กฐ๊ฑด์„ ๋งŒ์กฑํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ๋งŒ ์Šค์บ” ๋Œ€์ƒ์œผ๋กœ ํฌํ•จ๋œ๋‹ค.

๐Ÿ“Œ FilterType ์ข…๋ฅ˜

FilterType.ANNOTATION: ํŠน์ • ์• ๋…ธํ…Œ์ด์…˜์ด ์ ์šฉ๋œ ํด๋ž˜์Šค๋ฅผ ๋Œ€์ƒ์œผ๋กœ ํ•œ๋‹ค.
FilterType.ASSIGNABLE_TYPE:  ํŠน์ • ํด๋ž˜์Šค๋‚˜ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ƒ์†ํ•˜๊ฑฐ๋‚˜ ๊ตฌํ˜„ํ•œ ํด๋ž˜์Šค๋ฅผ ๋Œ€์ƒ์œผ๋กœ ํ•œ๋‹ค.
FilterType.REGEX: ์ •๊ทœ์‹ ํŒจํ„ด๊ณผ ์ผ์น˜ํ•˜๋Š” ํด๋ž˜์Šค ์ด๋ฆ„์„ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋Œ€์ƒ์œผ๋กœ ํ•œ๋‹ค.
FilterType.ASPECTJ: AspectJ ํŒจํ„ด๊ณผ ์ผ์น˜ํ•˜๋Š” ํด๋ž˜์Šค๋ฅผ ๋Œ€์ƒ์œผ๋กœ ํ•œ๋‹ค.
FilterType.CUSTOM: ์ปค์Šคํ…€ ํ•„ํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์Šค์บ” ๋Œ€์ƒ์„ ์ œ์–ดํ•œ๋‹ค. ์ปค์Šคํ…€ ํ•„ํ„ฐ๋Š” TypeFilter ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•ด์•ผ ํ•˜๋ฉฐ, match() ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด ์กฐ๊ฑด์„ ์ •์˜ํ•œ๋‹ค.

4. Autowired

 

SpringBoot 1-2์—์„œ ์ž ๊น ๋‹ค๋ค˜๋˜ DI ์ข…๋ฅ˜๋“ค์ด๋‹ค.

์˜ˆ์‹œ๋ฅผ ๋“ค์–ด ์ข€ ๋” ์ž์„ธํžˆ ์‚ดํŽด๋ณด์ž.

 

DI ์ข…๋ฅ˜

 

๐Ÿ‘† ์ƒ์„ฑ์ž ์ฃผ์ž… (Constructor Injection)

 

๊ฐ์ฒด์˜ ์ƒ์„ฑ์ž๋ฅผ ํ†ตํ•ด ์˜์กด์„ฑ์„ ์ฃผ์ž…ํ•˜๋Š” ๋ฐฉ์‹

๊ฐ์ฒด์˜ ์ƒ์„ฑ ์‹œ์ ์— ํ•„์š”ํ•œ ์˜์กด์„ฑ์„ ์™ธ๋ถ€์—์„œ ์ „๋‹ฌ๋ฐ›์•„ ์‚ฌ์šฉํ•œ๋‹ค.

 

private final VoucherRepository voucherRepository;

public VoucherService(VoucherRepository voucherRepository) {
    this.voucherRepository = voucherRepository;
}

์ƒ์„ฑ์ž๊ฐ€ ํ•˜๋‚˜์ธ ๊ฒฝ์šฐ์—๋งŒ ์ž๋™์œผ๋กœ @Autowired๊ฐ€ ๋ถ™๋Š”๋‹ค.

 

๐Ÿ‘† setter ์ฃผ์ž…(Setter Injection)

 

๊ฐ์ฒด์˜ setter ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด ์˜์กด์„ฑ์„ ์ฃผ์ž…ํ•˜๋Š” ๋ฐฉ์‹

์˜์กด์„ฑ์„ ์„ค์ •ํ•˜๊ธฐ ์œ„ํ•ด setter ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ์™ธ๋ถ€์—์„œ ์˜์กด์„ฑ์„ ์ฃผ์ž…ํ•œ๋‹ค.

 

private VoucherRepository voucherRepository;

@Autowired
public void setVoucherRepository(VoucherRepository voucherRepository) {
    this.voucherRepository = voucherRepository;
}

 

๐Ÿ‘† ํ•„๋“œ ์ฃผ์ž…(Field Injection)

 

์˜์กด์„ฑ์„ ํด๋ž˜์Šค์˜ ๋ฉค๋ฒ„ ํ•„๋“œ๋กœ ์ง์ ‘ ์ฃผ์ž…ํ•˜๋Š” ๋ฐฉ์‹

์ฃผ๋กœ @Autowired ์–ด๋…ธํ…Œ์ด์…˜์„ ์‚ฌ์šฉํ•˜์—ฌ ํ•„๋“œ์— ์ž๋™์œผ๋กœ ์˜์กด์„ฑ์„ ์ฃผ์ž…ํ•œ๋‹ค.

 

private VoucherRepository voucherRepository;

@Autowired
private VoucherRepository voucherRepository;

 

๐Ÿค” ์ƒ์„ฑ์ž ์ฃผ์ž… ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•˜๋Š”๋ฐ ์ƒ์„ฑ์ž๊ฐ€ 2๊ฐœ๋ฉด ์–ด๋–ป๊ฒŒ ํ•ด์•ผ ํ• ๊นŒ?

 

๋‘ ์ƒ์„ฑ์ž ์ค‘ DI๋ฅผ ํ•˜๋Š” ์ƒ์„ฑ์ž์— @Autowired ์• ๋…ธํ…Œ์ด์…˜์„ ๋‹ฌ์•„์„œ ๋ช…์‹œ์ ์œผ๋กœ ์˜์กด์„ฑ์„ ์ฃผ์ž…ํ•œ๋‹ค.

 

์–ด๋–ค DI ๋ฐฉ๋ฒ•์„ ์„ ํƒํ•ด์•ผ ํ• ๊นŒ?

 

https://docs.spring.io/spring-framework/reference/core/beans/dependencies/factory-collaborators.html#beans-setter-injection

์Šคํ”„๋ง ๊ณต์‹ ๋ฌธ์„œ์— ์ƒ์„ฑ์ž ์ฃผ์ž… ๋ฐฉ์‹์„ ๊ถŒ์žฅํ•œ๋‹ค๊ณ  ์“ฐ์—ฌ์žˆ๋‹ค.

๊ทธ ์ด์œ ๊ฐ€ ๋ฌด์—‡์ผ๊นŒ?

 

๐Ÿ‘† ๋‹จ์œ„ ํ…Œ์ŠคํŠธํ•˜๊ธฐ์— ์šฉ์ดํ•˜๋‹ค.

์˜์กด์„ฑ์„ ์™ธ๋ถ€์—์„œ ์ฃผ์ž…๋ฐ›๊ธฐ ๋•Œ๋ฌธ์— ๋‹จ์œ„ ํ…Œ์ŠคํŠธ์—์„œ ๋ชจ์˜ ๊ฐ์ฒด(Mock Object)๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์˜์กด์„ฑ์„ ์ฃผ์ž…ํ•˜๋Š” ๊ฒƒ์ด ์‰ฝ๋‹ค.

 

๋˜ํ•œ ๋‹ค๋ฅธ ์ฃผ์ž… ๋ฐฉ์‹์€ ์ˆœ์ˆ˜ ์ž๋ฐ” ์ฝ”๋“œ๋กœ ๋‹จ์œ„ ํ…Œ์ŠคํŠธ๋ฅผ ์ž‘์„ฑํ•˜๋Š” ๊ฒƒ์ด ํž˜๋“ค๋‹ค.

ํ…Œ์ŠคํŠธ์ฝ”๋“œ๋Š” Spring ์œ„์—์„œ ๋™์ž‘ํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ ์˜์กด ๊ด€๊ณ„ ์ฃผ์ž…์ด ๋ฐœ์ƒํ•˜์ง€ ์•Š์•„์„œ NPE(Null Pointer Exception)๋ฅผ ๋ฐœ์ƒํ•œ๋‹ค.

 

๐Ÿ‘† ๋ถˆ๋ณ€์„ฑ์„ ํ™•๋ณดํ•œ๋‹ค.

์˜์กด์„ฑ์ด ์ฃผ์ž…๋œ ๊ฐ์ฒด๋Š” ๋ณ€๊ฒฝํ•  ์ˆ˜ ์—†๋Š” ๋ถˆ๋ณ€ ๊ฐ์ฒด๋กœ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.

์˜์กด์„ฑ์€ ๊ฐ์ฒด๊ฐ€ ์ƒ์„ฑ๋  ๋•Œ ์ฃผ์ž…๋˜๋ฉฐ, ์ดํ›„์—๋Š” ๋ณ€๊ฒฝํ•  ์ˆ˜ ์—†๋‹ค.

์ด๋Š” ๊ฐ์ฒด์˜ ์•ˆ์ •์„ฑ๊ณผ ์˜ˆ์ธก ๊ฐ€๋Šฅ์„ฑ์„ ๋†’์—ฌ์ค€๋‹ค.

 

๐Ÿ‘†์ˆœํ™˜ ์ฐธ์กฐ๋ฅผ ๋ฐฉ์ง€ํ•œ๋‹ค.

์ˆœํ™˜ ์ฐธ์กฐ๋ฅผ ๋Ÿฐํƒ€์ž„ ์‹œ์ ์— ๊ฐ์ง€ํ•˜๊ณ  ์˜ˆ์™ธ๋ฅผ ๋ฐœ์ƒ์‹œ์ผœ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋‹ค.

 

์ƒ์„ฑ์ž ์ฃผ์ž…์€ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๋Š” ์‹œ์ ์— ์˜์กด์„ฑ์„ ์ฃผ์ž…ํ•˜๊ณ  ๋‹ค๋ฅธ ๋ฐฉ๋ฒ•์€ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•œ ํ›„ ์˜์กด์„ฑ์„ ์ฃผ์ž…ํ•œ๋‹ค.

๋”ฐ๋ผ์„œ ์ƒ์„ฑ์ž ์ฃผ์ž…์€ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๋Š” ์‹œ์ ์—์„œ ๋ฌธ์ œ๋ฅผ ํƒ์ง€ํ•  ์ˆ˜ ์žˆ๊ณ  ๋‚˜๋จธ์ง€ ๋ฐฉ๋ฒ•์€ ์‹ค์ œ ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜ ์‹คํ–‰ํ•  ๋•Œ ๋ฌธ์ œ๋ฅผ ์•Œ ์ˆ˜ ์žˆ๋‹ค.

 

๐Ÿ‘†๊ฐœ๋ฐœ์ž์˜ ์˜์กด์„ฑ ์ฃผ์ž… ์‹ค์ˆ˜ ๋ฐฉ์ง€ (final ํ‚ค์›Œ๋“œ์˜ ์‚ฌ์šฉ)

๊ตฌํ˜„์ฒด ์ฃผ์ž…์— ๋Œ€ํ•œ ์ฝ”๋“œ๋ฅผ ์žŠ์–ด๋ฒ„๋ฆฌ๊ณ  ์ ์ง€ ์•Š์•„๋„ ์ปดํŒŒ์ผ ์‹œ์ ์—์„œ ๋ˆ„๋ฝ๋œ ์˜์กด์„ฑ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.


5. Beans Scope

 

https://docs.spring.io/spring-framework/reference/core/beans/factory-scopes.html

 

 

์Šคํ”„๋ง ํ”„๋ ˆ์ž„์›Œํฌ์—์„œ๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ์‹ฑ๊ธ€ํ†ค(Singleton)๊ณผ ํ”„๋กœํ† ํƒ€์ž…(Prototype) ๋‘ ๊ฐ€์ง€ ์Šค์ฝ”ํ”„๋ฅผ ์ง€์›ํ•œ๋‹ค.

๊ทธ ์ด์œ ๋Š” ์ด ๋‘ ๊ฐ€์ง€ ์Šค์ฝ”ํ”„๊ฐ€ ๋Œ€๋ถ€๋ถ„์˜ ์ƒํ™ฉ์—์„œ ์š”๊ตฌ์‚ฌํ•ญ์„ ์ถฉ์กฑ์‹œํ‚ฌ ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

๐Ÿ‘† ์‹ฑ๊ธ€ํ†ค ์Šค์ฝ”ํ”„

ํ•˜๋‚˜์˜ ๋นˆ ์ธ์Šคํ„ด์Šค๋ฅผ ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ ๋‹น ํ•˜๋‚˜๋งŒ ์ƒ์„ฑํ•˜์—ฌ ๊ด€๋ฆฌํ•œ๋‹ค.

๋”ฐ๋ผ์„œ ๋™์ผํ•œ ๋นˆ์„ ์š”์ฒญํ•  ๋•Œ๋งˆ๋‹ค ํ•ญ์ƒ ๋™์ผํ•œ ์ธ์Šคํ„ด์Šค๊ฐ€ ๋ฐ˜ํ™˜๋œ๋‹ค.

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

๐Ÿ‘† ํ”„๋กœํ† ํƒ€์ž… ์Šค์ฝ”ํ”„

์š”์ฒญํ•  ๋•Œ๋งˆ๋‹ค ์ƒˆ๋กœ์šด ๋นˆ ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.

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

์˜ˆ๋ฅผ ๋“ค์–ด, ๊ฐ๊ฐ์˜ ์š”์ฒญ์— ๋Œ€ํ•ด ๋ณ„๋„์˜ ์ƒํƒœ๋ฅผ ์œ ์ง€ํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ์— ํ”„๋กœํ† ํƒ€์ž… ์Šค์ฝ”ํ”„๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

 

๋นˆ ์Šค์ฝ”ํ”„๋ฅผ ๋ณ€๊ฒฝํ•˜๋Š” ๋ฐฉ๋ฒ•

 

ํ•ด๋‹น ๋นˆ์˜ ํด๋ž˜์Šค๋‚˜ ๊ตฌ์„ฑ ํŒŒ์ผ์— @Scope ์• ๋…ธํ…Œ์ด์…˜์„ ์ถ”๊ฐ€ํ•˜๊ณ  ์›ํ•˜๋Š” ์Šค์ฝ”ํ”„ ๊ฐ’์„ ์„ค์ •ํ•˜๋ฉด ๋œ๋‹ค. 

@Scope(value = ConfigurableBeanFactory.SCOPE_SINGLETON)  // default
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)

6. Lifes Cycle

 

Spring Application Context๋Š” ๊ฐ์ฒด์˜ ์ƒ์„ฑ๊ณผ ์†Œ๋ฉธ, ์ฆ‰ ์ƒ๋ช…์ฃผ๊ธฐ(Life Cycle)๋ฅผ ๊ด€๋ฆฌํ•œ๋‹ค.

applicationContext.close();

close()๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด applicationContext๊ฐ€ ์†Œ๋ฉธ๋˜๋ฉฐ, ์ปจํ…Œ์ด๋„ˆ์— ๋“ฑ๋ก๋œ ๋ชจ๋“  ๋นˆ๋„ ํ•จ๊ป˜ ์†Œ๋ฉธ๋œ๋‹ค.

์ด ๊ณผ์ •์— ์†Œ๋ฉธ์— ๋Œ€ํ•œ callback์ด ๋™์ž‘ํ•œ๋‹ค.

 

Bean ์ƒ์„ฑ ์ƒ๋ช…์ฃผ๊ธฐ ์ฝœ๋ฐฑ

 

1. @PostConstruct ์• ๋…ธํ…Œ์ด์…˜์ด ์ ์šฉ๋œ ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ

@PostConstruct
public void postConstruct() {}

2. Bean์ด InitializingBean ์ธํ„ฐํŽ˜์ด์Šค ๊ตฌํ˜„์‹œ afterPropertiesSet() ํ˜ธ์ถœ

@Repository
public class MemoryVoucherRepository implements VoucherRepository, InitializingBean {
    @Override
    public void afterPropertiesSet() throws Exception {}
}

 

3. @Bean ์• ๋…ธํ…Œ์ด์…˜์˜ initMethod์— ์„ค์ •ํ•œ ๋ฉ”์†Œ๋“œ ํ˜ธ์ถœ

public class AppConfiguration {
    @Bean(initMethod = "init")
    public BeanOne beanOne() {

    class BeanOne {
        private void init() {}
    }
}

 

Bean ์†Œ๋ฉธ ์ƒ๋ช…์ฃผ๊ธฐ ์ฝœ๋ฐฑ

 

1. @PreDestory ์• ๋…ธํ…Œ์ด์…˜์ด ์ ์šฉ๋œ ๋ฉ”์†Œ๋“œ ํ˜ธ์ถœ

@Override
public void destroy() throws Exception {}

 

2. Bean์ด DisposableBean ์ธํ„ฐํŽ˜์ด์Šค ๊ตฌํ˜„์‹œ destroy() ํ˜ธ์ถœ

@Repository
public class MemoryVoucherRepository implements VoucherRepository, DisposableBean {
    @PreDestroy
    public void preDestroy() {}
}

 

3. @Bean ์• ๋…ธํ…Œ์ด์…˜์˜ destroyMethod์— ์„ค์ •ํ•œ ๋ฉ”์†Œ๋“œ ํ˜ธ์ถœ

public class AppConfiguration {
    @Bean(initMethod = "destroy")
    public BeanOne beanOne() {

    class BeanOne {
        private void destroy() {}
    }
}

 

Reference

Circular Dependencies in Spring

HashMap vs HashTable vs ConcurrentHashMap

Spring @ComponentScan - ํ•„ํ„ฐ ์œ ํ˜•

[Spring] ์ƒ์„ฑ์ž ์ฃผ์ž…์„ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋Š” ์ด์œ 

[Spring] ๋‹ค์–‘ํ•œ ์˜์กด์„ฑ ์ฃผ์ž… ๋ฐฉ๋ฒ•๊ณผ ์ƒ์„ฑ์ž ์ฃผ์ž…์„ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋Š” ์ด์œ  - (2/2)

'๐Ÿ•Š๏ธ ํ”„๋กœ๊ทธ๋ž˜๋จธ์Šค ๋ฐ๋ธŒ์ฝ”์Šค' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

SpringBoot Part1-5  (0) 2023.06.26
SpringBoot Part1-4  (0) 2023.06.23
SpringBoot Part1-2  (0) 2023.06.21
SpringBoot Part 1-1  (0) 2023.06.21
ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ์œ„ํ•œ JAVA - OOP  (0) 2023.06.11

๋Œ“๊ธ€