스프링 MVC 밑바닥부터 만들어보기2 - 서블릿과 JSP
이제부터는 간단하게 회원을 저장하는 기능와 조회하는 기능을 만들어볼려고 한다.
먼저 member클래스를 만들어준다.
@Getter @Setter
public class Member {
private Long id;
private String name;
private int age;
public Member() {
}
public Member(String name, int age) {
this.name = name;
this.age = age;
}
}
롬복을 이용해서 getter와 setter를 받았다.
id값은 테이블의 pk값의 용도로 사용할 것이기 때문에 생성자에서 받지 않고 자동증가 방식으로 입력할 것이다.
다음은 기능을 수행할 repository를 만들어주자.
public class MemberRepository {
private static Map<Long, Member> store = new HashMap<>();
private static long sequence = 0L;
private static final MemberRepository instance = new MemberRepository();
private MemberRepository() {}
public Member save(Member member) {
member.setId(++sequence);
store.put(member.getId(), member);
return member;
}
public Member findById(Long id) {
return store.get(id);
}
public List<Member> findAll() {
return new ArrayList<>(store.values());
}
public void clear() {
store.clear();
}
}
- map의 형식으로 store를 만들어서 키 값으로 id를 넣고 value로 member객체를 받도록 설정한다.
- sequence를 증가시킴으로 member객체의 id값을 증가시키며 추가할 수 있도록 준비한다.
- 싱글톤 패턴으로 만들것이기 때문에 private생성자로 외부에서의 접근을 차단하고 instance를 이용해서만 객체를 사용할 수 있도록 만든다.
- 저장, 단일조회, 전체조회, 전체삭제 기능을 추가한다.
이제 이름과 나이를 작성하는 html페이지를 만들어보자. 이 페이지에서 값을 입력후 버튼을 누르면 store에 저장되고 조회도 가능하게 할 것이다.
@WebServlet(name = "memberFormServlet", urlPatterns = "/servlet/members/new-form")
public class MemberFormServlet extends HttpServlet {
private MemberRepository memberRepository = MemberRepository.getInstance();
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html");
response.setCharacterEncoding("utf-8");
PrintWriter w = response.getWriter();
w.write("<!DOCTYPE html>\n" +
"<html>\n" +
"<head>\n" +
" <meta charset=\"UTF-8\">\n" +
" <title>Title</title>\n" +
"</head>\n" +
"<body>\n" +
"<form action=\"/servlet/members/save\" method=\"post\">\n" +
" username: <input type=\"text\" name=\"username\" />\n" +
" age: <input type=\"text\" name=\"age\" />\n" +
" <button type=\"submit\">전송</button>\n" +
"</form>\n" +
"</body>\n" +
"</html>\n");
}
}
서블릿을 만든 후 응답데이터로 Content-Type을 html로 설정하고 문자열로 html태그들을 직접 작성하였다. 이렇게 하면 기존에 정적인 html이 아니라 DB에서 가져온 값을 넣을수도 있고 반복되는 태그들은 for문을 이용해서 반복시킬 수도있는 동적페이지를 만들 수 있다.
그런데 html을 이렇게 문자열로 작성하게되면 문자열이기 때문에 컴파일단계에서 에러를 잡을수도 없고 내용이 길어지면 길어질수록 코드의 가독성도 떨어지게 된다. 이런 점을 편리하게 사용하기 위해서 '템플릿 엔진'을 사용한다.
여기서는 템플릿 엔진 중 하나인 JSP를 이용해서 만들어보도록 하겠다. JSP를 이용하면 JSP파일 내부에 자바코드를 넣을 수 있다. 서블릿에서 작업하는 member객체 저장과 조회를 JSP내부에서 작성하여 서비스로직을 처리할 수 있다.
JSP를 사용하기 위해서 라이브러리를 추가해주어야 한다. build.gradle에 필요한 라이브러리를 추가하자.
implementation 'org.apache.tomcat.embed:tomcat-embed-jasper'
implementation 'javax.servlet:jstl'
이제 main/webapp/jsp/members 패키지를 만든 후 new-form.jsp라는 파일을 만든다.
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<form action="/jsp/members/save.jsp" method="post">
username: <input type="text" name="username" />
age: <input type="text" name="age" />
<button type="submit">전송</button>
</form>
</body>
</html>
첫째줄에 있는 내용이 해당 파일이 JSP라는 것을 나타내는 내용이다.
JSP는 서버 내부에서 서블릿으로 변환되기 때문에 더이상 서블릿을 따로 만들어서 서블릿에 지정한 url로 이동하는 것이 아니라 JSP파일의 경로를 url로 입력해주면 된다.
new-form.jsp의 url은 http://localhost:8080/jsp/members/new-form.jsp이다.
이제는 전송버튼을 누르면 form에 입력된 데이터를 보낼 /jsp/members/save.jsp를 만들어주어야 한다.
save.jsp파일에서는 데이터를 저장한 후 저장된 데이터를 보여주는 작업을 할 것이다.
<%@ page import="hello.spring_mvc_study.domain.member.MemberRepository" %>
<%@ page import="hello.spring_mvc_study.domain.member.Member" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
// request, response 사용 가능
MemberRepository memberRepository = MemberRepository.getInstance();
String username = request.getParameter("username");
int age = Integer.parseInt(request.getParameter("age"));
Member member = new Member(username, age);
memberRepository.save(member);
%>
<html>
<head>
<meta charset="UTF-8">
</head>
<body>
성공
<ul>
<li>id=<%=member.getId()%></li>
<li>username=<%=member.getUsername()%></li>
<li>age=<%=member.getAge()%></li>
</ul>
<a href="/index.html">메인</a>
</body>
</html>
<% %> 안에는 자바코드를 작성할 수 있다. 서블릿에서 작성하던 비즈니스로직을 jsp에서 그대로 작성하여 데이터를 저장하는 작업을 하고있다.
서블릿에서도 필요한 클래스를 import하듯이 jsp에서도 import를 해야한다. import는 <%@ %> 안에 경로를 넣어주면 된다.
저장된 데이터를 <li>태그 안에서 출력해주고 있다. <%= %> 를 사용하면 받아온 객체의 값을 바로 출력할 수 있다.
request와 response는 jsp에서도 그대로 사용할 수 있도록 넘어오기 때문에 서블릿에서 사용하듯이 그대로 사용할 수 있다.
다음으로는 저장된 멤버리스트를 볼 수 있는 페이지를 만들어보자.
<%@ page import="java.util.List" %>
<%@ page import="hello.spring_mvc_study.domain.member.MemberRepository" %>
<%@ page import="hello.spring_mvc_study.domain.member.Member" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
MemberRepository memberRepository = MemberRepository.getInstance();
List<Member> members = memberRepository.findAll();
%>
<html>
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<a href="/index.html">메인</a>
<table>
<thead>
<th>id</th>
<th>username</th>
<th>age</th>
</thead>
<tbody>
<%
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>");
}
%>
</tbody>
</table>
</body>
</html>
save.jsp와 비슷하게 비즈니스로직을 작성해서 member객체를 가져온 후 아래에서 for문을 이용해서 member객체의 수 만큼 출력하고 있다.
out은 jsp에서 사용할 수 있는 예약어다. out.write를 사용하면 해당 내용을 같이 보낼 수 있다.
이제 jsp를 활용한 개발이 완료되었다. 스프링을 써본사람입장에서 보기에는 코드가 굉장히 지저분하다고 느껴질 것이다. 하나의 파일안에서 서비스로직도 있고 view도 있기 때문에 사용되는 객체도 전부 노출되고 수정이 일어난다면 실수로 다른 코드를 건드리면서 난감한 상황이 벌어질 수도 있다. 그리고 지금의 프로젝트는 굉장히 작은 수준이라서 이정도이지만 현업에서의 프로젝트는 규모가 크기 때문에 jsp의 코드길이가 몇백, 몇천 줄 까지도 길어질 수 있다.
서블릿으로만 개발했을 떄는 내부에 html코드를 작성하는 것이 곤란했고, jsp만 사용했을 때는 코드가 복합적으로 섞여버리면서 곤란해졌다. 이런 한계점을 해소하기위해서 나온 것이 MVC패턴이다. 다음부터는 MVC패턴을 이용한 리팩토링을 진행해보자.
모든 내용은 인프런의 김영한님의 강의를 참고하여 작성되었습니다.
https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-mvc-1/dashboard
사용된 전체 코드는 깃허브에서 보실 수 있습니다.
https://github.com/ssung0810/spring_study/tree/main/spring_mvc_study
'Spring > MVC' 카테고리의 다른 글
스프링 MVC 밑바닥부터 만들어보기5 - 서블릿 종속성 제거, Model분리 (0) | 2022.04.20 |
---|---|
스프링 MVC 밑바닥부터 만들어보기4 - 프론트 컨트롤러와 view의 분리 (0) | 2022.04.14 |
스프링 MVC 밑바닥부터 만들어보기3 - MVC패턴의 시작 (0) | 2022.04.14 |
스프링 MVC 밑바닥부터 만들어보기1 - 서블릿 탐구하기 (0) | 2022.04.11 |
스프링 MVC 여러 종류의 요청매핑 사용하는 방법 (0) | 2022.02.22 |
댓글
이 글 공유하기
다른 글
-
스프링 MVC 밑바닥부터 만들어보기4 - 프론트 컨트롤러와 view의 분리
스프링 MVC 밑바닥부터 만들어보기4 - 프론트 컨트롤러와 view의 분리
2022.04.14 -
스프링 MVC 밑바닥부터 만들어보기3 - MVC패턴의 시작
스프링 MVC 밑바닥부터 만들어보기3 - MVC패턴의 시작
2022.04.14 -
스프링 MVC 밑바닥부터 만들어보기1 - 서블릿 탐구하기
스프링 MVC 밑바닥부터 만들어보기1 - 서블릿 탐구하기
2022.04.11 -
스프링 MVC 여러 종류의 요청매핑 사용하는 방법
스프링 MVC 여러 종류의 요청매핑 사용하는 방법
2022.02.22