DevLog ๐ถ
[Spring] ์๋ธ๋ฆฟ์ด๋? HttpServletRequest, HttpServletResponse ๋ณธ๋ฌธ
[Spring] ์๋ธ๋ฆฟ์ด๋? HttpServletRequest, HttpServletResponse
dolmeng2 2022. 8. 10. 17:01- ๊น์ํ ๋์ '์คํ๋ง MVC 1ํธ - ๋ฐฑ์๋ ์น ๊ฐ๋ฐ ํต์ฌ ๊ธฐ์ '์ ๋ณด๊ณ ์ ๋ฆฌํ ๊ธ์ ๋๋ค ๐
- ์ง๋ ํฌ์คํ ๊ณผ ์ด์ด์ง๋๋ค :D
- ์ง๋ ํฌ์คํ ์์๋ ๊ฐ๋จํ๊ฒ ์น ๊ธฐ์ ์ ํ์ํ ํต์ฌ ๊ฐ๋ ๋ค์ ์์๋ณด์๋ค.
- ์ด๋ฒ์๋ ์คํ๋ง ๋ถํธ ํ๊ฒฝ์์ ์ง์ ์๋ธ๋ฆฟ์ ๋ฑ๋กํ๊ณ ์ฌ์ฉํด๋ณด์.
| ์๋ธ๋ฆฟ (Servlet)
- ๊ธฐ๋ณธ์ ์ผ๋ก ์คํ๋ง ๋ถํธ์ ๊ฒฝ์ฐ ํฐ์บฃ ์๋ฒ๋ฅผ ๋ด์ฅํ๊ณ ์๊ธฐ ๋๋ฌธ์, ์๋ธ๋ฆฟ์ ๋ํ ํธ๋ฆฌํ ๊ธฐ๋ฅ๋ค์ ๋ช ๊ฐ์ง ์ ๊ณตํ๋ค.
[SpringStudyApplication.java] - ๊ฐ์ฅ ๊ธฐ๋ณธ์ด ๋๋ ํ์ผ
@ServletComponentScan
@SpringBootApplication
public class SpringStudyApplication {
public static void main(String[] args) {
SpringApplication.run(SpringStudyApplication.class, args);
}
}
- ๋ค์๊ณผ ๊ฐ์ด @ServletComponentScan์ ์ถ๊ฐํด์ค๋ค.
[HelloServlet.java]
@WebServlet(name="helloServlet", urlPatterns = "/hello")
public class HelloServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("HelloServlet.service");
System.out.println("request = " + req);
System.out.println("response = " + resp);
// paramter ์ค์
String username = req.getParameter("username");
System.out.println("username = " + username);
// Response
resp.setContentType("text/plain");
resp.setCharacterEncoding("utf-8");
resp.getWriter().write("hello " + username);
}
}
- @WebServlet์ ํตํด ์๋ธ๋ฆฟ ์ด๋ฆ์ ๋ถ์ด๊ณ , urlPattern์ ํตํด url ๋งคํ์ ํด์ค๋ค.
- ์ ์์ ์์๋ /hello๋ผ๋ ๊ฒฝ๋ก๋ก ๋ค์ด์์ ๋ ์คํ๋๋ค.
http://localhost:8080/hello?username=hi
getParameter๋ฅผ ํตํด์, ์ฟผ๋ฆฌ ํ๋ผ๋ฏธํฐ๋ก ๋ค์ด์จ ๊ฐ์ ํ์ฑํ ์ ์๋ค.
์ ๊ฒฝ๋ก๋ก ์์ฒญํ๊ฒ ๋๋ฉด, ๋ค์๊ณผ ๊ฐ์ด ํ๋ฉด์ ์ถ๋ ฅ๋๋ค.
- ์ด๋, response.getWriter().write๋ฅผ ํตํด์ ํ๋ฉด์ ์ถ๋ ฅํด์ค ๋ถ๋ถ์ด๋ผ๊ณ ๋ณผ ์ ์๋ค. (HttpMessageBody์ ๊ฐ์ด ๋ค์ด๊ฐ๋ ๊ฑฐ)
์ฝ์์ ๋ค์๊ณผ ๊ฐ์ด ์ฐํ๋ ๊ฒ์ ๋ณผ ์ ์๋ค.
์ง๋ ํฌ์คํ ์์ ์ธ๊ธํ์๋ connector๋ฅผ ํตํด HttpServletRequest์ HttpServletResponse๊ฐ ์์ฑ๋ ๊ฒ์ ๋ณผ ์ ์๋ค.
์ฐธ๊ณ ๋ก, RequestFacade, ResponseFacade์ ๊ฒฝ์ฐ org.apache.catalina.connector.Request/Response์ ๊ตฌํ์ฒด์ด๋ค. (์ธํฐํ์ด์ค ๊ตฌํ์ฒด)
Facade๋ ๋์์ธ ํจํด์์๋ ์ฐ์ด๋๋ฐ, ๋ด๋ถ์ ๊ตฌ์กฐ๋ฅผ ์จ๊ธธ ๋ ์ฌ์ฉํ๋ค. ์ฆ, ๊ฐ๋ตํ๋ ์ธํฐํ์ด์ค๋ฅผ ์ ๊ณตํ๋ ๊ฒ.
๋ด๋ถ์ ์ผ๋ก ์์ฑ์๋ฅผ ํตํด ์ฃผ์ ๋ฐ์ ์ค์ Request/Response์ ๋ฉ์๋๋ฅผ ํธ์ถํ๋ ๊ฒ์ผ๋ก ๊ตฌํ๋์ด ์๋ค.
๐ฉ ์ฆ, ์คํ๋ง ๋ถํธ๊ฐ ๋ด์ฅ ํฐ์บฃ ์๋ฒ๋ฅผ ๊ฐ๋ํ๋ฉด ์๋ธ๋ฆฟ ์ปจํ ์ด๋๋ฅผ ๊ฐ์ง๊ณ ์๊ฒ ๋๊ณ ,
ํ์ฌ ์๋ธ๋ฆฟ ์ปจํ ์ด๋๋ฅผ ํตํด helloServlet ๊ฐ์ฒด๊ฐ ์์ฑ๋ ์ํ๋ผ๊ณ ๋ณผ ์ ์๋ค.
์ดํ, HTTP ์์ฒญ ๋ฉ์์ง (GET /hello?username=hi)๋ฅผ ๋ฐํ์ผ๋ก HttpServletRequest/Response๋ฅผ ์์ฑํ๊ณ ,
helloServlet์ ์คํํด์ค ๋ค์ (service()) ๋ฑ๋ก๋ HttpServletResponse ์ ๋ณด๋ฅผ ๋ฐํ์ผ๋ก HTTP ์๋ต์ ์์ฑํด์ค๋ค.
| HttpServletRequest
- ์๋ธ๋ฆฟ์ HTTP ์์ฒญ ๋ฉ์์ง๋ฅผ ํธ๋ฆฌํ๊ฒ ์ฌ์ฉํ ์ ์๋๋ก ๋์ HTTP ์์ฒญ ๋ฉ์์ง๋ฅผ ํ์ฑํด์ค๋ค.
- ๊ทธ๋์ get() ๋ฉ์๋๋ฅผ ํตํด์ ์ํ๋ ๋ด์ฉ (ํค๋, ๋ฐ๋ ๋ฑ...)์ ํธ๋ฆฌํ๊ฒ ์กฐํํ ์ ์๋ค.
- ๋ํ, HTTP ์์ฒญ์ด ๋๋ ๋๊น์ง ์ ์ง๋๋ ์์ ์ ์ฅ์ ๊ธฐ๋ฅ๋ ํ ์ ์๋ค.
- (์ ์ฅ) request.setAttribute(name, value) <-> (์กฐํ) request.getAttribute(name)
- ํน์, ์ธ์ ๊ด๋ฆฌ ๊ธฐ๋ฅ๋ ์ ๊ณตํด์ค๋ค.
- request.getSession(create: true) --> ์ฑํ ๋ฐฉ ๊ฐ์ ๊ธฐ๋ฅ์์ ์ธ์ ์ ๊ฐ์ ธ์ฌ ๋ ์ด๋ค...!
[๋ง์ด ์ฌ์ฉํ ๊ฒ ๊ฐ์ start-line ์ ๋ณด ํ์ฑ]
http://localhost:8080/request-header?username=hi
request.getMethod() | GET |
request.getProtocol() | HTTP/1.1 |
request.getScheme() | http |
request.getRequestURL(); | http://localhost:8080/request-header |
request.getRequestURI(); | /request-header |
request.getQueryString() | username=hi |
request.isSecure() | false (https ์ฌ๋ถ) |
โญ Http ์์ฒญ ๋ฉ์์ง๋ฅผ ํตํด ํด๋ผ์ด์ธํธ -> ์๋ฒ๋ก ๋ฐ์ดํฐ ์ ๋ฌํ๊ธฐ
โ GET - ์ฟผ๋ฆฌ ํ๋ผ๋ฏธํฐ
- /hello?username=hi&age=22
- ๋ฉ์์ง ๋ฐ๋๋ฅผ ์ฌ์ฉํ์ง ์๊ณ , URL์ ์ฟผ๋ฆฌ ํ๋ผ๋ฏธํฐ์ ๋ฐ์ดํฐ๋ฅผ ํฌํจํด์ ์ ๋ฌํ๋ ๋ฐฉ๋ฒ
ex) ๊ฒ์, ํํฐ, ํ์ด์ง์์ ๋ง์ด ์ฌ์ฉ
- HttpServletRequest๋ฅผ ํตํด์ ์ฟผ๋ฆฌ ํ๋ผ๋ฏธํฐ ์กฐํํ๊ธฐ
ํ์ | ๋ฆฌํด ํ์ | ์ค๋ช |
request.getParameter("username") | String | ๋จ์ผ ํ๋ผ๋ฏธํฐ ์กฐํ |
request.getParameterNames() | Enumeration<String> | ํ๋ผ๋ฏธํฐ ๋ค์ ๋ชจ๋ ์กฐํ |
request.getParameterMap() | Map<String, String[]> | Map ํ์์ผ๋ก ํ๋ผ๋ฏธํฐ ์กฐํ |
request.getParameterValues("username") | String[] | ๋์ผ ์ด๋ฆ์ ๋ณต์ ํ๋ผ๋ฏธํฐ ์กฐํ |
- ์ฐธ๊ณ ๋ก, ๋์ผํ ์ด๋ฆ์ ํ๋ผ๋ฏธํฐ๊ฐ ์กด์ฌํ์ ๋ getParameter๋ฅผ ์ฌ์ฉํ๋ฉด ์ฒซ ๋ฒ์งธ ๊ฐ์ ๋ฐํํ๋ค.
โ POST - HTML Form
- content-type: application/x-www-form-urlencoded
- ๋ฉ์์ง ๋ฐ๋์ ์ฟผ๋ฆฌ ํ๋ผ๋ฏธํฐ ํ์์ผ๋ก ์ ๋ฌํ๋ ๋ฐฉ๋ฒ (username=hi&age=22)
ex) ํ์ ๊ฐ์ , ์ํ ์ฃผ๋ฌธ, HTML form ์ฌ์ฉ (form action="" method="post")
- ์ฐธ๊ณ ๋ก, GET ๋ฐฉ์์ด๋ ํ์์ด ๋์ผํ๊ธฐ ๋๋ฌธ์ request.getParamter()๋ก ๋์ผํ๊ฒ ์กฐํ๊ฐ ๊ฐ๋ฅํ๋ค.
- ๋จ, GET ๋ฐฉ์์ ๊ฒฝ์ฐ ๋ฉ์์ง ๋ฐ๋๋ฅผ ์ฌ์ฉํ์ง ์๊ธฐ ๋๋ฌธ์ content-type์ด ์๊ณ ,
POST HTML form ๋ฐฉ์์ ๋ฉ์์ง ๋ฐ๋์ ๋ฐ์ดํฐ๋ฅผ ๋ฃ์ด์ ์ ์กํ๋ ๋ฐฉ๋ฒ์ด๊ธฐ ๋๋ฌธ์ content-type์ ์ง์ ํด์ฃผ๋ ๊ฒ์ด๋ค.
โ HTTP message body์ ์ง์ ๋ด๊ธฐ
- HTTP API์์ ์ฃผ๋ก ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ.
ex) JSON, XML, TEXT
- ์ฃผ๋ก JSON์ ๋ง์ด ์ฌ์ฉํ๋ค.
- POST, PUT, PATCH ๋ฐฉ์
@WebServlet(name = "requestHeaderServlet", urlPatterns = "/request-header")
public class RequestHeaderServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletInputStream inputStream = req.getInputStream();
String messageBody = StreamUtils.copyToString(inputStream,
StandardCharsets.UTF_8);
System.out.println("messageBody = " + messageBody);
resp.getWriter().write("ok");
}
}
- ๊ฐ์ฅ ๋จ์ํ text ํ์ ์ ์ด์ฉํด์ ํ ์คํธ ํ๋ ๋ฐฉ๋ฒ์ด๋ค. Postman์์ ํ์ ์ raw->text ํ์ ์ผ๋ก ํ๊ณ ์ ์กํ๋ฉด ๋๋ค.
- inputStream์ ํตํด์ ๋ฉ์์ง ๋ฐ๋์ ๋ฐ์ดํฐ๋ฅผ ๋ฐ์ดํธ ์ฝ๋๋ก ๋ฐ๋ก ์ป์ ์ ์๋ค.
- ๋ฐ์ดํธ ์ฝ๋๋ฅผ string์ผ๋ก ๋ฐ๊พธ๊ธฐ ์ํด์ StreamUtils.copyToString์ ์ฌ์ฉํ์๋ค. ์ธ์ฝ๋ฉ ํ์ ์ UTF_8์ด๋ค.
- ๋ค์์ผ๋ก, ๊ฐ์ฅ ๋ง์ด ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ธ JSON ํ์์ ์์๋ณด์.
- content-type์ raw -> application/json์ผ๋ก ๋ฐ๊ฟ์ค์ผ ํ๋ค.
- messageBody์๋ {"username:" "hi", "age": 22} ์ผ๋ก ์์ฑํด์ค๋ค.
- ํ์ฑ์ ์ํ ๊ฐ์ฒด ํ๋๋ฅผ ์์ฑํ์.
[HelloData.java]
@Data
public class HelloData {
private String username;
private int age;
}
- Setter๋ ๊ผญ ์ด์ด์ค์ผ ํ๋ค. (๊ทธ๋์ ์ฌ๋งํ๋ฉด ์ค์ ๊ฐ๋ฐ์์๋ DTO๋ฅผ ์ฌ์ฉํ๋ค)
๐ฉ ์ด๋ฒ์ ์ฐพ์๋ณด๋ฉด์ ์๊ฒ ๋์๋๋ฐ, ObjectMapper๋ฅผ ์ฌ์ฉํ๋ฉด setter๊ฐ ์์ด๋ ํ๋์ ์ ๊ทผํ ์ ์๋ค!
- ์ฐพ์๋ดค๋๋ฐ, ๊ธฐ๋ณธ์ ์ผ๋ก @Getter๋ @Setter ์ค์ ํ๋๋ง ์์ด๋ ๋์ํ๋ค.
- objectMapper๋ ๋์ผํ ์ด๋ฆ์ ํ๋๋ช ์ผ๋ก ๋งค์นญํ๋ ๊ฒ ์๋๋ผ, getter์ setter๋ฅผ ํตํด์ ๋งค์นญํด์ค๋ค!!
- @Setter๊ฐ ํ์์๋ ์ด์ ๋, BeanDeserializer -> deserializeAndSet ๋ฉ์๋์์ reflection์ ํตํด ๊ฐ์ ์ฃผ์ ํด์ฃผ๊ธฐ ๋๋ฌธ์ด๋ค...!)
- ๋ฆฌํ๋์ ์ ๋ฐํ์์์ ๊ฐ์ฒด๋ฅผ ์์ฑํด์ฃผ๋๊น, ๊ตณ์ด @Setter๋ฅผ ํตํด ๋ฏธ๋ฆฌ ํ ํ์๊ฐ ์๋ค๋ ๊ฑฐ.
(์ฐธ๊ณ : ์๋ ๋ธ๋ก๊ทธ ๋งํฌ! :D)
- ๊ทธ๋ ๊ธฐ ๋๋ฌธ์ objectMapper๋ฅผ ์ฌ์ฉํ๋ @RequestBody์์๋ ๊ธฐ๋ณธ์ ์ผ๋ก DTO์ @Setter๋ฅผ ์ ๋ถ์ฌ์ค๋ ๋๋ค...!
- @Getter๋ฅผ ํตํด ์ฌ์ฉํ๋ค๋ฉด public, @Setter๋ฅผ ์ฌ์ฉํ๋ค๋ฉด private~public ๋ชจ๋ ์ ๊ทผ์ง์ ์๊ฐ ๊ฐ๋ฅํ๋ค๊ณ ํ๋ค.
@WebServlet(name = "requestHeaderServlet", urlPatterns = "/request-header")
public class RequestHeaderServlet extends HttpServlet {
private final ObjectMapper objectMapper = new ObjectMapper();
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletInputStream inputStream = req.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());
resp.getWriter().write("ok");
}
}
- ์๋ฌดํผ, ๋ค์ ๋ณธ๋ก ์ผ๋ก ๋์์์...
- Jackson์ ObjectMapper๋ฅผ ์ถ๊ฐํด์ฃผ์๋ค. ๋ณดํต์ Bean์ผ๋ก ๋ฑ๋กํด์ ์ฌ์ฉํ์ง๋ง, ์ฌ๊ธฐ๋ ํ ์คํธ๋๊น ๊ทธ๋ฅ ๋ฐ๋ก ๊ฐ์ฒด๋ฅผ ์์ฑํด์ฃผ์๋ค.
- messageBody์ ๋ด๊ธด ๋ฐ์ดํฐ๋ฅผ HelloData๋ผ๋ ์๋ฐ ๊ฐ์ฒด๋ก ๋ณํํด์ค๋ค.
- ์คํํด๋ณด๋ฉด getUsername, getAge๋ฅผ ํตํด ๋ฐ์ดํฐ๊ฐ ์ ๋ฐ์์ง ๊ฑธ ํ์ธํด๋ณผ ์ ์๋ค :)
| HttpServletResponse
- HttpServletResponse์ ๊ฒฝ์ฐ HTTP ์๋ต ๋ฉ์์ง๋ฅผ ์์ฑํด์ค๋ค.
- HTTP response Code, Header, Body๋ฅผ ์์ฑํด์ค ์ ์๋ค.
- ํน์, Content-type์ ์ง์ ํ๊ฑฐ๋ ์ฟ ํค ์์ฑ, Redirect ๊ฐ์ ๊ธฐ๋ฅ๋ ์ ๊ณตํ๋ค!
[์๋ต ์ฝ๋ ์ง์ ]
response.setStatus(HttpServletResponse.SC_OK); // 200
[ํค๋ ์ง์ ]
response.setHeader("Content-Type", "text/plain;charset=utf-8")
[๋ฐ๋ ์ง์ ]
response.getWriter().println("ok")
[content-type ํธ์ ๊ธฐ๋ฅ] - ํค๋์์ ์ง์ ํ Content-Type์ ์กฐ๊ธ ๋ ์ฝ๊ฒ ์ง์
response.setContentType("text/plain");
response.setCharacterEncoding("utf-8");
response.setContentLength(2)" // default๋ก 2.
[์ฟ ํค ํธ์ ๊ธฐ๋ฅ] - Set-Cookie : myCookie=hello; Max-Age=600
Cookie cookie = new Cookie("myCookie", "hello");
cookie.setMaxAge(600);
response.addCookie(cookie);
[redirect ํธ์ ๊ธฐ๋ฅ] response.setStatus(HttpServletResponse.SC_FOUND); // 302
- redirectresponse.setHeader("Location", "/hello.html");
// ์์ ๋ ์ฝ๋๋ฅผ ํ๋๋ก ํฉ์ณ์ค ๊ธฐ๋ฅ
response.sendRedirect("/hello.html");
โญ HTML ์๋ต ๋ฐ์ดํฐ
โ ํ ์คํธ๋ก ์๋ตํ๊ธฐ
writer.println("hi");
โ HTML๋ก ์๋ตํ๊ธฐ
@WebServlet(name = "responseHeaderServlet", urlPatterns = "/response-header")
public class ResponseHeaderServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html");
resp.setCharacterEncoding("utf-8");
PrintWriter writer = resp.getWriter();
writer.println("<html>");
writer.println("<body>");
writer.println(" <div>์๋
?</div>");
writer.println("</body>");
writer.println("</html>");
resp.getWriter().write("ok");
}
}
- ์๋นํ ํ๋์ฝ๋ฉ์ด์ง๋ง ์ด๋ฐ ์์ผ๋ก ์ ์ html ์๋ต๋ ๊ฐ๋ฅํ๋ค. (ํ์ง๋ง ์ด๊ฑธ ์ฐ๋ ์ผ์ ์์ ๊ฒ ๊ฐ๋ค...)
โ JSON์ผ๋ก ์๋ตํ๊ธฐ
@WebServlet(name = "responseHeaderServlet", urlPatterns = "/response-header")
public class ResponseHeaderServlet extends HttpServlet {
private final ObjectMapper objectMapper = new ObjectMapper();
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setHeader("content-type", "application/json");
resp.setCharacterEncoding("utf-8");
HelloData data = new HelloData();
data.setUsername("hi");
data.setAge(22);
String result = objectMapper.writeValueAsString(data);
resp.getWriter().write(result);
}
}
- content-type์ json์ผ๋ก ์ค์ ํด์ฃผ์๋ค. ๊ฐ์ฒด์ setter๋ฅผ ํตํด ๋ฃ์ด์ฃผ๊ณ , objectMapper๋ฅผ ํตํด์ JSON์ผ๋ก ๋ณํํด์ค๋ค.
- ์ด๋ ๊ฒ ๊ธฐ๋ณธ์ ์ธ httpServletRequest, httpServletResponse์ ๋ํด์ ์์๋ณด์๋ค.
- ๋ค์ ํฌ์คํ ์์๋ ๋ณธ๊ฒฉ์ ์ธ ํ์ ๊ด๋ฆฌ ์์คํ ์ ์ ์ํ์ฌ JSP, MVC ํจํด์ ๋ณธ๊ฒฉ์ ์ผ๋ก ๋ค๋ฃจ์ด๋ณด๊ฒ ๋ค.