본문으로 바로가기

목차

    1. DI(의존성 주입)

    스프링 의존성 주입 방식에는 3가지 방식이 있습니다.

    1. 필드 주입
    2. setter 주입
    3. 생성자 주입

    예시는 컨트롤러에 서비스 객체 의존성을 주입한다고 가정합니다.

     

    [서비스]

    @Service
    public class MemberService {
    
        //( ... ) 생략   
    }

    2. 필드 주입

    [컨트롤러]

    @Controller
    public class MemberController {
    
        @Autowired
        private MemberService memberService;
    }
    • 필드 주입은 소스 수정이 쉽지 않으므로 별로 권장하지 않음(구현 클래스의 변경 같은 상황에 대처가 힘듭니다.)

    3. setter 주입

    [컨트롤러]

    @Controller
    public class MemberController {
    
        private final MemberService memberService;
    
        @Autowired
        public void setMemberController(MemberService memberService) {
            this.memberService = memberService;
        }
    }
    • 생성은 생성자대로 되고 setter는 따로 실행되면서 의존성 주입을 실행합니다.
    • setter 주입 방식은 접근 지정자가 public로 누구나 접근 가능하도록 노출이 되면서 변경을 누구나 할 수 있는 상황이 생기게 되는데 변경이 잘못되면 큰 문제가 생길 수 있습니다.
    • 과거에는 자주 사용하였으나 보통은 생성되고 바뀔 일이 거의 없으므로 권장되지 않는 방식입니다.

    4. 생성자 주입

    [컨트롤러]

    @Controller
    public class MemberController {
    
        private final MemberService memberService;
    
        @Autowired
        public MemberController(MemberService memberService) {
            this.memberService = memberService;
        }
    }
    • 가장 권장되는 방식입니다.
    • 따라서 생성자가 1개인 경우 @Autowired를 생략해도 주입이 가능하도록 편의를 제공합니다.
    • 의존관계가 실행 중에 동적으로 변하는 경우는 거의 없으므로 생성자 주입을 권장합니다.(아얘 없다고 보면 됩니다.)

    5. 생성자 주입을 사용해야 되는 이유

    1. 객체의 불변성 확보
      • 의존 관계 주입의 변경이 필요한 상황은 거의 없습니다.
      • OOP의 5가지 개발 원칙 중 OCP(Open-Closed Principal, 개방-폐쇄의 법칙)를 위반하지 않도록 생성자 주입을 통해 변경의 가능성을 배제하고 불변성을 보장하는 것이 좋습니다.
    2. 테스트 코드의 작성
      • 실제 코드가 필드 주입으로 작성된 경우에는 순수한 자바 코드로 단위 테스트를 작성하는 것이 불가능 합니다.
    3. final 키워드 작성 가능
      • 생성자 주입을 사용하면 필드 객체에 final 키워드를 사용할 수 있으며, 컴파일 시점에 누락된 의존성을 확인할 수 있습니다. 
      • 다른 주입 방법들은 객체의 생성(생성자 호출) 이후에 호출되므로 final 키워드를 사용할 수 없습니다.
    4. 순환 참조 에러 방지
      • 애플리케이션 구동 시점(객체의 생성 시점)에 순환 참조 에러를 방지할 수 있다.
      • StackOverflow 방지