Flaming Soccer ball
SPRING BOOT

100일차 REST API

leo lee 2023. 2. 22.
반응형

 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)의 개념

→ 참고 블로그

https://inpa.tistory.com/entry/WEB-%F0%9F%93%9A-CORS-%F0%9F%92%AF-%EC%A0%95%EB%A6%AC-%ED%95%B4%EA%B2%B0-%EB%B0%A9%EB%B2%95-%F0%9F%91%8F

반응형

댓글