✶ REST API (REpresentational State Transfer API)
REST API를 이용하면 서버 간 통신과 클라이언트 서버 통신이 가능하다.
*스프링의 기존 데이터 처리 방식 : Handler Adapter
기존에 요청을 핸들링하는 단계에서 어노테이션 기반으로 데이터를 처리했다. 가능한 이유는 내부적으로 Argument Resolver가 동작하여 데이터를 맵핑하기 때문이다.
Cf.) 스프링에서 값을 받는 방법 : HttpServletRequest, @RequestParam, @ModelAttribute, Model, VO 맵핑 등
*스프링 메시지 컨버터
- HTTP 메시지 컨버터란, 요청본문에서 메시지를 읽어들이거나(@RequestBody), 응답 본문에 메시지를 작성할 때 @ResponseBody 를 사용하여 요청 브라우저로 응답을 바꾸는 장치이다.
- 뷰 템플릿으로 HTML로 응답하는게 아니라, 화면에서 처리할 JSON or 문자열 or xml 형태로 응답하는 기능이다. 스프링부트는 이런 메시지 컨버터에 특화되어있다.
- HTTP 요청 데이터 읽기 : HTTP 요청이 들어오고, 컨트롤러에서 @RequestBody 나 HttpEntity 파라미터를 사용
- HTTP 응답 데이터 생성 : 컨트롤러에서 @ResponseBody 나 HttpEntity로 값 반환
Cf.) @RequestBody : json 객체로 넘어오는 데이터를 Java 객체로 맵핑 해준다.
*@RestController : @Controller + @ResponseBody
- RequestMapping으로 들어오는 요청을 받아들이는 것은 동일하지만 return의 결과는 뷰리졸버가 아니라 요청한 화면으로 리턴된다.
- return에 처리하는 데이터를 조금 다른 타입으로 처리하는 형식이다. 즉, 객체(데이터)를 반환할 수도 있고 객체(데이터)를 받을 수도 있다.(JSON or XML 형식 이용)
- 객체를 보낼 수도 있다. 단, 자동으로 JSON형(XML형)으로 변환해주는 jackson-databind(xml-databind) 라이브러리가 반드시 필요하다.(스프링 부트는 기본으로 가지고 있으므로 따로 가져올 필요없다.)
Cf.) JSON(JavaScript Object Notation)
- 자바스크립트 객체로 구성된 데이터이다. 자바스크립트 객체 형태의 문자열인 셈이다.
- 형식 : {키: 값, 키: 값, 키: [배열] }
*기본 어노테이션
- @RestController : Controller가 REST 방식임을 명시
- @ResponseBody : 뷰 리졸버로 전달하는게 아니라 데이터를 요청한 화면으로 전달함을 명시
- @PathVariable : URL 경로에 파라미터를 줄 수도 있으며, URL 경로에 있는 값을 추출할 때 사용
- @RequestBody : JSON 데이터를 자동으로 바인딩 처리
*@RestController 전송 방식
작업 | 전송방식 | URI |
등록 | POST | /reply/등록 |
조회 | GET | /reply/{id} |
수정 | PUT | /reply/{id}제이슨 |
삭제 | DELETE | /reply/{id} |
다양한 전송방식은 URL 주소에 다음과 같은 형식으로 표기하는 것을 규칙으로 하지만 JSON 형식으로 주고받도록 처리한다.
*주고 받는 데이터 형식(서버측 기준)
- 보내는 형식 : produces(server) - Data-Type(client)
- 받는 형식 : consumes(server) - Content-Type(client)
*REST API의 데이터 형식 제어(생략 가능 - default: application/json)
소비자(consumes) vs 제공자(produces)
(Ex> produces="application/json”, consumes="application/json”)
1. consumes : 서버측에서 특정 타입의 데이터를 받도록 처리하는 옵션(기본값 : json)
- 클라이언트 측에서는 Content-Type 을 이용하여 클라이언트 측에서 보내는 데이터에 대한 타입을 명시
- Content-Type : Client 가 보내는 데이터 타입
2. produces : 서버측에서 제공하는 데이터의 타입 정의
- Accept Header가 produces에 명시한 Media Type 과 같을 때, 해당 타입으로 response를 보내준다.
- Accept : client가 backend 서버에 어떤 형식(Media Type)으로 달라고 하는 요청 방식
*html form 태그를 사용하여 post 방식으로 요청하거나
JQuery의 ajax 등의 요청을 할 때, default Content-Type은 "application/json"이 아니라 "application/x-www-form-urlencoded'이다.
*확장 프로그램 설치(크롬)(시크릿 모드 안됨)
Boomerang - SOAP & REST Client
→ 설치 후 클릭 - 탭 생성(new request) - Request URL 입력
*값을 보내는 법
Return 에 보낼 값을 담아준다.
*값을 받는 법
1. GET 형식으로 값 받는 법
(1) 쿼리 스트링 : ?키=값&키=값
주소를 send 할 때, 쿼리 스트링 형식으로 값을 보낸다.
Ex> http://localhost:8080/getKey?id=tempID&name=tempName
(2) 쿼리 파라미터 : URL/키/키
주소를 send 할 때, 쿼리 파람 형식으로 값을 보낸다.
Ex> http://localhost:8080/getPath/article/tempKey
2. POST 형식으로 값 받는 법
URL에 데이터가 실리지 않고 BODY 에 데이터가 실려온다.
→ 값을 넘겨줄 때 참조되는 vo 내 멤버변수의 1번째, 2번째 문자는 소문자여야 한다.
(1) VO 맵핑
(2) Map 맵핑
*특정 헤더를 갖고 있는 경우 데이터를 받지 않도록 제약조건을 걸어줄 수 도 있다.
✶ 코딩 실습
< Controller >
package com.simple.basic.controller;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.simple.basic.command.SimpleVO;
@RestController //@Controller + @ResponseBody
public class RestBasicController {
/*
* 1. ResponseBody는 return 값이 뷰 리졸버가 아니고, 요청이 들어온 곳으로 반환된다.
*/
@GetMapping("/getTest")
public String getTest() {
return "Hello, World!";
}
//객체를 담게 되면 application/json 형식으로 반환한다.
// @GetMapping(value="/getObject", produces="text/plain") //보내는 형식이 json 이므로 에러 발생
@GetMapping(value="/getObject", produces="application/json")
public SimpleVO getObject() {
SimpleVO vo = new SimpleVO(3, "김일번", "abc123");
return vo;
}
//맵형식의 반환
@GetMapping("/getObject2")
public Map<String, Object> getObject2() {
Map<String, Object> map = new HashMap<>();
SimpleVO vo = new SimpleVO(3, "김이번", "bcd234");
map.put("total", 100);
map.put("data", vo);
return map;
}
//리스트 형식의 반환
@GetMapping("/getObject3")
public List<SimpleVO> getObject3() {
List<SimpleVO> list = new ArrayList<>();
SimpleVO vo1 = new SimpleVO(1, "김일번", "abc123");
SimpleVO vo2 = new SimpleVO(2, "김이번", "bcd234");
SimpleVO vo3 = new SimpleVO(3, "김삼번", "cde345");
list.add(vo2);
list.add(vo1);
list.add(vo3);
return list;
}
//GET 형식 값 받는 법1 - 쿼리 스트링
@GetMapping("/getKey")
//http://localhost:8080/getKey?id=tempID&name=tempName
public String getKey(@RequestParam("id") String id,
@RequestParam("name") String name) {
System.out.println(id);
System.out.println(name);
return "success";
}
//GET 형식 값 받는 법2 - 쿼리 파라미터
@GetMapping("/getPath/{sort}/{APIKEY}")
//http://localhost:8080/getPath/article/tempKey
public String getPath(@PathVariable("sort") String sort,
@PathVariable("APIKEY") String key) {
System.out.println(sort);
System.out.println(key);
return "success!";
}
//POST 형식 값 받는 법1 - VO로 맵핑
@PostMapping("getJson")
@CrossOrigin("http://localhost:3000") //3000번 포트에서의 요청을 허용
public String getJson(@RequestBody SimpleVO vo) {
System.out.println("Enter getJson!");
System.out.println(vo);
return "success~";
}
//POST 형식 값 받는 법2 - Map으로 맵핑
@PostMapping("getMap")
public String getMap(@RequestBody Map<String, Object> map) {
System.out.println(map);
return "success#";
}
//consumer를 통한 받는 데이터 제한
@PostMapping(value = "getResult", consumes = "text/plain")
// @PostMapping(value = "getResult") //consumes 생략하면 default는 JSON
public String getResult(@RequestBody SimpleVO vo) {
System.out.println(vo);
return "success%";
}
//응답문서의 형태를 직접 선언 - ResponseEntity
@PostMapping("/createRes")
public ResponseEntity createRes() {
SimpleVO vo = new SimpleVO(1, "abc123", "김일번"); //데이터
HttpHeaders header = new HttpHeaders(); //헤더
header.add("Authorization", "tempToken");
HttpStatus status = HttpStatus.ACCEPTED; //상태 코드(성공or실패)
ResponseEntity<SimpleVO> entity = new ResponseEntity<>(vo, header, status);
System.out.println(entity);
return entity;
}
@PostMapping("/getAjax")
@CrossOrigin({"http://127.0.0.1:5500",
"http://localhost:5500"})
public Map<String, Object> getAjax(@RequestBody SimpleVO vo){
//받을 데이터
System.out.println(vo);
//보내는 데이터
Map<String, Object> map = new HashMap<>();
SimpleVO vo2 =new SimpleVO(1, "abc123", "김일번");
map.put("total", 100);
map.put("data", vo2);
return map;
}
}
< 값 리턴에 실어 보내기 >
String
객체 - VO
json - body
json - headers
map
list
< 값 client 측에서 받아오기 >
get - 1
get - 2
post - form
post - json
post - map
consumes - success (consumes default : application/json)
consumes - fail (text/plain 으로 지정했지만 json 형식으로 왔기 때문)
ResponseEntity - body
ResponseEntity - headers : 특정 헤더를 추가해주는 것이 가능
특정 header 값 포함 시, 데이터를 받지 않도록 설정
header 제한 (성공 케이스)
CrossOrigin_react
CrossOrigin with react server
*Spring Security와JWT
API 서버 개발자라면 알아야 하는 preflight와 cors(Cross origin resources sharing)의 개념
→ 참고 블로그
'SPRING BOOT' 카테고리의 다른 글
102일차 판매자 전용 페이지 구현 실습 (0) | 2023.02.22 |
---|---|
101일차 JQUERY (0) | 2023.02.22 |
99일차 Spring Boot 판매자 페이지 구현 실습 (1) | 2023.02.22 |
98일차 Spring Boot DB 연결 (0) | 2023.02.15 |
98일차 Spring Boot Validation (0) | 2023.02.15 |
댓글