nyximos.log

[Spring] 서블릿, JSP, MVC 패턴 본문

Programming/Spring

[Spring] 서블릿, JSP, MVC 패턴

nyximos 2022. 2. 10. 16:24

PrintWriter의 getWriter() 메소드를 사용하여 서블릿과 자바 코드만으로 동적인 HTML을 만들 수 있다.

그러나 이러한 방법은 복잡하고 비효율적이므로 템플릿 엔진을 사용한다.

 

🍕 템플릿 엔진

  • HTML의 문서에서 필요한 곳만 코드를 적용하여 동적으로 변경해준다.
  • 많은 코드를 줄일수 있고 재사용성이 높으며 유지보수가 용이하다.
  • JSP, Thymeleaf, Freemarker, Velocity 등이 있다.
  • 최근에는 Thymeleaf를 많이 쓰는 추세이며 레거시 프로젝트의 경우 JSP를 사용한 것을 많이 볼 수 있다.
  • 템플릿 엔진을 사용하기 위해서 해당 라이브러리를 추가해야 한다. 
  • build.gradle에 사용할 dependency를 추가
dependencies{
    //JSP 추가
    implementation 'org.apache.tomcat.embed:tomcat-embed-jasper'
    implementation 'javax.servlet:jstl'

    //Thymeleaf 추가
    implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
}
  • 오른쪽 상단의 아이콘을 눌러 Gradle refresh 해주자.

 

 

🍳 JSP

JSP 문서는 이렇게 시작한다.

<%@ page contentType="text/html;charset=UTF-8" language="java" %>

 

JSP는 자바 코드를 그대로 사용할 수 있다.

아래의 코드는 자바의 import문과 같다.

<%@ page import="hello.servlet.domain.member.MemberRepository" %>

 

이 부분에 자바 코드를 입력할 수 있다.

<% ~~ %>

 

이 부분에 자바 코드를 출력할 수 있다.

<%= ~~ %>

 

실행시 .jsp까지 함께 적어주자.

http://localhost:8080/jsp/members/new-form.jsp

 

<c:forEach> 기능을 사용하려면 다음과 같이 선언해야 한다.(권장)

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>

이렇게 출력해도 된다.

<%
    for (Member member : members) {
        out.write(" <tr>");
        out.write(" <td>" + member.getId() + "</td>");
        out.write(" <td>" + member.getUsername() + "</td>");
        out.write(" <td>" + member.getAge() + "</td>");
        out.write(" </tr>");
     }
%>

 

🍙 서블릿과 JSP의 한계

서블릿으로만 개발

뷰 View 화면을 위한 HTML을 만드는 작업이 자바 코드에 섞여서 복잡했다.

 

서블릿 + 템플릿엔진 사용

JSP 사용하여 동적이 필요한 부분에만 자바 코드를 적용한다.

 

 하나의 서블릿/JSP만으로 처리

Java 코드, 리포지토리, 비즈니스 로직등 다양한 코드가 한 파일에 뒤섞여 작성된다.

한 파일이 많은 역할을 하게 된다. → 유지보수🤯

 

변경의 라이프 사이클

UI와 비즈니스 로직을 수정하는 일은 각각 다르게 발생하고 서로에게 영향을 주지 않음

변경의 라이프 사이클이 다른 부분을 하나의 코드로 관리 → 유지보수🤯

 

기능 특화

뷰 템플릿화면을 렌더링하는데 최적화 되어 있다.

이 부분의 업무만 담당하는 것이 효과적 👍

 

🥪 MVC 패턴

하나의 서블릿이나 JSP로 처리하던 것을 역할을 나누어 영역을 지정한다.

서블릿 - 비즈니스 로직

뷰 템플릿 -  화면(View)

웹 애플리케이션은 보통 MVC 패턴을 사용한다.

 

🍱 컨트롤러 Controller

HTTP 요청을 받아서 파라미터를 검증하고 비즈니스 로직 실행(호출)

뷰에 전달할 결과 데이터를 조회해서 모델에 담는다.

 

컨트롤러에 비즈니스 로직을 두면 컨트롤러가 많은 역할을 담당하게 되기 때문에

컨트롤러 - 서비스 호출

Service 계층 - 비즈니스 로직

 

🥡 뷰 View

모델에 담겨있는 데이터를 사용해서 화면을 그리는 일에 집중한다.

HTML을 생성하는 부분을 말한다.

 

🍣 모델 Model

뷰에 출력할 데이터를 담아둔다.

뷰가 필요한 데이터를 모두 모델에 담아서 전달하기 때문에,

뷰는 비즈니스 로직이나 데이터 접근을 몰라도 화면을 렌더링할 수 있다.

 

 

MVC 패턴 이전

 

MVC 패턴1

 

 

MVC 패턴2

 

 

Controller  - 서블릿

View             - JSP

Model          - HttpServletRequest 객체

 

  • request는 내부에 데이터 저장소를 가지고 있다.
  • request.setAttribute(), request.getAttribute()를 사용하여 데이터를 보관, 조회하자.

 

 

/WEB-INF

  • /WEB-INF 경로 안에 JSP가 있으면 직접 JSP를 호출할 수 없다.

 

dispatcher.forward()

  • 다른 서블릿이나 JSP로 이동할 수 있는 기능
  • 서버 내부에서 다시 호출이 발생 
  • redirect와 다르다.

 

🤔 redirect와 forward의 차이

redirect

  • 실제 클라이언트(웹 브라우저)에 응답이 나갔다가, 클라이언트가 redirect 경로(URL)로 다시 요청
  • request, response 새로 생성
  • 클라이언트가 인지 🙆‍♀️
  • URL 경로가 실제로 변경된다.
  • 시스템에 변화가 생기는 요청에 사용 (로그인, 회원가입, 글 작성)

 

forward

  • 내부에서 일어나는 호출 (요청과 응답이 한번만 이루어짐) → 요청 정보가 그대로 유지
  • 실행중인 페이지와 호출될 페이지가 request, response 객체 공유
  • 클라이언트가 인지 🙅‍♀️ → 웹 브라우저는 다른 페이지로 이동했는지 알 수 없다.
  • 요청 URL로 동작된 이후에도 URL이 같다.
  • 단순 요청에 사용 (글 목록 조회, 검색)

 

MVC 패턴 한계

1. 포워드 중복

View로 이동하는 코드가 항상 중복 호출

메서드로 공통화 하더라도 메서드를 직접 호출해야 하는 번거로움이 생긴다.

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

 

2. ViewPath 중복

jsp가 아닌 다른 뷰로 변경시 전체 코드를 변경해야 한다.

String viewPath = "/WEB-INF/views/hello.jsp";

 

3. 사용하지 않는 코드

HttpServletRequest, HttpServletRespons를 사용할 때도 있고 사용하지 않을 때도 있다.

또한 HttpServletRequest, HttpServletRespons를 사용하는 코드는 테스트 케이스를 작성하기 어렵다.

 

4. 어려운 공통 처리

기능이 복잡할수록 컨트롤러에서 처리할 부분이 증가한다.

복잡한 기능을 메소드로 만든다해도 항상 호출해야 한다. (호출도 중복)

 

 

 

해결법이 뭘까?

 

Front Controller

스프링 MVC의 핵심도 프론트 컨트롤러(Front Controller)에 있다.

Front Controller는 컨트롤러 호출 전에 공통 기능을 처리해준다.

다음 포스팅에서 알아보도록 하자.

 

 

 

참조

김영한, 스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술

 

스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술 - 인프런 | 강의

웹 애플리케이션을 개발할 때 필요한 모든 웹 기술을 기초부터 이해하고, 완성할 수 있습니다. 스프링 MVC의 핵심 원리와 구조를 이해하고, 더 깊이있는 백엔드 개발자로 성장할 수 있습니다., -

www.inflearn.com