티스토리 뷰

Springboot를 활용하여 공부하고 있는 중 의존성 주입을 할때, Field, Setter Injection은 좋지 않다는 것을 알게 되었다. 왜 그런지 찾아보았고 정리해본다.
우선, 의존성 주입의 종류로는 Field, Setter, Constructor이 있다.

1.

의존성 주입의 종류


1.Field Injection

    @Service
    public class MemberService{

        @Autowired
        private MemberRepository memberRepository;
    }

2.Setter Injection

    @Service
    public class MemberService{

        private MemberRepository memberRepository;

        @Autowired
        public void setMemberRepository(MemberRepository memberRepository){
            this.memberRepository = memberRepository;
        }
    }

3.Constructor Injection

    @Service
    public class MemberService{

        private MemberRepository memberRepository;

        @Autowired
        public MemberService(MemberRepository memberRepository){
            this.memberRepository = memberRepository;
        }
    }

2. 왜 Constructor Injection을 권장하는가?


1. 단일 책임의 원칙

생성자의 인자가 많을 경우 코드량도 많아지고, 의존관계도 많아져 단일 책임의 원칙에 위배된다. 그래서 Constructor Injection을 사용함으로써 의존관계, 복잡성을 쉽게 알수 있어 리팩토링의 단초를 제공하게 된다.

2. 테스트 용이성

DI 컨테이너에서 관리되는 클래스는 특정 DI 컨테이너에 의존하지 않고 POJO여야 한다. DI 컨테이너를 사용하지 않고도 인스턴스화 할 수 있고, 단위 테스트도 가능하며, 다른 DI 프레임 워크로 전환할 수도 있게 된다.

3. Immutability

Constructor Injection에서는 필드는 final로 선언할 수 있다. 불변 객체가 가능한데 비해 Field Injection은 final는 선언할 수 없기 때문에 객체가 변경 가능한 상태가 된다.

4. 순환 의존성

Constructor Injection에서는 멤버 객체가 순환 의존성을 가질 경우 BeanCurrentlyInCreationException이 발생해서 순환 의존성을 알 수 있게 된다.

순환 의존성이란?
A Class가 있고 B Class가 있는데, 각각 서로가 서로를 참조하고 있는 상황에서 발생한다. 이러한 상황에서 A Class가 메모리에 올라가기 전에 B Class가 A Class를 의존주입하는 상황이나 혹은 그 반대의 경우 문제가 발생한다.

5. 의존성 명시

의존 객체 중 필수는 Constructor Injection을 옵션인 경우는 Setter Injection을 활용할 수 있다.

3. 테스트 코드 작성하기 좋다.


field Injection의 경우 간단하긴하지만 테스트 코드를 작성할 때 불편하다는 단점이 있다. 어떤 불편함이냐면 단위 테스트를 하기위해 저 코드에서 Mock 객체로 끼워넣기가 복잡하다. 이유는 생성자도, 수정자(setter)도 없기때문이다.

그럼 setter Injection은? setter Injection은 테스트 코드 작성 시 mock를 주입할 수 있다. 하지만 객체가 생성된 이후에도 주입된 객체들을 바꿀 수 있다는 단점이 있다. 하지만 내부 객체가 프로덕션 코드에서도 변경될 수 있기때문에 위험하기도 하다.

field, setter 주입은 이런 단점이 있기 때문에 Constructor Injection(생성자 주입)을 사용해야된다. Constructor Injection은 객체 생성시 주입객체를 받기 때문에 주입된 객체를 수정할 수 없다. 또한 생성자가 명시적으로 존재하기때문에 Mock 객체를 주입하기에도 편하다.

4. Lombok를 사용한 생성자 주입 방법


Constructor Injection를 사용하면 코드가 복잡해 보일 수 있다. 이런 점을 보완하기 위해 Lombok을 활용하는 방법도 많이 쓴다.

Lombok@RequiredArgsConstructor를 사용하는 방법인데 final이나 @NonNull이 설정된 필드 값을 파라미터로 받는 생성자를 만들어 준다.

    @Service
    @RequiredArgsConstructor
    public class MemberService{

        private final MemberRepository memberRepository;
    }

위와 같은 코드를 작성하면 MemberRepository에 한해서 생성자를 만들어 준다. 여러개의 의존성을 주입받는 경우 코드가 복잡해 보일 수 있기 때문에 위의 방법을 사용하는 것도 좋다.

5. 참고


공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/11   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
글 보관함