본문 바로가기
Spring Boot

230216 Spring Boot Rest API

REST API (Representational State Transfer API)


REST API를 이용하면 서버 간 통신과 클라이언트 서버 통신이 가능하다.

+)스프링의 기존 데이터 처리 방식 : Handler Adapter
 
기존에 요청을 핸들링하는 단계에서 어노테이션 기반으로 데이터를 처리했다. 가능한 이유는 내부적으로 Argument Resolver가 동작하여 데이터를 맵핑하기 때문이다.
+) 스프링에서 값을 받는 방법 : HttpServletRequest, @RequestParam, @ModelAttribute, Model, VO 맵핑 등


스프링 메시지 컨버터


- HTTP 메시지 컨버터란, 요청본문에서 메시지를 읽어들이거나(@RequestBody), 응답 본문에 메시지를 작성할 때 @ResponseBody 를 사용하여 요청 브라우저로 응답을 바꾸는 장치이다.
- 뷰 템플릿으로 HTML로 응답하는게 아니라, 화면에서 처리할 JSON or 문자열 or xml 형태로 응답하는 기능이다. 스프링부트는 이런 메시지 컨버터에 특화되어있다.
- HTTP 요청 데이터 읽기 : HTTP 요청이 들어오고, 컨트롤러에서 @RequestBody 나 HttpEntity 파라미터를 사용
- HTTP 응답 데이터 생성 : 컨트롤러에서 @ResponseBody 나 HttpEntity로 값 반환
+) @RequestBody : json 객체로 넘어오는 데이터를 Java 객체로 맵핑 해준다.


@RestController : @Controller + @ResponseBody

- RequestMapping으로 들어오는 요청을 받아들이는 것은 동일하지만 return의 결과는 뷰리졸버가 아니라 요청한 화면으로 리턴된다.
- return에 처리하는 데이터를 조금 다른 타입으로 처리하는 형식이다. 즉, 객체(데이터)를 반환할 수도 있고 객체(데이터)를 받을 수도 있다.(JSON or XML 형식 이용)
- 객체를 보낼 수도 있다. 단, 자동으로 JSON형(XML형)으로 변환해주는 jackson-databind(xml-databind) 라이브러리가 반드시 필요하다.(스프링 부트는 기본으로 가지고 있으므로 따로 가져올 필요없다.)


+) 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형식으로 주고받도록 처리합니다.

 


REST API의 데이터 형식 제어

소비자(consumes) vs 제공자(produces)
1. consumers–보내는 데이터는 반드시 이 타입이어야 한다!
2. produces –제공하는 데이터는 이 타입이다!
ex) produces="application/json”, consumes="application/json”


확장 프로그램 설치-Boomerang

-확장 프로그램 설치(크롬)(시크릿 모드 안됨)


Boomerang - SOAP & REST Client
->설치 후 클릭 - 탭 생성(new request) - Request URL 입력


SimpleVO.java

더보기
package com.simple.basic.command;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class SimpleVO {
	private int num;
	private String id;
	private String name;
	
}

 

 

RestBasicController.java

더보기
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 {
	
	
	//ResponseBody는 return이 view Resolver가 아닌 요청이 들어온 곳으로 되돌아간다.
	
	//@Value("${값}")
	//String Server;
	
	@GetMapping(value="/getText", produces="text/plain")
	public String getText() {
		return "hello world";
	}
	
	//객체를 담게 되면 application/json 형식으로 반환하게 된다.
	/*
	 * produces - 보내는 데이터에 대한 타입 (생략 json)
	 * consumes - 받는 데이터에 대한 타입 (생략 json)
	 */
	@GetMapping(value="/getObject", produces="application/json")
	public SimpleVO getObject() {
		SimpleVO vo = new SimpleVO(1,"aaa123", "홍길동");
		return vo;
	}
	
	//맵형식의 반환
	@GetMapping("/getObject2")
	public Map<String, Object>getObject2(){
		Map<String, Object> map=new HashMap<>();
		SimpleVO vo = new SimpleVO(1,"aaa123", "홍길동");
		map.put("total", 100);
		map.put("data", vo);
		
		return map;
	}
	
	//리스트 형식의 반환
	@GetMapping("/getObject3")
	public List<SimpleVO> getObject3(){
		List<SimpleVO> list = new ArrayList<>();
		
		for(int i=1;i<=10;i++) {
			list.add(new SimpleVO(i,"aaa123"+i,"홍길동"+i));
		}
		return list;
	}
	
	//get형식 값을 받는방법1 - 쿼리스트링 ?키=값
	//http://localhost:8383/getKey?id=aaaa&name=홍길동
	@GetMapping("/getKey")
	public String getKey(@RequestParam("id")String id,@RequestParam("name")String name,@RequestParam("num")int num) {
		System.out.println(id);
		System.out.println(name);
		System.out.println(num);
		
		return "success";
	}
	
	//get형식 값을 받는방법2 - 쿼리파람 URL/키/키
	//http://localhost:8383/getPath/솔트/에이피아이키
	@GetMapping("getPath/{sort}/{apiKey}")
	public String getPath(@PathVariable("sort") String sort, @PathVariable("apiKey") String apiKey) {
		System.out.println(sort);
		System.out.println(apiKey);
		return "seccess";
	}
	
	
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	///////////////////////////////////////post형식의 처리
	
	//값을 받는 방법1 - post형은 VO로 맵핑
	//JSON형식의 데이터를 자바의 객체로 맵핑 ->@RequestBody
	//{"num":30,"id":"kier","name":"키에르"}
	
	//cors-기본적으로 서버가 다르면 요청을 거절하는데(특정 서버의 요청에 대하여 허용)
	//@CrossOrigin("*") or 필터를통한 자바설정
	 @CrossOrigin("http://localhost:3000")
	 @PostMapping("/getJson")
	 public String getJson(@RequestBody SimpleVO vo) {
		 System.out.println(vo.toString());
		 return "success"; 
	 }
	 

	
	//값을 받는 방법2 -Map으로 맵핑
	@PostMapping("/getMap")
	public String getMap(@RequestBody Map<String, Object> map) {
		System.out.println(map.toString());
		
		return "success";
	}
	
	//consumer를 통한 데이터제한
	//consumes = "application/json" => 상대측에서 꼭 json형식으로 보내야 함
	//consumes = "text/plain" 로 하면 String으로 받아야 함, 보낼 때는 TEXT문서로(보내는 데이터의 타입을 text로 맞춘다는 뜻).
	//->HEADERS에선 Name칸에 Content-Type, Value칸에 text/plain으로. 이걸 명시하면 어떤 문서든간에 text형식이 된다.
	//consumes는 특정타입의 데이터를 받도록 처리하는 옵션(기본값 json)
	//클라이언트에는 Content-type을 이용해서 보내는 데이터에 대한 타입을 명시(반드시 필수)
	@PostMapping(value="/getResult",consumes = "text/plain")
	public String getResult(@RequestBody String data) {
		System.out.println(data);
		return "success";
	}
	
	//응답문서의 형태를 직접선언 - ResponseEntity
	@PostMapping("/createRes")
	public ResponseEntity createRes() {
		SimpleVO vo = new SimpleVO(4,"daei12","데이");
		HttpHeaders header = new HttpHeaders();//헤더정보
		header.add("Authorization", "token");
		HttpStatus status=HttpStatus.ACCEPTED;//상태코드(성공 or 실패)
		
		//제네릭은 데이터를 따라갑니다.
		ResponseEntity<SimpleVO> entity=new ResponseEntity<>(vo, header, status);
		return entity;
	}
	

}

컨트롤러에 

@RestController //Controller + ResponseBody

를 반드시 줘야 한다.

 

 

 

...컨트롤러와 rest api...

 

서버를 키고 실행

 

@GetMapping(value="/getText", produces="text/plain")
	public String getText() {
		return "hello world";
	}

SEND버튼을 누르면 실행.

@GetMapping이므로 Get방식에서 실행해야 함.

ResponseBody는 return이 view Resolver가 아닌 요청이 들어온 곳으로 되돌아간다.


//객체를 담게 되면 application/json 형식으로 반환하게 된다.
/*
 * produces - 보내는 데이터에 대한 타입
 * consumes - 받는 데이터에 대한 타입
 */
@GetMapping(value="/getObject", produces="application/json")
public SimpleVO getObject() {
	SimpleVO vo = new SimpleVO(1,"aaa123", "홍길동");
	return vo;
}

객체를 담게 되면 application/json 형식으로 반환하게 된다.

 


맵형식의 반환

//맵형식의 반환
@GetMapping("/getObject2")
public Map<String, Object>getObject2(){
	Map<String, Object> map=new HashMap<>();
	SimpleVO vo = new SimpleVO(1,"aaa123", "홍길동");
	map.put("total", 100);
	map.put("data", vo);
	
	return map;
}


리스트 형식의 반환

//리스트 형식의 반환
@GetMapping("/getObject3")
public List<SimpleVO> getObject3(){
	List<SimpleVO> list = new ArrayList<>();
	
	for(int i=1;i<=10;i++) {
		list.add(new SimpleVO(i,"aaa123"+i,"홍길동"+i));
	}
	return list;
}


값 얻기

get방식


get형식1-쿼리스트링

//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";
}

콘솔출력문

aaaa
홍길동

 



get형식2-쿼리파람

//get형식 값을 받는방법2 - 쿼리파람 URL/키/키
//http://localhost:8383/getPath/솔트/에이피아이키
@GetMapping("getPath/{sort}/{apiKey}")
public String getPath(@PathVariable("sort") String sort, @PathVariable("apiKey") String apiKey) {
	System.out.println(sort);
	System.out.println(apiKey);
	return "seccess";
}

콘솔출력문

솔트
에이피아이키

post방식

-vo로 맵핑 or map으로 맵핑
-form형식과 json방식이 있다.

 

 

이때,

자바의 매개변수는 객체임.
JSON을 다 분해해서 자바의 Object로 맵핑해야 한다.
->
@RequestBody : JSON형식의 데이터를 자바의 객체로 맵핑한다.

 

 

 

post형식 vo로 맵핑(json방식)

//값을 받는 방법1 - post형은 VO로 맵핑
//JSON형식의 데이터를 자바의 객체로 맵핑 ->@RequestBody
//{"num":30,"id":"kier","name":"키에르"}

@PostMapping("/getJson")
public String getJson(@RequestBody SimpleVO vo) {
	System.out.println(vo.toString());
	
	return "success";
}

콘솔출력문

SimpleVO(num=30, id=kier, name=키에르)

 

post형식 vo로 맵핑(form형식)

@PostMapping("/getJson")
public String getJson(SimpleVO vo) {
	System.out.println(vo.toString());
	
	return "success";
}

form형식일 떄는 @RequestBody 어노테이션을 사용하지 않는다.

콘솔출력문

SimpleVO(num=11, id=starB22, name=스타)

post형식 map으로 맵핑(json방식)

 

//값을 받는 방법2 -Map으로 맵핑
@PostMapping("/getMap")
public String getMap(@RequestBody Map<String, Object> map) {
	System.out.println(map.toString());
	
	return "success";
}

콘솔출력문

{num=30, id=kier, name=키에르}

consumes를 통한 데이터제한

//consumer를 통한 데이터제한
//consumes = "application/json" => 상대측에서 꼭 json형식으로 보내야 함
//consumes = "text/plain" 로 하면 String으로 받아야 함, 보낼 때는 TEXT문서로(보내는 데이터의 타입을 text로 맞춘다는 뜻).
//->HEADERS에선 Name칸에 Content-Type, Value칸에 text/plain으로. 이걸 명시하면 어떤 문서든간에 text형식이 된다.
//consumes는 특정타입의 데이터를 받도록 처리하는 옵션(기본값 json)
//클라이언트에는 Content-type을 이용해서 보내는 데이터에 대한 타입을 명시(반드시 필수)
@PostMapping(value="/getResult",consumes = "text/plain")
public String getResult(@RequestBody String data) {
	System.out.println(data);
	return "success";
}

콘솔출력문

데이타입니다

 

 

 

HEADERS에서

를 하면 text형식으로만 보낼 수 있다. 

컨트롤러에서 받을 때 @RequestBody String 타입으로 받는다.

 

consumes는 특정타입의 데이터를 받도록 처리하는 옵션이다. 기본값은 JSON이다.

 

 

 

 

※서버와 클라이언트 둘 다 생략하면 기본 타입이 둘다 application/json”임.
양방향 통신이다. 둘 다 맞춰줘야 한다.

클라이언트의 content-type과 서버의 consumes가 짝,
클라이언트의 data-type과 서버의 produces가 짝
+)data-type은 코드에서만 있다.
post방식에선 무조건 맞춰야 한다.


응답문서의 형태를 직접선언 - ResponseEntity

안적어도 스프링이 자동으로 해줌. 명시를 위함.
generic타입은 무조건 데이터타입을 따라간다.

new ResponseEntity<>(데이터, 헤더, 상태코드);

 


 

//응답문서의 형태를 직접선언 - ResponseEntity
@PostMapping("/createRes")
public ResponseEntity createRes() {
	SimpleVO vo = new SimpleVO(4,"daei12","데이");
	HttpHeaders header = new HttpHeaders();//헤더정보
	header.add("Authorization", "token");
	HttpStatus status=HttpStatus.ACCEPTED;//상태코드(성공 or 실패)
	
	//제네릭은 데이터를 따라갑니다.
	ResponseEntity<SimpleVO> entity=new ResponseEntity<>(vo, header, status);
	return entity;
}

-반환이 ResponseEntity.

 

HttpHeaders, HttpStatus, ResponseEntity는 모두 springframework에서 import.