본문 바로가기
Spring

(Spring) IoC / DI

by windy7271 2022. 6. 24.
728x90
반응형

IoC  

기존 프로그램은 구현 객체가 스스로 필요한 구현 객체를 생성, 연결, 실행 하였다. 즉 구현 객체가 프로그램의 제어 흐름을 스스로 조종했다.

객체 생성을 컨테이너에게 위임해서 처리하는 방식이다.

이런 프로그램의 제어 흐름을 구현 객체가 직접 제어하는 것이 아닌 외부에서 관리하는 것을  제어의 역전(IoC) 이라고 한다.

 

특징

- 직접  객체 생성을 직접하지 않고 컨테이너에게 생성, 소멸 등을 관리 한다.

- 개발자가 직접 컨트롤 할 수 없다.

Spring 에서는 beab.xml / annotaition 을 이용하여 객체를 관리한다.

 

장점

- 의존성으로부터 격리되어 코드테스트에 용이하다

- 코드 확장하거나 변경할 때 영향을 최소화 한다.

- 순환참조를 막을 수 있다.

 

의존관계 주입을 사용하면 정적인 클래스  의존관계를 변경하지 않고, 동적인 객체 인스턴스 의존관계를 쉽게 변경할 수 있다.

 

DI

IoC 컨테이너에 빈으로 등록이 되어야 의존성 주입 가능.

 

DI 란 IoC의 핵심 요소이고 제어의 역전이 일어날 때 스프링이 내부에 있는 객체들간의 관계를 관리할 때 사용하는 기법이다.

의존성 주입을 의미하며 이는 의존적인 객체를 직접 생성하거나 제어하는 것이 아니라, 특정 객체에 필요한 객체를 외부에서 결정해

연결시키는 것을 의미한다. 즉 클래스의 기능을 추상적 으로 묶어놓은 인터페이스를 가져다 쓰면 되고, 그 밖은 스프링에서 객체를 주입해줌.

모듈간 결합도는 낮아지고 유연성은 높아진다.

 

객체 인스턴스를 생성하면 참조값 전달 후 연결되고 di를 사용하면 클라이언트 코드 변경 없이 클라이언트가 호출하는 대상의 타입 인스턴스를 변경할 수 있다.의존또한 의존관계를 변경하지 않고 동적인 객체 인스턴스의 의존관계를 쉽게 변경할 수 있다.

이런 의존관계를 연결해 주는 것을 IoC컨테이너/ DI컨테이너 라고 부른다.

 

특징

- 하나의 모듈 서비스가 가지고 있는 의존성을 외부로 통해 주입받는다

- 생성자/ setter를 이용하여 의존성을 주입 받을 수 있다.

- Spring 에서는 @Autowired 사용하여 의존성 주입이 되는 대상을 지정한다.

 

 

1. 생성자 주입 : 생성자의 호출 시점에 1회 호출 되는 것이 보장된다. >> 주입받은 객체가 변하지 않거나, 반드시 객체의 주입이 필요한 경우

강제하기 위해 사용한다, 또한 Spring 에서 생성자 주입을 지원한다. 생성자가 1개 인 경우 @Autowirde 생략해도 주입 가능

 

- 생성자에 많은 의존성이 추가 될 경우 리팩토리 시점 감지 가능

- 의존성 주입 대상 필드를 final로 불편 객체 선언할 수 있음

- spring 에서 지원함

- 생성자 호출시점에 딱 1번만 호출되는 것이 보장된다

- 불변 필수 의존관계에 사용된다

 

public class MemberServiceImpl implements MemberService {
    private final MemberRepository memberRepository;
    public MemberServiceImpl(MemberRepository memberRepository) {
        this.memberRepository = memberRepository;
    }
    public void join(Member member) {
        memberRepository.save(member);
    }
    public Member findMember(Long memberId) {
        return memberRepository.findById(memberId);
    } }

 

 

 

2. 수정자 주입: 필드 값을 변경 하는 경우 Setter 를 통해 의존 관계 주입한다.

주입받는 객체가 변경 될 가능성이 있는 경우 사용 한다. (거의 안씀) 

 

- 의존성이 선택적으로 필요한 경우 사용

- 과도하게 복잡해질 수 있는 것 을 선택적으로 나눠 주입 할 수 있게 부담을 덜어줌

- 의존성 주입 대상 필드가 final 선언 불가

@Component
    public class OrderServiceImpl implements OrderService {
        private MemberRepository memberRepository;
        private DiscountPolicy discountPolicy;
       
        @Autowired        
        public void setMemberRepository(MemberRepository memberRepository) {
            this.memberRepository = memberRepository;
        }
        
        @Autowired       
        public void setDiscountPolicy(DiscountPolicy discountPolicy) {
            this.discountPolicy = discountPolicy;
        }
}

 

 

3. 필드 주입: 필드에 바로 의존 관계를 주입하는 방법. (추천하지 않음)

 

코드가 간결해 진다.    하지만 외부에서 접근이 불가능한 단점  또한 반드시 DI Framework가 존재해야한다.

 

- 의존 관계가 눈에 잘 보이지 않아 추상적 >>> 의존성 관계가 복잡해 질 쑤 있음.

- 의존성 주입 대상 필드가 final 선언 불가

- DI container 와 강한 결합을 가져 외부 사용이 어려움

- DI 프레임 워크가 없으면 아무것도 못한다.

 

 

@Service
public class UserService {

    @Autowired
    private UserRepository userRepository;
    @Autowired
    private MemberService memberService;

}

 

 

 

 

반응형

댓글