본문 바로가기

코딩/JAVA 공부

[Spring] JSP 와 Servlet, JSP 를 활용한 MVC 구조

JSP는 HTML에서 동적인 부분을 JAVA 언어로 작성 가능하게 해 준다.

아래 코드는 username을 쿼리 파라미터로 넣어줄 때 이를 출력해 주는 JSP이다.

이때 URL 주소는 Servlet과 달리 따로 지정하진 않고, JSP파일이 있는 위치를 사용하게 된다.

따라서 JSP를 사용하기 위해선 파일을 특정 폴더에 넣어둬야 한다.

webapp, WEB-INF 폴더에 넣어둬야 한다. 

webapp 폴더 안에 있으면 외부에서 호출이 가능하고,

WEB-INF 폴더 안에 있으면 외부에서 호출이 불가능하다.

참고로 WEB-INF 폴더는 webapp 폴더 안에 있어야 한다.

 

나는 외부에서 호출해야 하기 때문에 webapp폴더 안에 jsp 폴더를 만들어 파일을 넣었다.

파일 이름은 new.jsp로 이 경우 url은

localhost:8080/jsp/new.jsp 가 된다. 또 파라미터 값을 넣어주기 위해

localhost:8080/jsp/new.jsp? username=k라는 url을 입력해 주었다.

  <%@ page contentType="text/html;charset=UTF-8" language="java" %> // JSP문서는 이렇게 시작해야한다.
  <%  // <% ~~ %> 이 부분에 자바 코드를 입력할 수 있다.
  
  // request, response 사용 기능
      String username = request.getParameter("username");
  %>
  <html>
  <body>
  	<div>username=<%=username%> </div> // <%= ~~ %> 이 부분에 자바 코드를 출력할 수 있다
  </body>
  </html>

보다시피 JSP는 비즈니스 로직 코드와 view를 위한 코드가 하나의 페이지에 있다.

지금은 코드가 짧지만, 이런 형태는 양이 많으면 많을수록 유지보수하기 힘들어질 것이다.

또 중요한 점으로 비즈니스 로직의 변경 주기와 view의 변경 주기가 다르다는 것이다.

view의 경우가 비즈니스 로직보다 상대적으로 자주 변경할 텐데, 이때마다 파일을 열어 수정하다 보면 실수로 비즈니스 로직을 수정하는 일이 발생할 수 도 있다.

이를 방지하기 위해 view와 비즈니스 로직을 분리할 필요가 있고 이를 해결한 것이 MVC 패턴이다.

 

MVC 패턴은 JSP로 처리하던 것을 컨트롤러(Controller)와 뷰(View)로 서로 역할을 나눈 것이다. (+모델(Model))

컨트롤러 : HTTP 요청을 받아 파라미터를 검증하고 비즈니스 로직을 실행하며 뷰에 전달할 데이터를 모델에 담는다.

모델: 뷰에 출력할 데이터를 담아 전달한다. 뷰가 화면 렌더링에 집중할 수 있도록 해준다.

뷰: 모델에 담겨있는 데이터를 사용해 화면을 렌더링 한다. 웹에선 HTML 생성을 한다.

 

** 컨트롤러에 비즈니스 로직을 담을 수 있지만, 이러면 컨트롤러가 너무 거대해지기 때문에 비즈니스 로직은 서비스(Service)라는 계층을 만들어 별도 처리한다. 컨트롤러에선 서비스를 호출해 비즈니스 로직을 수행한다.

 

그렇다면 우리는 서블릿을 컨트롤러로 사용하고, JSP를 뷰로 사용해 MVC 패턴을 적용해 볼 수 있다.

 

먼저 컨트롤러로 사용할 Servelet을 만들어보자

직전 게시글에서 만들어봤던 Servlet과 구분하기 위해 url과 이름에 2를 붙였다

@WebServlet(name = "helloServlet2", urlPatterns = "/hello2")
public class HelloServlet2 extends HttpServlet {
    @Override
    protected void service(HttpServletRequest request, HttpServletResponseresponse) throws ServletException, IOException {
      
    String username = request.getParameter("username");
    
    String viewPath = "WEB-INF/views/new.jsp";
    RequestDispatcher dispatcher = request.getRequestDispatcher(viewPath);
    dispatcher.forward(request, reponse);
    }
}

이후 이를 받을 서블릿은 webapp 폴더 안에 WEB-INF 폴더에 views 폴더를 만들어 new.jsp를 만들자.

/webapp/WEB-INF/views/new.jsp

  <%@ page contentType="text/html;charset=UTF-8" language="java" %>
  <%
      String username = request.getParameter("username");
  %>
  <html>
  <body>
  	<div>username=<%=username%> </div>
  </body>
  </html>

위에서 작성했던 JSP를 동일하게 사용했다.

 

URL 맵핑을 Servelet에서 했기 때문에 이번 URL은

http://localhost:8080/hello2?username=newh

이다.

 

이를 통해 컨트롤러 역할과 뷰 역할을 명확하게 구분했다.

여기서 몇 가지 개선할 수 있는 부분이 있는데

1. 포워드 중복

 - 뷰에 request, response를 전달할 때 아래 코드를 작성해야 한다. 즉 모든 컨트롤러에서 이 코드를 작성해야한다.

RequestDispatcher dispatcher = request.getRequestDispatcher(viewPath);
dispatcher.forward(request, reponse);

2. ViewPath 중복

ViewPath에서 "/WEB_INF/views" 나. jsp 같은 부분은 공통되는 부분으로 중복이 발생한다.

또 만약 템플릿 엔진을 변경하면 ViewPath를 전부 다 변경해야 한다.

 

즉 공통으로 처리할 수 있는 부분을 각 컨트롤러에서 처리해 불필요한 코드가 늘어난다.

이를 해결하기 위해 FrontController 패턴을 도입할 수 있다.