주요글: 도커 시작하기
반응형
모델2 구조에 대한 기본적인 내용을 살펴본다.

모델1 구조

JSP는 이제 더 이상 일부 자바 개발자만 사용하는 기술이 아닌 웹 프로그래밍을 해야 하는 개발자들이 알아야 하는 기술이 되고 있다. 서점에 가보면 20여종에 가까운 JSP 서적이 존재하고 있으며 JSP 서적을 찾는 사람들 역시 많아지고 있다.

JSP가 이처럼 인기를 얻어 가고 있지만 막상 JSP 자체를 올바르게 사용하는 개발자는 매우 드문 것 같다. 특히 JSP 페이지로만 모든 걸 해결하는 개발자들도 많다고 볼 수 있다. 심지어는 ASP 코드를 그대로 JSP에서 사용하고(물론, VB 스크립트를 Java 언어로 변경하지만) 또는 PHP와 비슷한 형태로 사용하는 경우도 있다. 하지만, JSP가 세상에 나온 이유 중의 하나는 로직(logic)과 프리젠테이션(presentation)을 구분하기 위한 것이었다.

JSP는 로직과 표현부를 알맞게 구분하기 위해 모델 2 구조를 지원하고 있다. 이 글에서는 모델 2 구조가 무엇이며 어떤 식으로 구현되는 지, 그리고 모델 2 구조를 사용했을 때의 장단점에 대해서 살펴보도록 하자.

모델 1 구조와 단점

모델 2 구조에 대해 알아보기 전에 먼저 모델 1 구조에 대해서 살펴보자. 모델 1 구조는 JSP 페이지만으로 구성되어 있는 구조를 말한다. 즉, JSP 페이지에서 동적인 부분(즉, 로직 부분)은 스크립트릿으로 처리하고 그외 나머지 부분은 템플릿으로 처리하는 것이다. 그림1은 모델 1 구조의 전체 흐름을 보여주고 있다.


모델 1 구조의 전체 흐름

위 그림에서 클라이언트는 JSP 콘테이너에 HTTP 요청을 전송한다. 그러면 JSP 콘테이너는 HTTP 요청에 따라 알맞은 JSP에 그 요청을 전달하며, JSP 페이지는 클라이언트의 요청을 알맞게 처리한 후 응답을 클라이언트에 전송한다. 여기서 JSP 페이지는 클라이언트의 요청을 알맞게 처리하는 로직 부분을 구현하고 있다. 때에 따라 자바빈 컴포넌트에 로직 부분을 옮길 수도 있으나, 대부분의 경우 자바빈 컴포넌트는 단순히 데이터를 저장하는 역할만을 맡게 되며 모델 1 구조에서 JSP 페이지는 로직과 프리젠테이션의 역할을 동시에 맡게 된다.

예를 들어, 사용자가 특정한 JSP 페이지를 몇번 보았는지 알려주는 것을 생각해보자. 이 경우 세션이나 쿠키를 사용하여 사용자가 방문한 회수를 저장할 수 있다. 세션을 사용한다고 할 경우, JSP 페이지만을 사용하는 모델 1 구조에서는 다음과 같은 JSP 페이지를 작성할 것이다.

  <%@ page contentType="text/html; charset="euc-kr" %>
  <%@ page import="SessionCountBean" %>
  <%
     SessionCountBean count = (SessionCountBean)session.getAttribute("count");
     if (count == null) {
        count = new SessionCountBean();
        session.setAttribute("count", count);
     } else {
        count.increase();
     }
  %>
  <html>
  <head><title>방문회수</title></head>
  <body>
  지금까지 <%= count.getPageCount() %> 만큼 이 페이지에 방문하셨습니다.
  </body>
  </html>

위 코드를 보면 알겠지만 이 간단한 JSP 페이지에서조차도 HTML 코드 못지 않게 많은 양의 스크립트 코드가 JSP에 삽입되어 있다. JSP 페이지에서 데이터베이스부터 시작해서 모든 걸 처리한다고 할 경우 스크립트 코드와 HTML 코드는 스파게티처럼 막 뒤 섞이게 된다.

이렇게 로직 부분과 프리젠테이션 부분이 함께 섞여 있는 것은 JSP 개발자와 웹 디자이너가 함께 작업하는 데 많은 불편을 제공한다. 예를 들어, 개발자는 웹 디자이너가 작업한 HTML 문서의 알맞은 위치를 찾아서 스크립트 코드를 삽입해야 한다. 반대로 웹 디자이너는 디자인을 변경해야 할 때 최소한 JSP 스크립트 코드가 어떤 것인지 알아야 하며, 또한 HTML 코드 사이에 난잡하게 존재하는 스크립트 코드 때문에 사소한 디자인 변경 작업조차도 어려운 상황이 발생한다. 심지어, 개발자가 없이는 디자인을 변경하지 못하는 상황이 발생하기도 한다.

물론 위 코드를 다음과 같이 변경할 수도 있다.

  <%@ page contentType="text/html; charset="euc-kr" %>
  <jsp:useBean id="count" scope="session" class="SessionCountBean" />
  <%
     SessionCountBean count = (SessionCountBean)session.getAttribute("count");
     count.increase();
  %>
  <html>
  <head><title>방문회수</title></head>
  <body>
  지금까지 <jsp:getProperty name="count" property="pageCount" />
  만큼 이 페이지에 방문하셨습니다.
  </body>
  </html>

위 예제는 자바빈 컴포넌트 관련 JSP 태그를 사용한 것이다. 이전 예제에 비해 확실히 스크립트 코드의 양이 준것을 알 수 있다. 하지만, 여전히 JSP 페이지에서 로직과 관련된 부분을 처리하고 있으며 좀더 복잡한 로직을 갖는 웹 어플리케이션을 개발해야 할 경우 JSP 페이지는 로직과 프리젠테이션이 복잡하게 뒤섞이는 스파게티 코드가 될 것이다.

지금까지 살펴본 바와 같이 JSP 페이지가 모든 역할을 맡는 모델 1 구조의 경우는 JSP의 기본 목적인 로직과 프리젠테이션의 분리를 제대로 할 수 없음을 알 수 있다. 물론, 기본의 CGI나 서블릿에 비교해보면 많은 발전이 있지만 ASP나 PHP와 비교해볼 때 별다른 장점을 보이고 있지 못하다.

모델 2 구조

앞에서 살펴본 바와 같이 모델 1 구조는 로직과 프리젠테이션의 구분에 한계를 갖고 있다. 이를 알았는지 JSP 규약을 만든 사람들은 모델 2 구조라는 멋진 걸 만들어냈다. 모델 2 구조는 JSP와 서블릿 그리고 자바빈 컴포넌트를 함께 사용한다. 다음 그림은 모델 2 구조의 전체적인 흐름을 보여주고 있다.


모델 2 구조의 전체 흐름

위 그림을 보면 모델 1 구조와 달리 모델 2 구조는 서블릿이 클라이언트 요청을 처리하게 된다. 서블릿은 클라이언트의 요청을 받으면 그에 알맞은 로직을 실행한 후, 그 결과를 자바빈 컴포넌트와 같은 형태로 JSP 페이지에 전달한다. 객체를 전달받은 JSP 페이지는 그 결과를 사용하여 알맞은 결과 화면을 보여주기만 하면 된다. 즉, 모델 2 구조를 사용함으로써 JSP 페이지에서 로직을 처리하기 위한 스크립트 코드가 사라지는 것이다.

모델 2 구조의 구현

모델 2 구조를 구현하기 위해서는 기본적으로 서블릿에 대해 이해하고 있어야 하며, 더 나아가 RequestDispatcher 클래스에 대한 이해가 필요하다. javax.servlet.RequestDispatcher 클래스는 현재 클라이언트의 요청을 다른 서블릿/JSP 페이지로 전달하거나 또는 다른 서블릿/JSP 페이지의 결과를 현재 위치에 포함하고자 할 때 사용된다.

RequestDispatcher 객체는 이러한 기능을 제공하기 위해 forward() 메소드와 include() 메소드를 제공하고 있으며, 이 두 메소드는 JSP의 <jsp:forward> 액션태그와 <jsp:include> 액션태그와 같은 기능을 제공한다. 예를 들어, 현재 요청을 showCount.jsp로 보내고 싶다면 다음과 같이 RequestDispatcher 클래스의 forward() 메소드를 사용하면 된다.

  public void doGet(HttpServletRequest request, HttpServletResponse response) .. {
     ...
     
     RequestDispatcher rd = request.getRequestDispatcher("/showCount.jsp");
     rs.forward(request, response);
  }

모델 2 구조는 바로 이 RequestDispatcher.forward() 메소드를 통해서 구현된다. 모델 1 구조에서 예로 들었던 페이지 카운터를 모델 2 구조로 구현해보자. 먼저 로직을 처리하는(즉, 카운트를 1 증가시켜주는) 서블릿은 다음과 같다.

  import javax.servlet.*;
  import javax.servlet.http.*;
  import java.io.IOException;
  
  public class CounterServlet extends HttpServlet {
  
     public void doGet(HttpServletRequest request,
                       HttpServletResponse reponse)
                       throws ServletException, IOException {
        HttpSession session = request.getSession(true);
        SessionCountBean count = 
                    (SessionCountBean)session.getAttribute("count");
        if (count == null) {
           count = new SessionCountBean();
           session.setAttribute("count", count);
        }
        count.increase();
        
        RequestDispatcher rd = request.getRequestDispatcher("/showCount.jsp");
        rs.forward(request, response);
     }
  }

CounterServlet은 로직에 해당하는 부분을 모두 처리하고 있으며, 그 결과를 세션에 저장한다. 그런 후, RequestDispatcher.forward() 메소드를 사용하여 프리젠테이션 역할을 담당하는 JSP 페이지에 클라이언트의 요청을 전달한다. 이것으로서 CounterServlet의 모든 임무는 끝이난다. CounterServlet은 프리젠테이션과 관련된 어떤 것도 처리하지 않으며, 오직 로직을 처리하는 임무만을 담당한다.

이제 showCount.jsp를 살펴보자. showCount.jsp는 이미 CountServlet은 로직과 관련된 부분을 모두 처리해주고 있기 때문에 프리젠테이션과 관련된 부분만 처리하면 된다. 실제로 이 예제에 알맞은 JSP 페이지는 다음과 같다.

  <%@ page contentType="text/html; charset="euc-kr" %>
  <jsp:useBean id="count" scope="session" class="SessionCountBean" />
  <html>
  <head><title>방문회수</title></head>
  <body>
  지금까지 <jsp:getProperty name="count" property="pageCount" />
  만큼 이 페이지에 방문하셨습니다.
  </body>
  </html>

위 코드를 살펴보면 어떤 스크립트 코드도 존재하지 않는 것을 알 수 있다. 물론, 이 예제는 모델 2 구조를 설명하기 위해 만들어지긴 것이긴 하지만, 모델 2 구조를 사용할 경우 모델 1 구조를 사용할 때에 비해 로직과 프리젠테이션을 확실하게 구분할 수 있다는 것을 알 수 있다.

비니니스 로직이 제 아무리 복잡해진다 해도 JSP 페이지에 삽입되는 스크립트 코드의 양은 크게 증가하지 않는다. 왜냐면 서블릿이 전송한 자바빈 컴포넌트는 모두 <jsp:useBean>과 <jsp:getProperty>와 같은 HTML과 비슷한 JSP 태그를 사용하여 처리할 수 있기 때문이다.

모델 2 구조의 장단점

지금까지 설명한 내용을 살펴보면 모델 2 구조를 사용할 경우 모델 1 구조로는 흉내낼 수 없을 정도로 로직과 프리젠테이션의 구분을 명확하게 할 수 있다는 것을 알 수 있다. 하지만, 모델 2 구조가 장점만 존재하는 것은 아니다. 이 글에서는 마지막으로 모델 2 구조의 장점과 단점에 대해서 살펴보자.

먼저 모델 2 구조의 장점은 다음과 같다.

  • 로직과 프리젠테이션의 구분을 좀더 명확히 할 수 있다! 역시 모델 2 구조의 최대 장점은 로직과 프리젠테이션의 구분을 명확하게 할 수 있다는 것이다. 로직의 구현을 담당하는 개발자들은 서블릿을 개발하는 데에만 온 신경을 집중하면 된다. 물론, <jsp:getProperty>와 같은 JSP 태그를 알맞게 JSP 페이지에 삽입해야 하지만 이 작업은 스크립트릿이나 표현식과 같은 스크립트 요소를 삽입하는 것에 비해 매우 간단하며 복잡하지도 않다.

    디자이너 역시 작업이 수월해진다. JSP와 관련된 태그가 <jsp:... > 형태를 갖는다는 정도만 알고 있으면 되며, 차후에 디자인을 일부 수정할 때 역시 복잡한 스크립트 코드가 들어가 있지 않기 때문에 개발자의 도움 없이도 손쉽게 원하는 작업을 수행할 수 있게 된다.

  • 유지보수가 편해지고 뛰어난 확장성을 갖는다 모든 로직 부분은 서블릿에서 처리되므로 로직이 변경될 경우 서블릿 또는 서블릿이 사용하는 클래스만 변경하면 되며, 프리젠테이션 부분은 전혀 손댈 필요가 없다. 또한, 프리젠테이션 부분이 변경되더라도 로직 부분은 변경할 필요가 없다. 모델 1 구조의 경우 로직과 프리젠테이션이 한데 섞여 있으므로 변경하는 작업 자체가 고될 수 있다.

    뿐만 아니라 확장성에 있어서도 모델 1 구조와 상대가 안 된다. 모델 1 구조는 프리젠테이션과 로직이 복잡하게 섞여 있기 때문에 확장가능한 형태로 개발한다는 것이 좀처럼 쉬운 일이 아니다. 하지만, 모델 2 구조는 확장 가능한 구조를 갖도록 설계하는 것이 크게 어렵지 않으며, 특히 최근 유행하고 있는 커맨드 패턴이나 팩토리 패턴등을 함께 사용하면 확장성은 극도로 향상된다.

모델 2 구조가 위와 같은 장점을 갖고 있긴 하지만, 단점 역시 갖고 있다. 여기서 나열하는 단점은 모델 1 구조에 있어서는 장점으로 작용한다.

  • 개발이 어려워질 수 있다 모델 2 구조는 기본적으로 서블릿/자바빈 컴포넌트/JSP의 세 가지 요소가 필요하다. 즉, JSP 페이지 하나만을 개발하면 되는 모델 1 구조에 비해 개발해야 할 것이 증가한다는 것이다. 게다가 자바빈 컴포넌트를 올바르게 설계할 능력을 갖추고 있지 않다면 모델 2 구조를 사용하는 것은 오히려 프로젝트의 암덩어리가 될 수도 있다.

    특히 최근에는 JSP 페이지만 슥듭한 개발자들이 많아지고 있으며, 이러한 개발자의 경우 자바 언어 자체에 대한 이해는 상당히 부족한 편이다. 모델 2 구조가 비록 JSP와 서블릿을 사용하는 것이지만, 이 두 기술은 모두 자바에 기반하고 있다는 점을 생각해볼 때 자바에 대한 기초가 약한 개발자들이 증가한다는 것은 그 만큼 모델 2 구조를 사용하는 것 자체가 힘들수도 있다는 것을 의미한다.

  • 비용이 증가한다. 모델 2 구조를 사용하여 개발하기 위해서는 충분한 시간을 갖고서 어플리케이션의 전체 구조를 생각해보야만 한다. 물론, 자바빈 컴포넌트와 같은 추가적인 개발 시간도 필요하다. 게다가 좀더 안정적이고 좀더 확장가능하도록 하려면 그만큼 웹 어플리케이션을 설계하는 데 많은 시간이 소요되며, 이는 곧 비용의 증가와 연결된다.

이처럼 모델 2 구조는 장점도 갖고 있고 단점도 갖고 있다. 여기서 설명하진 않았지만, 모델 2 구조는 또한 모델 1 구조에 비해 웹 어플리케이션의 흐름을 보다 효과적으로 제어할 수 있으며 또한 보다 안정적으로 웹 어플리케이션을 개발할 수 있도록 해준다. 이러한 모델 2 구조의 특징 때문에 모델 2 구조는 EJB를 사용하는 대규모 프로젝트에서 주로 사용되고 있다. 반면에 웹 사이트의 전체 흐름이 비교적 간단하고 빠른 시간내에 제작해야 소규모 프로젝트에서는 모델 1 구조가 주로 사용된다.

결론

이번 글에서는 모델 2 구조가 어떤 흐름을 갖는 지에 대해서 살펴보았고, 모델 2 구조의 구현에 대해서도 간단하게 살펴보았다. 또한, 모델 2 구조의 장단점에 대해서 살펴봄으로써 모델 2 구조를 언제 사용해야 할지에 대한 내용도 살펴보았다.

아직 이번 글만으로는 모델 2 구조가 어떤 면에서 모델 1 구조보다 나은 지 확실하지 않을 것이다. 다음 글에서는 모델 2 구조와 MVC(Model-View-Controller) 패턴에 대해서 살펴볼 것이다. 이를 통해 여러분은 모델 2 구조의 장점을 좀더 명확하게 이해할 수 있을 것이며, 더 나아가 모델 2 구조의 매력을 느끼게 될 것이다.

관련링크:

+ Recent posts