HTTP 응답 메시지 생성

  • HTTP 응답코드 지정
  • 헤더 생성
  • 바디 생성

* 편의기능 : Content-Type 편리하게 지정, 쿠키를 객체로 관리할 수 있는 방법, Redirect 기능

 

 

 

헤더 생성하기

[ 소스코드 ]

protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // [status-line]
        response.setStatus(HttpServletResponse.SC_OK); // HTTP 응답 코드 넣기

        //[response-header]
        response.setHeader("Content-Type", "text/plain");
        response.setHeader("Cache-Control", "no-cache, no-store, must- revalidate"); // 캐시 무효화
        response.setHeader("Pragma", "no-cache");
        response.setHeader("my-header","hello"); // 임의의 헤더 만들기

        PrintWriter writer = response.getWriter();
        writer.println("ok");
 }

 

[ 테스트 확인 ]

url : http://localhost:8080/response-header

Response Header 가 정상적으로 생성됬음을 알 수 있습니다.

 

 

Header 편리하게 생성하기

[ 소스코드 ]

private void content(HttpServletResponse response) {
        //Content-Type: text/plain;charset=utf-8
        // Content-Length: 2
        //response.setHeader("Content-Type", "text/plain;charset=utf-8");
        response.setContentType("text/plain");
        response.setCharacterEncoding("utf-8");
        //response.setContentLength(2); //(생략시 자동 생성)
}

위의 코드를 작성하면 직접 타이핑할 필요 없이 content 에 response 만 넣어주면 자동으로 헤더가 생성됩니다.

 

 

 

Cookie 편리하게 생성하기

[ 소스코드 ]

private void cookie(HttpServletResponse response) {
        //Set-Cookie: myCookie=good; Max-Age=600;
        // response.setHeader("Set-Cookie", "myCookie=good; Max-Age=600");
        Cookie cookie = new Cookie("myCookie", "good");
        cookie.setMaxAge(600); //600초
        response.addCookie(cookie);
}

쿠키가 정상적으로 출력됨을 볼 수 있습니다.

 

 

Redirect 사용하기

1) 상태코드 : 302

= setStatus( HttpServletResponse.SC_FOUND )

 

2) 로케이션 : /basic/hello-form.html 로 보냄

= setHeader ( "Location", 디렉토리 )

 

[ 소스코드 ]

private void redirect(HttpServletResponse response) throws IOException {
        //Status Code 302
        //Location: /basic/hello-form.html
        //response.setStatus(HttpServletResponse.SC_FOUND); //302
        //response.setHeader("Location", "/basic/hello-form.html");
        response.sendRedirect("/basic/hello-form.html"); // 4,5 번째 줄은 이 한줄로 해결가능
}

 

정상적으로 리다이렉트 됩니다.

 

 

JSON 데이터를 java 객체에 담아 출력하기

private ObjectMapper objectMapper = new ObjectMapper();

    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("application/json");
        response.setCharacterEncoding("UTF-8");

        helloData helloData = new helloData();
        helloData.setUsername("jun");
        helloData.setAge(30);

        String result = objectMapper.writeValueAsString(helloData);

        response.getWriter().write(result);
}

request 와 비슷하나 writeValueAsString ( helloData ) 라는 메서드를 사용한다는 차이점이 있습니다.

데이터가 정상 출력됩니다.

'HTTP' 카테고리의 다른 글

JSON 형식으로 받은 데이터를 객체로 변환하기  (0) 2022.11.26
HTTP 요청 데이터 작성하기  (0) 2022.11.26
DTO  (0) 2022.08.22
RestAPI 활용하기  (0) 2022.08.22
Message States Server  (0) 2022.08.19

JSON 형식 전송

  • POST http://localhost:8080/request-body-json
  • content-type = application/json
  • message body : {"username" : "hello", "age" : 20 }
  • 결과 : messagebody = {"username" : "hello", "age" : 20 }

 

 

JSON 형식 파싱 추가

JSON 형식으로 파싱할 수 있게 객체를 하나 생성

 

 

 

테스트 해보기

1) 소스코드는 Text 로 작성하는 것과 같습니다.

@WebServlet(name = "requestBodyJsonServlet", urlPatterns = "/request-body-json")
public class RequestBodyJsonServlet extends HttpServlet {
    @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);
    }
}

 

2) Postman 에서 JSON 데이터 사용하기

 

raw 에서 JSON 으로 변경만 해주면 됩니다.

3) 정상 작동 확인

 

 

 

JSON 데이터를 Java 객체로 변환하기

: JSON 을 변환시켜주는 라이브러리 필요

 

1) ObjectMapper object 객체 생성 ( SpringBoot 에서 기본적으로 지원해줌 )

2) objectMapper.readValue ( 메세지, Class ) 실행

3) 해당 메서드를 통해 자바 객체를 사용할 수 있게 됩니다.

 

[ 소스코드 ]

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("username : "+helloData.getUsername());
        System.out.println("age : "+helloData.getAge());

        response.getWriter().write("ok");
}

정상 출력됨이 확인됩니다.

'HTTP' 카테고리의 다른 글

HttpServletResponse 사용해보기  (0) 2022.11.26
HTTP 요청 데이터 작성하기  (0) 2022.11.26
DTO  (0) 2022.08.22
RestAPI 활용하기  (0) 2022.08.22
Message States Server  (0) 2022.08.19

HTTP 요청 메시지를 통한 데이터 전달 방법

 

GET
  • /url ? username = hello & age = 20
  • 메시지 바디 없이 URL 의 쿼리 피라미터에 데이터를 포함해서 전달
  • ex. 검색, 필터, 페이징 등에서 많이 사용하는 방식

[ 소스 코드 ]

 

package servletTest.servlet.request;

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

@WebServlet(name = "requestParamServlet", urlPatterns = "/request-param")
public class RequestParamServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        System.out.println("전체 파라미터 조회 - start");
        request.getParameterNames().asIterator().forEachRemaining(paramName -> System.out.println(paramName + " : " + request.getParameter(paramName)));
        System.out.println("전체 파라미터 조회 - end");

        System.out.println("단일 파라미터 조회 - start");
        String username = request.getParameter("username");
        String age = request.getParameter("age");

        System.out.println("username = " + username);
        System.out.println("age = " + age);
        System.out.println();
        System.out.println("단일 파라미터 조회 - end");

        System.out.println("중복되는 복수 파라미터 조회");
        String[] usernames = request.getParameterValues("username");
        for (String i : usernames) {
            System.out.println("username = " + i);
        }

    }
}

* 여기서 주의할 점은 복수 파리미터에 대한 부분입니다.

http://localhost:8080/request-param?username=hello&age=20&username=hello2

와 같은 url 로 username 을 중복해서 부르게 된다면 그 값이 없어지는게 아니라,

username 안에 두 값을 받아오게 됩니다.

 

그래서 값들을 담는 배열 객체를 만들어 저장 후 출력이 가능합니다.

 

 

 

 

POST
  • content-type : application / x-www.form-urlencoded
  • 메시지 바디에 쿼리 피라미터 형식으로 전달 username = hello & age = 20 ( url 형태와 비슷함 )
  • ex. 회원 가입, 상품 주문, HTML form 사용

 

1) POST 를 사용하려면 HTML Form이 필요합니다.

- webapp/basic 경로에 hello-form.html 을 생성해줍니다.

- http://localhost:8080/basic/hello-form.html 로 브라우저 접속

 

[ 폼 형태 ]

<form action="/request-param" method="post">
    username: <input type="text" name="username" />
    age: <input type="text" name="age" /> <button type="submit"> 전송 </button>
</form>

위의 폼을 보면 다음을 알 수 있습니다.

Form 전송을 누르게 되면 이전에 서블릿 경로로 만들어놨던 "/request-param" 경로로 전송하게 됩니다.

개발자도구를 켜서 폼 데이터를 보면 데이터가 제대로 들어왔음을 확인할 수 있습니다.

 

 

2) 위 데이터를 컨텐트 바디에 보내게 됩니다.

다음과 같이 엔코딩되어 전송 됩니다.

 

 

3) 데이터 확인

데이터가 정상적으로 출력되고 있음이 확인가능합니다.

 

 

 

 

[ 중간 정리 ]

1) request.getParameter 형식은 GET / POST 둘 다 지원한다.

2) POST 는 브라우저가 알아서 형식을 만들어서 전송한다.

3) GET 은 사용자가 Url 을 입력한다.

4) 즉, 클라이언트 입장에선 다르게 작성하지만

          서버입장에선 GET/POST 구분없이 조회가 가능합니다.

 

Q. 그럼 위와 같은 HTTP 메서드 테스트를 할 때, 매번 Html 파일을 만들어야 하는가?

A. 아니다. Postman 을 활용하자 !!

위의 과정을 Postman 을 통해 테스트한 결과, 200 OK가 나오면 정상 작동하는 것입니다.

 

 

HTTP message body 에 데이터 직접 담아서 요청
  • HTTP API 에서 주로 사용
  • JSON, XML, TEXT
  • 데이터 형식은 주로 JSON 사용
  • POST, PUT, PATCH

[ 소스 코드 ]

@WebServlet(name = "requestBodyStringServlet", urlPatterns = "/request-body-string")
public class RequestBodyStringServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        ServletInputStream inputStream = request.getInputStream();// 메세지 바디의 코드를 바이트 코드로 얻을 수 있음
        String messageBody = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8);// StreamUtils 를 통해 인코딩 정보를 알려주고 바이트 코드로 변환 시켜줌

        System.out.println("messageBody : " + messageBody);
        response.getWriter().write("ok");
    }
}

[ Postman Test ]

정상적으로 출력됨을 볼 수 있습니다.

'HTTP' 카테고리의 다른 글

HttpServletResponse 사용해보기  (0) 2022.11.26
JSON 형식으로 받은 데이터를 객체로 변환하기  (0) 2022.11.26
DTO  (0) 2022.08.22
RestAPI 활용하기  (0) 2022.08.22
Message States Server  (0) 2022.08.19

DTO ( Data Transfer Object )

[ 클라이언트에서 서버쪽으로 전송하는 요청 데이터 ]

[서버에서 클라이언트 쪽으로 전송하는 응답 데이터 ] 의 형식으로 클라이언트와 서버 간에 데이터 전송이 이뤄집니다.

 

 

DTO 를 왜 사용하는가?

 

1. 코드의 간결성

 

ResponseEntity 를 통해 데이터를 저장하는 곳에는 @RequestParam 애노테이션이 사용됩니다.

그런데 프로젝트의 규모가 커질 수록 RequestParam 의 개수는 늘어날 수 밖에 없습니다.

만약, 클라이언트와 요청 데이터를 하나의 객체로 모두 전달 받을 수 있다면 코드 자체가 아주 간결해질 것입니다.

DTO 클래스가 바로 요청 데이터를 하나의 객체로 전달 받는 역할을 해줍니다.

 

 

2. 데이터 유효성 검증의 단순화

 

이메일이 유효한 입력 값인지 확인하려면 email.matches("^[~~$") 와 같이 복잡한 정규 표현식으로 코드를 작성하게 됩니다.

하지만 HTTP 요청을 전달 받는 핸들러 메서드는 요청을 받는 것이 주목적이기 때문에 최대한 간결하게 작성되는 것이 좋습니다.

 

그래서 DTO 클래스에 이러한 유효성 검증을 작성하면 핸들러 메서드에는 아주 간결하게 표현될 수 있습니다.

 

 

DTO 클래스를 적용하기 위한 코드 리팩토링 절차

  • 회원 정보를 전달 받을 DTO 클래스를 생성합니다.

컨트롤러에서 현재 회원 정보로 전달 받는 각 데이터 항복을 DTO 클래스의 멤버 변수로 추가해줍니다.

 

  • 클라이언트 쪽에서 전달하는 요청 데이터를 @RequestParam 애너테이션으로 전달 받는 핸들러 메서드를 찾습니다.

RequestBody 가 필요한 핸들러는 POST, PATCH, PUT 과 같이 리소스 수정/추가 발생할 때 입니다.

GET 은 조회하는 용도이기 때문에 Body 는 필요 없습니다.

 

  • @RequestParam 코드를 DTO 클래스의 객체로 수정합니다.

Map 객체로 JSON 을 받아오는 객체 였다면 Reponse Body 를 DTO 클래스 객체로 변경해줍니다.

 

 

 

 

DTO 클래스에 유효성 검증 적용하기

org.springframework.boot:spring-boot-starter-validation 이라는 디펜던시 항목을 추가해줘야 합니다.

 

[ DTO 내부 멤버에서 검증 애노테이션 ]

@NotBlank : 정보가 비어있지 않은지를 검증

@Email : 이메일 주소인지 검증

@Pattern : 정규표현식에 매치되는 유효한 번호인지 검증

 

[ 유효성 검증 시작 ]

@RestController
@RequestMapping("/v1/members")
public class MemberController {
    @PostMapping
    public ResponseEntity postMember(@Valid @RequestBody MemberPostDto memberDto) {
        return new ResponseEntity<>(memberDto, HttpStatus.CREATED);
    }
		...
		...
}

@Valid 애노테이션을 추가해줍니다.

 

[ @PathVariable 이 추가된 유효성 검증하기 ]

@RestController
@RequestMapping("/v1/members")
@Validated   // (1)
public class MemberController {
		...
		...

    @PatchMapping("/{member-id}")
    public ResponseEntity patchMember(@PathVariable("member-id") @Min(1) long memberId,
                                    @Valid @RequestBody MemberPatchDto memberPatchDto) {
        memberPatchDto.setMemberId(memberId);

        // No need Business logic

        return new ResponseEntity<>(memberPatchDto, HttpStatus.OK);
    }
}

- @Min(1) : memberId 가 1 이상의 숫자일 경우에만 검증에 통과하도록 해줍니다.

- @Validated : @PathVariable 이 추가된 변수에 유효성 검증이 정상적으로 수행되려면 해당 애노테이션이 필수입니다.

'HTTP' 카테고리의 다른 글

JSON 형식으로 받은 데이터를 객체로 변환하기  (0) 2022.11.26
HTTP 요청 데이터 작성하기  (0) 2022.11.26
RestAPI 활용하기  (0) 2022.08.22
Message States Server  (0) 2022.08.19
HTTP 메서드와 속성  (0) 2022.08.18

[ 기본 개념 ]

@RestController

Spring MVC 에서 특정 클래스에 @RestController 를 추가하면 해당 클래스가 REST API 리소스를 처리하기 위한 API 엔드포인트로 동작함을 정의합니다.

그리고 해당 애노테이션이 추가된 클래스는 애플리케이션 로딩 시, Spring Bean 으로 등록해줍니다.

 

 

 

@RequestMapping

클라이언트의 요청과 그 요청을 처리하는 핸들러 메서드를 매핑해주는 역할을 합니다.

예를 들어, RequsetMapping("v1/member") 을 하게 된다면 괄호 안에 있는 코드는 Controller 클래스 레벨에 추가하여 클래스 전체에 사용되는 공통 URL 설정을 하게 됩니다. 이러한 메서드를 핸들러 메서드라고 부릅니다.

 

 

 

@RequestMapping(value, produces)

[produces]
해당 속성은 응답 데이터를 어떤 미디어 타입으로 클라이언트에게 전송할 지를 설정합니다.
JSON 형식의 데이터를 응답 데이터로 전송하겠다는 의미로는
MediaType.APPLICATION_JSON_VALUE 로 값을 설정할 수 있습니다.
이 설정을 하지않는다면 JSON 형식이 아닌, 문자열 자체를 전송하게 됩니다.

 

 

 

@PostMapping

클라이언트 요청 데이터를 서버에 생성할 때 사용하는 애너테이션입니다.

주로 회원 정보를 등록해주는 역할을 해줍니다.



 

@RequsetParam

핸들러 메서드의 피라미터 종류 중 하나입니다.

주로 클라이언트쪽에서 전송하는 요청 데이터를 [ 쿼리 피라미터, 폼 데이터, x-www-form-urlencoded 형식 ] 으로 전송하면

이를 서버쪽에서 전달 받을 때 사용하는 애너테이션입니다.

 

 

* 쿼리 피라미터

요청 URL 에서 "?" 를 기준으로 붙는 key/value 쌍의 데이터를 말합니다.

 

- 예시
http://localhost:8080/coffees/1?page=1&size=10

 

 

* 리턴 값

postMapping 애노테이션 메서드의 리턴 타입이 String 인 경우에는,

클라이언트 쪽에서 JSON 형식의 데이터를 전송 받아야 하기 때문에, 응답 문자열을 JSON 형식에 맞게 작성해줘야합니다.

 

일반적으로 POST Method 를 처리하는 핸들러 메서드는 데이터를 생성한 후에 클라이언트 쪽에서 생성한 데이터를 리턴해주는 것이 관례입니다.

 

 

 

@GetMapping

클라이언트가 서버에 리소스를 조회할 때 사용하는 애너테이션입니다.

주로 회원 정보를 클라이언트쪽에서 제공할 때 사용하는 메서드입니다.

 

- 예시
/v1/members/{member-id} 의 경우,
member-id 는 회원 식별자를 의미하며 클라이언트가 요청을 보낼 때 URI 로 어떤 값을 지정하느냐에 따라서 동적으로 바뀌는 값입니다.

 

 

@PathVariable

핸들러 피라미터 종류 중 하나입니다.

괄호 안에 입력한 문자열 값은 중괄호 안의 문자열과 동일해야합니다.

다를 경우 MssingPathVariableException 이 발생합니다.

[예시]
@GetMapping("/{member-id}")
public String getMember(@PathVariable("member-id") long memberId){ ~~ }

 

 

 

 

JSON 형식의 응답 문자열을 수작업으로 작성하는 경우를 개선하는 방법

[ 기존 코드와 차이점 ]

1. produce 설정 제거

 

 

2. map 객체로 생성

Map 객체를 리턴해주게 되면 내부적으로 이 데이터는 JSON 형식의 응답 데이터로 변환해야 되는 거구나를 인지하게 됩니다.

그래서 자동으로 JSON 형식으로 변환하게 됩니다.

 

 

3) return value 를 ResponseEntity 객체로 변경합니다.

사실 리턴값을 Map 객체로 리턴해도 JSON 응답 데이터를 받을 수 있습니다.

하지만 ResponseEntity 를 사용하게 될 경우 응답 데이터를 래핑함으로써 응답 상태를 명시적으로 함께 전달 할 수 있다는 장점이 있습니다.

 

- 예시
return new ResponseEntity<>(map, Httpstatus.CREATE);
or
return new ResponseEntity<>(HttpStatus.OK);

* HttpStatus.CREATE 는 클라이언트의 POST 요청을 처리해서 요청 데이터가 정상적으로 생성되었음을 의미하는 HTTP 응답 상태입니다. ( 응답 상태 문서 : https://developer.mozilla.org/ko/docs/Web/HTTP/Status )

 

 

 

 

HTTP 헤더

HTTP 메시지의 구성 요소 중 하나로써 클라이언트 요청이나 서버의 응답에 포함되어 부가적인 정보를 HTTP 메시지에 포함할 수 있도록 해줍니다.

 

[ 사용 목적 ]

 

  • 클라이언트와 서버 관점에서의 대표적인 HTTP 헤더 예시

클라이언트와 서버 관점에서 내부적으로 가장 많이 사용되는 헤더 정보로는 "Content-Type" 이 있습니다.

클라이언트와 서버가 HTTP 메시지 바디의 데이터 형식이 무엇인지를 알려주는 역할을 합니다.

 

그래서 클라이언트와 서버는 Content-Type 이 명시된 데이터 형식에 맞는 데이터를 주고 받는 것입니다.

 

 

  • 개발자들이 직접 실무에서 사용하는 대표적인 HTTP 헤더 예시

사실 개발자들이 직접 HTTP 헤더를 건드릴 일은 없습니다.

하지만 코드 레벨에서 컨트롤해야 하는 경우가 있는데 이런 경우의 대표적인 예시 두가지를 보겠습니다.

 

1. Authorization

이는 클라이언트가 적절한 자격 증명을 가지고 있는지를 확인하기 위한 정보입니다.

일반적으로 REST API 기반 애플리케이션의 경우 클라이언트와 서버간의 로그인 인증에 통과한 클라이언트들은

"Authorization" 헤더 정보를 기준으로 인증에 통과한 클라이언트가 맞는지 확인하는 절차를 가집니다.

 

 

2. User-Agent

여러 유형의 클라이언트가 하나의 서버 애플리케이션에 요청을 전송하는 경우가 많습니다.

어떤 사용자는 데스크탑 웹 브라우저에서 서버에 요청을 보내고, 또 다른 사람은 스마트폰에서 요청을 보냅니다.

이런 경우 들어오는 요청을 구분해서 응답 데이터를 다르게 보내줘야 되는 경우가 있습니다.

예를 들어, 데스크탑 브라우저에서는 더 큰 화면인만큼 더 많은 정보를 보여줍니다.

이 경우, "User-Agent" 정보를 통해서 구분할 수 있습니다.

 

 

 

HTTP Request 헤더 정보 얻기

  • @RequestHeader("user-agent") : 특정 헤더 정보만 읽는 예제입니다.
  • HttpServletRequest 객체 : Request 헤더 정보에 다양한 방법으로 접근이 가능합니다.
  • HttpEntity 객체 : Request 헤더와 바디 정보를 래핑하고 있으며, 조금 더 쉽게 헤더와 바디에 접근할 수 있습니다.

* HttpEntity 객체

Entry 를 통해 각각의 헤더 정보에 접근할 수 있는데, 특이한 것은 자주 사용될만한 헤더 정보들은 get() 으로 가져올 수 있습니다.

 

 

 

HTTP Response 헤더 정보 추가

  • ResponseEntity 와 HttpHeaders 를 이용해 헤더 정보 추가하기
@RestController
@RequestMapping(path = "/v1/members")
public class MemberController{
    @PostMapping
    public ResponseEntity postMember(@RequestParam("email") String email,
                                     @RequestParam("name") String name,
                                     @RequestParam("phone") String phone) {
        // (1) 위치 정보를 헤더에 추가
        HttpHeaders headers = new HttpHeaders();
        headers.set("Client-Geo-Location", "Korea,Seoul");

        return new ResponseEntity<>(new Member(email, name, phone), headers,
                HttpStatus.CREATED);
    }
}

 

 

 

 

RestClient

REST API 서버에 HTTP 요청을 보낼 수 있는 클라이언트 툴 또는 라이브러리를 의미합니다.

Postman 은 UI 가 갖춰진 RestClient 라고 볼 수 있습니다.

 

- Client : 서버쪽의 리소스를 이용하는 쪽

 

* 그래서 [ 어떤 서버가 HTTP 통신을 통해서 다른 서버의 리소스를 이용한다면 그 때만큼은 클라이언트의 역할을 합니다. ]

위의 그림에서는 웹 브라우저가 클라이언트가 됩니다.

 

 

 

RestTemplate

Java 에서 사용할 수 있는 다양한 HTTP Client 라이브러리가 있습니다. ( HttpURLConnection, OkHttp 3, Netty 등 )

Spring 에서는 이 HTTP Client 라이브러리 중 하나를 이용해 다른 백엔스 서버에 HTTP 요청을 보낼 수 있는 REST Client API 를 제공하는데, 이를 RestTemplate 라고 합니다.

 

이 템플릿을 이용하면 Rest EndPoint 지정, 헤더 설정, 피라미터 및 바디 설정을 한 줄의 코드로 쉽게 할 수 있습니다.

 

[ URI 생성 ]

import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponents;
import org.springframework.web.util.UriComponentsBuilder;

import java.net.URI;

public class RestClientExample01 {
    public static void main(String[] args) {
        // (1) 객체 생성
        RestTemplate restTemplate =
                new RestTemplate(new HttpComponentsClientHttpRequestFactory());

        // (2) URI 생성
        UriComponents uriComponents =
                UriComponentsBuilder
                        .newInstance()
                        .scheme("http")
                        .host("worldtimeapi.org")
//                        .port(80)
                        .path("/api/timezone/{continents}/{city}")
                        .encode()
                        .build();
        URI uri = uriComponents.expand("Asia", "Seoul").toUri();
    }
}
[ 설명 ]
newInstance(): UriComponentsBuilder 객체를 생성합니다.
scheme(): URI의 scheme을 설정합니다.
host(): 호스트 정보를 입력합니다.
port(): 디폴트 값은 80이므로 80 포트를 사용하는 호스트라면 생략 가능합니다.
path(): URI의 경로(path)를 입력합니다.
     URI의 path에서 {continents}, {city} 의 두 개의 템플릿 변수를 사용하고 있습니다.
    두 개의 템플릿 변수는 uriComponents.expand("Asia", "Seoul").toUri(); 에서 expand() 메서드 파라미터의 문자열로 채      워집니다. 즉, 빌드 타임에 {continents}는 ‘Asia’, {city}는 ‘Seoul’로 변환됩니다.
encode(): URI에 사용된 템플릿 변수들을 인코딩 해줍니다.여기서 인코딩의 의미는 non-ASCII 문자와 URI에 적절하지 않은 문자를 Percent Encoding 한다는 의미입니다.
build(): UriComponents 객체를 생성합니다.
expand(): 파라미터로 입력한 값을 URI 템플릿 변수의 값으로 대체합니다.
toUri(): URI 객체를 생성합니다.

 

[ 요청 전송 ]

public class RestClientExample01 {
    public static void main(String[] args) {
        // (1) 객체 생성
        RestTemplate restTemplate =
                new RestTemplate(new HttpComponentsClientHttpRequestFactory());

        // (2) URI 생성
        UriComponents uriComponents =
                UriComponentsBuilder
                        .newInstance()
                        .scheme("http")
                        .host("worldtimeapi.org")
//                        .port(80)
                        .path("/api/timezone/{continents}/{city}")
                        .encode()
                        .build();
        URI uri = uriComponents.expand("Asia", "Seoul").toUri();

        // (3) Request 전송
        String result = restTemplate.getForObject(uri, String.class);

        System.out.println(result);
    }
}

- getForObject : HTTP get 요청을 통해 서버의 리소스를 조회합니다.

    이는 커스텀 클래스 타입으로 원하는 정보만 응답으로 전달 받을 수도 있습니다.

 

 

 

 

 

 

이 외에도 정보를 전달받는 여러 방법이 있습니다.

'HTTP' 카테고리의 다른 글

HTTP 요청 데이터 작성하기  (0) 2022.11.26
DTO  (0) 2022.08.22
Message States Server  (0) 2022.08.19
HTTP 메서드와 속성  (0) 2022.08.18
HTTP API 설계와 메서드  (0) 2022.08.14

Endpoint

  • root-endpoint( root-URL )

: API 로 요청을 서버와 통신할 때, 서버가 요청을 수락하는 시작점을 의미합니다.

 

  • path ( url-path )

: path 는 API 를 통해 서버와 통신할 때, 서버와 통신할 수 있는 key 역할을 합니다.

서버에 정의된 문자열에 따라 path 가 달라집니다. 예를 들어, https://api.github.com/user 에서는

'user' 가 path입니다.

 

Github API 의 root-endpoint
: https://api.github.com

트위터 API 의 root-endpoint
: https://api.twitter.com

일반적으로 root-endpoint 는 도메인 주소와 루트(/) 를 가리킵니다.

마찬가지로 Message States Server 의 URL 을 기준으로 파악할 수 있는 root-endpoint 는
Message States Server 의 가장 마지막 Location 인 호스트의 루트(/) 입니다.

 

 

메시지 조회

Request

GET /{githubID}/messages

* 추가적인 피라미터 : /{GithubID}/message?roomname=로비

 

Response

 

( 예시 )

[
  {
     "username": "김코딩", "text": "안녕하세요", "roomname": "로비",
   },
   // ...여러 개의 메시지
]

 

 

메세지 추가

Request

POST /{githubID}/messages

 

Response

 

(예시)

{
   "id": 5
}

 

 

메세지 초기화

Request

POST /{githubID}/clear

 

Reponse

 

(예시)

{
   "message": "message initialized!"
}

'HTTP' 카테고리의 다른 글

DTO  (0) 2022.08.22
RestAPI 활용하기  (0) 2022.08.22
HTTP 메서드와 속성  (0) 2022.08.18
HTTP API 설계와 메서드  (0) 2022.08.14
HTTP - 짧게 정리  (0) 2022.08.13

안전

  • 호출해도 리소스가 변하지 않음
  • 만약, 로그가 쌓여서 장애가 발생한다면?
  • 그런 부분은 고려하지 않고, 오로지 리소스가 변경되고 삭제됬는지만 고려합니다.

 

 

멱등

  • 한번 호출하든, 백번 호출하든 결과가 똑같습니다.
  • 멱등 메서드는 무엇이 있을까?
PUT : 결과를 대체하는 메서드이므로, 몇번 하든 결과가 같다 ( 멱등 )
GET : 한번 조회하든, 두번 조회하든 결과가 조회된다. ( 멱등 )
DELETE : 결과를 삭제한다. 같은 요청을 여러번해도 삭제된 결과는 같다 ( 멱등 )
POST : 두 번 호출하면 결과가 중복될 수 있다. ( 멱등이 아니다 !! )

 

 

멱등 활용하기

  • 자동 복구 메커니즘
  • 서버가 TIMEOUT 등으로 정상 응답을 주지 못할 때, 클라이언트가 같은 요청을 다시 해도 되는가의 판단 근거가 됩니다.

 

 

멱등은 중간에 리소스를 변경하는 것도 고려를 하는가?

GET -> PUT -> GET 으로 데이터가 바뀐것을 조회할 수 있습니다.

멱등은 외부 요인으로 중간에 리소스가 변경되는 것은 고려하지 않습니다.

 

 

 

캐시 가능

  • 응답 결과 리소스를 캐시해서 사용해도 되는가?
  • GET, HEAD, POST, PATCH 캐시 가능
  • 실제로는 GET, HEAD 정도만 캐시로 사용되며, POST,PATCH 는 본문 내용까지 캐시 키로 고려해야하는데, 구현이 쉽지 않음

 

 

클라이언트에서 서버로 데이터 전송하는 방법

  • 쿼리 파라미터를 통한 데이터 전송

URI 끝에 쿼리 파라미터를 넣어서 전송하는 방법입니다.

이것은 주로 GET 으로 정렬 필터 ( 검색어 ) 에 사용을 많이 하는 편입니다.

 

  • 메시지 바디를 통한 데이터 전송

HTTP 메세지 바디를 통해서 전송하는데, POST/PUT/PATCH 를 이용해서

회원가입, 상품주문, 리소스 등록, 리소스 변경할 때 주로 사용합니다.

 

 

클라이언트에서 서버로 데이터를 전송하는 상황 4가지

  • 정적 데이터 조회

- 이미지, 정적텍스트 문서

- 조희는 GET 사용

- 정적 데이터는 일반적으로 쿼리 피라미터 없이 리소스 경로로 단순하게 조회 가능

 

 

  • 동적 데이터 조회

- 주로 검색, 게시판 목록에서 정렬필터 ( 검색어 )

- 조회 조건을 줄여주는 필터, 조회 결과를 정렬하는 정렬 조건에 주로 사용

- 조회는 GET 사용

- GET 은 쿼리 피라미터 사용해서 데이터 전달

 

        클라이언트                                                                                서버

 

  

 

  • HTML Form 을 통한 데이터 전송

- 회원가입, 상품 주문, 데이터 변경

 

클라이언트                                                                               서버

- HTML Form submit 시 POST 전송

- 회원 가입, 상품 주문, 데이터 변경에 주로 사용됨

- Content-Type : application/x-www-form-urlencoded 사용

   -> form 내용을 메세지 바디에 넣어줘서 전송 ( 쿼리 피라미터 형식 )

   -> 전송 데이터를 url encoding 처리

 

클라이언트                                                                                 서버

- GET 은 메세지 바디를 쓰지않고, 쿼리 파라미터에 넣어서 서버에 전달합니다.

- 그러나 위의 예제에서는 저장하는 save 메서드에 GET ( 조회 ) 메서드를 사용하므로 쓰면 안되는 문장입니다.

 

- 위와 같이 멤버를 조회하는 문장에는 사용할 수 있습니다.

 

- 파일 업로드 같은 바이너리 데이터 전송시 사용

- 이름이 multipart 인 이유는 다른 종류의 여러 파일과 폼의 내용 함께 전송 가능하기 때문입니다.

 

*** HTML Form 전송은 GET,POST 만 지원

 

 

 

  • HTTP API 를 통한 데이터 전송

ex. 안드로이드 앱 애플리케이션에서 클라이언트에서 서버로 데이터를 바로 전송해줘야 할 때,

       이를 HTTP API 로 전송한다고 부릅니다. ( 그냥 다 만들어서 넘기는 것입니다. )

 

- 서버에서 서버로 백엔드 시스템 통신

- 앱 클라이언트 ( 아이폰, 안드로이드 )

- 웹 클라이언트

     -> HTML 에서 Form 전송 대신 자바 스크립트를 통한 통신에 사용 ( AJAX )

     -> React, Vue.js 같은 웹 클라이언트와 API 통신

- POST, PUT, PATCH : 메세지 바디를 통해 데이터 전송

- GET : 조회,쿼리 피라미터로 데이터 전달

- Content-Type : application/json 을 주로 사용 ( TEXT, XML, JSON 등등 )

 

'HTTP' 카테고리의 다른 글

RestAPI 활용하기  (0) 2022.08.22
Message States Server  (0) 2022.08.19
HTTP API 설계와 메서드  (0) 2022.08.14
HTTP - 짧게 정리  (0) 2022.08.13
HTTP  (0) 2022.08.03

주제

회원 정보 관리 API 생성

  • 회원 목록 조회
  • 회원 조회
  • 회원 등록
  • 회원 수정
  • 회원 삭제

 

 

 API URI 설계

  • 회원 목록 조회 / read-member-list
  • 회원 조회 / read-member-by-id
  • 회원 등록 / create-member
  • 회원 수정 / update-member
  • 회원 삭제 / delete-member

이렇게 설계하는 것은 좋은 URI 설계인가?

 

URI 설계를 할 때 가장 중요한 것은 리로스 식별 입니다.

 

 

API URI 고민

  • 리소스의 의미는 뭘까?

- 회원 등록/수정/조회 하는게 리소스가 아니다.

- 회원이라는 개념 자체가 바로 리소스이다.

 

  • 리소스를 어떻게 식별하는게 좋을까?

- 회원을 등록, 수정, 조회하는 것을 모두 배제

- 회원이라는 리소스만 식별하면 됨 => 회원 리소스를 URI 에 매핑

 

 

리소스와 행위를 분리

가장 중요한 것은 리소스를 식별하는 것

 

  • URI 는 리소스만 식별
  • 리소스와 해당 리소스를 대상으로 하는 행위를 분리 ( 리소스 : 회원 / 행위 : 조회,등록,삭제,수정 )
  • 리소스는 명사, 행위는 동사 ( 미네랄을 캐라 )
  • 행위 ( 메서드 ) 는 어떻게 구분? ( HTTP 메서드 - GET,POST )

HTTP 메서드

클라이언트가 서버에 무언가를 요청을 할 때 기대하는 행동입니다.

 

[ 주요 메서드 ]

  1. GET : 리소스 조회
  2. POST : 요청 데이터 처리, 주로 등록에 사용
  3. PUT : 리소스를 대체, 해당 리소스가 없으면 생성
  4. PATCH : 리소스 부분 변경
  5. DELETE : 리소스 삭제

[ 기타 메서드 ]

  1. HEAD : GET 과 동일하지만 메시지 부분을 제외하고, 상태 줄과 헤더만 반환
  2. OPTIONS : 대상 리소스에 대한 통신 가능 옵션(메서드) 를 설명 ( 주로 CORS 에서 사용 )
  3. CONNECT : 대상 자원으로 식별되는 서버에 대한 터널을 설정
  4. TRACE : 대상 리소스에 대한 경로를 따라 메시지 루프백 테스트를 수행

 

GET

  • 리소스 조회
  • 서버에 전달하고 싶은 데이터는 query 를 통해서 전달
  • 메시지 바디를 사용해서 데이터 전달 가능하지만, 지원하지 않는 곳이 많아서 권장하지 않음

 

[ 과정 ]

1. 클라이언트가 GET 메서드로 리소스 요청

2. 서버는 데이터를 JSON 형태로 응답데이터를 전송해줌

 

 

 

POST

  • 요청 데이터 처리
  • 메시지 바디를 통해 서버로 요청 데이터 전달
  • 서버는 요청 데이터를 처리 -> 메시지 바디를 통해 들어온 데이터를 처리하는 모든 기능 수행
  • 주로 전달된 데이터로 신규 리소스 등록, 프로세스 처리에 사용 

[ 부가 설명 ]

서버한테 위와 같이 데이터를 줄 것이라고 알려주고,

데이터를 처리해달라고 클라이언트에서 서버로 요청을 하는 것

 

즉, 핵심은 [ 메시지 바디를 통해 서버로 요청 데이터를 전달 ] 하는 것입니다.

그러면 서버는 이 요청데이터를 받아서 처리하는데, 보통 메시지 바디를 통해 들어온 데이터를 처리하는 모든 기능을

다 수행합니다.

 

* 신규 등록시, 리소스 등록3 에서 Location 에 자원의 신규 생성된 URI 경로를 적어줍니다.

 

POST

요청 데이터를 어떻게 처리한다는 뜻일까?

 

  • 스펙 : POST 메서드는 대상 리소스가 리소스의 고유 한 의미 체계에 따라 요청에 포함 된 표현을 처리하도록 요청합니다.
  • 예시
- HTML 양식에 입력 된 필드와 같은 데이터 블록을 데이터 처리 프로세스에 제공
 ex.  HTML 폼에 입력한 정보로 회원가입,주문 등에서 사용

- 게시판, 뉴스, 그룹, 메일링, 리스트, 블로그 또는 유사한 기사 그룹에 메시지 게시
 ex. 게시판 글쓰기, 댓글 달기

- 서버가 아직 식별하지 않은 새 리소스 생성
 ex. 신규 주문 생성

- 기존 자원에 데이터 추가
 ex. 한 문서 끝에 내용 추가하기
  • 정리 : 이 리소스 URI 에 POST 요청이 오면 요청 데이터를 어떻게 처리할지 리소스마다 따로 정해야함 ( 정해진게 없음 )

 

POST 정리

  • 새 리소스 생성 ( 등록 ) - 서버가 아직 식별하지 않은 새 리소스 생성
  • 요청 데이터 처리
- 단순히 데이터를 생성/변경하는 것을 넘어서 프로세스를 처리하는 경우
ex. 주문의 결제완료 -> 배달시작 -> 배달 완료처럼 단순히 값 변경을 넘어 프로세스의 상태가 변경되는 경우
   ( 배달 시작을 누르게되면 그 후에 굉장히 큰 프로세스가 실행됨 )

- POST 의 결과로 새로운 리소스가 생성되지 않을 수 있음
ex. POST /orders/{ordered}/start-delivery ( 컨트롤 URI )
  • 다른 메서드로 처리하기 애매한 경우 ( JSON 으로 조회 데이터 넘겨야하는데, GET 사용 어려운 경우 )

 

PUT

  • 리소스 수정이 아니라 리소스를 완전히 갈아치움
  • 리소스가 있으면 대체 ( 쉽게 말해 덮어 쓰기 )
  • 리소스가 없으면 생성
  • 클라이언트가 리소스 위치를 알고 URI 지정 ( POST 와의 차이점 )
  • 즉, 클라이언트가 리소스 위치를 알고 있어야함.

 

위의 예제에서 만약 member/100 리소스가 없으면, 신규로 생성이 됩니다.

그런데 만약 있으면 [ 기존것은 없어지고 새로 들어감 ]

 

[ age 만 50으로 수정 ] 을 하고 싶어도 username 이 없어지고 age 50이 들어와버립니다.

그래서 이러한 수정을 위해서 PATCH 를 사용합니다.

 

 

PATCH

- 리소스 부분 변경

- PATCH 를 못쓰는 버젼이 있어서 그런 경우 POST 를 사용해야함

 

 

DELETE

리소스 제거

 

 

 

 

'HTTP' 카테고리의 다른 글

RestAPI 활용하기  (0) 2022.08.22
Message States Server  (0) 2022.08.19
HTTP 메서드와 속성  (0) 2022.08.18
HTTP - 짧게 정리  (0) 2022.08.13
HTTP  (0) 2022.08.03

HTTP

모든 데이터를 전송 가능

 

  • HTML,TXT
  • IMAGE, 음성, 영상, 파일
  • JSON, XML
  • 서버간에 데이터를 주고 받을 때도 대부분 HTTP 사용

 

 

HTTP 메시지 구조

* 공백은 무조건 필요함

 

 

HTTP 요청 메시지

 

 

HTTP 응답 메시지

 

 

시작 라인

요청 메시지

 

  • start-line = request-line / status-line

start-line 을 request-line 과 status-line 이 있는데

요청 메시지는 request-line 이라고 부릅니다.

 

  • request-line = method SP(공백) request-target SP HTTP-version CRLF (엔터) 

method : GET/POST 등

request-target : 요청하는 대상

 

 

 

HTTP method

  • 종류 : GET,POST,PUT,DELETE...
  • 서버가 수행해야 할 동작 지정

- GET : 리소스를 달라고 요청하고, 리소스 조회

- POST : 리소스를 줄테니까 작업을 요청, 요청 내역 정리

 

 

 

Request-target

  • absolute-path [?query] ( 절대경로 [?쿼리] )
  • 절대경로= "/" 로 시작하는 경로
  • 참고 : * , http://...?x=y 와 같이 다른 유형의 경로 지정 방법도 있음
[ 예제 ]
GET / search?q=hello&hl=ko HTTP/1.1
Host : www.google.com 

 

 

응답 메시지

  • start-line = request-line / status-line

status-line 에 해당합니다.

  • status-line = HTTP-version SP(공백) status-code SP reason-phrase CRLF

 

  • HTTP version
  • HTTP status code : 요청 성공, 실패를 나타냄
200 - 성공
400 - 클라이언트 요청 오류
500 - 서버 내부 오류

[ 예제 ]

 

 

HTTP 헤더

  • header-field = field-name ":" OWS field-value OWS ( OWS : 띄어쓰기를 써도 되고,안해된다. 즉 허용해준다는 뜻 )
  • field-name : 대소문자 구분 없음

* 단,  [Host SP :] 의 형태는 안됩니다. 즉, 공백을 주의깊게 보고 사용해야합니다.

 

 

HTTP 헤더의 용도

  • HTTP 전송에 필요한 모든 부가정보 ( 메시지 바디 내용, 메시지 바디 크기, 압축, 인증, 캐시 관리 정보,,, 등등 )
  • 표준 헤더가 너무 많음
  • 필요시 임의의 헤더 추가 가능

 

 

HTTP 메시지 바디의 용도

  • 실제 전송할 데이터
  • HTML 문서, 이미지, 영상, JSON 등 byte로 표현할 수 있는 모든 데이터 전송 가능

 

 

HTTP 정리

  • HTTP 메시지에 모든 것을 전송
  • HTTP/1.1 을 기준으로 학습
  • 클라이언트 서버 구조
  • 무상태 프로토콜 ( 스테이스리스 )
  • HTTP 메시지
  • 단순함, 확장 가능

'HTTP' 카테고리의 다른 글

RestAPI 활용하기  (0) 2022.08.22
Message States Server  (0) 2022.08.19
HTTP 메서드와 속성  (0) 2022.08.18
HTTP API 설계와 메서드  (0) 2022.08.14
HTTP  (0) 2022.08.03
HTTP

- HyperText Transfer Protocol 의 줄임말

- HTML가 같은 문서 전송을 위한 Application Layer 프로토콜

- 웹 브라우저와 웹 서버의 소통을 위해 디자인

 

 

HTTP messages

클라이언트와 서버 사이에서 데이터가 교환되는 방식

 

 - 요청

 - 응답

 

HTTP messages 는 몇 줄의 텍스트 정보로 구성되어 있습니다.

그러나 개발자는 이런 메시지를 직접 작성할 필요가 거의 없습니다.

구성 파일, API, 기타 인터피에스에서 자동 완성해줍니다.

요청과 응답은 다음과 같은 구조를 가집니다.

 

 1. start line : 요청이나 응답의 상태를 나타냄. 항상 첫 번째 줄에 위치합니다.

 2. HTTP headers : 요청을 지정하거나, 메시지에 포함된 본문을 설명하는 헤더의 집합

 3. empty line : 헤더와 본문을 구분하는 빈 줄이 있습니다.

 4. body : 요청과 관련된 데이터나 응답과 관련된 데이터 또는 문서를 포함 ( 요청,응답 유형에 따라 선택적 사용됨 )

 

 

Request

Start Line

HTTP 요청은 클라이언트가 서버에 보내는 메시지입니다.

Start Line 에는 세가지 요소가 있습니다.

 

 1. 수행할 작업 ( GET, PUT, POST 등 ) 이나 방식 ( HEAD, OPTIONS ) 을 설명하는 HTTP method 를 나타냅니다.

 2. 요청 대상 또는 프로토콜, 포트, 도메인의 절대 경로는 요청 컨텍스트에 작성됩니다. 이 요청 형식은 HTTP method 마다 다릅니다.

     - origin 형식 : ? 와 쿼리 문자열이 붙는 절대 경로입니다. POST, GET, HEAD, OPTIONS 등의 메서드와 함께 사용됩니다.

     - absolute 형식 : 완전한 URL 형식으로, 프록시에 연결하는 경우 대부분 GET method 와 함께 사용됩니다.

     - authority 형식 : 도메인 이름과 포트 번호로 이뤄진 URL 의 authority component 입니다. HTTP 터널을 구축하는 경우,

                                  CONNECT 와 함께 사용할 수 있습니다.

     - asterisk 형식 : OPTIONS 와 함께 별표( ) 하나로 서버 전체를 표현합니다.

 

Headers

헤더 이름 ( 대소문자 구분이 없는 문자열 ), 콜론 ( : ), 값을 입력합니다.

값은 헤더에 따라 다릅니다. 여러 종류의 헤더가 있고, 다음과 같이 그룹을 나눌 수 있습니다.

 

 - General headers : 메시지 전체에 적용되는 헤더로, body를 통해 전송되는 데이터와는 관련이 없는 헤더입니다.

 - Request headers : fetch를 통해 가져올 리소스나 클라이언트 자체에 대한 자세한 정보를 포함하는 헤더를 의미합니다.

                                  User-Agent, Accept-Type, Accept-Language 와 같은 헤더는 요청을 보다 구체화합니다.

                                  Referer 처럼 컨텍스트를 제공하거나 If-None 가 같은 조건에 따라 제약을 추가할 수 있습니다.

 - Representation headers : 이전에는 Entity Headers 로 불렀으며, body에 담긴 리소스의 정보를 포함하는 헤더입니다.

 

Body

요청의 본문은 HTTP messages 구조의 마지막에 위치합니다. 모든 요청에 body가 필요하지는 않습니다. GET, HEAD, DELETE, OPTIONS처럼 서버에 리소스를 요청하는 경우에는 본문이 필요하지 않습니다. POST나 PUT과 같은 일부 요청은 데이터를 업데이트하기 위해 사용합니다. body는 다음과 같이 두 종류로 나눌 수 있습니다.

  • Single-resource bodies(단일-리소스 본문) : 헤더 두 개(Content-Type과 Content-Length)로 정의된 단일 파일로 구성됩니다.
  • Multiple-resource bodies(다중-리소스 본문) : 여러 파트로 구성된 본문에서는 각 파트마다 다른 정보를 지닙니다. 보통 HTML form과 관련이 있습니다.

 

응답(Responses)

Status line

응답의 첫 줄은 Status line이라고 부르며, 다음의 정보를 포함합니다.

  1. 현재 프로토콜의 버전(HTTP/1.1)
  2. 상태 코드 - 요청의 결과를 나타냅니다. (200, 302, 404 등)
  3. 상태 텍스트 - 상태 코드에 대한 설명

Status line은 HTTP/1.1 404 Not Found. 처럼 생겼습니다.

Headers

응답에 들어가는 HTTP headers는 요청 헤더와 동일한 구조를 가지고 있습니다. 대소문자 구분 없는 문자열과 콜론(:), 값을 입력합니다. 값은 헤더에 따라 다릅니다. 요청의 헤더와 마찬가지로 몇 그룹으로 나눌 수 있습니다.

  • General headers : 메시지 전체에 적용되는 헤더로, body를 통해 전송되는 데이터와는 관련이 없는 헤더입니다.
  • Response headers : 위치 또는 서버 자체에 대한 정보(이름, 버전 등)와 같이 응답에 대한 부가적인 정보를 갖는 헤더로, Vary, Accept-Ranges와 같이 상태 줄에 넣기에는 공간이 부족했던 추가 정보를 제공합니다.
  • Representation headers : 이전에는 Entity headers로 불렀으며, body에 담긴 리소스의 정보(콘텐츠 길이, MIME 타입 등)를 포함하는 헤더입니다.

Body

응답의 본문은 HTTP messages 구조의 마지막에 위치합니다. 모든 응답에 body가 필요하지는 않습니다. 201, 204와 같은 상태 코드를 가지는 응답에는 본문이 필요하지 않습니다. 응답의 body는 다음과 같이 두 종류로 나눌 수 있습니다.

  • Single-resource bodies(단일-리소스 본문) :
    • 길이가 알려진 단일-리소스 본문은 두 개의 헤더(Content-Type, Content-Length)로 정의합니다.
    • 길이를 모르는 단일 파일로 구성된 단일-리소스 본문은 Transfer-Encoding이 chunked 로 설정되어 있으며, 파일은 chunk로 나뉘어 인코딩되어 있습니다.
  • Multiple-resource bodies(다중-리소스 본문) : 서로 다른 정보를 담고 있는 body입니다.

Stateless

Stateless는 말 그대로 상태를 가지지 않는다는 뜻입니다. HTTP로 클라이언트와 서버가 통신을 주고받는 과정에서, HTTP가 클라이언트나 서버의 상태를 확인하지 않습니다.

사용자는 쇼핑몰에 로그인하거나 상품을 클릭해서 상세 화면으로 이동하고, 상품을 카트에 담거나 로그아웃을 할 수도 있습니다. 클라이언트에서 발생한 이런 모든 상태를 HTTP 통신이 추적하지 않습니다.

만약 쇼핑몰에서 카트에 담기 버튼을 눌렀을 때, 카트에 담긴 상품 정보(상태)를 저장해둬야 합니다. 그러나 HTTP는 통신 규약일 뿐이므로, 상태를 저장하지 않습니다.

따라서, 필요에 따라 다른 방법(쿠키-세션, API 등)을 통해 상태를 확인할 수 있습니다. 

Stateless(무상태성)이 HTTP의 큰 특징이라고 기억하면 됩니다.

'HTTP' 카테고리의 다른 글

RestAPI 활용하기  (0) 2022.08.22
Message States Server  (0) 2022.08.19
HTTP 메서드와 속성  (0) 2022.08.18
HTTP API 설계와 메서드  (0) 2022.08.14
HTTP - 짧게 정리  (0) 2022.08.13

+ Recent posts