STUDY๐Ÿ„

[Spring ๊ธฐ๋ณธ] 7. ์˜์กด ๊ด€๊ณ„ ์ž๋™ ์ฃผ์ž…

์ด๋ฆฌ์ญ 2025. 4. 23. 18:00

์•ˆ๋…•ํ•˜์„ธ์š”!

์ด๋ฒˆ ์„น์…˜์€ ์–ด์—„์ฒญ ๊ธธ์–ด์šฅ..ใ…œใ…œ ์˜ค๋ž˜ ๊ฑธ๋ฆด ์˜ˆ์ •..ใ…Ž

๊ทธ๋Ÿผ ์‹œ์ž‘ํ•ด ๋ณผ๊ฒŒ์š”! ๊ณ ๊ณ !!


1. ๋‹ค์–‘ํ•œ ์˜์กด ๊ด€๊ณ„ ์ฃผ์ž… ๋ฐฉ๋ฒ•

์˜์กด ๊ด€๊ณ„ ์ฃผ์ž…์€ ํฌ๊ฒŒ 4๊ฐ€์ง€ ๋ฐฉ๋ฒ•์ด ์žˆ์Šต๋‹ˆ๋‹ค.

  • ์ƒ์„ฑ์ž ์ฃผ์ž…
  • ์ˆ˜์ •์ž ์ฃผ์ž… (setter ์ฃผ์ž…)
  • ํ•„๋“œ ์ฃผ์ž…
  • ์ผ๋ฐ˜ ๋ฉ”์„œ๋“œ ์ฃผ์ž…

๊ทธ๋ƒฅ ๊ทธ๋ ค๋ดค์–ด์šฅ..

1-1. ์ƒ์„ฑ์ž ์ฃผ์ž…โญ

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

์ง€๊ธˆ๊นŒ์ง€ ์ œ๊ฐ€ ์ง„ํ–‰ํ–ˆ๋˜ ๋ฐฉ๋ฒ•์ด ๋ฐ”๋กœ ์ƒ์„ฑ์ž ์ฃผ์ž…์ž…๋‹ˆ๋‹ค.

 

<ํŠน์ง•>

1. ์ƒ์„ฑ์ž ํ˜ธ์ถœ ์‹œ์ ์— ๋”ฑ 1๋ฒˆ๋งŒ ํ˜ธ์ถœ๋˜๋Š” ๊ฒƒ์ด ๋ณด์žฅ๋ฉ๋‹ˆ๋‹ค. (์ฃผ๋กœ ์‚ฌ์šฉ)

2. ๋ถˆ๋ณ€, ํ•„์ˆ˜ ์˜์กด ๊ด€๊ณ„์— ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

@Component
public class OrderServiceImpl implements OrderService{

    private final MemberRepository memberRepository;
    private final DiscountPolicy discountPolicy;

    //์ƒ์„ฑ์ž ๋ถ€๋ถ„
    @Autowired
    public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
        this.memberRepository = memberRepository;
        this.discountPolicy = discountPolicy;
    }
    ...
}

์ƒ์„ฑ์ž ์ฃผ์ž…์ด ์ด๋ ‡๊ฒŒ ๋˜์–ด์žˆ๋Š”๋ฐ, ์ด๊ฑด ๋ถˆ๋ณ€, ํ•„์ˆ˜๋กœ ๋งŒ๋“ค์–ด๋†“์€ ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์— public์œผ๋กœ ๊ฐ’์„ ๋ฐ”๊พธ๊ฑฐ๋‚˜ ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

- private final = ์ƒ์„ฑ์ž์—์„œ ๋“ค์–ด์˜จ ๊ฐ’์ด ๋ฌด์กฐ๊ฑด ์žˆ์–ด์•ผ ํ•œ๋‹ค. (์ƒ์„ฑ์ž์—๋Š” ๊ฐ’์„ ์ฑ„์›Œ๋„ฃ์–ด์•ผ ํ•จ), ํ•„์ˆ˜

์ค‘์š”!! ์ƒ์„ฑ์ž๊ฐ€ ๋”ฑ 1๊ฐœ๋งŒ ์žˆ์œผ๋ฉด @Autowired๋ฅผ ์ƒ๋žตํ•ด๋„ ์ž๋™ ์ฃผ์ž…๋ฉ๋‹ˆ๋‹ค.
๋ชฐ๋ก , ์Šคํ”„๋ง ๋นˆ์—๋งŒ ํ•ด๋‹นํ•ฉ๋‹ˆ๋‹ค.

 

1-2. ์ˆ˜์ •์ž ์ฃผ์ž… (setter ์ฃผ์ž…)

setter๋ผ ๋ถˆ๋ฆฌ๋Š” ํ•„๋“œ์˜ ๊ฐ’์„ ๋ณ€๊ฒฝํ•˜๋Š” ์ˆ˜์ •์ž ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด์„œ ์˜์กด ๊ด€๊ณ„๋ฅผ ์ฃผ์ž…ํ•˜๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค.

 

<ํŠน์ง•>

1. ์„ ํƒ์ , ๋ณ€๊ฒฝ ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ๋Š” ์˜์กด ๊ด€๊ณ„์— ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. (๊ฐ€๋” ์‚ฌ์šฉ)

2. ์ž๋ฐ”๋นˆ ํ”„๋กœํผํ‹ฐ ๊ทœ์•ฝ์˜ ์ˆ˜์ •์ž ๋ฉ”์„œ๋“œ ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค.

@Component
public class OrderServiceImpl implements OrderService {
	
    private MemberRepository memberRepository;
    private DiscountPolicy discountPolicy;
    
    //์ˆ˜์ •์ž ๋ถ€๋ถ„
    @Autowired
    public void setMemberRepository(MemberRepository memberRepository) {
    	this.memberRepository = memberRepository;
    }
    
    //์ˆ˜์ •์ž ๋ถ€๋ถ„
    @Autowired
    public void setDiscountPolicy(DiscountPolicy discountPolicy) {
    	this.discountPolicy = discountPolicy;
    }
    ...
}

์ƒ์„ฑ์ž์™€ ์ˆ˜์ •์ž๊ฐ€ ๋‘˜ ๋‹ค ์žˆ์œผ๋ฉด ์ƒ์„ฑ์ž๊ฐ€ ๋” ๋จผ์ € ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค.

์ฐธ๊ณ !! @Autowired์˜ ๊ธฐ๋ณธ ๋™์ž‘์€ ์ฃผ์ž…ํ•  ๋Œ€์ƒ์ด ์—†์œผ๋ฉด ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.
์ฃผ์ž…ํ•  ๋Œ€์ƒ์ด ์—†์–ด๋„ ๋™์ž‘ํ•˜๊ฒŒ ํ•˜๋ ค๋ฉด @Autowired(required = false)๋กœ ์ง€์ •ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.
์ฐธ๊ณ !! ์ž๋ฐ”๋นˆ ํ”„๋กœํผํ‹ฐ, ์ž๋ฐ”์—์„œ๋Š” ๊ณผ๊ฑฐ๋ถ€ํ„ฐ ํ•„๋“œ์˜ ๊ฐ’์„ ์ง์ ‘ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š๊ณ , setXxx, getXxx๋ผ๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด์„œ ๊ฐ’์„ ์ฝ๊ฑฐ๋‚˜ ์ˆ˜์ •ํ•˜๋Š” ๊ทœ์น™์„ ๋งŒ๋“ค์—ˆ๋Š”๋ฐ, ๊ทธ๊ฒƒ์ด ์ž๋ฐ”๋นˆ ํ”„๋กœํผํ‹ฐ ๊ทœ์•ฝ์ž…๋‹ˆ๋‹ค,

 

<์ž๋ฐ”๋นˆ ํ”„๋กœํผํ‹ฐ ๊ทœ์•ฝ ์˜ˆ์‹œ>

class Data {
	private int age;
    public void setAge(int age) {
    	this.age = age;
    }
    
    public int getAge() {
    	return age;
    }
}

 

1-3. ํ•„๋“œ ์ฃผ์ž…

์ด๋ฆ„ ๊ทธ๋Œ€๋กœ ํ•„๋“œ์— ๋ฐ”๋กœ ์ฃผ์ž…ํ•˜๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค.

 

<ํŠน์ง•>

1. ์ฝ”๋“œ๊ฐ€ ๊ฐ„๊ฒฐํ•ด์„œ ๋งŽ์€ ๊ฐœ๋ฐœ์ž๋“ค์„ ์œ ํ˜นํ•˜์ง€๋งŒ, ์™ธ๋ถ€์—์„œ ๋ณ€๊ฒฝ์ด ๋ถˆ๊ฐ€๋Šฅํ•ด์„œ ํ…Œ์ŠคํŠธ๊ฐ€ ํž˜๋“ค๋‹ค๋Š” ์น˜๋ช…์ ์ธ ๋‹จ์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

2. DI ํ”„๋ ˆ์ž„์›Œํฌ๊ฐ€ ์—†์œผ๋ฉด ์•„๋ฌด ๊ฒƒ๋„ ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

3. ๊ฒฐ๋ก ์€ ์‚ฌ์šฉํ•˜์ง€ ๋ง์ž!! (์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์‹ค์ œ ์ฝ”๋“œ์™€ ๊ด€๊ณ„ ์—†๋Š” ํ…Œ์ŠคํŠธ ์ฝ”๋“œ์—์„œ๋Š” ์‚ฌ์šฉ ๊ฐ€๋Šฅ)

4. ์Šคํ”„๋ง ์„ค์ •์„ ๋ชฉ์ ์œผ๋กœ ํ•˜๋Š” @Configuration ๊ฐ™์€ ๊ณณ์—์„œ๋งŒ ํŠน๋ณ„ํ•œ ์šฉ๋„๋กœ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

5. ์˜์กด ๊ด€๊ณ„๋ฅผ ํ•„๋“œ์— ๋ฝ! ๋„ฃ์–ด์ฃผ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

@Component
public class OrderServiceImpl implements OrderService {
	
    //ํ•„๋“œ ์ฃผ์ž… ๋ถ€๋ถ„
    @Autowired
    private MemberRepository memberRepository;
    @Autowired
    private DiscountPolicy discountPolicy;
}

๊ถŒ์žฅํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค!!

์ฐธ๊ณ !! ์ˆœ์ˆ˜ํ•œ ์ž๋ฐ” ํ…Œ์ŠคํŠธ ์ฝ”๋“œ์—์„œ๋Š” ๋‹น์—ฐํžˆ @Autowired๊ฐ€ ๋™์ž‘ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
@SpringBootTest์ฒ˜๋Ÿผ ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๋ฅผ ํ…Œ์ŠคํŠธ์— ํ†ตํ•ฉํ•œ ๊ฒฝ์šฐ์—๋งŒ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.
@Bean
OrderService orderService(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
	return new OrderServiceImpl(memberRepository, discountPolicy);
}
์ฐธ๊ณ !! ์œ„์˜ ์ฝ”๋“œ์™€ ๊ฐ™์ด @Bean์—์„œ ํŒŒ๋ผ๋ฏธํ„ฐ์— ์˜์กด๊ด€๊ณ„๋Š” ์ž๋™ ์ฃผ์ž…๋ฉ๋‹ˆ๋‹ค.
์ˆ˜๋™ ๋“ฑ๋ก ์‹œ ์ž๋™ ๋“ฑ๋ก ๋œ ๋นˆ์˜ ์˜์กด ๊ด€๊ณ„๊ฐ€ ํ•„์š”ํ•  ๋•Œ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

1-4. ์ผ๋ฐ˜ ๋ฉ”์„œ๋“œ ์ฃผ์ž…

์ผ๋ฐ˜ ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด์„œ ์ฃผ์ž…๋ฐ›์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

<ํŠน์ง•>

1. ํ•œ ๋ฒˆ์— ์—ฌ๋Ÿฌ ํ•„๋“œ๋ฅผ ์ฃผ์ž…๋ฐ›์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. (์•„๋ฌด ๋ฉ”์„œ๋“œ์— ๋Œ€๊ณ  @Autowired๋ฅผ ์“ธ ์ˆ˜ ์žˆ์Œ)

2. ์ผ๋ฐ˜์ ์œผ๋กœ ์ž˜ ์‚ฌ์šฉํ•˜์ง€๋Š” ์•Š์Šต๋‹ˆ๋‹ค. (์‚ฌ์‹ค ์™ ๋งŒํ•˜๋ฉด ์ƒ์„ฑ์ž ์ฃผ์ž…, ์ˆ˜์ •์ž ์ฃผ์ž…์„ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ)

@Component
public class OrderServiceImpl implements OrderService {
	
    private MemberRepository memberRepository;
    private DiscountPolicy discountPolicy;
    
    @Autowired
    public void init(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
    	this.memberRepository = memberRepository;
        this.discountPolicy = discountPolicy;
    }
}
์ฐธ๊ณ !! ์˜์กด ๊ด€๊ณ„ ์ž๋™ ์ฃผ์ž…์€ ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๊ฐ€ ๊ด€๋ฆฌํ•˜๋Š” ์Šคํ”„๋ง ๋นˆ์ด์–ด์•ผ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค.
์Šคํ”„๋ง ๋นˆ์ด ์•„๋‹Œ Member ๊ฐ™์€ ํด๋ž˜์Šค์—์„œ @Autowired ์ฝ”๋“œ๋ฅผ ์ ์šฉํ•ด๋„ ์•„๋ฌด ๊ธฐ๋Šฅ๋„ ๋™์ž‘ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

 


2. ์˜ต์…˜ ์ฒ˜๋ฆฌ ๋ฐฉ๋ฒ•

์ฃผ์ž…ํ•  ์Šคํ”„๋ง ๋นˆ์ด ์—†์–ด๋„ ๋™์ž‘ํ•ด์•ผ ํ•  ๋•Œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋Ÿฐ๋ฐ, @Autowired๋งŒ ์‚ฌ์šฉํ•˜๋ฉด, required ์˜ต์…˜์˜ ๊ธฐ๋ณธ๊ฐ’์ด true๋กœ ๋˜์–ด ์žˆ์–ด์„œ

์ž๋™ ์ฃผ์ž… ๋Œ€์ƒ์ด ์—†์œผ๋ฉด ๋ฌด์กฐ๊ฑด ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

 

<์ž๋™ ์ฃผ์ž… ๋Œ€์ƒ์„ ์˜ต์…˜์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐฉ๋ฒ•>

1. @Autowired(required = false): ์ž๋™ ์ฃผ์ž…ํ•  ๋Œ€์ƒ์ด ์—†์œผ๋ฉด, ์ˆ˜์ •์ž ๋ฉ”์„œ๋“œ ์ž์ฒด๊ฐ€ ํ˜ธ์ถœ์ด ์•ˆ ๋ฉ๋‹ˆ๋‹ค.

2. org.springframework.lang.@Nullable: ์ž๋™ ์ฃผ์ž…ํ•  ๋Œ€์ƒ์ด ์—†์œผ๋ฉด, null์ด ์ž…๋ ฅ๋ฉ๋‹ˆ๋‹ค.

3. Optional<>: ์ž๋™ ์ฃผ์ž…ํ•  ๋Œ€์ƒ์ด ์—†์œผ๋ฉด, Optional.empty๊ฐ€ ์ž…๋ ฅ๋ฉ๋‹ˆ๋‹ค.

 

์˜ˆ์ œ๋กœ ํ™•์ธํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

test ํŒจํ‚ค์ง€์˜ hello.core์— autowired๋ผ๋Š” ํŒจํ‚ค์ง€๋ฅผ ๋งŒ๋“ค์–ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ์ด ํŒจํ‚ค์ง€ ์•ˆ์— AutowiredTest๋ผ๋Š” ์ž๋ฐ” ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค์–ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

public class AutowiredTest {

    @Test
    void AutowiredOption() {
        AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(TestBean.class);
    }

    static class TestBean {

        //1. ์ž๋™ ์ฃผ์ž…ํ•  ๋Œ€์ƒ์ด ์—†์œผ๋ฉด, ์ˆ˜์ •์ž ๋ฉ”์„œ๋“œ ์ž์ฒด๊ฐ€ ํ˜ธ์ถœ์ด ์•ˆ ๋ฉ๋‹ˆ๋‹ค.
        //๊ธฐ๋ณธ๊ฐ’์€ true
        @Autowired(required = false)
        public void setNoBean1(Member noBean1) {
            System.out.println("noBean1 = " + noBean1);
        }

        //2. ์ž๋™ ์ฃผ์ž…ํ•  ๋Œ€์ƒ์ด ์—†์œผ๋ฉด, null์ด ์ž…๋ ฅ๋ฉ๋‹ˆ๋‹ค.
        @Autowired
        public void setNoBean2(@Nullable Member noBean2) {
            System.out.println("noBean2 = " + noBean2);
        }

        //3. ์ž๋™ ์ฃผ์ž…ํ•  ๋Œ€์ƒ์ด ์—†์œผ๋ฉด, Optional.empty๊ฐ€ ์ž…๋ ฅ๋ฉ๋‹ˆ๋‹ค.
        @Autowired
        public void setNoBean3(Optional<Member> noBean3) {
            System.out.println("noBean3 = " + noBean3);
        }
    }
}

์ด๋ ‡๊ฒŒ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์งœ ๋ดค์Šต๋‹ˆ๋‹ค.

์—ฌ๊ธฐ์„œ Member๋Š” ์Šคํ”„๋ง ๋นˆ์ด ์•„๋‹ˆ์–ด์„œ ์ž๋™ ์ฃผ์ž…ํ•  ๋Œ€์ƒ์ด ์—†๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

๊ฒฐ๊ณผ๋Š” ์–ด๋–ป๊ฒŒ ๋‚˜์˜ฌ๊นŒ์š”?

์˜ต์…˜ ์ฒ˜๋ฆฌ ๊ฒฐ๊ณผ

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

required = false๋ฅผ true๋กœ ๋ฐ”๊พธ๋ฉด ๋ฐ”๋กœ ์˜ค๋ฅ˜๊ฐ€ ๋–  ๋ฒ„๋ฆฝ๋‹ˆ๋‹ค.

2๋ฒˆ์˜ ๊ฒฝ์šฐ์™€ 3๋ฒˆ์˜ ๊ฒฝ์šฐ ๋‘˜ ๋‹ค ์˜ˆ์ƒํ•œ ๋Œ€๋กœ ์ž๋™ ์ฃผ์ž…ํ•  ๋Œ€์ƒ์ด ์—†์–ด์„œ ๊ฐ๊ฐ null๊ณผ Optional.empty๊ฐ€ ๋–ด์Šต๋‹ˆ๋‹ค.

์ฐธ๊ณ !! @Nullable, Optional์€ ์Šคํ”„๋ง ์ „๋ฐ˜์— ๊ฑธ์ณ์„œ ์ง€์›๋ฉ๋‹ˆ๋‹ค.
์˜ˆ๋ฅผ ๋“ค์–ด์„œ, ์ƒ์„ฑ์ž ์ž๋™ ์ฃผ์ž…์—์„œ ํŠน์ • ํ•„๋“œ์—๋งŒ ์‚ฌ์šฉํ•ด๋„ ๋ฉ๋‹ˆ๋‹ค.

 


3. ์ƒ์„ฑ์ž ์ฃผ์ž…์„ ์„ ํƒํ•ด๋ผ!!

๊ณผ๊ฑฐ์—๋Š” ์ˆ˜์ •์ž ์ฃผ์ž…๊ณผ ํ•„๋“œ ์ฃผ์ž…์„ ๋งŽ์ด ์‚ฌ์šฉํ–ˆ์ง€๋งŒ, ์ตœ๊ทผ์—๋Š” ์Šคํ”„๋ง์„ ํฌํ•จํ•œ DI ํ”„๋ ˆ์ž„์›Œํฌ ๋Œ€๋ถ€๋ถ„์ด ์ƒ์„ฑ์ž ์ฃผ์ž…์„ ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค.

์ด์œ ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

 

3-1. ์ด์œ 1 - ๋ถˆ๋ณ€

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

 

3-2. ์ด์œ 2 - ๋ˆ„๋ฝ

ํ”„๋ ˆ์ž„์›Œํฌ ์—†์ด ์ˆœ์ˆ˜ํ•œ ์ž๋ฐ” ์ฝ”๋“œ๋ฅผ ๋‹จ์œ„ ํ…Œ์ŠคํŠธ ํ•˜๋Š” ๊ฒฝ์šฐ์—... (๋”ฑ OrderServiceImpl๋งŒ ํ…Œ์ŠคํŠธ๋ฅผ ํ•˜๊ณ  ์‹ถ๋‹ค!)

๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ˆ˜์ •์ž ์˜์กด ๊ด€๊ณ„์ธ ๊ฒฝ์šฐ

public class OrderServiceImpl implements OrderService{

    private MemberRepository memberRepository;
    private DiscountPolicy discountPolicy;

    @Autowired
    public void setMemberRepository(MemberRepository memberRepository) {
    	this.memberRepository = memberRepository;
    }
    
    @Autowired
    public void setDiscountPolicy(DiscountPolicy discountPolicy) {
    	this.discountPolicy = discountPolicy;
    }
    ...
}

@Autowired๊ฐ€ ํ”„๋ ˆ์ž„์›Œํฌ ์•ˆ์—์„œ ๋™์ž‘ํ•  ๋•Œ๋Š” ์˜์กด ๊ด€๊ณ„๊ฐ€ ์—†์œผ๋ฉด ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜์ง€๋งŒ, ์ง€๊ธˆ์€ ํ”„๋ ˆ์ž„์›Œํฌ ์—†์ด ์ˆœ์ˆ˜ํ•œ ์ž๋ฐ” ์ฝ”๋“œ๋กœ๋งŒ ๋‹จ์œ„ ํ…Œ์ŠคํŠธ๋ฅผ ์ˆ˜ํ–‰ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

 

์ด๋ ‡๊ฒŒ ํ…Œ์ŠคํŠธ๋ฅผ ์ˆ˜ํ–‰ํ•˜๋ฉด ์‹คํ–‰์€ ๋ฉ๋‹ˆ๋‹ค.

@Test
void createOrder() {
	OrderServiceImpl orderService = new OrderServiceImpl();
    orderService.createOrder(1L, "itemA", 10000);
}

๊ทธ๋Ÿฐ๋ฐ ๋ง‰์ƒ ์‹คํ–‰ ๊ฒฐ๊ณผ๋Š” NPE(Null Point Exception)์ด ๋ฐœ์ƒํ•˜๋Š”๋ฐ, memberRepository์™€ discountPolicy ๋ชจ๋‘ ์˜์กด ๊ด€๊ณ„ ์ฃผ์ž…์ด ๋ˆ„๋ฝ๋˜์—ˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

 

์ƒ์„ฑ์ž ์ฃผ์ž…์„ ์‚ฌ์šฉํ•˜๋ฉด ๋‹ค์Œ์ฒ˜๋Ÿผ ์ฃผ์ž… ๋ฐ์ดํ„ฐ๋ฅผ ๋ˆ„๋ฝํ–ˆ์„ ๋•Œ ์ปดํŒŒ์ผ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ , IDE์—์„œ ๋ฐ”๋กœ ์–ด๋–ค ๊ฐ’์„ ํ•„์ˆ˜๋กœ ์ฃผ์ž…ํ•ด์•ผ ํ•˜๋Š”์ง€ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

3-3. ์ด์œ 3 - final ํ‚ค์›Œ๋“œ

์ƒ์„ฑ์ž ์ฃผ์ž…์„ ์‹คํ–‰ํ•˜๋ฉด ํ•„๋“œ์— final ํ‚ค์›Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋ž˜์„œ, ์ƒ์„ฑ์ž์—์„œ ํ˜น์‹œ๋ผ๋„ ๊ฐ’์ด ์„ค์ •๋˜์ง€ ์•Š๋Š” ์˜ค๋ฅ˜๋ฅผ ์ปดํŒŒ์ผ ์‹œ์ ์—์„œ ๋ง‰์•„์ค๋‹ˆ๋‹ค. (๋ˆ„๋ฝ๋˜๊ฑฐ๋‚˜ ํ•ด๋„ ๋‹ค ๋ง‰์•„์คŒ)

@Component
public class OrderServiceImpl implements OrderService{

    private final MemberRepository memberRepository;
    private final DiscountPolicy discountPolicy;

    @Autowired
    public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
        this.memberRepository = memberRepository;
    }
    ...
}

์ž˜ ๋ณด๋ฉด ํ•„์ˆ˜ ํ•„๋“œ์ธ discountPolicy์— ๊ฐ’์„ ์„ค์ •ํ•ด์•ผ ํ•˜๋Š”๋ฐ, ์ด ๋ถ€๋ถ„์ด ๋ˆ„๋ฝ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

์ž๋ฐ”๋Š” ์ปดํŒŒ์ผ ์‹œ์ ์— java: variable discountPolicy might not have been initialized ์˜ค๋ฅ˜๋ฅผ ๋ฐœ์ƒ์‹œํ‚ต๋‹ˆ๋‹ค.

์ปดํŒŒ์ผ ์˜ค๋ฅ˜๋Š” ์„ธ์ƒ์—์„œ ๊ฐ€์žฅ ๋น ๋ฅด๊ณ  ์ข‹์€ ์˜ค๋ฅ˜ ์ž…๋‹ˆ๋‹ค!!!!

์ฐธ๊ณ !! ์ˆ˜์ •์ž ์ฃผ์ž…์„ ํฌํ•จํ•œ ๋‚˜๋จธ์ง€ ์ฃผ์ž… ๋ฐฉ์‹์€ ๋ชจ๋‘ ์ƒ์„ฑ์ž ์ดํ›„์— ํ˜ธ์ถœ๋˜๋ฏ€๋กœ, ํ•„๋“œ์— final ํ‚ค์›Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.
์˜ค์ง ์ƒ์„ฑ์ž ์ฃผ์ž… ๋ฐฉ์‹๋งŒ final ํ‚ค์›Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.โญ

 

<์ •๋ฆฌโœ๏ธ>

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

 


4. ๋กฌ๋ณต(Lombok)๊ณผ ์ตœ์‹  ํŠธ๋žœ๋“œ

๋ง‰์ƒ ๊ฐœ๋ฐœ์„ ํ•ด๋ณด๋ฉด ๋Œ€๋ถ€๋ถ„์ด ๋‹ค ๋ถˆ๋ณ€์ž…๋‹ˆ๋‹ค.

๊ทธ๋ž˜์„œ ํ•„๋“œ์— final ํ‚ค์›Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

๊ทธ๋Ÿฐ๋ฐ, ์ƒ์„ฑ์ž๋„ ๋งŒ๋“ค์–ด์•ผ ํ•˜๊ณ .. ์ฃผ์ž…๋ฐ›์€ ๊ฐ’์„ ๋Œ€์ž…ํ•˜๋Š” ์ฝ”๋“œ๋„ ๋งŒ๋“ค์–ด์•ผ ํ•˜๊ณ ...

ํ•„๋“œ ์ฃผ์ž…์ฒ˜๋Ÿผ ์ข€ ํŽธ๋ฆฌํ•˜๊ฒŒ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ์—†์„๊นŒ์š”?

 

4-1. ๊ธฐ๋ณธ ์ฝ”๋“œ ์ตœ์ ํ™”

<๊ธฐ๋ณธ ์ฝ”๋“œ>

@Component
public class OrderServiceImpl implements OrderService{

    private final MemberRepository memberRepository;
    private final DiscountPolicy discountPolicy;

    @Autowired
    public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
        this.memberRepository = memberRepository;
        this.discountPolicy = discountPolicy;
    }
}

์ƒ์„ฑ์ž๊ฐ€ ๋”ฑ 1๊ฐœ๋งŒ ์žˆ์œผ๋ฉด @Autowired๋ฅผ ์ƒ๋žตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

@Component
public class OrderServiceImpl implements OrderService{

    private final MemberRepository memberRepository;
    private final DiscountPolicy discountPolicy;
    
    public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
        this.memberRepository = memberRepository;
        this.discountPolicy = discountPolicy;
    }
}

 

 

4-2. ๋กฌ๋ณต ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ ์šฉ ๋ฐฉ๋ฒ•

์ด์ œ ๋กฌ๋ณต์„ ์ ์šฉํ•ด๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

๋กฌ๋ณต ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ์ œ๊ณตํ•˜๋Š” @RequiredArgsConstructor ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜๋ฉด final์ด ๋ถ™์€ ํ•„๋“œ๋ฅผ ๋ชจ์•„์„œ ์ƒ์„ฑ์ž๋ฅผ ์ž๋™์œผ๋กœ ๋งŒ๋“ค์–ด์ค๋‹ˆ๋‹ค. (๋‹ค์Œ ์ฝ”๋“œ์—๋Š” ๋ณด์ด์ง€ ์•Š์ง€๋งŒ ์‹ค์ œ ํ˜ธ์ถœ์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.)

 

์š”์ฆ˜ ๋กฌ๋ณต ์ธ๊ธฐ ๋งŽ์•„์„œ spring initializr์—์„œ Dependencies์— Lombok ๋ฐ”๋กœ ์ถ”๊ฐ€ํ•˜๋ฉด ์ž๋™์œผ๋กœ ๋กฌ๋ณต ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ ์šฉ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

์ฒ˜์Œ์— ๋กฌ๋ณต ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ ์šฉํ•˜์ง€ ์•Š๊ณ  ํ”„๋กœ์ ํŠธ๋ฅผ ์ƒ์„ฑํ–ˆ์œผ๋ฉด ๋ฐ‘์— ๋ฐฉ๋ฒ•๋Œ€๋กœ ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

 

<build.gradle์— ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๋ฐ ํ™˜๊ฒฝ ์ถ”๊ฐ€>

plugins {
	id 'java'
	id 'org.springframework.boot' version '3.4.4'
	id 'io.spring.dependency-management' version '1.1.7'
}

group = 'hello'
version = '0.0.1-SNAPSHOT'

java {
	toolchain {
		languageVersion = JavaLanguageVersion.of(17)
	}
}

repositories {
	mavenCentral()
}

dependencies {
	implementation 'org.springframework.boot:spring-boot-starter'

	//Lombok ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ถ”๊ฐ€ ์‹œ์ž‘
	compileOnly 'org.projectlombok:lombok'
	annotationProcessor 'org.projectlombok:lombok'

	testCompileOnly 'org.projectlombok:lombok'
	testAnnotationProcessor 'org.projectlombok:lombok'
	//Lombok ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ถ”๊ฐ€ ๋
	
	testImplementation 'org.springframework.boot:spring-boot-starter-test'
	testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
}

tasks.named('test') {
	useJUnitPlatform()
}

์œ„์— ์ฝ”๋“œ์ฒ˜๋Ÿผ ๋กฌ๋ณต ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ถ”๊ฐ€ํ•˜๊ณ , ์•„๋ž˜์™€ ๊ฐ™์€ ๋ฐฉ๋ฒ•์œผ๋กœ ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

1. Preferences(์œˆ๋„์šฐ File๐Ÿ‘‰๐ŸปSettings)๐Ÿ‘‰๐Ÿปplugin๐Ÿ‘‰๐Ÿปlombok ๊ฒ€์ƒ‰ ์„ค์น˜ ์‹คํ–‰ (์žฌ์‹œ์ž‘)

2. Preferences๐Ÿ‘‰๐ŸปAnnotation Processors ๊ฒ€์ƒ‰๐Ÿ‘‰๐ŸปEnable annotation processing ์ฒดํฌ (์žฌ์‹œ์ž‘)

3. ์ž„์˜์˜ ํ…Œ์ŠคํŠธ ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค๊ณ , @Getter์™€ @Setter ํ™•์ธ

 

์ž˜ ๋˜์—ˆ๋Š”์ง€ ํ™•์ธํ•ด๋ณด๊ธฐ ์œ„ํ•ด์„œ ์ž„์˜์˜ ํ…Œ์ŠคํŠธ ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค์–ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

src.main.java.hello.core์— HelloLombok์ด๋ผ๋Š” ์ž๋ฐ” ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค์–ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

package hello.core;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

@Getter
@Setter
@ToString
public class HelloLombok {

    private String name;
    private int age;

    public static void main(String[] args) {
        HelloLombok helloLombok = new HelloLombok();
        helloLombok.setName("์ด๋ฆฌ์ญ");

        System.out.println("helloLombok = " + helloLombok);
    }
}

 

4-3. ๋กฌ๋ณต ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ ์šฉ ํ›„

์ตœ์ข… ๊ฒฐ๊ณผ ์ฝ”๋“œ๋ฅผ ๋ณด๋ฉด ์ •๋ง ๊ฐ„๊ฒฐํ•˜๋‹ค๋Š” ๊ฒƒ์„ ๋А๋‚„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

<์ตœ์ข… ๊ฒฐ๊ณผ ์ฝ”๋“œ>

@Component
@RequiredArgsConstructor
public class OrderServiceImpl implements OrderService{

    private final MemberRepository memberRepository;
    private final DiscountPolicy discountPolicy;
}

์ด ์ตœ์ข… ๊ฒฐ๊ณผ ์ฝ”๋“œ์™€ ์ด์ „์˜ ์ฝ”๋“œ๋Š” ์™„์ „ํžˆ ๋™์ผํ•ฉ๋‹ˆ๋‹ค.

๋กฌ๋ณต์ด ์ž๋ฐ”์˜ ์• ๋…ธํ…Œ์ด์…˜ ํ”„๋กœ์„ธ์„œ๋ผ๋Š” ๊ธฐ๋Šฅ์„ ์ด์šฉํ•ด์„œ ์ปดํŒŒ์ผ ์‹œ์ ์— ์ƒ์„ฑ์ž ์ฝ”๋“œ๋ฅผ ์ž๋™์œผ๋กœ ์ƒ์„ฑํ•ด์ค๋‹ˆ๋‹ค.

์‹ค์ œ class๋ฅผ ์—ด์–ด๋ณด๋ฉด ๋ฐ‘์— ์ฝ”๋“œ๊ฐ€ ์ถ”๊ฐ€๋˜์–ด ์žˆ๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
        this.memberRepository = memberRepository;
        this.discountPolicy = discountPolicy;
}
<์ •๋ฆฌโœ๏ธ>

์ตœ๊ทผ์—๋Š” ์ƒ์„ฑ์ž๋ฅผ ๋”ฑ 1๊ฐœ ๋‘๊ณ , @Autowired๋ฅผ ์ƒ๋žตํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์ฃผ๋กœ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
์—ฌ๊ธฐ์— Lombok ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ @RequiredArgsConstructor๋ฅผ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๋ฉด ๊ธฐ๋Šฅ์€ ๋‹ค ์ œ๊ณตํ•˜๋ฉด์„œ, ์ฝ”๋“œ๋Š” ๊น”๋”ํ•˜๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

5. ์กฐํšŒ ๋นˆ์ด 2๊ฐœ ์ด์ƒ - ๋ฌธ์ œ

@Autowired๋Š” ํƒ€์ž…(Type)์œผ๋กœ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค.

@Autowired
private DiscountPolicy discountPolicy

ํƒ€์ž…์œผ๋กœ ์กฐํšŒํ•˜๊ธฐ ๋•Œ๋ฌธ์—, ๋งˆ์น˜ ac.getBean(DiscountPolicy.class)์™€ ์œ ์‚ฌํ•˜๊ฒŒ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค.

=> ์‹ค์ œ๋กœ๋Š” ๋” ๋งŽ์€ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

 

์Šคํ”„๋ง ๋นˆ ์กฐํšŒ์—์„œ ๋ดค๋“ฏ์ด, ํƒ€์ž…์œผ๋กœ ์กฐํšŒํ•˜๋ฉด ์„ ํƒ๋œ ๋นˆ์ด 2๊ฐœ ์ด์ƒ์ผ ๋•Œ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

DiscountPolicy์˜ ํ•˜์œ„ ํƒ€์ž…์ธ FixDiscountPolicy, RateDiscountPolicy ๋‘˜ ๋‹ค ์Šคํ”„๋ง ๋นˆ์œผ๋กœ ์„ ์–ธํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

 

<FixDiscountPolicy>

@Component
public class FixDiscountPolicy implements DiscountPolicy { }

<RateDiscountPolicy>

@Component
public class RateDiscountPolicy implements DiscountPolicy { }

๊ทธ๋ฆฌ๊ณ , ์ด๋ ‡๊ฒŒ ์˜์กด ๊ด€๊ณ„ ์ž๋™ ์ฃผ์ž…์„ ์‹คํ–‰ํ•˜๋ฉด

@Autowired
private DiscountPolicy discountPolicy

๋ฐ‘์—์ฒ˜๋Ÿผ NoUniqueBeanDefinitionException ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

NoUniqueBeanDefinitionException: No qualifying bean of type
'hellp.core.discount.DiscountPolicy' avaliable: expected single matching bean
but found 2: fixDiscountPolicy, rateDiscountPolicy

์˜ค๋ฅ˜ ๋ฉ”์‹œ์ง€๊ฐ€ ์นœ์ ˆํ•˜๊ฒŒ๋„ ํ•˜๋‚˜์˜ ๋นˆ์„ ๊ธฐ๋Œ€ํ–ˆ๋Š”๋ฐ fixDiscountPolicy, rateDiscountPolicy 2๊ฐœ๊ฐ€ ๋ฐœ๊ฒฌ๋˜์—ˆ๋‹ค๊ณ  ์•Œ๋ ค์ค๋‹ˆ๋‹ค.

 

์ด ๋•Œ, ํ•˜์œ„ ํƒ€์ž…์œผ๋กœ ์ง€์ •ํ•  ์ˆ˜๋„ ์žˆ์ง€๋งŒ, ํ•˜์œ„ ํƒ€์ž…์œผ๋กœ ์ง€์ •ํ•˜๋Š” ๊ฒƒ์€ DIP๋ฅผ ์œ„๋ฐ˜ํ•˜๊ณ  ์œ ์—ฐ์„ฑ์ด ๋–จ์–ด์ง‘๋‹ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ , ์ด๋ฆ„๋งŒ ๋‹ค๋ฅด๊ณ  ์™„์ „ํžˆ ๋˜‘๊ฐ™์€ ํƒ€์ž…์˜ ์Šคํ”„๋ง ๋นˆ์ด 2๊ฐœ ์žˆ์„ ๋•Œ ํ•ด๊ฒฐ์ด ์•ˆ ๋ฉ๋‹ˆ๋‹ค.

 

์Šคํ”„๋ง ๋นˆ์„ ์ˆ˜๋™ ๋“ฑ๋กํ•ด์„œ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•ด๋„ ๋˜์ง€๋งŒ,

์˜์กด ๊ด€๊ณ„ ์ž๋™ ์ฃผ์ž…์—์„œ ์กฐํšŒ ๋Œ€์ƒ ๋นˆ์ด 2๊ฐœ ์ด์ƒ์ผ ๋•Œ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  • @Autowired ํ•„๋“œ ๋ช… ๋งค์นญ
  • @Qualifier๐Ÿ‘‰๐Ÿป@Qualifier๋ผ๋ฆฌ ๋งค์นญ๐Ÿ‘‰๐Ÿป๋นˆ ์ด๋ฆ„ ๋งค์นญ
  • @Primary ์‚ฌ์šฉ

 

5-1. ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•1 - @Autowired ํ•„๋“œ ๋ช… ๋งค์นญ

@Autowired๋Š” ํƒ€์ž… ๋งค์นญ์„ ์‹œ๋„ํ•˜๋Š”๋ฐ ์ด ๋•Œ ์—ฌ๋Ÿฌ ๋นˆ์ด ์žˆ์œผ๋ฉด ํ•„๋“œ ์ด๋ฆ„, ํŒŒ๋ผ๋ฏธํ„ฐ ์ด๋ฆ„์œผ๋กœ ๋นˆ ์ด๋ฆ„์„ ์ถ”๊ฐ€ ๋งค์นญํ•ฉ๋‹ˆ๋‹ค.

 

<๊ธฐ์กด ์ฝ”๋“œ>

@Autowired
private DiscountPolicy discountPolicy

<ํ•„๋“œ ๋ช…์„ ๋นˆ ์ด๋ฆ„์œผ๋กœ ๋ณ€๊ฒฝ>

@Autowired
private DiscountPolicy rateDiscountPolicy

ํ•„๋“œ ๋ช…์ด rateDiscountPolicy์ด๋ฏ€๋กœ ์ •์ƒ ์ฃผ์ž…๋ฉ๋‹ˆ๋‹ค.

ํ•„๋“œ ๋ช… ๋งค์นญ์€ ๋จผ์ € ํƒ€์ž… ๋งค์นญ์„ ์‹œ๋„ํ•˜๊ณ , ๊ทธ ๊ฒฐ๊ณผ์— ์—ฌ๋Ÿฌ ๋นˆ์ด ์žˆ์„ ๋•Œ ์ถ”๊ฐ€๋กœ ๋™์ž‘ํ•˜๋Š” ๊ธฐ๋Šฅ์ž…๋‹ˆ๋‹ค.

<์ •๋ฆฌโœ๏ธ>

1. ํƒ€์ž… ๋งค์นญ
2. ํƒ€์ž… ๋งค์นญ์˜ ๊ฒฐ๊ณผ๊ฐ€ 2๊ฐœ ์ด์ƒ์ผ ๋•Œ ํ•„๋“œ ๋ช…, ํŒŒ๋ผ๋ฏธํ„ฐ ๋ช…์œผ๋กœ ๋นˆ ์ด๋ฆ„ ๋งค์นญ

 

 

5-2. ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•2 - @Qualifier ์‚ฌ์šฉ

@Qualifier๋Š” ์ถ”๊ฐ€ ๊ตฌ๋ถ„์ž๋ฅผ ๋ถ™์—ฌ์ฃผ๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค.

์ฃผ์ž… ์‹œ ์ถ”๊ฐ€์ ์ธ ๋ฐฉ๋ฒ•์„ ์ œ๊ณตํ•˜๋Š” ๊ฒƒ์ด๊ณ , ๋นˆ ์ด๋ฆ„์„ ๋ณ€๊ฒฝํ•˜๋Š” ๊ฒƒ์€ ์•„๋‹™๋‹ˆ๋‹ค.

 

<๋นˆ ๋“ฑ๋ก ์‹œ @Qualifier๋ฅผ ๋ถ™์—ฌ์ค๋‹ˆ๋‹ค.>

@Component
@Qualifier("mainDiscountPolicy")
public class RateDiscountPolicy implements DiscountPolicy {}
@Component
@Qualifier("fixDiscountPolicy")
public class FixDiscountPolicy implements DiscountPolicy {}

์ฃผ์ž… ์‹œ์— @Qualifier๋ฅผ ๋ถ™์—ฌ์ฃผ๊ณ  ๋“ฑ๋กํ•œ ์ด๋ฆ„์„ ์ ์–ด์ค๋‹ˆ๋‹ค.

 

<์ƒ์„ฑ์ž ์ž๋™ ์ฃผ์ž… ์˜ˆ์‹œ>

@Autowired
public OrderServiceImpl(MemberRepository memberRepository, @Qualifier("mainDiscountPolicy") DiscountPolicy discountPolicy) {
     this.memberRepository = memberRepository;
     this.discountPolicy = discountPolicy;
}

<์ˆ˜์ •์ž ์ž๋™ ์ฃผ์ž… ์˜ˆ์‹œ>

@Autowired
public DiscountPolicy setDiscountPolicy(@Qualifier("mainDiscountPolicy") DiscountPolicy discountPolicy) {
	this.discountPolicy = discountPolicy;
}

@Qualifier๋กœ ์ฃผ์ž…ํ•  ๋•Œ @Qualifier("mainDiscountPolicy")๋ฅผ ๋ชป ์ฐพ์œผ๋ฉด ์–ด๋–ป๊ฒŒ ๋ ๊นŒ์š”?

๊ทธ๋Ÿฌ๋ฉด mainDiscountPolicy๋ผ๋Š” ์ด๋ฆ„์˜ ์Šคํ”„๋ง ๋นˆ์„ ์ถ”๊ฐ€๋กœ ์ฐพ์Šต๋‹ˆ๋‹ค.

ํ•˜์ง€๋งŒ, @Qualifier๋Š” @Qualifier๋ฅผ ์ฐพ๋Š” ์šฉ๋„๋กœ๋งŒ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๋ช…ํ™•ํ•˜๊ณ  ์ข‹์Šต๋‹ˆ๋‹ค.

 

๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ง์ ‘ ๋นˆ ๋“ฑ๋ก ์‹œ์—๋„ @Qualifier๋ฅผ ๋™์ผํ•˜๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

@Bean
@Qualifier("mainDiscountPolicy")
public DiscountPolicy discountPolicy() {
	return new ...
}
<์ •๋ฆฌโœ๏ธ>

1. @Qualifier๋ผ๋ฆฌ ๋งค์นญ
2. ๋นˆ ์ด๋ฆ„ ๋งค์นญ
3. NoSuchBeanDefinitionException ์˜ˆ์™ธ ๋ฐœ์ƒ

 

 

5-3. ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•3 - @Primary ์‚ฌ์šฉ

@Primary๋Š” ์šฐ์„ ์ˆœ์œ„๋ฅผ ์ •ํ•˜๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค. (ํŽธ๋ฆฌํ•˜๊ณ , ์ž์ฃผ ์‚ฌ์šฉ)

@Autowired ์‹œ์— ์—ฌ๋Ÿฌ ๋นˆ์ด ๋งค์นญ๋˜๋ฉด @Primary๊ฐ€ ์šฐ์„ ๊ถŒ์„ ๊ฐ€์ง‘๋‹ˆ๋‹ค.

 

<rateDiscountPolicy๊ฐ€ ์šฐ์„ ๊ถŒ์„ ๊ฐ€์ง€๋„๋ก ํ•˜์ž>

@Component
@Primary
public class RateDiscountPolicy implements DiscountPolicy {}

@Component
public class FixDiscountPolicy implements DiscountPolicy {}

<์‚ฌ์šฉ ์ฝ”๋“œ>

//์ƒ์„ฑ์ž
@Autowired
public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
	this.memberRepository = memberRepository;
    this.discountPolicy = discountPolicy;
}

//์ˆ˜์ •์ž
@Autowired
public DiscountPolicy setDiscountPolicy(DiscountPolicy discountPolicy) {
	this.discountPolicy = discountPolicy;
}

์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•ด๋ณด๋ฉด ๋ฌธ์ œ ์—†์ด @Primary๊ฐ€ ์ž˜ ๋™์ž‘ํ•˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

์—ฌ๊ธฐ๊นŒ์ง€ ๋ณด๋ฉด @Primary์™€ @Qualifier ์ค‘์— ์–ด๋–ค ๊ฒƒ์„ ์‚ฌ์šฉํ•˜๋ฉด ์ข‹์„์ง€ ๊ณ ๋ฏผํ•  ์ˆ˜๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

@Qualifier์˜ ๋‹จ์ ์€ ์ฃผ์ž…๋ฐ›์„ ๋•Œ ๋ชจ๋“  ์ฝ”๋“œ์— @Qualifier๋ฅผ ๋ถ™์—ฌ์ฃผ์–ด์•ผ ํ•œ๋‹ค๋Š” ์ ์ž…๋‹ˆ๋‹ค.

@Autowired
public OrderServiceImpl(MemberRepository memberRepository, @Qualifier("mainDiscountPolicy") DiscountPolicy discountPolicy) {
     this.memberRepository = memberRepository;
     this.discountPolicy = discountPolicy;
}
<๐Ÿ‘ป์ฐธ๊ณ  - @Primary, @Qualifier ํ™œ์šฉ๐Ÿ‘ป>

์ฝ”๋“œ์—์„œ ์ž์ฃผ ์‚ฌ์šฉํ•˜๋Š” ๋ฉ”์ธ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์˜ ์ปค๋„ฅ์…˜์„ ํš๋“ํ•˜๋Š” ์Šคํ”„๋ง ๋นˆ์ด ์žˆ๊ณ , ์ฝ”๋“œ์—์„œ ํŠน๋ณ„ํ•œ ๊ธฐ๋Šฅ์œผ๋กœ ๊ฐ€๋” ์‚ฌ์šฉํ•˜๋Š” ์„œ๋ธŒ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์˜ ์ปค๋„ฅ์…˜์„ ํš๋“ํ•˜๋Š” ์Šคํ”„๋ง ๋นˆ์ด ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.
๋ฉ”์ธ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์˜ ์ปค๋„ฅ์…˜์„ ํš๋“ํ•˜๋Š” ์Šคํ”„๋ง ๋นˆ์€ @Primary๋ฅผ ์ ์šฉํ•˜๊ณ  ์กฐํšŒํ•˜๋Š” ๊ณณ์—์„œ @Qualifier ์ง€์ • ์—†์ด ํŽธ๋ฆฌํ•˜๊ฒŒ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค.
๊ทธ๋ฆฌ๊ณ , ์„œ๋ธŒ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ปค๋„ฅ์…˜ ๋นˆ์„ ํš๋“ํ•  ๋•Œ๋Š” @Qualifier๋ฅผ ์ง€์ •ํ•ด์„œ ๋ช…์‹œ์ ์œผ๋กœ ํš๋“ํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
์š”๋ ‡๊ฒŒ ํ•˜๋ฉด ์ฝ”๋“œ๋ฅผ ๊น”๋”ํ•˜๊ฒŒ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๋ชฐ๋ก  ์ด ๋•Œ ๋ฉ”์ธ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์˜ ์Šคํ”„๋ง ๋นˆ์„ ๋“ฑ๋กํ•  ๋•Œ @Qualifier๋ฅผ ์ง€์ •ํ•ด์ฃผ๋Š” ๊ฒƒ์€ ์ƒ๊ด€ ์—†์Šต๋‹ˆ๋‹ค.
<์šฐ์„ ์ˆœ์œ„โญ>

@Primary๋Š” ๊ธฐ๋ณธ๊ฐ’์ฒ˜๋Ÿผ ๋™์ž‘ํ•˜๋Š” ๊ฒƒ์ด๊ณ , @Qualifier๋Š” ๋งค์šฐ ์ƒ์„ธํ•˜๊ฒŒ ๋™์ž‘ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.
์ด๋Ÿฐ ๊ฒฝ์šฐ ์–ด๋–ค ๊ฒƒ์ด ์šฐ์„ ๊ถŒ์„ ๊ฐ€์ ธ๊ฐˆ๊นŒ์š”?
์Šคํ”„๋ง์—์„œ๋Š” ์ž์„ธํ•œ ๊ฒƒ์ด ์šฐ์„ ๊ถŒ์„ ๊ฐ€์ ธ๊ฐ‘๋‹ˆ๋‹ค.
์ž๋™๋ณด๋‹ค๋Š” ์ˆ˜๋™์ด, ๋„“์€ ๋ฒ”์œ„์˜ ์„ ํƒ๊ถŒ๋ณด๋‹ค๋Š” ์ข์€ ๋ฒ”์œ„์˜ ์„ ํƒ๊ถŒ์ด ์šฐ์„ ์ˆœ์œ„๊ฐ€ ๋†’์Šต๋‹ˆ๋‹ค.
๋”ฐ๋ผ์„œ, ์—ฌ๊ธฐ์„œ๋„ @Qualifier๊ฐ€ ์šฐ์„ ๊ถŒ์ด ๋†’์Šต๋‹ˆ๋‹ค.

 

 

5-4. ์• ๋…ธํ…Œ์ด์…˜ ์ง์ ‘ ๋งŒ๋“ค๊ธฐ

@Qualifier("mainDiscountPolicy") ์ด๋ ‡๊ฒŒ ๋ฌธ์ž๋ฅผ ์ ์œผ๋ฉด ์ปดํŒŒ์ผ ์‹œ ํƒ€์ž… ์ฒดํฌ๊ฐ€ ์•ˆ ๋ฉ๋‹ˆ๋‹ค.

๋‹ค์Œ๊ณผ ๊ฐ™์€ ์• ๋…ธํ…Œ์ด์…˜์„ ๋งŒ๋“ค์–ด์„œ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

main์˜ hello.core์— annotation์ด๋ผ๋Š” ํŒจํ‚ค์ง€๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

์ด ํŒจํ‚ค์ง€ ์•ˆ์— MainDiscountPolicy๋ผ๋Š” ์• ๋…ธํ…Œ์ด์…˜์„ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
@Qualifier("mainDiscountPolicy")
public @interface MainDiscountPolicy {
}

์ด ์• ๋…ธํ…Œ์ด์…˜์— @Qualifier("mainDiscountPolicy")๋ฅผ ์ ์–ด์ค๋‹ˆ๋‹ค.

@Component
@MainDiscountPolicy
public class RateDiscountPolicy implements DiscountPolicy{

    private int discountPercent = 10; //10% ํ• ์ธ

    @Override
    public int discount(Member member, int price) {
        if(member.getGrade() == Grade.VIP) {
            return price * discountPercent /100;
        }
        else {
            return 0;
        }
    }
}

๊ทธ๋ฆฌ๊ณ , ์œ„์—์„œ ์ ์—ˆ๋˜ mainDiscountPolicy๋ฅผ ์—ฌ๊ธฐ์— @MainDiscountPolicy๋กœ ์ ์–ด์ค๋‹ˆ๋‹ค.

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์žฅ์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

๊ธฐ์กด์˜ @Qualify("mainDiscountPolicy")๋Š” ๊ด„ํ˜ธ ์•ˆ์— ์žˆ๋Š” ๊ฒƒ์„ ๋ฌธ์ž๋กœ ์ธ์‹ํ•ด์„œ ์ฒ ์ž๊ฐ€ ํ‹€๋ฆฌ๊ฑฐ๋‚˜ ํ•˜๋ฉด ์˜ค๋ฅ˜๋ฅผ ์žก์•„๋‚ด์ง€ ๋ชปํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋Ÿฐ๋ฐ ์ด๋ ‡๊ฒŒ ๋ฐ”๊พธ๋ฉด์„œ ์ฒ ์ž๊ฐ€ ํ‹€๋ ค๋„ ์˜ค๋ฅ˜๋ฅผ ์žก์•„๋‚ผ ์ˆ˜ ์žˆ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

 

 

์• ๋…ธํ…Œ์ด์…˜์—๋Š” ์ƒ์†์ด๋ผ๋Š” ๊ฐœ๋…์ด ์—†์Šต๋‹ˆ๋‹ค.

์ด๋ ‡๊ฒŒ ์—ฌ๋Ÿฌ ์• ๋…ธํ…Œ์ด์…˜์„ ๋ชจ์•„์„œ ์‚ฌ์šฉํ•˜๋Š” ๊ธฐ๋Šฅ์€ ์Šคํ”„๋ง์ด ์ง€์›ํ•ด์ฃผ๋Š” ๊ธฐ๋Šฅ์ž…๋‹ˆ๋‹ค.

@Qualifier ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ๋‹ค๋ฅธ ์• ๋…ธํ…Œ์ด์…˜๋“ค๋„ ํ•จ๊ป˜ ์กฐํ•ฉํ•ด์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋‹จ์ ์œผ๋กœ @Autowired๋„ ์žฌ์ •์˜ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ชฐ๋ก  ์Šคํ”„๋ง์ด ์ œ๊ณตํ•˜๋Š” ๊ธฐ๋Šฅ์„ ๋šœ๋ ทํ•œ ๋ชฉ์  ์—†์ด ๋ฌด๋ถ„๋ณ„ํ•˜๊ฒŒ ์žฌ์ •์˜ํ•˜๋Š” ๊ฒƒ์€ ์œ ์ง€๋ณด์ˆ˜์— ๋” ํ˜ผ๋ž€๋งŒ ๊ฐ€์ค‘ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.


6. ์กฐํšŒํ•œ ๋นˆ์ด ๋ชจ๋‘ ํ•„์š”ํ•  ๋•Œ: List, Map

์˜๋„์ ์œผ๋กœ ์ •๋ง ํ•ด๋‹น ํƒ€์ž…์˜ ์Šคํ”„๋ง ๋นˆ์ด ๋‹ค ํ•„์š”ํ•œ ๊ฒฝ์šฐ๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด์„œ ํ• ์ธ ์„œ๋น„์Šค๋ฅผ ์ œ๊ณตํ•˜๋Š”๋ฐ, ํด๋ผ์ด์–ธํŠธ๊ฐ€ ํ• ์ธ์˜ ์ข…๋ฅ˜(rate, fix)๋ฅผ ์„ ํƒํ•  ์ˆ˜ ์žˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

์Šคํ”„๋ง์„ ์‚ฌ์šฉํ•˜๋ฉด ์†Œ์œ„ ๋งํ•˜๋Š” ์ „๋žต ํŒจํ„ด์„ ๋งค์šฐ ๊ฐ„๋‹จํ•˜๊ฒŒ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

Test ํŒจํ‚ค์ง€์—์„œ autowired ํŒจํ‚ค์ง€ ์•ˆ์— AllBeanTest๋ผ๋Š” ์ž๋ฐ” ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค์–ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

public class AllBeanTest {
    
    @Test
    void findAllBean() {
        ApplicationContext ac = new AnnotationConfigApplicationContext(DiscountService.class);
    }
    
    static class DiscountService {
        private final Map<String, DiscountPolicy> policyMap;
        private final List<DiscountPolicy> policies;
        
        public DiscountService(Map<String, DiscountPolicy> policyMap, List<DiscountPolicy> policies) {
            this.policyMap = policyMap;
            this.policies = policies;
            System.out.println("policyMap = " + policyMap);
            System.out.println("policies = " + policies);
        }
    }
}

์กฐํšŒํ•œ ๋นˆ์ด ๋ชจ๋‘ ํ•„์š”ํ•˜๊ธฐ์— Map๊ณผ List๋ฅผ ์‚ฌ์šฉํ•˜์˜€์Šต๋‹ˆ๋‹ค.

์ž๋™ ์˜์กด๊ด€๊ณ„ ์ฃผ์ž…์ด ๋˜๊ธฐ ์ „์ž…๋‹ˆ๋‹ค. ๊ฒฐ๊ณผ๊ฐ€ ๊ณผ์—ฐ ์–ด๋–ป๊ฒŒ ๋‚˜์˜ฌ๊นŒ์š”?

์ž๋™ ์˜์กด๊ด€๊ณ„ ์ฃผ์ž… ์ „

์ด๋ ‡๊ฒŒ ์•„๋ฌด ๊ฐ’๋„ ์•ˆ ๋‚˜์˜ต๋‹ˆ๋‹ค.

 

์ด๋ฒˆ์—” ์ž๋™ ์˜์กด๊ด€๊ณ„ ์ฃผ์ž…์„ ํ•ด๋ณผ๊ฒŒ์š”.

public class AllBeanTest {

    @Test
    void findAllBean() {
        ApplicationContext ac = new AnnotationConfigApplicationContext(AutoAppConfig.class, DiscountService.class);
    }

    static class DiscountService {
        private final Map<String, DiscountPolicy> policyMap;
        private final List<DiscountPolicy> policies;

        @Autowired
        public DiscountService(Map<String, DiscountPolicy> policyMap, List<DiscountPolicy> policies) {
            this.policyMap = policyMap;
            this.policies = policies;
            System.out.println("policyMap = " + policyMap);
            System.out.println("policies = " + policies);
        }
    }
}

AutoAppConfig.class์™€ @Autowired๋ฅผ ์ถ”๊ฐ€ํ–ˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋Ÿผ ๊ฒฐ๊ณผ๋ฅผ ํ•œ ๋ฒˆ ๋ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

์ž๋™ ์˜์กด๊ด€๊ณ„ ์ฃผ์ž… ํ›„

๊ฐ’์ด ์ž˜ ๋‚˜์˜ต๋‹ˆ๋‹ค.

List๋Š” Value๋งŒ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์ด๋ฆ„์ด ์—†๊ณ , Map์€ <Key, Value> ๋‘˜ ๋‹ค ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์ด๋ฆ„์ด ์žˆ์Šต๋‹ˆ๋‹ค.

 

๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ ๋งŒ๋“ค์–ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

@Test
    void findAllBean() {
        ApplicationContext ac = new AnnotationConfigApplicationContext(AutoAppConfig.class, DiscountService.class);

        DiscountService discountService = ac.getBean(DiscountService.class);
        Member member = new Member(1L, "userA", Grade.VIP);
        int discountPrice = discountService.discount(member, 10000, "fixDiscountPolicy");
        
        assertThat(discountService).isInstanceOf(DiscountService.class);
    }

VIP ๋“ฑ๊ธ‰์ธ userA๋ผ๋Š” ์‚ฌ๋žŒ๊ณผ ๊ทธ ์‚ฌ๋žŒ์ด 10000์›์งœ๋ฆฌ ๋ฌผ๊ฑด์„ ์ƒ€์„ ๋•Œ์˜ ํ• ์ธ ๊ธˆ์•ก์˜ ์ฝ”๋“œ๋ฅผ ์ ์—ˆ์Šต๋‹ˆ๋‹ค.

์ด๋ ‡๊ฒŒ ํ•ด๋†“์œผ๋ฉด discount์— ๋นจ๊ฐ„์ƒ‰์ด ๋œฐ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

discount์— create Method๋ฅผ ํ•˜๋ฉด 

 public int discount(Member member, int i, String fixDiscountPolicy) {
      return 0;
}

์ด ์ฝ”๋“œ๊ฐ€ ์ƒ๊ธธ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

 

 

 

 


์ด๋ฒˆ ์„น์…˜๋„ ์ด๋ ‡๊ฒŒ ๋์ด ๋‚ฌ์Šต๋‹ˆ๋‹ค.

ํ›„.. ์—„์ฒญ ๊ธธ์—ˆ๋„ค์šฅ..!!

๋‹ค์Œ ์„น์…˜์€ ๋นˆ ์ƒ๋ช…์ฃผ๊ธฐ ์ฝœ๋ฐฑ์— ๊ด€๋ จํ•ด์„œ ํ•  ์˜ˆ์ •์ž…๋‹ˆ๋‹ค.

๊ทธ๋Ÿผ ์•ˆ๋‡ฝ!!