Spring HTTP 요청과 응답

2023. 11. 13. 19:55Springboot

1. HTTP란?

    HTTP은 Hyper Text Transfer Protocol의 약자이며, 인터넷 상에서 데이터를 주고 받기 위한 약속이다.

   즉, 클라이언트와 서버간의 데이터, HTML, 이미지 등등을 주고 받기 위한 통신 규약이다.

2. HTTP 구조

   HTTP에는 Header와 Body가 존재합니다.
   a. Header : http 메세지(요청, 응답)과 본문에 대한 정보를 말해주고 있다.
       해당 메세지가 제공하는 기능에 대한 최소한의 정보가 정리된 요약본이며, 
       헤더에 그 프로토콜에 불필요한 내용을 담으면 네트워크로 전송되는 데이터의 크기가

       커져서 빠른 전송이 불가능하기에 프로토콜을 설계할 때부터 꼭 필요한 내용만 담아야 하고,

       모든 기능이 표현되어야 한다. header에는 3가지로 구성됩니다.

       [출처]  : https://hazel-developer.tistory.com/145 
 

 

HTTP의 구조에 대해 이해하기(특히 Header 구조 파악하기)

HTTP 구조 HTTP 헤더와 본문으로 구성되어 있다. HTTP 본문에는 실제로 통신과정에서 주고 받을 컨텐츠가 담겨져 있다. HTTP헤더는 HTTP메시지(요청/응답)와 본문에 대한 정보를 말해주고 있다. 이에

hazel-developer.tistory.com

 

       1) General header :
          전송되는 컨텐츠에 대한 정보보다는 요청/응답이 이루어지는 날짜/시간등의 표현이 있습니다.
           ex) date, pargma(캐시 제어), cache-controle, private, must-revalidate, no-store,

                transfer-encoding, content-type, content-encoding, expires, 

                allow, last-modified, connection....

        2) Request/Response Header
            request -> host, authorization, cookie, content-location

            response -> location(statusCode), server, www-authenticate, proxy-authenticate

            HttpStatusCode[출처] : https://developer.mozilla.org/ko/docs/Web/HTTP/Status

 

 

HTTP 상태 코드 - HTTP | MDN

HTTP 응답 상태 코드는 특정 HTTP 요청이 성공적으로 완료되었는지 알려줍니다. 응답은 5개의 그룹으로 나누어집니다: 정보를 제공하는 응답, 성공적인 응답, 리다이렉트, 클라이언트 에러, 그리고

developer.mozilla.org

 

     3) Entity header 
        실제 주고받는 컨텐츠와 관련된 http 본문에 대한 정보

  b. Body :
      실제로 가져올 데이터, 메세지 본문이 나타남.
      리소스에 html코드, 이미지, css, stylesheet, javascript 등등...

3. Spring boot에서의 HTTP 요청과 응답

Spring boot Request, Response

  Request 

  Client >> DispatcherServlet >> Controller

       Client에서 jsp방식 ${visit} 또는 타임리프방식 : <th:>과 같은 요청을 받은 데이터를 처리하기 위해

       DispatcherServlet이 HandlerMapping에게 해당하는 url과 매핑되는 http메서드가 있는지 확인합니다.

      확인을 하고 url과 일치하는 [**]HTTP메서드가 존재하면 ② →  ③,

      확인을 마치고 없으면 상태코드와 함께 ⑥  →  ⑦로 client에게 응답을 합니다. 

 

   [**] HTTP메서드

       1) GET :  URL 경로에 데이터를 첨부하여 리소스를 요청하며,

                       데이터를 URL 매개변수나 경로 변수로 전달할 수 있습니다.

       2) POST : 데이터를 요청 본문에 담아 서버로 전송합니다.

       3) PUT : 데이터를 요청 본문에 담아 리소스를 업데이트합니다.

       4) DELETE : 특정 리소스를 삭제하는데 사용합니다.

 

  Response

  Controller >> DispatcherServlet

       Controller에서 데이터를 받아 그에 맞게 Service, Repository에서 데이터를 가공하는 

       비지니스 로직을 수행하고 다시 Controller로 와서 Client에게 응답합니다.

       이에 Spring boot에서는 응답하는 방법 2가지 있습니다.

       a. 뷰 반환

           해당 templates폴더 안에 있는 해당이름의 파일을 반환합니다.

           뷰 안에 데이터를 반환하고 싶다면 Model model을 활용해서

           modeladdAttribute(String, your data);를 넣습니다.(Controller >> ViewResolver ④ → ⑤)

           예시코드 :       

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class ViewController {

    @GetMapping("/view")
    public String view(Model model) {
        // 모델에 데이터를 추가
        model.addAttribute("message", "Hello, World!");
        // 뷰 이름 반환 (templates 폴더 내의 HTML 파일 이름)
        return "index";
    }
}

 

       b. JSON 반환

           1) @RestController

                @RestController는 해당 컨트롤러가 RESTful 엔드포인트에 대한 요청을 처리하고

                JSON 형식의 데이터를 반환한다는 것을 나타냅니다.

           2) ResponseEntity

                ResponseEntity를 사용하여 HTTP 상태 코드와 함께 JSON 형식으로 데이터를 반환할 수 있습니다.

           예시코드 (ResponseEntity) : 

package com.pjh.todoapp.controller.apiController;

import com.pjh.todoapp.Entity.dto.CMRespDto;
import com.pjh.todoapp.Entity.dto.web.LoginRequestDto;
import com.pjh.todoapp.Entity.dto.web.SignupRequestDto;
import com.pjh.todoapp.service.UserService;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import java.util.HashMap;
import java.util.Map;

@RestController
@RequiredArgsConstructor
public class AuthApiController {

    private final UserService userService;

    @PostMapping("/api/user/signup")
    public ResponseEntity<?> signup(@Valid SignupRequestDto signupRequestDto, BindingResult bindingResult, RedirectAttributes redirectAttributes){
        if (bindingResult.hasErrors()) {
            Map<String, String> errorMap = new HashMap<>();
            for (FieldError error : bindingResult.getFieldErrors()) {
                errorMap.put(error.getField(), error.getDefaultMessage());
            }
            return new ResponseEntity<>(new CMRespDto<>(HttpStatus.BAD_REQUEST.value(),"회원가입 실패",errorMap),HttpStatus.BAD_REQUEST);
        }
        userService.회원가입(signupRequestDto);
        return ResponseEntity.status(HttpStatus.SEE_OTHER).header("Location", "/login").body("회원가입 성공");
    }

    @PostMapping("/api/user/login")
    public ResponseEntity<?> login(@Valid LoginRequestDto loginRequestDto, BindingResult bindingResult, RedirectAttributes redirectAttributes){
        if(bindingResult.hasErrors()){
            Map<String, String> errorMap = new HashMap<>();
            for(FieldError error : bindingResult.getFieldErrors()){
                errorMap.put(error.getField(), error.getDefaultMessage());
            }
            return ResponseEntity.status(HttpStatus.UNAUTHORIZED).header("Location", "/login").body("로그인 실패");
        }
        redirectAttributes.addFlashAttribute("loginSuccess", true);
        return ResponseEntity.status(HttpStatus.SEE_OTHER).header("Location", "/").body("로그인 성공");
    }
}

 

'Springboot' 카테고리의 다른 글

Spring boot Test code(1)  (0) 2023.12.04
Spring boot 중복된 Bean 에러  (0) 2023.11.30
Spring boot의 인증 방식  (0) 2023.11.10
스프링 유저 프로필 사진  (5) 2023.11.09
스프링 이미지 업로드(2)  (0) 2023.11.07