이 포스트는 다음 강의의 내용을 포함하고 있습니다 링크

목표

  • Request 객체 & Response 객체에 대해 이해한다.

 

 


 

API 서버를 구성하다보면 reqest와 response 객체를 자주 접하게 된다.

 

주로 Node.js의 express.js로 서버를 구축하면, API 요청을 응답할 때 req, res로 줄여서 사용하곤 한다.

/* GET home page. */
router.get("/", function(req, res, next) {
  console.log(res);    // 객체 정보가 정말 많으므로 콘솔로 바로 확인하는것은 추천하지 않는다...
  console.log(req);
  res.render("index", { title: "Express" });
});

다음 코드는 express에서 get요청을 받았을 때 다음을 수행한다.

  • console.log로 각 객체를 출력해준다.
  • index페이지를 렌더링 해준다. (단순히 라우팅의 역할을 수행한다)

response 객체를 출력해보면... 다음과 같다

ServerResponse {
  _events:
   [Object: null prototype] { finish: [Array], end: [Function: onevent] },
  _eventsCount: 2,
  _maxListeners: undefined,
  output: [],
  outputEncodings: [],
  outputCallbacks: [],
  outputSize: 0,
  writable: true,
  _last: false,
  chunkedEncoding: false,
  shouldKeepAlive: true,
  useChunkedEncodingByDefault: true,
  sendDate: true,
  _removedConnection: false,
  _removedContLen: false,
  _removedTE: false,
  _contentLength: null,
  _hasBody: true,
  _trailer: '',
  finished: false,
  _headerSent: false,
  socket:
   Socket {
     connecting: false,
     _hadError: false,
     _handle: [TCP],
     _parent: null,
     _host: null,
     _readableState: [ReadableState],
     readable: true,
     _events: [Object],
     _eventsCount: 8,
     _maxListeners: undefined,
     _writableState: [WritableState],
     writable: true,
     allowHalfOpen: true,
     _sockname: null,
     _pendingData: null,
     _pendingEncoding: '',
     server: [Server],
     _server: [Server],
     timeout: 120000,
     parser: [HTTPParser],
     on: [Function: socketOnWrap],
     _paused: false,
     _httpMessage: [Circular],
     _peername: [Object],
     [Symbol(asyncId)]: 7,
     [Symbol(lastWriteQueueSize)]: 0,
     [Symbol(timeout)]: [Timeout],
     [Symbol(kBytesRead)]: 0,
     [Symbol(kBytesWritten)]: 0 },
  connection:
   Socket {
     connecting: false,
     _hadError: false,
     _handle: [TCP],
     _parent: null,
     _host: null,
     _readableState: [ReadableState],
     readable: true,
     _events: [Object],
     _eventsCount: 8,
     _maxListeners: undefined,
     _writableState: [WritableState],
     writable: true,
     allowHalfOpen: true,
     _sockname: null,
     _pendingData: null,
     _pendingEncoding: '',
     server: [Server],
     _server: [Server],
     timeout: 120000,
     parser: [HTTPParser],
     on: [Function: socketOnWrap],
     _paused: false,
     _httpMessage: [Circular],
     _peername: [Object],
     [Symbol(asyncId)]: 7,
     [Symbol(lastWriteQueueSize)]: 0,
     [Symbol(timeout)]: [Timeout],
     [Symbol(kBytesRead)]: 0,
     [Symbol(kBytesWritten)]: 0 },
  _header: null,
  _onPendingData: [Function: bound updateOutgoingData],
  _sent100: false,
  _expect_continue: false,
  req:
   IncomingMessage {
     _readableState: [ReadableState],
     readable: true,
     _events: [Object],
     _eventsCount: 1,
     _maxListeners: undefined,
     socket: [Socket],
     connection: [Socket],
     httpVersionMajor: 1,
     httpVersionMinor: 1,
     httpVersion: '1.1',
     complete: true,
     headers: [Object],
     rawHeaders: [Array],
     trailers: {},
     rawTrailers: [],
     aborted: false,
     upgrade: false,
     url: '/',
     method: 'GET',
     statusCode: null,
     statusMessage: null,
     client: [Socket],
     _consuming: false,
     _dumped: false,
     next: [Function: next],
     baseUrl: '',
     originalUrl: '/',
     _parsedUrl: [Url],
     params: {},
     query: {},
     res: [Circular],
     _startAt: [Array],
     _startTime: 2020-02-09T07:52:51.231Z,
     _remoteAddress: '::1',
     body: {},
     secret: undefined,
     cookies: [Object: null prototype] {},
     signedCookies: [Object: null prototype] {},
     _parsedOriginalUrl: [Url],
     route: [Route] },
  locals: [Object: null prototype] {},
  _startAt: undefined,
  _startTime: undefined,
  writeHead: [Function: writeHead],
  __onFinished: { [Function: listener] queue: [Array] },
  [Symbol(isCorked)]: false,
  [Symbol(outHeadersKey)]: [Object: null prototype] { 'x-powered-by': [Array] } }

엄청 많은 정보들이 포함되어 있는 것을 확인할 수 있다!

이 객체에 대해 전부 설명하기 보다는 필요한 부분만 설명하고자 한다.

Request, Response 객체?

request객체는 클라이언트(브라우저)를 통해 서버에 어떤 정보를 요청하는 정보를 담고있는 객체이다.

response객체는 서버가 클라이언트의 요청에 응답하는 정보를 담고 있는 객체이다.

 

일반적으로 요청은 다음과 같은 순서로 이루어진다.

  1. 클라이언트에서 서버로 요청
  2. 서버는 클라이언트에 응답

requset > response 로 간략화 할 수도 있을것이다.

클라이언트와 서버의 응답

여기서 WAS는 Web Application Server를 의미하므로 편의상 서버라고 하자.

 

이 그림에선 요청와 응답 객체에 어떤 정보를 포함하고 있는지 나와있지 않다.

과연 어떤 정보를 포함하고 있을까?

 

캡틴판교님의 글에 나와있는 그림을 확인해보자

 

출처 https://joshua1988.github.io/web-development/http-part1/

 

각 객체가 가지고 있는 정보

더 자세한 정보는 MDN 문서에서 확인할 수 있다. 링크

 

HTTP 메시지

HTTP 메시지는 서버와 클라이언트 간에 데이터가 교환되는 방식입니다. 메시지 타입은 두 가지가 있습니다. 요청(request)은 클라이언트가 서버로 전달해서 서버의 액션이 일어나게끔 하는 메시지고, 응답(response)은 요청에 대한 서버의 답변입니다.

developer.mozilla.org

Request

시작 줄

  • 요청 메소드 타입 (GET, POST, PUT, DELETE... 그리고 잘 사용하지 않는 HEAD, OPTION)
  • URL 정보

헤더

  • HTTP 헤더

본문 (옵션)

  • 패러미터 (전달받은 데이터)

Response

상태 줄

  • 프로토콜 버전
  • 상태 코드
  • 상태 텍스트

헤더

  • HTTP 헤더

본문 (옵션)

response객체의 헤더 예시

Java Servlet으로 실습

다음 링크의 코드를 이용해 실습을 해보자 링크

<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    </head>
    <body>
        <h1>Request API</h1>
        <ul>
            <li>접속자 IP주소: <%= request.getRemoteAddr() %></li>
            <li>서버 이름: <%= request.getServerName() %></li>
            <li>요청 방식: <%= request.getMethod() %></li>
            <li>프로토콜: <%= request.getProtocol() %></li>
            <li>요청 URL: <%= request.getRequestURL() %></li>
        </ul>
    </body>
</html>

다음 jsp 파일을 보면 request 객체의 값들을 다음 메소드들을 통해서 가져옴을 알 수 있다.

 

다음 링크에서 Servlet에서 제공하는 Requset, Response의 API들을 확인할 수 있다.

HttpServletRequest

 

HttpServletRequest (Servlet 3.0 API Documentation - Apache Tomcat 7.0.99)

Reconstructs the URL the client used to make the request. The returned URL contains a protocol, server name, port number, and server path, but it does not include query string parameters. Because this method returns a StringBuffer, not a string, you can mo

tomcat.apache.org

HttpServletResponse

 

HttpServletResponse (Servlet 3.0 API Documentation - Apache Tomcat 7.0.99)

Deprecated.  As of version 2.1, due to ambiguous meaning of the message parameter. To set a status code use setStatus(int), to send an error with a description use sendError(int, String).

tomcat.apache.org

 

request객체에 parameter가 같이 오는 경우 어떻게 이용할 수 있을까??

 

다음와 코드를 살펴보자

package examples;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Servlet implementation class ParameterServlet
 */
@WebServlet("/param")
public class ParameterServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;

    /**
     * @see HttpServlet#HttpServlet()
     */
    public ParameterServlet() {
        super();
        // TODO Auto-generated constructor stub
    }

    /**
     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html");
        PrintWriter out = response.getWriter();
        out.println("<html>");
        out.println("<head><title>form</title></head>");
        out.println("<body>");

        String name = request.getParameter("name");        // "name"이란 key를 가진 parameter의 값을 가져오는 부분
        String age = request.getParameter("age");

        out.println("name : " + name + "<br>");
        out.println("age : " +age + "<br>");

        out.println("</body>");
        out.println("</html>");
    }

}

다음 코드에서 이 부분을 유심히 살펴보자

String name = request.getParameter("name");        // "name"이란 key를 가진 parameter의 값을 가져오는 부분

이 방법으로 request 객체의 패러미터를 이용할 수 있다.

 


 

강의의 댓글 중 다음과 같은 질문이 눈에 띄었다.

 

 

궁금한게 있습니다.

ParameterServlet.java 파일에

request의 모든 헤더를 확인하는 코드도 추가해봤습니다(이전 동영상 실습)

request에 getParameter() 함수도 있으니까 파라미터 정보도 담고있는지 확인하고 싶어서요

그런데 모든 헤더 정보를 출력하는 부분에 파라미터 정보는 왜 출력되지 않는걸까요?

아시는분 답글 부탁드릴게요~! 감사합니다

 

질문자가 첨부한 이미지 파일

왜 헤더 정보를 출력할 때 파라미터를 확인할 수 없을까?

 

답은 본문의 request 객체가 포함하고 있는 정보를 설명한 부분에 있다.

 

파라미터 정보는 애초에 헤더에 들어가지 않는다!

 

크롬 네트워크 탭으로 확인해보자

 

크롬 개발자도구의 Network 탭에서 다양한 정보를 확인할 수 있다.

 

 

+ Recent posts