본문 바로가기

항해99

항해99 4주차 WIL - IOC, DI

쌓아놨던 기술 부채 하나였던 4주차 WIL를 처리하려고 합니다.

 

IOC와 DI는 다른 개념이지만 자칫하면 헷갈릴수도 있습니다.

 

IOC란 제어의 역전입니다.

프로그램의 제어권을 개발자가 같는 것이 아니라 프로그램이 같는 것을 말합니다.

쉽게 말해 프로그램이 대신 해주는 것입니다.

 

우리는 따로 어떠한 코드를 짜지 않아도 스프링 빈이 싱글톤으로 관리되는 것도 스프링이 제어권을 가지고 있기 때문입니다. 또한 @Controller, @Service, @Repository이 어느 시점에 호출되는지도 개발자가 딱히 신경쓰지 않더라도 스프링이 대신 처리합니다.

 

스프링 IoC 컨테이너에 들어가게 되면 수행되는 것 중 하나가 DI입니다.


DI란 의존관계 주입입니다.

의존관계를 자신이 아니라 외부에서 하는 것을 말합니다.

 

아래는 의존 관계를 자신이 하는 사례입니다. 

public class MemberController() {
	SocialService socialService = new GoogleSocialService();
  	JwtAuth jwtAuth = new SimpleJwtAuth();
    
    // ... 이하 회원가입, 로그인 메소드 등 생략
}

 

우선 이럴 경우 구현체에 의존하면서 DIP를 위반하게 됩니다.

그리고 객체의 역할이 너무나도 많습니다.

 

1. 컨트롤러로서 Http 요청, 응답을 처리해야 합니다.

2. 인터페이스 구현체 결정

 

DI를 통해 컨트롤러의 역할을 1로 한정시키면서 DIP를 준수할 수 있습니다.

우선 DIP를 준수하기 위해서는 아래와 같이 코드가 변경되어야 합니다.

public class MemberController() {
	SocialService socialService;
  	JwtAuth jwtAuth;
    
    // ... 이하 회원가입, 로그인 메소드 등 생략
}

 

그리고 이 인터페이스에 대한 구현체는 외부에서 전달해야합니다.

 

먼저 의존 관계를 주입할 방식을 선택해야 합니다. 여기서는 생성자 주입을 사용하겠습니다.

public MemberController(SocialService socialService, JwtUtil jwtUtil) {
    this.memberService = memberService;
    this.jwtUtil = jwtutil;
}

 

아래와 같이 인터페이스의 구현체를 설정하는 역할을 맡은 클래스를 따로 두는 것입니다.

public class AppConfig {
    public SocialService socialService() {
        return new GoogleSocialService();
    }
    public JwtAuth jwtAuth() {
        return new SimpleJwtAuth();
    }
    public MemberController memberController() {
    	return new MemberController(socialService(), jwtAuth())
    }
}

 

 

이를 통해서

1. DIP 원칙을 준수할 수 있게 되었고

2. 컨트롤러가 1번 역할에 집중할 수 있도록 만들어 줍니다.

 

위 코드는 순수 자바를 사용한 DI 방식입니다. IoC와 DI에 대한 개념이 조금 이해가 되었을까요?