1.4.1 오브젝트 팩토리
- 설계도로서의 팩토리
- 이렇게 분리된 오브젝트들의 역할과 관계를 분석해보자.
- UserDao와 ConnectionMaker는 각각 애플리케이션의 핵심적인 데이터 로직과 기술 로직을 담당하고 있고, DaoFactory는 이런 애플리케이션의 오브젝트들을 구성하고 그 관계를 정의하는 책임을 맡고 있다.
- 전자가 실질적인 로직을 담당하는 컴포넌트라면, 후자는 애플리케이션을 구성하는 컴포넌트의 구조와 관계를 정의한 설계도 같은 역할을 한다고 볼 수 있다.
- 설계도라고 하면 간단히 어떤 오브젝트가 어떤 오브젝트를 사용하는지를 정의해놓은 코드라고 생각하면 된다.
- 이런 작업이 애플리케이션 전체에 걸쳐 일어난다면 컴포넌트의 의존관계에 대한 설계도와 같은 역할을 하게 될 것이다.
- DaoFactory를 분리했을 때 얻을 수 있는 장점은 매우 다양하다. 그중에서도 애플리케이션의 컴포넌트 역할을 하는 오브젝트와 애플리케이션의 구조를 결정하는 오브젝트를 분리했다는 데 가장 의미가 있다.
1.4.2 오브젝트 팩토리의 활용
- DaoFactory를 좀 더 살펴보자.
- DaoFactory에 UserDao가 아닌 다른 DAO의 생성 기능을 넣으면 어떻게 될까?
- AccountDao, MessageDao 등을 만들었다고 해보자. 이 경우에 UserDao를 생성하는 userDao() 메소드를 복사해서 accountDao(), messageDao() 메소드를 만든다면 새로운 문제가 발생한다.
- ConnectionMaker 구현 클래스의 오브젝트를 생성하는 코드가 메소드마다 반복되는 것이다.
- 어떤 ConnectinoMaker 구현 클래스를 사용할지를 결정하는 기능이 중복돼서 나타난다고 볼 수 있다.
- 여러 개의 DAO를 생성하는 메소드가 추가된 리스트 1-16을 살펴보자.
public class DaoFactory {
public UserDao userDao() {
return new UserDao(new DConnectionMaker()); // ConectionMaker 구현 클래스를 선정하고 생성하는 코드의 중복
}
public AccountDao accountDao() {
return new AccountDao(new DConnectionMaker()); // ConectionMaker 구현 클래스를 선정하고 생성하는 코드의 중복
}
public MessageDao messageDao() {
return new MessageDao(new DConnectionMaker()); // ConectionMaker 구현 클래스를 선정하고 생성하는 코드의 중복
}
}
[리스트 1-16 DAO 생성 메소드의 추가로 인해 발생하는 중복]
- 세 개의 DAO를 만드는 팩토리 메소드 안에 모두 new DConnectionMaker라는 ConnectionMaker 구현 클래스의 인스턴스를 만드는 부분이 반복돼서 나타난다.
- 이렇게 오브젝트 생성 코드가 중복되는 건 좋지 않은 현상이다. DAO가 더 많아지면 ConnectionMaker의 구현 클래스를 바꿀 때마다 모든 메소드를 일일이 수정해야 하기 때문이다.
- 중복 문제를 해결하려면 역시 분리해내는 게 가장 좋은 방법이다.
- ConnectionMaker의 구현 클래스를 결정하고 오브젝트를 만드는 코드를 별도의 메소드로 뽑아내자.
- DAO를 생성하는 각 메소드에서는 새로 만든 ConnectionMaker 생성용 메소드를 이용하도록 수정한다.
- 이렇게 해두면 아무리 DAO 팩토리 메소드가 많아져도 문제가 없다.
- ConnectionMaker의 구현 클래스를 바꿀 필요가 있을 때도 리스트 1-17과 같이 딱 한 군데만 수정하면 모든 DAO 팩토리 메소드에 적용된다.
public class DaoFactory {
public UserDao userDao() {
return new UserDao(connectionMaer());
}
public AccountDao accountDao() {
return new AccountDao(connectionMaer());
}
public MessageDao messageDao() {
return new MessageDao(connectionMaer());
}
public ConnectionMaker connectionMaer() {
return new DConnectionMaker(); // 분리해서 중복을 제거한 ConnectionMaker 타입 오브젝트 생성 코드
}
}
[리스트 1-17 생성 오브젝트 코드 수정]
1.4.3 제어권의 이전을 통한 제어관계 역전
- 제어의 역전이라는 건, 간단히 프로그램의 제어 흐름 구조가 뒤바뀌는 것이라고 설명할 수 있다.
- 모든 오브젝트가 능동적으로 자신이 사용할 클래스를 결정하고, 언제 어떻게 그 오브젝트를 만들지를 스스로 관장한다. 모든 종류의 작업을 사용하는 쪽에서 제어하는 구조다.
- 제어의 역전이란 이런 제어 흐름의 개념을 거꾸로 뒤집는 것이다.
- 제어의 역전에서는 오브젝트가 자신이 사용할 오브젝트를 스스로 선택하지 않는다. 당연히 생성하지도 않는다. 또 자기도 어떻게 만들어지고 어디서 사용되는지를 알 수 없다.
- 모든 제어 권한을 자신이 아닌 다른 대상에게 위임하기 때문이다.
- 프로그램의 시작을 담당하는 main()과 같은 엔트리 포인트를 제외하면 모든 오브젝트는 이렇게 위임받은 제어 권한을 갖는 특별한 오브젝트에 의해 결정되고 만들어진다.
- 제어의 역전 개념은 사실 이미 폭넓게 적용되어 있다. 서블릿을 개발해서 서버에 배포할 수는 있지만, 그 실행을 개발자가 직접 제어할 수 있는 방법은 없다. 서블릿 안에 main() 메소드가 있어서 직접 실행시킬 수 있는 것도 아니다.
- 대신 서블릿에 대한 제어 권한을 가진 컨테이너가 적절한 시점에 서블릿 클래스의 오브젝트를 만들고 그 안의 메소드를 호출한다.
- 이렇게 서블릿이나 JSP, EJB처럼 컨테이너 안에서 동작하는 구조는 간단한 방식이긴 하지만 제어의 역전 개념이 적용되어 있다고 볼 수 있다.
- 제어의 역전 개념이 적용된 예를 디자인 패턴에서도 여럿 찾아볼 수 있다.
- 제어권을 상위 탬플릿 메소드에 남기고 자신은 필요할 때 호출되어 사용되도록 한다는, 제어의 역전 개념을 사용한다.
- 탬플릿 메소드는 제어의 역전이라는 개념을 활용해 문제를 해결하는 디자인 패턴이라고 볼 수 있다.
- 프레임워크도 제어의 역전 개념이 적용된 대표적인 기술이다.
- 프레임워크가 어떤 것인지 이해하려면 라이브러리와 프레임워크가 어떻게 다른지 알아야 한다.
- 라이브러리를 사용하는 애플리케이션 코드는 애플리케이션 흐름을 직접 제어한다. 단지 동작하는 중에 필요한 기능이 있을 때 능동적으로 라이브러리를 사용할 뿐이다.
- 반면에 프레임워크는 거꾸로 애플리케이션 코드가 프레임워크에 의해 사용된다.
- 보통 프레임워크 위에 개발한 클래스를 등록해두고, 프레임워크가 흐름을 주도하는 중에 개발자가 만든 애플리케이션 코드를 사용하도록 만드는 방식이다.
- 최근에는 톨킷, 엔진, 라이브러리 등도 유행을 따라서 무작정 프레임워크라고 하는데, 이는 잘못된 것이다.
- 프레임워크에는 분명한 제어의 역전 개념이 적용되어 있어야 한다.
- 애플리케이션 코드는 프레임워크가 짜놓은 틀에서 수동적으로 동작해야 한다.
- 자연스럽게 관심을 분리하고 책임을 나누고 유연하게 확장 가능한 구조로 만들기 위해 DaoFactory를 도입했던 과정이 바로 IoC를 적용하는 작업이었다고 볼 수 있다.
- IoC를 적용함으로써 설계가 깔끔해지고 유연성이 증가하며 확장성이 좋아지기 때문에 필요할 때면 IoC 스타일의 설계의 코드를 만들어 사용하면 된다.
- 제어의 역전에서는 프레임워크 또는 컨터이너와 같이 애플리케이션 컴포넌트의 생성과 관계설정, 사용, 생명주기 관리 등을 관장하는 존재가 필요하다.
- DaoFactory는 오브젝트 수준의 가장 단순한 IoC 컨테이너 내지는 IoC 프레임워크라고 불릴 수 있다.
- 단순한 적용이라면 DaoFactory와 같이 IoC 제어권을 가진 오브젝트를 분리해서 만드는 방법이면 충분하겠지만, IoC를 애플리케이션 전반에 걸쳐 본격적으로 적용하려면 스프링과 같은 IoC 프레임워크의 도움을 받는 편이 훨씬 유리하다.
- 스프링은 IoC를 모든 기능의 기초가 되는 기반 기술로 삼고 있으며, IoC를 극한까지 적용하고 있는 프레임워크다.
'Review > Spring' 카테고리의 다른 글
토비의 스프링 1장. 1.4 제어의 역전(IoC) (0) | 2022.10.02 |
---|