일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 | 29 |
30 | 31 |
- rest api
- 옵티마저
- 스프링요청반응
- 불변객체
- 중첩클래스
- equals
- HttpServlet
- 공유기작동방식
- DispatcherServlet
- multiparfile데이터
- 프로세스 생성
- Wrapper class
- fcmv1
- biblecash
- 동기비동기블로킹논블로킹
- rest api 검증
- multipart바인딩
- HTTP프로토콜
- 옵티마이저
- 동등성동일성
- fcm성능비교
- 데이터베이스파서
- fcm데이터구조
- 디스패처서블릿
- 왜불변객체인가
- 검증 실패 예외처리
- 클라이언트요청반응
- java enum
- 래퍼클래스
- httpservlet기술
- Today
- Total
개발은 아름다워
[ Spring ] 고대의 서블릿을 찾아서(1) - 서블릿으로만 웹 앱을 만들어보자 본문
깊이 있는 이해를 하기 위해서는 때로는 발전 과정을 알아야한다고 생각한다. Spring으로 만든 웹 애플리케이션은 오랫동안 사용되면서 발전해왔고 지금도 발전 중이다. 발전이란 불편함을 개선하는 점에서 시작된다. 그렇다면 고대의(?) Spring 웹 애플리케이션은 어떤 점이 불편했고 어떻게 발전해왔을까? 고대의 서블릿을 찾아서 시리즈를 통해서 웹 애플리케이션으로 어떻게 발전했는지 공부하며 스프링에 대한 깊이 있는 이해를 다지는 시간으로 만들고 싶다.
HttpServletRequest,HttpServletResponse 객체와 자바코드로만 웹 앱 만들기
Spring이 제공하는 서블릿 객체인 HttpServletRequest와 HttpServletResponse 자바 코드만을 이용해서 회원 관리 웹 애플리케이션을 만들어보자.
회원 관리 웹 애플리케이션 요구 사항은 다음과 같다.
- 회원 정보 : 이름(username) , 나이(age)
- 기능 요구사항 : 회원 저장, 회원 목록 조회
== Member ==
@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 ==
public class MemberRepsository {
private static Map<Long,Member> store = new HashMap<>();
private static long sequence = 0L;
private static final MemberRepsository instance = new MemberRepsository();
public static MemberRepsository getInstance(){
return instance;
}
private MemberRepsository(){
}
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 clearStore(){
store.clear();
}
}
MemberRespository에서는 싱글톤 객체를 사용했다. 왜냐하면 한 개의 저장소에 데이터들이 저장되어야 하기 때문이다.
- 클라이언트에서 http:localhost:8080/servlet/members/new-form 이라는 요청을 보내면, 서버에서는 응답으로 html 데이터를 내려주고 브라우저는 응답 데이터를 화면에 보여준다.
@WebServlet(name = "memberFormServlet",urlPatterns = "/servlet/members/new-form")
public class MemberFormServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html");
resp.setCharacterEncoding("utf-8");
PrintWriter w = resp.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");
}
}
- 위에서 만들어진 button을 누르면 http://localhost:8080/servlet/members/save 으로 서버에 요청을 보낸다. 클라이언트로부터 HTML form 데이터이므로 서버에서 HttpServletRequest 객체가 getParameter 로 데이터를 받을 수 있다.
@WebServlet(name = "memberSavaServlet",urlPatterns ="/servlet/members/save")
public class MemberSaveServlet extends HttpServlet {
private MemberRepsository memberRepsository = MemberRepsository.getInstance();
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) 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);
System.out.println("member = " + member);
memberRepsository.save(member);
resp.setContentType("text/html");
resp.setCharacterEncoding("utf-8");
PrintWriter w = resp.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>");
}
}
- 등록된 member 조회를 하기 위해서 클라이언트에서 http://localhost:8080/servlet/members 으로 서버에 요청을 보낸다. 서버로 부터 응답 받은 데이터를 브라우저는 해석하여 화면에 보여준다.
@WebServlet(name = "memberListServlet",urlPatterns = "/servlet/members")
public class MemberListServlet extends HttpServlet{
private MemberRepsository memberRepsository = MemberRepsository.getInstance();
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html");
resp.setCharacterEncoding("utf-8");
List<Member> members = memberRepsository.findAll();
PrintWriter w = resp.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("<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(" </tbody>");
w.write("</table>");
w.write("</body>");
w.write("</html>");
}
}
정리
서블릿 객체와 자바코드로만 웹 애플리케이션을 만들 수 있으나 굉장히 힘들다. 응답으로 Html 데이터를 내려주기 위해 저 코드를 하나씩 작성하는게 매우 불편했다. 그리고 한 줄 한줄 쳐야하니 놓치는 부분도 있었다. 특히 저 많은 String 문자열에 오타가 날 경우 내가 원하는 결과가 나오지 않았고, 어디서 오타가 난건지 찾기도 어려웠다. 고대의 서블릿과 자바로 웹 애플리케이션 만들 경우 매~~우 불편했다. html은 고정적인데, 고정적인 부분을 자바 코드로 작성하는 것은 매우 비효율적이다. HTML 문서에 동적으로 변경해야 하는 부분만 자바 코드를 넣을 수 있다면 편리해질 것이다. 이것이 바로 템플릿 엔진이 나온 이유이다. 다음에는 지금 버전을 개선하여 템플릿 엔진을 이용한 경우를 한 번 알아볼 것이다.
참고
https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-mvc-1/dashboard
'스프링' 카테고리의 다른 글
[ Spring ] 고대의 서블릿을 찾아서(3) 템플릿 엔진을 너머 MVC패턴으로 (0) | 2024.10.12 |
---|---|
[ Spring ] 고대의 서블릿을 찾아서(2) - 서블릿을 넘어 템플릿 엔진으로 (0) | 2024.10.12 |
[ Spring ] HTTP 요청 데이터와 HtttpServletRequest,HttpServletResponse 객체의 역할 (1) | 2024.10.12 |
[ Spring ] DispatcherServlet 니 누구야? (0) | 2024.10.12 |
[ Spring ] customException API를 만들어보자(feat. 체크예외와 언체크예외 이해하기) (0) | 2024.10.12 |