회원 관리 웹 애플리케이션을 Servlet, JSP, MVC 패턴 차례대로 개발하며 비교해보겠다.
본 글에서는 Servlet으로 개발하고, JSP와 MVC 패턴은 추가적으로 글을 올리겠다.
회원 관리 웹 애플리케이션의 요구사항은 간단하게 준비해보았다.
- 회원 저장
- 회원 목록 조회
회원 관리 웹 애플리케이션 코드 비교
- JSP: yeonyeon.tistory.com/101
- MVC 패턴: yeonyeon.tistory.com/102
회원 모델 생성
main/.../domain/member/Member.java
(나는 기본적으로 파일을 저장한 폴더 위치까지 기록하는 편인데 폴더명이나 위치까지 따라할 필요는 없다..)
@Getter @Setter
public class Member {
private Long id;
private String username;
private int age;
public Member() {
}
public Member(String username, int age) {
this.username = username;
this.age = age;
}
}
- 아이디, 이름, 나이를 저장하는 Member 객체
- @Getter, @Setter는 롬복 라이브러리 이용
회원 저장소 생성
main/.../domain/member/MemberRepository.java
보통 저장소 저장하는 폴더를 따로 생성하지만 소규모 프로젝트이니 회원 모델과 같은 위치에 생성했다.
public class MemberRepository {
private static Map<Long, Member> store = new ConcurrentHashMap<> ();
private static long sequence = 0L;
// 싱글톤으로 생성
private static final MemberRepository instance = new MemberRepository();
public static MemberRepository getInstance() {
return instance;
}
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()); //store룰 보호하기 위해 arraylist를 새로 생성
}
public void clearStore() {
store.clear();
}
}
- 멤버 저장, 아이디로 찾기, 전체 조회 기능 생성
- clearStore은 테스트에서 사용하기 위함
- private static final 키워드를 이용해 MemberRepository를 싱글톤으로 생성
회원 저장소 테스트 작성
test/.../domain/member/MemberRepositoryTest.java
public class MemberRepositoryTest {
MemberRepository memberRepository = MemberRepository.getInstance();
@AfterEach
void afterEach() { // 테스트 종료 할때마다 store 날려주기
memberRepository.clearStore();
}
@Test
void save() {
// given
Member member = new Member("hello",20);
// when
Member savedMember = memberRepository.save(member);
// then
Member findMember = memberRepository.findById(savedMember.getId());
Assertions.assertThat(findMember).isEqualTo(savedMember);
}
@Test
void findAll() {
// given
Member member1 = new Member("mem1",20);
Member member2 = new Member("mem2",25);
memberRepository.save(member1);
memberRepository.save(member2);
// when
List<Member> result = memberRepository.findAll();
// then
Assertions.assertThat(result.size()).isEqualTo(2);
Assertions.assertThat(result).contains(member1, member2);
}
}
- 저장 및 전체 조회 기능 테스트
- @AfterEach를 이용해 테스트 종료 시마다 store clear
Servlet
이제 본격적으로 Servlet을 이용해 회원 관리 웹 애플리케이션을 만들 것이다.
각 서블릿들은 web/servlet 패키지를 만들어 그 위치에 저장했다.
MemberFormServlet.java
@WebServlet(name="memberFormServlet", urlPatterns = "/servlet/members/new-form")
public class MemberFormServlet extends HttpServlet {
private MemberRepository memberRepository = MemberRepository.getInstance();
@Override
protected void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
res.setContentType("text/html");
res.setCharacterEncoding("utf-8");
PrintWriter w = res.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, Encoding 설정 세팅
- PrintWriter를 통해 html 코드 직접 입력
- 'Java 코딩'과는 거리가 멀다
MemberSaveServlet.java
@WebServlet(name="memberSaveServlet", urlPatterns = "/servlet/members/save")
public class MemberSaveServlet extends HttpServlet {
private MemberRepository memberRepository = MemberRepository.getInstance();
@Override
protected void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
System.out.println("MemberSaveServlet.service");
String username = req.getParameter("username");
int age = Integer.parseInt(req.getParameter("age"));
Member member = new Member(username, age);
memberRepository.save(member);
res.setContentType("text/html");
res.setCharacterEncoding("utf-8");
PrintWriter w = res.getWriter();
w.write("<html>\n" +
"<head>\n" +
" <meta charset=\"UTF-8\">\n" +
"</head>\n" +
"<body>\n" +
"성공\n" +
"<ul>\n" +
" <li>id="+member.getId()+"</li>\n" +
" <li>username="+member.getUsername()+"</li>\n" +
" <li>age="+member.getAge()+"</li>\n" +
"</ul>\n" +
"<a href=\"/index.html\">메인</a>\n" +
"</body>\n" +
"</html>");
}
}
- MemberFormServlet에서 호출되는 /servlet/members/save 부분
- 성공 시 member에서 정보를 가져와 화면에 보여줌
MemberListServlet.java
@WebServlet(name="memberListServlet", urlPatterns = "/servlet/members")
public class MemberListServlet extends HttpServlet {
private MemberRepository memberRepository = MemberRepository.getInstance();
@Override
protected void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
List<Member> members = memberRepository.findAll();
res.setContentType("text/html");
res.setCharacterEncoding("utf-8");
PrintWriter w = res.getWriter();
w.write("<html>");
w.write("<head>");
w.write(" <meta charset=\"UTF-8\">");
w.write(" <title>Title</title>");
w.write("</head>");
w.write("<body>");
w.write("<a href=\"/index.html\">메인</a>");
w.write("<table>");
w.write(" <thead>");
w.write(" <th>id</th>");
w.write(" <th>username</th>");
w.write(" <th>age</th>");
w.write(" </thead>");
w.write(" <tbody>");
for (Member member : members) {
w.write(" <tr>");
w.write(" <td>" + member.getId() + "</td>");
w.write(" <td>" + member.getUsername() + "</td>");
w.write(" <td>" + member.getAge() + "</td>");
w.write(" </tr>");
}
w.write(" </tbody>");
w.write("</table>");
w.write("</body>");
w.write("</html>");
}
}
- for문에서 보듯 동적으로 데이터 추가가 가능
예제를 통해 보듯이 Servlet은 너무 불편하다.
Printwriter를 통해 html을 다 작성해야해서 비효율적이고 Java 코딩이라기보다 html의 코딩이라는 느낌이 강하다.
이를 좀더 편리하게 개선하기 위해 나온 것이 JSP이다.
본 게시글은 김영한 님의 '스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술' 강의를 구매 후 정리하기 위한 포스팅입니다.
내용을 임의로 추가, 수정, 삭제한 부분이 많으며 정확한 이해를 위해서 강의를 구매하시는 것을 추천 드립니다.
'Develop > Java' 카테고리의 다른 글
[MVC패턴] 회원 관리 웹 애플리케이션 (0) | 2021.05.10 |
---|---|
[JSP] 회원 관리 웹 애플리케이션 (0) | 2021.05.07 |
[Servlet] HttpServletResponse (0) | 2021.04.30 |
[Servlet] HTTP 요청 데이터 - GET, POST, Text, JSON (0) | 2021.04.30 |
[Servlet] HttpServletRequest 이용하기 (0) | 2021.04.09 |