본문 바로가기
Develop/Java

[Servlet] 회원 관리 웹 애플리케이션

by 연로그 2021. 5. 6.
반응형

회원 관리 웹 애플리케이션을 Servlet, JSP, MVC 패턴 차례대로 개발하며 비교해보겠다.
본 글에서는 Servlet으로 개발하고, JSP와 MVC 패턴은 추가적으로 글을 올리겠다.


회원 관리 웹 애플리케이션의 요구사항은 간단하게 준비해보았다.

  • 회원 저장
  • 회원 목록 조회

 

회원 관리 웹 애플리케이션 코드 비교

  1. JSP: yeonyeon.tistory.com/101
  2. 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 코딩'과는 거리가 멀다

/servlet/members/new-form 접속

 

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편 - 백엔드 웹 개발 핵심 기술' 강의를 구매 후 정리하기 위한 포스팅입니다.

내용을 임의로 추가, 수정, 삭제한 부분이 많으며 정확한 이해를 위해서 강의를 구매하시는 것을 추천 드립니다.

 

inf.run/B756

 

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

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

www.inflearn.com

 

반응형