끄적끄적

[JAVA] 의존성 주입(DI) 본문

Back-end/Java

[JAVA] 의존성 주입(DI)

mashko 2021. 5. 6. 23:27
반응형

 

 

의존성 주입 Dependency Injection
spring 환경에 lombok을 이용한 개발을 하다보면 여러방법으로 의존성 주입을 하게 됩니다.
의존성 주입 방법에 대해 정리해보려고 합니다. 앞서 포스팅에서 IOC컨테이너와 DI에 대해 정리했는데
(객체 자체가 아니라 Framework에 의해 객체의 의존성이 주입되는 설계 패턴)
컨테이너가 빈을 생성하고 종속성 주입을 하는데 이 부분에서 프로그램 제어권을 프레임워크가 가져가는 구조라 제어의 역전(Dependency Injection)이라고 합니다.

 

 

의존성 주입하는 방법에 대해 몇 가지 정리해봅시다.

@Autowired를 통한 의존성 주입

public class Example {

    @Autowired
    private InvalidFacilityInterceptor invalidFacilityInterceptor;

    public void addInterceptors(InterceptorRegistry registry) {

        ....

    }
}

위의 방식처럼 단순하게 @Autowired를 통해 IOC컨테이너 안에 존재하는 Bean을 자동으로 주입해 줄 수 있습니다.
하지만 순환참조에 대한 에러를 잡아내지 못하고 런타임에서 메서드 실행시 에러를 발생합니다.

@RequiredArgsConstructor을 통한 의존성주입

@RequiredArgsConstructor
public class Example {

    private final InvalidFacilityInterceptor invalidFacilityInterceptor;

    public void addInterceptors(InterceptorRegistry registry) {

        ....

    }
}

위의 방식대로 @RequiredArgsConstructor를 통해 따로 생성자코드를 만들지 않아도 자동으로 주입시켜줍니다.
하지만 여러 어노테이션이 사용이 되기 때문에 불필요한 메서드가 생성되기도 합니다.
또한 필드선언 순서에 의해 생성자의 파라미터가 생성됩니다.
필드주입방식이 위의 방식도 생성자를 통한 주입이 되기 때문에 순환참조에 대해 방지할 수 있습니다.

constructor를 통한 의존성주입

public class Example {

    private final InvalidFacilityInterceptor invalidFacilityInterceptor;

    public Example(InvalidFacilityInterceptor invalidFacilityInterceptor) {
        this.invalidFacilityInterceptor = invalidFacilityInterceptor;
    }

    public void addInterceptors(InterceptorRegistry registry) {

        ....

    }
}

제일 권장되는 주입방식입니다.
생성자주입을 사용하게 되면 위에 방식에 대해 두 단점을 보완할 수 있으면서, 주입 순서에 대해 필드 선언 순서가 아닌 파라미터 순서에 의해 보장받게 됩니다.

결론
Spring Team recommends: “Always use constructor based dependency injection in your beans. Always use assertions for mandatory dependencies”.

생성자 주입이 아닌 다른 방식으로 주입하면 위와 같은 경고문을 볼 수 있듯이 생성자 주입방식을 권고하고 있습니다.
왜인지 몇가지 정리해봅시다.

  • 순환참조방지
    (필드주입방식을 이용해 개발을 하다보면 StackOverflowError라는 문구를 접할 수 있는데 순환참조에 대한 메소드 실행 시점 전까지 알 수가 없습니다.)
    Description:
    The dependencies of some of the beans in the application context form a cycle:
    ┌─────┐
    | ExampleService defined in file [/ExampleService.class]
    ↑ ↓
    | ExampleService defined in file [
    /ExampleService.class]
    └─────┘
    생성자 주입방식의 개발에서의 순환참조에 대한 메세지.
  • final 선언
    (생성자 주입과 달리 나머지 주입방식은 final을 선언 할 수 없습니다.(런타임에 객체 불변성을 보장합니다.))
  • 테스트 코드 작성 용이
    (독립적으로 인스턴스화를 할 수 있어서 DI컨테이너를 사용하지 않아도 단위 테스트에서의 목킹을 하지 않아도 인스턴스를 통해 테스트가 가능합니다.)
  • 코드 품질
    (어느정도의 인지를 할 수 있는 구실을 주어, 의존성주입에 대해 인지를 시켜 줄 수 있습니다. 코드를 정리하지 않고 덧붙이는 걸 조금은 방지 할 수 있고, 파라미터의 순서에 대해 인지 할 수 있습니다.(@Autowired나 @RequiredArgsConstructor는 선언 순서대로 인자값이 부여됨))
반응형

'Back-end > Java' 카테고리의 다른 글

[JAVA] JavaTimeModule 포멧팅  (0) 2021.11.12
[JAVA] Enum 삽질기..  (1) 2021.11.11
[JAVA] Spring Boot json Enum json object or jsonvalue  (0) 2021.11.10
[JAVA] JVM 동작원리  (0) 2021.05.10
[JAVA] spring - IOC,AOP,DI 란?  (0) 2020.04.13
Comments