API 메시지 바디
단순 텍스트
messageBody에 단순 텍스트를 보내게 되면 content-type이 text/plain으로 설정되어 요청이 넘어온다.
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
ServletInputStream inputStream = request.getInputStream();
String messageBody = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8);
System.out.println("messageBody = " + messageBody);
response.getWriter().write("ok");
}
서블릿 라이브러리의 ServletInputStream과 StreamUtils를 사용해 byte로 된 전달 받은 텍스트를 문자표(Charset)를 사용해 String으로 파싱해준다.
JSON
json을 사용하는 방식은 http api에서 주로 사용한다. 이때는 content-type이 application/json으로 설정되고,messageBody가 json 형식으로 작성된다. messageBody = {"username": "hello", "age": 20}
private ObjectMapper objectMapper = new ObjectMapper();
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
ServletInputStream inputStream = request.getInputStream();
String messageBody = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8);
System.out.println("messageBody = " + messageBody);
HelloData helloData = objectMapper.readValue(messageBody, HelloData.class);
System.out.println("helloData.getUsername() = " + helloData.getUsername());
System.out.println("helloData.getAge() = " + helloData.getAge());
response.getWriter().write("ok");
}
json은 텍스트를 파싱하는 것과는 다르게 잭슨이라는 json 파싱 라이브러리의 ObjectMapper를 사용해 미리 만둘어둔 객체의 형식에 맞추어 json을 객체로 파싱하여 사용하게 된다. 물론 json 또한 문자열이기 때문에 String으로도 파싱할 수 있다.
HTTP 응답
HttpRequestServlet과 유사하게 HttpResponseServlet은 응답 메시지를 만드는 역할을 한다. http 응답코드를 지정하고, 헤더와 바디를 생성하고, content-type, 쿠키, redirect 등의 기능을 한다.
단순 텍스트, HTML
단순 텍스트는 앞에서 이미 나왔듯이 writer.println()을 사용해 내용을 작성해 response 내용을 만들어낼 수 있다. 다만 html로 전송하고 싶다면 content-type을 text/html로 정해줘야한다.
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// Content-type: text/html;charset=utf-8
response.setContentType("text/html");
response.setCharacterEncoding("utf-8");
PrintWriter writer = response.getWriter();
writer.println("<html>");
writer.println("<body>");
writer.println(" <div>안녕?</div>");
writer.println("</body>");
writer.println("</html>");
}
API JSON
json을 반환할 때는 content-type을 application/json으로 지정하고, 요청을 처리할 때와 비슷하게 잭슨 라이브러리가 제공하는 ObjectMapper의 writeValueAsString() 메서드를 사용해 객체를 json 문자로 변경한다.
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// Content-Type: application/json
response.setContentType("application/json");
response.setCharacterEncoding("UTF-8");
HelloData helloData = new HelloData();
helloData.setUsername("kik");
helloData.setAge(18);
// {"username": "kik", "age": 18}
String result = objectMapper.writeValueAsString(helloData);
response.getWriter().write(result);
}
+추가적으로, application/json은 스펙상 utf-8을 사용하도록 되어있어서 charset=utf-8과 같은 추가 파라미터를 지원하지 않아서 따로 작성하지 않아도 된다.
서블릿, JSP, MVC 패턴
회원 관리 웹 애플리케이션 요구사항
회원 정보: 이름(username), 나이(age)
기능 요구사항: 저장, 목록 조회
이 정도 간단한 기능을 서블릿, JSP, MVC 패턴 모델 순서대로 구현하며 어떻게 변화해왔는지 알아본다.
서블릿으로 만들기
회원 객체와 리포지토리를 생성한다. 리포지토리는 싱글톤 패턴에 주의하여 설계한다.
/**
* 동시성 문제가 고려되어 있지 않음, 실무에서는 ConcurrentHashMap, AtomicLong 사용 고려
*/
public class MemberRepository {
private static Map<Long, Member> store = new HashMap<>();
private static Long sequence = 0L;
private static final MemberRepository instance = new MemberRepository();
public static MemberRepository getInstance() {
return instance;
}
private MemberRepository() {}
...
}
회원을 저장할 수 있는 간단한 폼을 아래와 같이 Servlet을 사용해 만들어준다.
그리고 폼을 전송하면 이를 처리하도록 파라미터를 읽어낸다.
@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 {
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);
...
}
}
그리고 회원 목록을 띄워주는 서블릿을 작성했습니다.
@WebServlet(name = "memberListServlet", urlPatterns = "/servlet/members")
public class MemberListServlet 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");
List<Member> members = memberRepository.findAll();
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>");
/*
w.write(" <tr>");
w.write(" <td>1</td>");
w.write(" <td>userA</td>");
w.write(" <td>10</td>");
w.write(" </tr>");
*/
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>");
}
}
서블릿을 사용하면 반복문으로 html을 작성해서 생성해낼 수 있다.
위에서 볼 수 있듯이 자바 코드만으로 html을 작성하는 것은 매우 귀찮다. 이렇게 끝까지 다 만들지 않고, 이미 있던 html에 수정할 부분만 고치며 동적으로 만들 수 있도록 도와주는 것이 템플릿 엔진이다. 그 중에는 JSP, Thymleaf 등이 있는데 다음으로는 JSP를 해볼 것이다.
'WINK-(Web & App) > Spring Boot 스터디' 카테고리의 다른 글
[2025 1학기 스프링부트 스터디] 장민주 #7주차 (0) | 2025.05.27 |
---|---|
[2025 1학기 스프링 부트 스터디] 석준환 #7주차 (0) | 2025.05.27 |
[2025 1학기 스프링 부트 스터디] 여민호 #7주차 (1) | 2025.05.26 |
[2025 1학기 스프링 부트 스터디] 이상래 #7주차 (0) | 2025.05.25 |
[2025 1학기 스프링부트 스터디] 고윤정 #7주차 (0) | 2025.05.24 |