Request & Response
2023-02-22
1.Request & Response
Request
요청(Request)은 클라이언트가 서버로 전달하는 메시지로, 서버 측 액션을 유도한다.
GET방식
- GET은 요청을 전송할 때 필요한 데이터를 Body에 담지 않고, URL 뒤에 Query String(key와 value)을 통해 전송한다.
- URL뒤에 데이터값이 노출되어 보안에 취약하다.
- 캐싱(한번 접근 후 또 요청할 시 빠르게 접근하기 위해 레지스터에 데이터를 저장시켜 놓는것)이 가능하므로 속도가 빠르다.
- 전송 가능한 데이터 양에 한계가 존재한다. (브라우저 마다 GET요청 길이 제한 존재)
POST방식
- POST는 데이터를 URL뒤에 붙여서 서버로 보내는 것이 아닌 Body에 담아서 전송하기 떄문에 GET방식보다 상대적으로 보안적이다.
- URL에 데이터가 노출되지 않으므로 캐싱이 불가능하다.
- 요청 헤더의 Content - TYpe에 콘텐츠 타입을 명시한다.
- 브라우저 히스토리에 기록이 남지 않는다.
- 클라이언트에서 인코딩, 서버에서 디코딩을 한다.
- 요청받는 시간제한이 존재한다.
- 데이터 길이에 제한이 없다.
GET과 POST의 차이점
- 사용목적
GET은 서버의 리소스에서 데이터를 요청할 때, POST는 서버의 리소스를 새로 생성하거나 업데이트할 때 사용한다. - DB로 따지면 GET은 SELECT에 가깝고, POST는 Create에 가깝다고 보면 된다.
- 요청에 Body 유무 : GET은 URL 파라미터에 요청하는 데이터를 담아 보내기 떄문에 HTTP 메시지에 Body가 없다.
POST는 Body에 데이터를 담아 보내기 떄문에 멱등이며, POST는 멱등이 아니다.
멱등이란?
멱등의 사전적 정의는 연산을 여러 번 적용하더라도 결과가 달라지지 않는 성질을 의미한다.
GET은 리소스를 조회한다는 점에서 여러 번 요청하더라도 응답이 똑같을 것 이다. 반대로 POST는 리소스를 새로 생성하거나 업데이트할 때 사용되기 때문에 멱등이 아니라고 볼 수 있다. (POST 요청이 발생하면 서버가 변경될 수 있다.)
Response
응답(response)은 요청에 대한 서버의 답변이다.
2.HTTP Request 메서드 종류
GET
‘GET’ = 가져오다.
서버에게 resource를 보내달라고 요청한다. 서버(혹은 DB)의 resource는 클라이언트로 전달만 될 뿐 변경되지 않는다.
POST
‘POST’ = 게시하다.
서버에게 resource를 보내면서 생성해 달라고 요청다.
PUT
‘PUT’ = 집어넣다.
서버에게 resource의 업데이트 하거나 resource가 없다면 새로운 resource를 생성해 달라고 요청다.
PUT은 PATCH와 비교해서 전체 데이터를 교체하는 차이점이 있습니다.
PATCH
‘PATCH’ = 고치다.
리소스의 부분만을 수정하는데 쓴다.
PATCH는 PUT과 비교해서 부분 데이터를 업데이트하는 차이점이 있습니다.
DELETE
‘DELETE’ = 삭제하다.
서버에게 resource의 삭제를 요청한다.
외 OPTIONS, HEAD, CONNECT, TRACE
OPTIONS
목적 resource의 통신을 설정한다.
HEAD
GET메서드의 요청과 동일한 응답을 요구하지만, 응답 본문을 포함하지 않는다.
CONNECT
목적 resource로 식별되는 서버로의 터널을 맺는다.
TRACE
목적 resource의 경로를 따라 메시지 loop-back 테스트를 한다.
3.Request 데이터 전달 방법
HTTP 요청 메세지를 통해 클라이언트에서 서버로 데이터를 전달하는 방법은 3가지를 주로 사용한다.
GET - 쿼리 파라미터
- /user?username=hello&age=20
- 메세지 바디 없이 url에 쿼리 파라미터로 데이터를 포함해서 전달
- 검색, 필터, 페이징등에 주로 사용됨
POST - HTML Form
- content-type:application/x-www-form-urlencoded
- 메세지 바디에 쿼리 파라미터 형식으로 전달
- 회원가입, 상품주문, form 데이터 전달에 사용
HTTP message body에 데이터를 직접 담아서 요청
- HTTP API에 주로 사용
- JSON, XML, TEXT의 데이터를 전달
4.스프링 Request 데이터 받기 설정
class 단위의 controller 설정
- @Controller : 반환 값이 String이면 뷰 이름으로 인식된다. 그래서 뷰를 찾고 뷰가 렌더링 된다.
- @RestController : 반환 값이 HTTP message body에 입력된다. 따라서 실행결과를 메세지로 받을 수 있다.
method 단위 설정
@RequestMapping(“url”) : url 호출이 오면 해당 메서드가 실행된다. 또한 배열로 제공하여 다중 설정이 가능하다
- @RequestMapping({“url1”,”url2”)
- method 속성을 명시하지 않으면 모든 요청에 호출된다. @RequestMapping(value = “url”, method = mehtod)
- method를 지정하는 @GetMapping, @PostMapping, @PutMapping 등 사용이 가능하다.
- 특정 parameter나 headers, Content-Type, accpet에 대해 조건 매핑이 가능하다.
- @ReqeustMapping(value = “url”, params = “mode=debug”)
- @ReqeustMapping(value = “url”, headers = “mode=debug”)
- @ReqeustMapping(value = “url”, consumes = “application/json”)
- @ReqeustMapping(value = “url”, produce = “application/json”)
parameter 단위 설정
-
@PathVariable : URL 경로에 담긴 값을 변수에 담아 사용한다.
- ‘/board/{boardName}/{boardId}’를 아래와 같이 파라미터 변수에 담아 사용할 수 있다.
http://localhost:8080/board/free/110
@ResponseBody @RequestMapping(value = "/board/{boardName}/{boardId}", method = RequestMethod.GET) public String getBoardDetail(@PathVariable("boardName") String boardName, @PathVariable("boardId") Long boardId){ log.info("boardName = {}, boardId = {}", boardName, boardId); return "Success"; }
- 파라미터 값
- name : 바인딩할 파라미터의 이름.
- value : URL에 있는 특정값을 지정.
- required : 필수값 여부.
-
@RequestParam : URL에 담긴 Query String(key와 value)에 담긴 값을 파라미터 변수에 담아 사용한다.
http://localhost:8080/board/free?target=all&keyword=스프링
- ‘?target=all&keyword=스프링’을 아래와 같이 변수에 담아 사용할 수 있다.
@ResponseBody @RequestMapping(value = "/board/free", method = RequestMethod.GET) public String getBoardSearch(@RequestParam(value = "target", defaultValue = "all") String target, @RequestParam(value = "keyword", defaultValue = "") String keyword){ log.info("target = {}, keyword = {}", target, keyword); return "Success"; }
- 파라미터 값
- defauultValue : 값이 없을 떄 기본으로 전달할 값.
- name : 바인딩할 파라미터의 이름.
- value : URL에서 바인딩하여 별칭으로 정할 값.
- required : 필수적으로 값이 전달되어져야 하는 파라미터 여부.
5.스프링 Request JSON 데이터 받기
Board 클래스 추가
src -> main -> java -> com -> first -> entity -> Board.java
@Getter
@Setter
public class Board {
String title;
String content;
}
Servlet으로 받기
@Log4j2
@Controller
public class BoardController {
private ObjectMapper objectMapper = new ObjectMapper();
@RequestMapping(value = "/board/write", method = RequestMethod.POST)
public void writeBoard(HttpServletRequest request, HttpServletResponse response) throws IOException {
ServletInputStream inputStream = request.getInputStream();
String messageBody = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8);
log.info("messageBody = {}", messageBody);
Board board = objectMapper.readValue(messageBody, Board.class);
log.info("title = {}, content = {}", board.getTitle(), board.getContent());
response.getWriter().write("Success");
}
}
Servlet의 InputStream을 가져와서 UTF-8로 디코딩하여 메세지 바디의 내용을 뽑아오는 방식이다.
ObjectMapper
JSON 형식을 사용할 때, 응답들을 직렬화하고 요청들을 역직렬화 할 때 사용하는 기술이다.
objectMapper.readValue(messageBody, Board.class) -> messageBody를 Board객체로 파싱한다.
파싱(Parsing)이란?
웹페이지에서 원하는 데이터를 추출하여 가공하기 쉬운 상태로 바꾸는 것이다.
@RequestBody 사용
@ResponseBody
@RequestMapping(value = "/board/write", method = RequestMethod.POST)
public String writeBoard(@RequestBody String messageBody) throws IOException {
Board board = objectMapper.readValue(messageBody, Board.class);
log.info("title = {}, content = {}", board.getTitle(), board.getContent());
return "Success";
}
@RequestBody를 사용하여 앞선 방식에서 Servlet을 String으로 치환하는 과정을 제거할 수 있다.
또한 @ResponseBody를 사용하여 반환되는 HTTP message body에 직접 내용을 전달할 수 있게 된다.
@ReqeustBody 사용2
@ResponseBody
@RequestMapping(value = "/board/write", method = RequestMethod.POST)
public String writeBoard(@RequestBody Board board) {
log.info("title = {}, content = {}", board.getTitle(), board.getContent());
return "Success";
}
위에서 사용된 방식과 동일한거 같지만 @RequestBody를 사용하여 Board 객체에 직접 전달받아서 사용했다.
HTTPEntity, @RequestBody를 사용하면 HTTP 메세지 컨버터가 HTTP 메세지 바디의 내용을 우리가 원하는 문자나 객체로 변환해준다.
HttpEntity 사용
@ResponseBody
@RequestMapping(value = "/board/write", method = RequestMethod.POST)
public String writeBoard(HttpEntity<Board> httpEntity) {
Board board = httpEntity.getBody();
log.info("title = {}, content = {}", board.getTitle(), board.getContent());
return "Success";
}
@RequestBody와 같이 HttpEntity를 직접사용해서 사용할 수 있다.
6.스프링 Response 응답
Response 데이터를 만드는 방법
- 정적 리소스 : HTML, css, js 등 웹 브라우저에 정적인 데이터를 제공할 때
- 뷰 템플릿 사용 : 웹 브라우저에 동적인 데이터를 제공할 때
- HTTP 메세지 사용 : HTTP API를 제공하는 경우 HTTP 메세지 바디에 데이터를 제공할 때
정적 리소스
/static, /public, /resources. /META-INF/resources
스프링 부트는 위의 디렉토리에 있는 정적 리소스를 제공한다.
뷰 템플릿
src/main/resources/templates
뷰 템플릿은 JSP, Thymeleaf 등의 뷰 템플릿을 거쳐 HTML이 생성되고 뷰가 응답을 만들어서 전달하는 것인데 스프링 부트는 기본적으로 위의 디렉토리에 있는 경로로 제공한다.
HTTP 메세지 사용
HTTP API의 경우 메세지 바디에 데이터를 전달해야 하므로 주로 json 형식으로 데이터를 전달한다.
@Slf4j
@Controller
public class BoardController {
//text 반환
@RequestMapping(value = "/response-body-string-v1", method = RequestMethod.POST)
public void responseBodyV1(HttpServletResponse response) throws IOException {
response.getWriter().write("Success");
}
@RequestMapping(value = "/response-body-string-v2", method = RequestMethod.POST)
public ResponseEntity<String> responseBodyV2() throws IOException {
return new ResponseEntity<>("Success", HttpStatus.OK);
}
@ResponseBody
@RequestMapping(value = "/response-body-string-v3", method = RequestMethod.POST)
public String responseBodyV3() {
return "Success";
}
//json 방식
@RequestMapping(value = "/response-body-json-v1", method = RequestMethod.POST)
public ResponseEntity<Board> responseBodyJsonV1(){
Board board = new board();
board.setTitle("제목");
board.setContent("내용");
return new ResponseEntity<>(board, HttpStatus.OK);
}
@ResponseStatus(HttpStatus.OK)
@ResponseBody
@RequestMapping(value = "/response-body-json-v2", method = RequestMethod.POST)
public HelloData responseBodyJsonV2(){
Board board = new board();
board.setTitle("제목");
board.setContent("내용");
return board;
}
}
json 방식의 v1와 v2
response-body-json-v1
V1의 경우 ResponseEntity를 직접사용하여 사용자에게 데이터를 반환하는 방법이다. 이 방식의 장점은 ResponseEntity의 상태값을 설정할 수 있는 매개변수가 존재하여 client에게 하나의 응답 상태값이 아닌 exception이나 어떠한 validation 체크를 통해 개발자가 유연하게 상태값을 설정하여 보낼 수 있다.
response-body-json-v2
V2의 경우 @ResponseStatus를 통해 응답 상태값을 보낼순 있지만 고정되어 있는 상태값이 전달되어진다. 하지만 간단한 요청과 같단한 응답의 로직이라면 V2의 코드가 훨씬 간결하고 코딩하기 편하다.
5.참조
POST와 GET의 차이
HTTP GET,POST방식 차이
HTTP 요청 메서드
[용어 뜻/설명] HTTP Methods(HTTP-Verbs) - GET, POST, PUT, PATCH, DELETE란?
Spring request 요청
댓글남기기