2023. 2. 8. 12:00ㆍ공부/Spring
본 포스팅은 김영한 강사님의 인프런 강의 "스프링 MVC 1편"을 정리한 포스팅입니다.
https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-mvc-1/dashboard
스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술 - 인프런 | 강의
웹 애플리케이션을 개발할 때 필요한 모든 웹 기술을 기초부터 이해하고, 완성할 수 있습니다. 스프링 MVC의 핵심 원리와 구조를 이해하고, 더 깊이있는 백엔드 개발자로 성장할 수 있습니다., -
www.inflearn.com
본격적인 MVC 강의에 앞서 과거에 사용하던 servlet에 대해서 간단하게 알아두는 편이 MVC를 제대로 이해하는 것에 도움이 된다고 한다.
웹 서버와 WAS
웹 서버 : http 기반으로 동작. html, css 이미지 같은 정적 리소스 제공. ex) NGINX, APACHE
WAS : http 기반으로 동작. 애플리케이션 로직 실행. 동적 html, JSON, MVC 등등 ex) Tomcat, Undertow
WAS는 정적 리소스를 제공할 수도 있지만 부하가 걸릴 것을 대비하여 웹 서버가 정적 리소스를 제공하도록 하는 편이 좋다.
서블릿(Servlet)
http를 기반으로 통신을 할 때 모든 요청이 동일한 기능을 하는 부분이 있다.
HTTP 요청을 파싱하여 어떤 요청인지 파악하는 기능과 HTTP 응답을 만들어서 전달하는 부분이다.
모든 요청마다 이러한 부분을 구현하면 비효율적이기 때문에 서블릿에서 이러한 기능을 편리하게 사용할 수 있도록 제공한다.

서블릿은 서블릿 컨테이너에서 관리하고 request와 response를 쉽게 관리할 수 있도록 한다.
서블릿의 형태는 아래와 같다.
@WebServlet(name = "helloServlet", urlPatterns = "/hello")
public class HelloServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
}
}
해당 url로 요청을 넣으면 실행된다. req는 요청, resp는 응답에 관한 기능을 수행한다.
Http 요청 데이터 파싱
1. GET 쿼리 스트링
url에 쿼리 스트링을 사용하여 key-value 쌍을 전달한다.
ex) http://localhost:8080/hello?name=chulsoo&age=20
서블릿에서는 req.getParameter(key)를 통해 key에 해당하는 value를 가져올 수 있다.
getParameter는 무조건 String으로 가져오므로 다른 타입을 원한다면 변환을 해줘야한다.
메시지 바디가 존재하지 않는다.
2. POST html form
<form action="/request-param" method="post">
<input type="text" name="username" />
<input type="text" name="age" />
<button type="submit">전송</button>
</form>
html form 안에 input 태그의 속성 값으로 name을 넣으면 name이 key가 되고 그 안의 값이 value가 된다.
메시지 바디 안에 쿼리 스트링과 비슷한 형태로 들어가게 되고 서블릿에서도 getParamter 메소드로 value를 가져올 수 있다.
3. POST 메시지 바디 안에 직접 데이터 넣기
메시지 바디 안에 데이터를 넣는다.
다음은 메시지 바디 안에 문자를 직접 넣을 때의 코드이다.
서블릿에서는 먼저 req.getInputStream 메소드를 사용하여 inputStream을 가져온다.
ServletInputStream inputStream = req.getInputStream();
문자로 바꿀 때는 StreamUtils의 copyToString을 사용한다.
String s = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8);
첫 번째 인자로 가져온 inputStream을 두 번째 인자로 타입을 적어준다.
다음은 JSON을 메시지 바디로 넣어줄 때의 파싱 방법이다.
먼저 객체를 만들어준다.
@Getter
@Setter
public class HelloData {
private String username;
private int age;
}
일단 문자로 변경한다.
ServletInputStream inputStream = req.getInputStream();
StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8);
이후 ObjectMapper를 사용해서 객체로 변화할 수 있다.
ObjectMapper objectMapper = new ObjectMapper();
HelloData helloData = objectMapper.readValue(s, HelloData.class);
System.out.println("username = " + helloData.getUsername());
System.out.println("age = " + helloData.getAge());
objectMapper의 readValue 메소드의 첫 번째 인자에 변환한 문자열을, 두 번째 인자에 반환 객체 타입을 넣어준다.
Http 응답 데이터 생성
1. http 상태 코드를 넣는다. (직접 코드를 넣기보단 HttpServletResponse 안의 값 활용)
resp.setStatus(HttpServletResponse.SC_OK);
2. 헤더 설정
resp.setContentType("text/plain"); //일반 텍스트 : text/plain, html : text/html JSON : application/json
resp.setCharacterEncoding("utf-8");
resp.setContentLength(2); //생략해도 됨
3. 쿠키 사용 시 설정
Cookie cookie = new Cookie("name", "chulsoo"); //원하는 key-value 쌍
cookie.setMaxAge(600); //초 단위 유효기간
resp.addCookie(cookie); //response에 추가
4. 바디 추가
PrintWriter writer = resp.getWriter();
writer.println("hello world");
html을 반환하고 싶다면 contentType을 text/html로 바꾸고 writer.println으로 태그들을 직접 String으로 넣으면 된다.
일반 문자열과 html을 반환하는 방법은 비슷하지만 JSON 형식으로 반환하고 싶다면 추가 작업을 진행해야한다.
반환할 객체를 ObjectMapper를 사용하여 문자열로 변환해야한다.
HelloData hello = new HelloData("chulsoo" ,20);
ObjectMapper objectMapper = new ObjectMapper();
String s = objectMapper.writeValueAsBytes(hello).toString();
이후 이 문자열을 write 해주면 된다.
PrintWriter writer = resp.getWriter();
writer.write(s);
<전체 코드>
@WebServlet(name = "responseHeaderServlet", urlPatterns = "/response-header")
public class ResponseHeaderServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setStatus(HttpServletResponse.SC_OK);
resp.setContentType("text/plain"); //일반 텍스트 : text/plain, html : text/html JSON : application/json
resp.setCharacterEncoding("utf-8");
Cookie cookie = new Cookie("name", "chulsoo"); //원하는 key-value 쌍
cookie.setMaxAge(600); //초 단위 유효기간
resp.addCookie(cookie); //response에 추가
HelloData hello = new HelloData("chulsoo" ,20);
ObjectMapper objectMapper = new ObjectMapper();
String s = objectMapper.writeValueAsBytes(hello).toString();
PrintWriter writer = resp.getWriter();
writer.write(s);
}
}
'공부 > Spring' 카테고리의 다른 글
[Spring][Thymeleaf] 타임리프 기초 문법 (2) | 2023.02.12 |
---|---|
[Spring][JPA] H2 데이터베이스를 사용한 JPA 기초 사용법 (0) | 2023.02.10 |
[Spring] JSON과 같이 이미지 요청 받아서 저장 (0) | 2023.02.06 |
[Spring][Lombok] @Data 어노테이션의 분석 (equals, hashCode) (0) | 2023.02.04 |
[Spring] Custom error 만들어서 공통 에러 처리하기 (0) | 2023.02.02 |