1. 모델1 VS 모델2

이전 글에서 살펴본 모델1과 모델2의 차이점은 다음과 같습니다.

  • JSP 파일 개수
  • JSP 코드에 삽입되는 java 코드 라인 수
  • 구체적인 MVC 구조 및 파일 구성
  • 사용자의 요청 URL을 제어


대부분 웹 서비스는 모델2 방식을 따르지만 여전히 모델1을 사용하는 서비스도 있습니다.

( 실질적으로 Spring 같은 프레임워크를 사용하여 강제적으로 MVC 패턴을 사용하긴 합니다. )

그 이유는 레거시 코드를 모델2로 마이그레이션하는데 비용이 발생하기 때문입니다.

실제 서비스를 버전 업그레이드, 마이그레이션한다는 것은 꽤 부담이 되기 때문이죠.


모델1은 어떤 문제점들이 있을까요?

  • 모든 요청마다 JSP 파일을 만들어야 하는 구조적인 문제
    • Servlet이 있다면 하나의 클래스로 모든 요청을 처리할 수 있지만, 모델1에서는 각 요청마다 JSP 파일을 만들어야 합니다.

    • 웹 서비스에는 매우 많은 요청들이 있텐데, 일일이 JSP 파일로 만들어서 관리한다는 것은 유지보수 측면에서 비용이 많이 드는 작업입니다.

  • 퍼블리셔와의 협업

위와 같은 이유로 모델1은 거의 존재하지 않습니다.





2. Factory 메서드 패턴

하지만 이전글에서 구현한 모델2도 문제점이 있습니다.

요청을 확장하려고 하면 Servlet 클래스에 else if( )를 추가하여 확장을 할 수 밖에 없습니다.

이는 객체지향 프로그래밍 답지 않으며, Servlet 클래스의 코드가 길어지게 되므로 개선이 필요합니다.


예를 들어, 이전에 구현한 방명록 애플리케이션에서 회원을 관리하는 기능이 추가되었다고 가정하겠습니다.

그러면 Servlet에는 기존의 요청과 더불어 새로운 요청에 대한 처리가 필요합니다.


이에 적용할 디자인 패턴은 팩토리 메서드 패턴입니다. ( 참고 )

Factory는 말 그대로 여러 Action들을 모아 놓은 공장같은 개념입니다.


방명록 애플리케이션을 디자인 패턴을 적용하여 구조를 바꾸면 아래와 같습니다.


  • Action 인터페이스
    • execute()는 액션을 실행하는 추상 메서드입니다.
  • 모든 Action 클래스
    • Action 인터페이스를 구현해야 합니다.
  • AbstarctActionFactory 추상클래스
    • Action 타입을 반환하는 getAction() 메서드가 있습니다.
  • GuestbookActionFactory / UserActionFactory 클래스
    • guestbook, user 객체가 할 수 있는 액션들을 모아 놓은 클래스로서, AbstractActionFactory를 상속받습니다.
    • 이 두 클래스는 요청 받은 Servlet에서 액션을 if - else if - else로 처리했던 로직이 있으며, 적절한 액션을 찾아 요청을 처리하게 됩니다.



GuestbookServlet 코드와 GuestbookActionFactory의 코드를 보면 이해가 좀 더 쉬울 것 같습니다.


1) GuestbookServlet.java

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String actionName = request.getParameter("a");
Action action = new GuestbookActionFactory().getAction(actionName);
action.execute(request, response);
}
  • Servlet에서는 자신의 ActionFactory인 GuestbookActionFactory 객체를 생성하여 적절한 Action타입의 객체를 반환합니다.
  • 반환된 객체에서 수행해야 할 로직을 실행하는 execute() 메서드만 호출하면, Servlet 클래스 내에서 할 일은 모두 끝난 것입니다.
    • execute() 메서드를 호출하면 getAction()을 통해 반환된 그 객체에서 수행할 로직이 담겨있습니다.
    • 즉, 요청을 골라내는 작업은 ActionFactory에서 수행하고, 실제로 수행하는 로직은 각 Action에서 구현하도록 하는 구조입니다.



2) GuestbookActionFactory.java

public Action getAction(String actionName) {
Action action = null;

if("add".equals(actionName)) {
action = new AddAction();
}
else if("delete".equals(actionName)) {
action = new DeleteAction();
}
else if("deleteform".equals(actionName)) {
action = new DeleteFormAction();
}
else {
action = new ListAction();
}

return action;
}
  • ActionFactory 클래스는 요청을 분기하여 Action타입의 객체를 반환하는 것이 전부입니다.





이상으로 모델1과 모델2를 비교하고, 모델2를 리팩토링 하는 팩토리 메서드 패턴에 대해 알아보았습니다.

꼭 이렇게 디자인 패턴을 써서 구현해야 한다는 것이 아닙니다.

다만 Servlet의 코드가 길어지는 것보다 객체지향 적으로 관리를 쉽게 할 수 있다면 유지보수가 좋기 때문에 리팩토링을 한 것입니다.

사실 자바 웹 개발은 프레임워크를 사용하게 되는데, 이 과정이 이미 프레임워크( 스프링 )에서 구현되어 있습니다.