Spring

[Spring] AppConfig 역할

배씌 2024. 5. 22. 16:30
public class OrderServiceImpl implements OrderService{
    private final MemberRepository memberRepository = new MemoryMemberRepository();
    private final DiscountPolicy discountPolicy = new FixDiscountPolicy();
}

 

위 코드를 보면

private final DiscountPolicy discountPolicy = new FixDiscountPolicy();

이렇게 인터페이스('DiscountPolicy') 도 참조하고, 구현체('FixDiscountPolicy') 도 같이 참조하는 것을 볼 수 있다.

A라는 공연에서 배우를 뽑을 때, 감독이 뽑는 것이 아닌 남자배우가 여자배우를 뽑는 것과 같다.

※ DIP위반

 

여기서 고정할인(FixDiscountPolicy) 에서 정률할인(RateDiscountPolicy) 로 변경하기 위해선

private final DiscountPolicy discountPolicy = new RateDiscountPolicy();

로 코드를 직접 작성해야 한다.

 

이는 ※OCP 위반

 

AppConfig

위와 같은 DIP, OCP를 위반하지 않도록 해주는 것이 AppConfig 이다.

애플리케이션의 전체 구성을 책임지는 담당자

이를 통해 생성자를 주입하게 된다.

 

AppConfig.java

public class AppConfig {
    public MemberService memberService(){
        return new MemberServiceImpl(new MemoryMemberRepository());
    }

    public OrderService orderService(){
        return new OrderServiceImpl(new MemoryMemberRepository(), new FixDiscountPolicy());
    }
}

 위와 같이 AppConfig에서 환경을 설정하고, 블록식으로 갈아끼울 수 있는 것이다.

현재 MemoryMemberRepository() 를 사용하고 있지만, 추후에 DB를 사용한다면 괄호 안 내용만 DB 로 수정해주면 된다.

 

이에 맞춰 Impl 클래스들도 모두 수정해주면 된다.

 

(수정전) OrderServiceImpl.java

public class OrderServiceImpl implements OrderService{
	// 인터페이스와 구현체 둘다 참조
    private final MemberRepository memberRepository = new MemoryMemberRepository();
    private final DiscountPolicy discountPolicy = new FixDiscountPolicy();

    @Override
    public Order createOrder(Long memberId, String itemName, int itemPrice){
        Member member = memberRepository.findById(memberId);
        int discountPrice = discountPolicy.discount(member, itemPrice);

        return new Order(memberId, itemName, itemPrice, discountPrice);
    }
}

 

(수정후) OrderServiceImpl.java

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;
    }

    @Override
    public Order createOrder(Long memberId, String itemName, int itemPrice){
        Member member = memberRepository.findById(memberId);
        int discountPrice = discountPolicy.discount(member, itemPrice);

        return new Order(memberId, itemName, itemPrice, discountPrice);
    }
}

 

인터페이스에만 의존하며, 생성자를 통해 AppConfig 에서 생성자를 주입함으로써, DIP를 준수한다.