작심삼일러의 스프링 시작하기(2)

서은경·2022년 7월 27일
0

Spring

목록 보기
5/43

의존 주입이란?(Dependency Injection)

의존이란 변경에 의해 영향을 받는 관계를 의미한다. 의존 주입은 객체 자체가 아니라 Framework에 의해 객체의 의존성이 주입되는 설계 패턴인데 IOC와 연결되는 개념이다. DI는 의존하는 객체를 직접 생성하는 대신 의존 객체를 전달받는 방식을 사용한다.

IOC란? (Inversion Of Controll : 제어의 역전)
객체의 생성과 그 객체들의 관리까지 모두 관리한다는 개념이다.
기존에 자바 기반으로 어플리케이션을 개발할 때 자바 객체를 생성하고 서로간의 의존 관계를 연결시키는 작업에 대한 제어권은 보통 개발되는 어플리케이션에 있었는데 IOC 컨테이너는 객체의 생성, 초기화, 서비스 소멸에 관한 모든 권한을 가지면서 객체의 생명주기를 관리한다.
이것을 제어권이 역전되었다해서 IOC라고 부른다.

가령 이런 서비스 클래스가 있다고 가정했을 때, 이 서비스 클래스는 memberDao의 selectByEmail() 메서드를 통해 중복처리를 해야하므로 memberDao 클래스에 의존한다고 표현한다.

의존 객체를 직접 생성하지 않고 생성자를 통해 주입받는 것을 볼 수 있는데 이 코드는 의존 주입 패턴을 따르고 있는 것이다.

public class MemberRegisterService {

    private MemberDao memberDao;

    public MemberRegisterService(MemberDao memberDao) {
        this.memberDao = memberDao;
    }

    public Long regist(RegisterRequest req) {
        Member member = memberDao.selectByEmail(req.getEmail());
        if (member != null) {
            throw new DuplicateMemberException("dup email" + req.getEmail());
        }

        Member newMember = new Member(req.getEmail(), req.getPassword(), req.getName(), LocalDateTime.now());
        memberDao.insert(newMember);
        return newMember.getId();
    }
}

의존 객체 변경의 유연함

클래스 내부에서 직접 의존 객체를 생성하는 것은 유지보수 관점에서 문제점을 유발할 수 있다. (코드 변경이 필요할 경우 사용되는 모든 클래스를 변경해줘야 하기 때문)
하지만 의존성 주입을 사용한다면 의존 주입 대상이 되는 객체를 생성하는 코드 한 곳만 변경해 줄 수 있다. (ex. memberRegisterService 객체를 생성하는 구간 한 곳!)
의존 객체를 직접 생성했던 방식에 비해 변경할 코드가 한 곳으로 집중되는 것을 알 수 있다.

객체 조립기(assembler)

=스프링
스프링 이해를 위한 클래스이므로 간단하게 설명하고 넘어간다. 객체를 생성하고 의존 객체를 주입하는 기능을 제공하는 클래스로 이 부분에서 객체 초기화하고 의존 객체 주입한다.

public class Assembler {

    private MemberDao memberDao;
    private MemberRegisterService regSvc;
    private ChangePasswordService pwdSvc;

    public Assembler() {
        memberDao = new MemberDao();
        regSvc = new MemberRegisterService(memberDao);
        pwdSvc = new ChangePasswordService();
        pwdSvc.setMemberDao(memberDao);
    }

바로 이런식으로 ~!

스프링 DI 설정

스프링은! 조립기처럼 필요한 객체를 생성하고 생성한 객체에 의존을 주입한다. 또한 객체를 제공하는 기능을 정의하고 있다!

  1. DI 방식1 : 생성자 방식
	private MemberDao memberDao;

    public MemberRegisterService(MemberDao memberDao) {
        this.memberDao = memberDao;
    }
  1. DI 방식2 : 세터 메서드 방식

    private MemberPrinter printer;

    public void setMemberDao(MemberDao memberDao) {
        this.memberDao = memberDao;
    }

    public void setPrinter(MemberPrinter printer) {
        this.printer = printer;
    }

각각의 방식에는 장단점이 있는데 필요에 의해 혼용하여 사용하면 되겠다.

  • 장점
    생성자 : 빈 객체를 생성하는 시점에 모든 의존 객체가 주입된다
    메서드 : 세터 메서드 이름을 통해 어떤 의존 객체가 주입되는지 알 수 있다
  • 단점
    생성자 : 파라미터 개수가 많을 경우 각 인자가 어떤 의존 객체를 설정하는지 알아내려면 생성자의 코드를 확인해야 한다
    메서드 : 빈 객체를 생성하는 시점에 필요한 모든 의존 객체를 주입받는 생성자 방식과 달리, 필요한 의존 객체를 전달하지 않아도 빈 객체가 생성되기 때문에 객체 사용 시점에 NullPointerException이 발생할 수 있다

@Configuration 설정 클래스의 @Bean 설정과 싱글톤

스프링 컨테이너는 @Bean이 붙은 메서드에 대해 한 개의 객체만 생성한다. >>> 설정 클래스를 그대로 사용하지 않고 설정 클래스를 상속한 새로운 설정 클래스를 만들어 사용하기 때문에 가능 !!

🙋‍♀️주입 대상 객체를 모두 빈으로 설정해야할까?
💡 객체를 스프링 빈으로 등록할 때와 등록하지 않을 때의 차이는 스프링 컨테이너가 객체를 관리하는지 여부이다!
스프링 컨테이너는 자동 주입, 라이프사이클 관리 등 단순 객체 생성 외에 객체 관리를 위해 다양한 기능을 제공하는데 빈으로 등록한 객체에만 기능을 적용한다.

0개의 댓글