여니의 프로그래밍 study/Spring & Spring Boot

[Spring] 스프링 DI (의존, 의존주입, 조립기) - 1

여니's 2023. 7. 23. 12:09

 

참고 자료 : 초보 개발자를 위한 스프링5 프로그래밍 입문

해당 게시글은 초보 개발자를 위한 스프링5 프로그래밍 입문


1. 의존이란? 

A라는 클래스 내에서 B라는 클래스의 메서드를 실행할 때

A 클래스가 B 클래스에 의존한다고 한다.

 

즉, 의존이란 

변경에 의해 영향을 받는 관계를 의미함

 

 

 

의존 객체 생성하는 방식

(1) 직접 의존 객체를 생성

> A 클래스 내에 B 클래스의 객체를 직접 new 연산자를 통해 생성하는 방식

public class MemberRegisterService {
	// 의존 객체를 직접 생성
    private MemberDao memberDao = new MemberDao();
}

// MemberRegisterService 객체를 생성하는 순간에
// MemberDao 객체도 생성된다. 
MemberRegisterService svc = new MemberRegisterService();

 

(2) 의존 객체를 전달받는 방식

> DI(Dependency Injection) , 의존 주입 방식이다. 

이 방식은 생성자를 통해서 객체를 전달받는다.

즉, 생성자를 통해 MemberRegisterService가 의존 객체를 직접 구하지 않고

생성자를 통해 전달받는다. 

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

 

따라서 MemberRegisterService 클래스를 사용하는 코드는

MemberRegisterService 객체를 생성할 때

생성자에 MemberDao 객체를 전달해야 한다. 

 

 

코드만 보면

1번 방식이 더 직관적이고

편리해보이는데

왜 2번 방식(의존 주입)을 사용해야 하는걸까?

 

 

해당 코드를 변경없이 사용한다고 하면

어떤 방식을 사용해도 무방하다.

 

 

그러나 새로운 기능이 생긴다거나

유지보수를 할 경우에는

말이 달라진다. 

 

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

public class ChangePasswordService {
	private MemberDao memberDao;
    public ChangePasswordService(MemberDao memberDao){
    	this.memberDao=memberDao;
    }
}

// 두 클래스의 객체 생성하는 코드
MemberDao memberDao= new MemberDao();
MemberRegisterService regSvc = new MemberRegisterService(memberDao);
ChangePasswordService pwdSvc = new ChangePasswordService(memberDao);


// MemberDao 대신 CachedMemberDao를 사용하도록 수정
MemberDao memberDao= new CachedMemberDao(); // 실제 객체 수정하는 한 곳만 수정하면 됨.
MemberRegisterService regSvc = new MemberRegisterService(memberDao);
ChangePasswordService pwdSvc = new ChangePasswordService(memberDao);

 

 


2. 조립기

-> 의존 대상 객체를 실제로 생성하는 코드는 어디에 구현해야할까?

main 메서드보다는

객체를 생성하고 의존 객체를 주입해주는 클래스를 따로 작성하는 것이 좋다.

 

의존 객체를 주입한다는 것은

서로 다른 두 객체를 조립한다고 생각할 수 있고

이런 의미에서 이 클래스를 조립기(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);
    	...
    }

 

main 메서드에서 객체를 생성하는 것보다

이렇게 객체를 생성하는 전용 클래스를 따로 만들어서 하는 것의 이점은

추후 코드 변경시 유지보수가 편리하다는 것이다. 

 

의존 객체 변경시 조립기의 코드만 수정하면 된다!

Assembler assembler = new Assembler();
ChangePasswordService changePwdSvc=
	assembler.getChangePasswordService();

changePwdSvc.changePasswordService("email","password","newpassword");