Servlet 5 - 서블릿으로 회원관리 만들어보기

Jan 10, 2023

8 mins read

순수 서블릿을 사용해 간단한 회원관리 웹앱을 만들어보자. (인프런 강의 듣는 중)

1. 회원 도메인 모델, 회원 저장관리 레포지토리 생성

  • hello.servlet.domain.member패키지를 만들고 Member, MemberRepository클래스를 만든다.

  • Member 회원 도메인 모델

package hello.servlet.domain.member;

import lombok.Getter;
import lombok.Setter;

@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;
	}
	
}
  • MemberRepository 회원 저장소
package hello.servlet.domain.member;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/*
 * 동시성 문제가 고려되어 있지 않음, 실무에서는 ConcorrentHashMap, AtomicLong 사용 고려
 * */

//간단하게 만드는거기 때문에 싱글톤으로 만들어서 사용 
public class MemberRepository {

	private static Map<Long, Member> store = new HashMap<>();
	private static long sequence = 0L;
	
	private static final MemberRepository instance = new MemberRepository();
	
	//getInstance로만 이 클래스 store 데이터를 가져올 수 있게만듬
	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());
	}
	
	//테스트하기 용이하게 Map 데이터 초기화 메소드 만듬
	public void clearStore() {
		store.clear();
	}
	
}
  • 만들어진 회원 도메인 모델과 회원 저장소는 JUnit과 AssertJ Api를 통해 테스트해 볼 수 있다.
  • 이클립스 프로젝트에서 src.test에 hello.servlet.domain.member를 똑같이 만들고 테스트 클래스 MemberRepositoryTest를 하나 만든다.
package hello.servlet.domain.member;

import java.util.List;

import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;

public class MemberRepositoryTest {
	
	MemberRepository memberRepository = MemberRepository.getInstance();
	
	//각 @Test 테스트 후 memberRepository 초기화
	@AfterEach
	void afterEach(){
		memberRepository.clearStore();		
	}
	
	//회원정보 저장해서 맞게 저장되었나 확인해보기
	@Test
	void save() { 
		
		//given
		Member member = new Member("aroong", 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("aroong1", 20);
		Member member2 = new Member("aroong2", 30);
		
		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);
	}

}
  • Junit Test 컴파일 돌려보면 두개 @Test가 성공하는걸 볼 수 있다.

member_junit_test

2. 서블릿으로 회원관리 웹앱 만들기

  • MemberFormServlet클래스를 생성하여 /new-form으로 접속하면 회원가입을 받을 수 있게 HTML FORM을 제공한다.
package hello.servlet.web.servlet;

import java.io.IOException;
import java.io.PrintWriter;

import hello.servlet.domain.member.MemberRepository;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

@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");
		
	}
	
}
  • 위 회원가입 HTML FORM에서 데이터를 입력하고 전송을 누르면 /servlet/members/save로 이동한다.
    /servlet/members/save용 MemberSaveServlet 클래스도 생성하고 여기서 회원 저장소에 회원정보를 저장한다.
    저장 후에는 결과용 HTML을 전송한다.
package hello.servlet.web.servlet;

import java.io.IOException;
import java.io.PrintWriter;

import hello.servlet.domain.member.Member;
import hello.servlet.domain.member.MemberRepository;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

@WebServlet(name = "memberSaveServlet", urlPatterns = "/servlet/members/save")
public class MemberSaveServlet 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");
		
		System.out.println("MemberSaveServlet.service");
		String username = request.getParameter("username");
		int age = Integer.parseInt(request.getParameter("age"));
		
		Member member = new Member(username, age);
		memberRepository.save(member);
		
		response.setContentType("text/html");
		response.setCharacterEncoding("utf-8");
		
		PrintWriter w = response.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>");
	}
	
}
  • 저장된 모든 회원 목록을 조회하는 기능도 만들어본다.
package hello.servlet.web.servlet;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;

import hello.servlet.domain.member.Member;
import hello.servlet.domain.member.MemberRepository;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

@WebServlet(name = "memerListServlet", urlPatterns = "/servlet/members")
public class MemerListServlet extends HttpServlet{

	private MemberRepository memberRepository = MemberRepository.getInstance();
	
	@Override
	protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		
		List<Member> members = memberRepository.findAll();
		
		response.setContentType("text/html");
		response.setCharacterEncoding("utf-8");
		
		PrintWriter w = response.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>");
	}
	
}
  • 회원 가입 member_send

  • 회원 가입 결과 member_saved

  • 회원 목록 member_list