스프링은 의존 주입(Dependency Injection)을 지원한다. 이는 스프링이 가진 가장 큰 특징 중 하나이다. 그렇다면 의존 주입이란 무엇일까? 의존 주입에 대한 정확한 개념과 의존 주입을 사용하는 이유에 대해서 알아보자.
의존 주입을 말할 때 의존이란 변경에 의해 영향을 받는 관계를 뜻한다. 즉, 객체 간의 의존을 말한다. 변경에 따른 영향이 전파되는 관계를 의존한다고 표현한다.
더 확실한 개념 이해를 위해 예를 들어보자.
package spring; import java.time.LocalDateTime; public class MemberRegisterService { private MemberDao memberDao = new MemberDao(); public void 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); } }
위 코드에서 주목할 점은 MemberRegisterService 클래스가 DB 처리를 위해 MemberDao 클래스의 메서드를 사용한다는 점이다.
이렇게 한 클래스가 다른 클래스의 메서드를 실행할 때 이를 의존한다고 표현한다.의존하는 대상을 가져오기 위해서 클래스 내부에서 직접 의존 객체를 생성하는 것은 쉽긴 하지만 유지보수 관점에서 문제가 생길 수 있다.
의존 주입은 직접 의존 객체를 생성하지 않고 의존 객체를 전달받는 방식을 이용한다.
앞서 의존에 대한 설명을 하며 살펴봤던 코드에 의존 주입을 적용해보자.
MemberRegisterService.java✔️
package spring; import java.time.LocalDateTime; public class MemberRegisterService { private MemberDao memberDao = new 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(); } }
자세히 살펴보기✔️
public MemberRegisterService(MemberDao memberDao) { this.memberDao = memberDao; }
생성자를 통해 MemberRegisterService가 의존(dependency)하고 있는 MemberDao 객체를 주입(Injection) 받고 있다는 것을 알 수 있다.
다음은 MemberRegisterService 클래스를 사용하기 위해서 필요한 코드의 변화다.
// 의존 주입 전 MemberRegisterService svc = new MemberRegisterService(); // 의존 주입 후 MemberDao dao = new MemberDao(); MemberRegisterService svc = new MemberRegisterService(dao);
MemberRegisterService 클래스를 사용하기 위한 코드의 길이가 길어진 것을 확인할 수 있다. 그런데 왜 의존 주입을 사용하는 것일까?
클래스 사용 코드가 길어질 수 있음에도 의존 주입을 사용하는 이유는 바로 유연성을 확보하기 위해서다.
지금까지 살펴본 기능은 회원가입에 대한 기능이다. 당장은 의존 주입을 적용하지 않아도 불편한 점이 크게 다가오지 않는다. 하지만 기능 구현을 이어가다보면 MemberDao 클래스 객체를 의존하는 클래스가 많아질 것이다.
MemberDao 클래스를 상속받은 더 향상된 클래스를 만들게 되었고, 이 클래스를 다른 기능들에 새로 적용시켜야한다고 생각해보자. 그렇다면 의존하고 있는 클래스 모두 동일하게 소스코드를 변경해야 한다.
동일한 상황에서 DI를 적용해두었다고 생각해보자. 그렇다면 실제 의존 객체를 생성하는 한 곳만 코드를 변경하면 된다.
변경할 코드가 한 곳으로 집중된다는 것은 프로그램 유지보수 관점에서 큰 이점으로 다가온다.
- 초보 웹 개발자를 위한 스프링5 프로그래밍 입문 | 최범균님 저