개요
1. 생성의 책임, 기능을 팩토리 클래스로 분리
2. 팩토리 클래스의 기능 확장, 개선
3. 제어의 역전 이해
본문
1. 생성의 책임, 기능을 팩토리 클래스로 분리
이전 코드에서 UserDaoTest에서 D사냐 N사냐를 결정할 수 있게끔 코드를 만들었다.
그러나 UserDaoTest의 만든 본 목적은 UserDao 제대로 작동하느냐 하는 것이다.
따라서 이를 분리할 필요가 있다. 객체의 생성 방법을 결정하고 오브젝트를 돌려주는 팩토리를 만들 필요가 있는 것이다.
package springbook.user.ex6.dao;
//UserDao의 생성 책임을 맡은 팩토리 클래스
public class DaoFactory {
public UserDao userDao() {
ConnectionMaker connectionMaker = new DConnectionMaker(); //팩토리의 메소드가 userdao타입의 오브젝트를 어떻게 만들고 준비시킬지 결정
UserDao userdao = new UserDao(connectionMaker);
return new UserDao(connectionMaker);
}
}
팩토리 생성에 맞춰서 UserDaoTest도 수정해준다.
public class UserDaoTest {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
UserDao dao = new DaoFactory().userDao();
...
}
}
이러면 클라이언트에서 D사냐 N사냐 하는 전략을 선택하던 전략패턴에서는 벗어나지만 여전히 UserDao는 D회사의 커넥션 메이커의 존재를 알지 못한 채 유지할 수 있고 UserDao의 코드 수정없이 팩토리를 수정하는 것으로 D사와 N사의 방법 선택이 가능하다.
2. 팩토리 클래스의 기능 확장, 개선
이번에는 팩토리에서 다른 DAO의 생성 기능을 넣는 식으로 기능을 확장해보자.
public class DaoFactory {
public UserDao userDao() {
return new UserDao(new DConnectionMaker());
}
public AccountDao accountDao() {
return new AccountDao(new DConnectionMaker());
}
public MessageDao messageDao() {
return new MessageDao(new DConnectionMaker());
}
//위의 코드는 DConnectionMaker를 생성하는 코드가 중복되어 비효율적이다
}
보이는 대로 AccountDao, MessageDao의 생성 기능도 맡게 되었다. 하지만 매 메소드마다 DConnectionMaker의 생성이 중복되어 효율적이지 않다. 이를 개선 하면 아래와 같다.
public class DaoFactory {
public UserDao userDao() {
return new UserDao(connectionMaker());
}
public AccountDao accountDao() {
return new AccountDao(connectionMaker());
}
public MessageDao messageDao() {
return new MessageDao(connectionMaker());
}
public ConnectionMaker connectionMaker() {
return new DConnectionMaker();
} // 분리해서 중복을 제거
//제어권이 상위 메소드 템플릿에게 맡겨지는 제어의 역전이 일어났다
}
중복이 제거되며 보다 효율적인 코드가 되었다. 이 과정에서 자연스럽게 제어의 역적이 일어났다. 이제 제어의 역전이란 무엇인지 보다 본격적으로 접근해보고자 한다.
3. 제어의 역전 이해
일반적으로 프로그램의 흐름은 각 오브젝트가 능동적으로 참여함으로써 이루어진다. 초기 UserDao를 보면 main()메소드에서 UserDao를 생성하고 그 오브젝트를 사용하며 만들어진 UserDao도 ConnectionMaker를 어떻게 구현할지 결정하고 만들며 사용한다. 제어의 역전은 이런 흐름의 개념을 뒤집는 것이다. 오브젝트가 자신이 사용할 오브젝트를 스스로 선택하지 않고 생성하지 않는다. 어떻게 만들어지는지 모른채 받아쓰듯, 만드는 쪽에서도 어떻게 사용될지 모른채 만든다. 이렇듯 서로의 관심이 분리될 수 있기에 응집도를 높이고 결합도를 낮출 수 있다. 프레임워크는 제어의 역전 개념이 적용된 대표적인 기술이다. 라이브러리와 차이를 만드는 부분이 여기에 있다. 라이브러리는 동작하는 중에 필요한 기능이 있을 때 능동적으로 사용하지만 프레임워크는 거꾸로 애플리케이션 코드가 프레임워크에 의해 사용된다. 프레임워크가 개발자가 만든 코드를 사용하도록 만드는 게 프레임워크를 이용한 개발 방식이다. 이 게시글의 예제 코드에서도 알기 쉬운 제어의 역적을 발견할 수 있다. 여러 Dao를 만드는 마지막 DaoFactory 코드에서 각 Dao생성 메소드들은 connectionMaker()가 뭘 만들어서 보내는지 알지 못한 채 받아서 쓴다. connectionMaker()역시 어떻게 쓸지 알지 못한 채 DConnectionMaker를 만들어서 보낸다. 이렇듯 제어의 역전을 그렇게 어려운 개념이 아니며 관심을 분리할 때 자연스럽게 이루어지는 기술이다.
정리
1. 제어의 역전이란 일반적으로 오브젝트가 능동적으로 생성하고 사용하는 흐름을 뒤집는 것을 의미한다.
2. 제어의 역전을 통해서 관심의 분리가 효율적으로 이루어질 수 있다.
3. 프레임워크가 제어의 역전으로 개발자가 프레임워크 위에 애플리케이션을 만들어 이것을 프레임워크가 사용하도록 하는 게 프레임워크 기반 개발이다.
소스 깃허브
https://github.com/cholongbul/Tobyspring
cholongbul/Tobyspring
토비의 스프링 연습. Contribute to cholongbul/Tobyspring development by creating an account on GitHub.
github.com
'스프링' 카테고리의 다른 글
토비의 스프링 - 1.6 싱글톤 레지스트리와 오브젝트 스코프 (0) | 2021.05.20 |
---|---|
토비의 스프링 - 1.5 스프링IoC (0) | 2021.05.20 |
토비의 스프링 - 1.3 DAO의 확장 (0) | 2021.05.19 |
토비의 스프링 - 1.2 DAO의 분리 (0) | 2021.05.19 |
토비의 스프링 - 1.1 초난감 DAO (0) | 2021.05.19 |