본문 바로가기

Spring

스프링 핵심 원리 - 기본편 : 의존관계 자동 주입(1/2)

스프링 핵심 원리 - 기본편 : 의존관계 자동 주입(1/2)

- 다양한 의존관계 주입 방법

지금까지 클라이언트 클래스가 구현클래스에게 의존하지 않고 생성자를 통한 의존관계 주입(DI)을 통해 객체지향의 OCP, DIP를 지킬 수 있었다. 하지만 의존관계 주입은 생성자 뿐만아니라 다양한 방법으로도 가능하다. 

생성자 주입

생성자를 통한 의존관계 주입

말그대로 클래스의 생성자를 통해 의존관계를 주입받는다.

 

딱 한번만 호출되어 주입된 객체의 불변성을 보장한다. 때문에 final 키워드를 사용할 수있다. final 은 불필요한 변경을 컴파일 단계에서 막을 수 있다는 장점을 가진다.

 

스프링을 통해 DI컨테이너를 생성할때, 컴포넌트 스캔을 통해 빈을 등록한다면 생성자가 단 하나만 존재한다면 @Autowired를 생략 가능하다. (스캔 당하는 클래스를 빈에 등록하는 과정에서 생성자가 필연적으로 호출되기 때문)

 

 

수정자 주입(setter 주입)

setter 메서드를 만들어서 의존관계를 주입하는 방법이다.

수정자를 통한 의존관계 주입

변경할 가능성이 있는 의존관계를 주입할 떄 사용한다. 주입되는 객체가 변경될 수 있으므로 final 키워드를 사용할 수 없다.

 

@Autowired를 꼭 붙혀주어야한다.

 

주입할 대상이 많을 경우 누락하게 될 가능성이 있어 조심히 사용해야한다.

 

 

필드 주입

필드에 그대로 주입하는 방법이다. 코드를 보면 이해가 쉽다.

필드를 통한 의존관계 주입

이와 같이 의존관계를 주입받을 필드 앞에 @Autowired 를 붙혀주면 스프링이 자동으로 맞는 타입의 빈을 찾아 의존관계를 주입해준다.

 

코드가 제일 간결해서 좋아보이지만 단점이 명확해서 요즘은 잘쓰지 않는다고 한다. 일단 외부에서 변경이 불가능 하기 때문에 테스트하기가 매우 힘들다. 생성자 또는 수정자를 통해 테스트 코드를 작성할 때는 매개변수를 통해 직접 의존관계를 주입해 줄 수 있지만, 필드주입에 경우 모든 것을 스프링에게 의존하기 때문에 순수한 자바 객체를 생성해 값을 테스트를 진행할 수 없어 꼭 DI 프레임워크에 의존해야만 한다.

 

그러니까 사용하지 말자!!

 

 

일반 메서드 주입

getter 를 통한 주입과 유사하다. 단 동시에 여러개의 매개변수를 받을 수 있다는 장점이 있다. 하지만 일반적으로 잘 사용하는 방법은 아니다.(약속되지 않은 방식) 

 

 

- 옵션 처리

기본설정으로 의존관계를 주입할 때 주입할 수 있는 빈이 없으면 프로그램은 종료된다. 하지만 빈이 존재하지 않아도 동작해야될 때가 있다. 이에 대해 3가지 방법으로 이를  지원한다.  

@Test
void AutowiredOption() {
    ApplicationContext ac = new AnnotationConfigApplicationContext(TestBean.class);
}

static class TestBean{

    @Autowired(required = false)
    public void setNoBean1(Member noBean1) {
        System.out.println("noBean1 = " + noBean1);
    }

    @Autowired
    public void setNoBean2(@Nullable Member noBean2) {
        System.out.println("noBean2 = " + noBean2);
    }

    @Autowired
    public void setNoBean3(Optional<Member> noBean3){
        System.out.println("noBean3 = " + noBean3);
        System.out.println(noBean3.get() == null);
    }
}

첫번쨰는 @Autowired의 required 옵션을 false로 하는 것이다. required 옵션은 true 가 default 로 설정되어있는데 이를 false로 바꿔주면 빈이 없을 때 메소드 자체를 호출 하지 않는다.

 

두번쨰는 매개변수에 @Nullable 을 붙히는 것이다. 이러면 의존관계 주입 시 빈을 찾지 못하면 null을 주입한다.

 

세번째는 Optional<> 객체를 매개변수로 받는것이다. 이 또한 주입할 빈을 찾지 못하면 Optional.empty가 입력된다.

 

 

- 생성자 주입을 선택해라!

과거에는 수정자, 필드 주입을 많이 사용했지만 요즘은 생성자 주입을 권장하고 주로 사용하는 추세이다.

그 이유는 크게 객체의 불변성을 지키기 위해, 그리고 테스트 시의 누락을 피하기 위해서 이다.

 

의존관계 주입을 통해 할당되는 객체는 대부분 종료시점까지 의존관계를 변경할 일이 없고, 불변해야만 하는 경우가 많다. 때문에 수정자를 통한 방식으로 의존관계를 주입받게 되면, 수정자 메소드는 public 으로 선언되기 때문에 다른 누군가가 실수로 다른 의존관계를 주입하는 실수를 만들 수 있다. 하지만 생성자를 통한 주입은 객체를 생성할 떄 단 한번만 호출되므로 객체가 변할 일이 없다. 즉 불변하게 설계할 수 있다.

 

또한 생성자 주입은 의존관계가 복잡하게 얽혀 있을 경우에 테스트에 편리하다. 순수한 자바 객체를 통해 테스를 진행할 경우 의존관계가 복잡하다면, 개발자가 의존하는 객체를 누락할 가능성이 크고, 이를 수정자를 통해 의존관계를 주입하는 로직을 갖고 있다면 실행타임에서야 오류를 발견할 수 있다. 하지만 생성자를 통해 의존관계를 주입할 경우, final 키워드를 사용하여 누락된 의존관계가 있을때 컴파일 자체가 되지 않기때문에 실행해보지 않아도 오류를 찾아 쉽게 고칠 수 있다. 

 


[참고 강의 출처]

https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EA%B8%B0%EB%B3%B8%ED%8E%B8/dashboard

 

스프링 핵심 원리 - 기본편 - 인프런 | 강의

스프링 입문자가 예제를 만들어가면서 스프링의 핵심 원리를 이해하고, 스프링 기본기를 확실히 다질 수 있습니다., 스프링 핵심 원리를 이해하고, 성장하는 백엔드 개발자가 되어보세요! 📢

www.inflearn.com