서블릿을 컨트롤러로 사용하고 JSP를 뷰로 사용하는 MVC 패턴을 사용해 본다. 사실 이거는 내가 전에 진행했던 프로젝트 구성과 비슷해서 친근한데 이제는 잘 안 쓰는 기술이라고 한다. 앞으로 조금 더 발전된 기술을 배우기 위해 열심히 강의를 듣고 공부를 한다.
회원 등록 폼 -View를 먼저 코딩해 본다.
강의 자료에서 발췌한 부분으로 모든 부분을 오픈할 수는 없고 일부분을 뗴어올 수 있다 출처는 글 맨 아래 남긴다.
String viewPath = "/WEB-INF/views/new-form.jsp";
RequestDispatcher dispatcher = request.getRequestDispatcher(viewPath);
dispatcher.forward(request, response);
dispatcher는Controller에서 View로 이동할 때 사용한다.
dispatcher.forward()는 다른 서블릿이나 JSP로 이동할 수 있는 기술인데 매우 중요하다고 한다. 서버 내부에서 다시 호출이 발생하는 형식이며 redirect가 아니다. 클라이언트가 호출하면 서버 안에서 자기들끼리(서블릿 호출하고 JSP 호출하고 등 )호출하거나 응답을 만들어서 보내는 등 서버 안에서 사용된다.
파일 경로를 보면 WEB-INF를 만들고 그 안에 views를 넣었다. WEB-INF 안에 있는 JSP는 밖에서 호출할 수 없다.
강의에서 redirect와 forward의 차이에 대해서도 알려주었다.
리다이렉트는 요청이 들어오면 응답을 한 번 나갔다가 클라이언트가 리다이렉트 경로로 다시 요청한다. 따라서 클라이언트가 인지할 수가 있고 URL 경로도 변경이 된다. 하지만 포워드는 위에서 설명 했듯이 서버 내부에서 일어나는 호출이기 때문에 클라이언트가 알 수가 없다.
<!-- 상대경로 사용, [현재 URL이 속한 계층 경로 + /save] -->
<form action="save" method="post">
username: <input type="text" name="username" />
age: <input type="text" name="age" />
<button type="submit">전송</button>
여기서 포인트는 action=”save”라고 했다. 절대 경로로 지정해 주지 않았고 상대 경로로 지정해 주었는데 이렇게 되면 현재 URL이 속한 계층 경로 + save가 호출이 된다.
회원 저장 - Controller 코딩을 해본다.
String username = request.getParameter("username");
int age = Integer.parseInt(request.getParameter("age"));
요청 정보를 먼저 받는다. 앞에서 공부한 부분과 많이 겹치는 부분이다.
Member member = new Member(username, age);
memberRepository.save(member);
member를 생성해주고 저장소에 저장을 해준다.
request.setAttribute("member", member);
setAttribute를 통해 request 객체에 있는 model에 데이터를 저장한다.
이 부분에 대해서는 추가로 찾아 본 것이 있는데 전에 비슷하게 model.setAttribute()를 본 것 같아서 알아보니 큰 차이는 없다고 한다. model은 추상화이며 해당 view에서 밖에 사용이 안 되지만 request에 담으면 어디서든지 사용할 수 있다고 한다. 조금 더 추가하면 model이 조금 더 가볍고 작업하기가 쉽다고 한다.
<ul>
<li>id=${member.id}</li>
<li>username=${member.username}</li>
<li>age=${member.age}</li>
</ul>
JSP가 제공하는 ${} 문법을 통해 request의 attribute에 담긴 데이터를 편하게 조회할 수 있다. 전에는 JSP에서 데이터를 조회하기 위해서는 <%= %>이런 문장과 맨 위에 Java 코드로 임포트 또한 해줬어야 하는데 이렇게 JSP에서 사용하는 문법을 사용하면 그런 문장 추가 없이 깔끔한 코드로 구성이 가능하다.
이런 점을 통해 Controller 로직과 View 로직이 확실히 분리되었다고 느낄 수 있었다. 만약 화면에 수정이 발생하면 View 로직만 변경하면 되므로 서로 간섭 없는 코드를 완전 엮을 필요가 없게 되어서 매우 편리해졌다.
회원 목록 조회 - Controller 부분을 마지막으로 코딩을 해본다.
List<Member> members = memberRepository.findAll();
request.setAttribute("members", members);
request 객체를 사용해 LIst<Member> members를 모델에 보관했다.
String viewPath = "/WEB-INF/views/members.jsp";
RequestDispatcher dispatcher = request.getRequestDispatcher(viewPath);
dispatcher.forward(request, response);
dispatcher는Controller에서 View로 이동할 때 사용한다.
dispatcher.forward()는 다른 서블릿이나 JSP로 이동할 수 있는 기술인데 매우 중요하다고 한다. 서버 내부에서 다시 호출이 발생하는 형식이며 redirect가 아니다. 클라이언트가 호출하면 서버 안에서 자기들끼리(서블릿 호출하고 JSP 호출하고 등 )호출하거나 응답을 만들어서 보내는 등 서버 안에서 사용된다.
위에 쓴 글을 복붙해서 넣었다. 똑같은 내용인데 한 번만 보면 까먹으니까 복사해서 넣어뒀다.
<%@ taglib prefix="c" uri="<http://java.sun.com/jsp/jstl/core>" %>
taglib 기능은 JSP가 제공하는 기능이다. 모델에 넣어둔 members를 taglib를 사용해 반복해서 출력할 수 있다. <c:forEach> 기능을 사용한다.
<c:forEach var="item" items="${members}">
<tr>
<td>${item.id}</td>
<td>${item.username}</td>
<td>${item.age}</td>
</tr>
</c:forEach>
이렇게 코드를 간단하게 짤 수 있다.
<%
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는 오래된 기술이기도 하고 요즘은 잘 안 쓰이기도 하지만 많은 자료를 찾아볼 수 있으므로 더 필요한 사람은 찾아보면 관련 정보를 많이 얻을 수 있다고 조언하고 있다.
스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술을 참고하여 공부하였습니다.
'Framework & Library > Spring Boot' 카테고리의 다른 글
[Spring Boot] : Front Controller란? (0) | 2022.01.21 |
---|---|
[Spring Boot] : MVC 패턴 적용해보고 한계 체크하기(3) (0) | 2022.01.21 |
[Spring Boot] : MVC 패턴 적용해보고 한계 체크하기(1) (0) | 2022.01.21 |
[Spring Boot] : JSP로 회원 관리 구현하기 (0) | 2022.01.21 |
[Spring Boot] : Servlet을 통한 회원 관리 웹 애플리케이션 구현 (0) | 2022.01.21 |
댓글