REST API란?
기존의 Controller는 return에 Model을 담아서 뷰에 전달하는 방식으로 사용했었는데,
REST API는 서버간 통신을 위한 Controller(클라이언트 서버 통신도 가능)이다
@RestController는 return에 처리하는 데이터를 조금 다른 타입으로 처리하는데, 객체(데이터)를 반환할 수 있고
객체(데이터)를 받을 수도 있게 처리한다
그러면 어떻게 보내고 어떻게 받는 건데요?
바로! JSON(JavaScript Object Notation)
핸들러 어댑터의 데이터 처리방식
기존에는 요청을 핸들링 하는 단계에서 어노테이션 기반으로 데이터를 처리했다
가능한 이유? 내부적으로 Argument Resolver가 동작하여 데이터를 맵핑하기 때문이다
스프링에서 값을 받는 방법은 무엇인가?
1️⃣ HttpServletRequest
2️⃣ @RequestParam
3️⃣ @ModelAttribute
4️⃣ VO맵핑
스프링 메시지 컨버터
👩💻 HTTP 메시지 컨버터란?
요청 본문에서 메시지를 읽어 들이거나(@RequestBody), 응답 본문에 메시지를 작성할 때(@ResponseBody) 사용하여 요청 브라우저로 응답을 바꾸는 장치이다
뷰 템플릿으로 HTML으로 응답하는 게 아니라, 화면에서 처리할 JSON or 문자열 or xml형태로 응답하는 기능이다
✅ 스프링 부트가 이러한 메시지 컨버터에 특화 되어있음!
HTTP 요청 데이터 읽기
HTTP 요청이 들어오게 되면 컨트롤러에서 @RequestBody나 HttpEntity 파라미터를 사용해서 데이터를 읽는다
HTTP 응답 데이터 생성
컨트롤러에서 @ResponseBody나 HttpEntity로 값 반환
@RequestController는 무엇인지 알고 있수?
@Controller ➕ @ResponseBody의 합성어
그래서 이게 어떤 역할을 하는데?
RequestMapping으로 들어오는 요청을 받아들이는 것은 동일하지만 return의 결과는 뷰리졸버가 아니라
요청한 화면으로 리턴된다
@RequestController를 사용할 때 필요한 기본 준비사항
객체를 보낼 수 있는데 단 자동으로 JSON형으로 변환해주는 Jackson-databind 라이브러리가 반드시 필요하다는 것!
( 다행히..스프링부트에서는 기본으로 라이브러리를 가지고 있다! 🥰 물론 스프링에서는 install 해야 한다 )
JSON(JavaScript Object Notation)은 자바스크립트 객체로 구성된 데이터로, 자바스크립트 객체 형태의 문자열인 셈으로
{ 키 : 값, 키 : 값, 키 : [ 배열 ] } 로 나타낸다
그렇다면 @RestController 기본 어노테이션에는 뭐가 있을까?
어노테이션 | 기능 |
@RestController | Controller가 rest방식임을 명시 |
@ResponseBody | 뷰리졸버로 전달하는 게 아니라 데이터를 요청한 화면으로 전달함을 명시 ( ✅ RestController에 이미 포함 ) |
@PathVariable | URL경로에 파라미터를 줄 수도 있으며, URL경로에 있는 값을 추출할 때 사용 |
@RequestBody | JSON 데이터를 자동으로 바인딩 처리 |
@RestController의 전송방식에는 어떤 게 있을까?
작업 | 전송방식 | URI |
등록 | POST | /reply/등록 |
조회 | GET | /reply/{id} |
수정 | PUT | /reply/{id} 제이슨 |
삭제 | DELETE | /reply/{id} |
✅ put과 delete는 post방식으로 대체 가능하다
✅ 다양한 전송방식은 URL주소에 위의 예시의 형식처럼 표기하는 것을 규칙으로 하지만 JSON형식으로 주고받도록 처리한다
데이터 형식을 제어하는 건 어떻게 하는가?
👩💻 Rest API의 데이터 형식 제어
소비자consumers) vs 제공자(produces)
1️⃣ consumers - "소비자 : 너네 데이터 보낼 때 이 타입으로 보내!" ( 들어오는 데이터 타입 제한 )
2️⃣ produces - "제공자 : 우리가 제공하는 데이터는 이 타입으로 보낼게"
기본 데이터 형식 (디폴트값)
consumes = "application/json"
proudces = "application/json"
확장 프로그램 설치해서 서버간의 통신(Rest API)을 확인해보려고 한다
1️⃣ 크롬 웹 스토어에서 rest만 검색해도 Boomerang이 나오는데 이걸 설치하면 된다
2️⃣ 클릭하고 들어와서 Chrome에 추가라는 버튼을 누르면 된다
3️⃣ 사용하기 위해서는 오른쪽 위에 있는 퍼즐 조각 모양을 클릭하면 다음과 같이 뜰 텐데,
이 때 설치된 부메랑을 누르면 사용이 가능하다
4️⃣ 다음과 같이 화면이 뜰 텐데, 서버간 통신을 진행할 것이기 때문에 HTTP request 버튼을 누른다
5️⃣ 서버를 켠 다음 실행을 시킨다
RestBasicController
@RestController //Controller + ResponseBody의 합성어
public class RestBasicController {
⭐ 기존의 controller와 restController를 구분하기 위해 반드시 다음과 같이 어노테이션을 주어야 한다
@GetMapping("/getText")
public String getText() {
return "hello world";
}
GetMapping이므로 get방식에서 실행해야 하고
header부분은 데이터의 타입을 알 수 있고 body부분은 데이터의 값을 알 수 있다
@ GetMapping
→ 👩💻 보내는 데이터의 타입에 따라 어떻게 다른지 확인해보자!
🔹객체를 담아서 보내는 경우
SimpleVO
package com.simple.basic.command;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class SimpleVO {
private int number;
private String name;
private String id;
}
RestBasicController
//객체를 담게 되면 application/json 형식으로 반환하게 됨
/*
* produces - 보내는 데이터에 대한 타입 (생략 가능)
* consumes - 받는 데이터에 대한 타입
*/
@GetMapping(value="/getObject", produces = "application/json")
public SimpleVO getObject() {
SimpleVO vo = new SimpleVO(123546, "홍길동", "1");
return vo ;
}
✅ 코드 해석 : /getObject라는 경로로 SimpleVO에 데이터 값을 세팅해서 JSON형식(produces)으로 보낼 거야
객체를 담게 되면 다음과 같이 application/json형식으로 반환된다
🔹map을 담아서 보내는 경우
//map형식의 반환 (map에 리스트도 담을 수 있음)
@GetMapping("/getObject2")
public Map<String, Object> getObject2(){
Map<String, Object> map = new HashMap<>();
SimpleVO vo = new SimpleVO(123546, "홍길동", "1");
map.put("total", 100);
map.put("data", vo);
return map;
}
✅ 코드 해석 : /getObject2라는 경로로 SimpleVO에 데이터 값을 세팅한 vo를 "data"라는 key값으로 새로 생성한 map에 담아서 보낼 거야 ("total"이라는 키값으로 100이라는 데이터를 보내는 것 보너스)
🔹List를 담아서 보내는 경우
//리스트 형식의 반환
@GetMapping("/getObject3")
public List<SimpleVO> getObject3(){
List<SimpleVO> list = new ArrayList<>();
for(int i = 1; i <= 10; i++) {
list.add(new SimpleVO(1235 + i, "홍순자" + i, "1"));
}
return list;
}
✅ 코드 해석 : /getObject3라는 경로로 SimpleVO에 데이터 값을 세팅해서 list에 담아서 보낼 거야
(list에 들어갈 simpleVO의 데이터는 반복문을 돌려서 총 10개의 데이터가 들어갈 거야)
Get형식에서 값을 얻는 방법
1️⃣ 쿼리스트링 ( key와 값 모두 경로에 노출 )
//get형식 값을 받는 방법1 - 쿼리스트링 ? 키=값
//http://localhost:8383/getKey?id=aaaa&name=홍길자
@GetMapping("/getKey")
public String getKey(@RequestParam("id") String id,
@RequestParam("name") String name) {
System.out.println(id);
System.out.println(name);
return "success";
}
쿼리 스트링의 경우 @RequestParam을 이용해서 값을 얻을 수 있다 (@PathVariable을 사용할 수 없음)
✅ 코드 해석 : 상대 서버에서 /getKey 라는 경로로 데이터를 실어서 보내면
(상대 서버는http://localhost:8383/getKey?id=aaaa&name=홍길자 )
각 key에 해당하는 값을 콘솔창에 출력해줘
2️⃣ 쿼리파람 ( 키만 경로에 노출 )
//get형식 값을 받는 방법2 - 쿼리파람 URL/키/키
@GetMapping("/getPath/{sort}/{apiKey}")
public String getPath(@PathVariable("sort") String sort,
@PathVariable("apiKey") String key) {
System.out.println(sort);
System.out.println(key);
return "success";
}
@PathVariable은 URL에 있는 값을 추출할 수 있는 기능을 갖고 있기 때문에 그 값을 사용할 이름을 지정하고
타입 값도 저장해주면 데이터를 이용할 수 있다 (쿼리스트링 외의 URL 값을 받아오는 어노테이션)
✅ 코드 해석 : 상대 서버에서 /getPath /{sort}/{apiKey}라는 경로로 데이터를 실어서 보내면,
각 key에 해당하는 값을 콘솔창에 출력해줘
Post형식에서 값을 얻는 방법
1️⃣ VO로 맵핑
🔹 Json방식
//값을 받는 방법1 - VO로 맵핑
//json형식의 데이터를 자바의 객체로 맵핑 -> @RequestBody
@PostMapping("/getJson")
public String getJson(@RequestBody SimpleVO vo) {
System.out.println(vo.toString());
return "success";
}
@RequestBody는 json형식의 데이터를 자바의 객체로 맵핑하는 기능을 지닌다
✅ 코드 해석 : /getJson의 경로에서 들어오는 데이터를 VO(객체)로 맵핑(@RequestBody)해서 데이터 출력해줘
🔹 Form방식
@PostMapping("/getJson")
public String getJson(SimpleVO vo) {
System.out.println(vo.toString());
return "success";
}
✅ 코드 해석 : /getJson의 경로에서 들어오는 데이터를 VO(객체)로 맵핑해서 데이터 출력해줘
⭐form형식으로 데이터를 보낼 때는 @RequestBody 어노테이션을 사용하지 않는다
2️⃣ Map형식
@PostMapping("/getMap")
public String getMap(@RequestBody Map<String, Object> map) {
System.out.println(map.toString());
return "success";
}
✅ 코드 해석 : /getMap의 경로에서 들어오는 데이터를 map형식으로 맵핑해서 데이터 출력해줘
json형식의 데이터를 보냈을 때 map형식으로 맵핑을 하면 다음과 같이 결과가 나온다
Consumes를 통한 데이터 제한
consumes는 특정타입의 데이터를 받도록 처리하는 옵션 ( 기본값 json )
예를 들어 consumes = "application/json" ➡️ 상대측에 반드시 json형식으로 보내야 함 ( 상대측도 json으로 받아야 함 )
반대로 consumes = "text/plain" ➡️ 상대측에 반드시 string으로 보내야 함 ( 상대측도 string으로 받아야 함 )
⭐ 클라이언트에는 Content-type을 이용해서 보내는 데이터에 대한 타입을 반드시 명시해야 한다
//consumer를 통한 데이터제한
//consumer는 특정타입의 데이터를 받도록 처리하는 옵션(기본값 json)
//클라이언트에는 Content-type을 이용해서 보내는 데이터에 대한 타입을 명시 (무조건 명시해야 함)
@PostMapping(value="/getResult", consumes = "text/plain")
public String getResult(@RequestBody String data) {
System.out.println(data);
return "success";
}
✅ 코드 해석 : /getResult의 경로에서 보내는(들어오는) 데이터는 텍스트 타입으로 보내고 받는 쪽(컨트롤러)에서도 데이터를 String 타입으로 받아야 한다 (양방향 통신이기 때문)
👩💻 총정리 Time
서버와 클라이언트 모두 content-type을 생략하게 되면 기본 타입이 "application/json"이다
서버와 클라이언트는 양방향 통신이기 때문에 서로 맞추어야 한다(일방적으로 데이터 타입을 정할 수 없음)
클라이언트의 content-type (보낼 데이터 타입) & 서버의 consumes (서버에서 받을 데이터 타입)
클라이언트의 data-type (받을데이터 타입) & 서버의 produces (서버에서 보낼 데이터 타입)
post방식에서는 반드시 양방향 모두 타입을 맞추어야 한다는 점을 명시해라!
응답문서의 형태를 직접 선언 - ResponseEntity ( 직접 작성하지 않아도 스프링이 자동으로 해줌 )
ResponseEntity란?
HttpEntity를 상속받는, 결과 데이터와 HTTP 상태 코드를 직접 제어할 수 있는 클래스이다
( 즉, HttpStatus, HttpHeaders, HttpBody를 포함하고 있는 구조이다 )
new ResponseEntity <> (데이터, 헤더, 상태코드);
//응답문서의 형태를 직접 선언 - ResponseEntity
@PostMapping("/createRes")
public ResponseEntity createRes() {
SimpleVO vo = new SimpleVO(1234, "황길순", "1"); //데이터
HttpHeaders header = new HttpHeaders(); //헤더정보
header.add("Authroization", "token");
HttpStatus status = HttpStatus.ACCEPTED; //상태코드(성공 or 실패)
//제네릭은 데이터를 따라간다
new ResponseEntity<>(vo, header, status);
ResponseEntity<SimpleVO> entity = new ResponseEntity<>(vo, header, status);
return entity;
}
'SpringBoot' 카테고리의 다른 글
[SpringBoot] 제이쿼리 환경설정 및 문법 ( ajax 통신, 이벤트 함수 등 ) (0) | 2023.02.17 |
---|---|
[SpringBoot] 유효성 검사(Validation) (0) | 2023.02.16 |
[SpringBoot] 판매자 관리 페이지 프로젝트(실습) - 공통 부분 템플릿화 하기, 상품 등록 기능 구현 (0) | 2023.02.15 |
[SpringBoot] 타임리프 문법의 모든 것(변수, 출력문, 조건문, 반복문, include, 내장함수 등)과 실습 (0) | 2023.02.13 |