개발이 좋아서/Spring이 좋아서

DI (Dependency Injection) / IoC (Inversion of Control) 예제로 알아보자

zoaseo 2024. 12. 27. 19:08
public class MemberServiceImpl implements MemberService {

    private final MemberRepository memberRepository = new MemoryMemberRepository();

    @Override
    public void join(Member member) {
        memberRepository.save(member);
    }

    @Override
    public Member findMember(Long memberId) {
        return memberRepository.findById(memberId);
    }
}

- MemberServiceImpl은 지금 MemberRepository(추상) 뿐만 아니라 MemoryMemberRepository(구체/구현)에도 의존하고 있다. 그렇기 때문에 DIP원칙을 위반하는 것이다.

- 그리고 구현체를 일일이 저기서 바꿔끼워줘야 하기때문에  OCP원칙도 위반이 된다.

 

public class AppConfig {

    public MemberService memberService() {
        return new MemberServiceImpl(memberRepository());
    }

    private MemberRepository memberRepository() {
        return new MemoryMemberRepository();
    }
}

- appConfig를 만들어 관심사를 분리했다. 외부에서 주입을 하게끔 만들었다.

public class MemberServiceImpl implements MemberService {

    private final MemberRepository memberRepository;

    public MemberServiceImpl(MemberRepository memberRepository) {
        this.memberRepository = memberRepository;
    }

    @Override
    public void join(Member member) {
        memberRepository.save(member);
    }

    @Override
    public Member findMember(Long memberId) {
        return memberRepository.findById(memberId);
    }
}

- 그래서 MemberServiceImpl에서 MemberRepository(구체/구현)에만 의존하게 되어 DIP원칙을 지킬 수 있다.

이것을 의존성 주입(Dependency Injection)이라고 한다.

 

public class AppConfig {

    public MemberService memberService() {
        return new MemberServiceImpl(memberRepository());
    }

    private MemberRepository memberRepository() {
        return new MemoryMemberRepository();
    }

    public OrderService orderService() {
        return new OrderServiceImpl(memberRepository(), discountPolicy());
    }

    private DiscountPolicy discountPolicy() {
//        return new FixDiscountPolicy();
        return new RateDiscountPolicy();
    }
}

- appConfig 안에서 FixDiscountPolicy에서 RateDiscountPolicy로 변경만 해주면 된다.

- 프로그램에 대한 권한은 모두 appConfig가 가지고 있다. 그런 사실도 모른체 MemberServiceImpl은 묵묵히 자신의 로직을 실행하고 있다. 이렇듯 프로그램의 제어 흐름을 직접 제어하는 것이 아니라 외부에서 관리하는 것을 제어의 역전(IoC)이라 한다.

- appConfig처럼 객체를 생성하고 관리하면서 의존관계를 연결해 주는 것을 IoC 컨테이너 또는 "DI 컨테이너"라고 한다.