Notice
Recent Posts
Recent Comments
Link
«   2025/07   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31
Tags
more
Archives
Today
Total
관리 메뉴

dearbeany

[REST] REST API @Annotation별 실습 본문

Spring

[REST] REST API @Annotation별 실습

dearbeany 2022. 10. 24. 16:29
더보기

REST API
- HTTP: 통신규약. (이러한 방식으로 쓰겠다~)

구성
자원 :URI (URL과는 엄밀히 다르나 추후에 알아볼 것 ) uri (- url - urn)
행위 : 어떤 방식으로 들어오겠다
표현
=> URI와 GET/POST/PUT/DELETE를 사용해서 표현할 수 있다.

기존의 웹 접근 방식과의 차이점
CRUD(생성, 조회, 수정, 삭제) -> 기본 기능
기존의 방식은 /board아래에 write요청을 POST로 보냈다. 왜 POST로 보냈나? 데이터 길이의 제한, 보안, 자료 수정 주로 자료수정하거나 감추고 싶을 때 POST사용했기 때문이다.
cf. GET은 자료읽어올 때 사용  ex)Read
?id=2 쿼리스트링은 Key-Value 쌍으로 날린다.

기존의 방식은 board의 기능을 수행하려할 때?
- write/detail/update/delete와 같은 부가적인 기능을 보내야만 했다. 
- GET과 POST만으로 자원에 대한 CRUD를 처리하며, URI는 액션을 나타냄.

REST로 변경하면?
- URI엔 실제로 필요한 자원을 심어서 쓰고, HTTP 메소드(POST, GET, PUT, DELETE)라는 걸 적극적으로 활용하여 명확,심플하게 작성하겠다.

API란?
- 두 SW요소들이 서로 통신할 수 있게 하는 방식 
- Application Progamming Interface (인터페이스=설계도)
- api통해서(유투브, 카카오, 공공데이터포털..) 데이터들을 받아다 쓸 수 있다.
(1) 데이터 달라고 요청을 먼저 날린다
(2) 자격을 갖춰야만 받을 수 있다 ex) 로그인, 키발급 등

 
REST API
- 기존 전송방식과 달리 서버는 요청으로 받은 리소스에 대해 순수한 데이터를 전송한다
- URI에 제어할 자원을 명시. HTTP METHOD를 통해서 자원을 제어한다.
- 단 표준이 없어서 암묵적인 표준만 정해져있음
- 언더바(_), 대문자, 확장자 포함된 파일이름 사용하지X


인터넷의 발전
(1) 정적페이지 (html, css, js)
(2) 동적페이지(Dynamic Web), 실시간 정보 -> Ajax통신
But.. 아직도 페이지가 여러 개다
(3) SPA 등장
하나의 페이지에 필요한 부품(=Component)만 갈아끼워서 사용하자 -> SPA(Single Page Application) 다음주 Vue.js 프레임워크사용해서 만든다.
페이지는  index.jsp하나뿐인데 부품을 실어서 사용하겠다.
(4) 반응형웹
이제부터 다양한 기기(스마트폰, 노트북, 태블릿..)에서 서버에 요청을 보내기 시작했다.
기기에 따라 화면이 만들어지는 것 -> 반응형웹.
서버는 데이터만 주도록 한다. 기기에 따른 화면은 프론트엔드에서 만들자.
(5) 스프링을 이용해서 REST하게 만들어서 데이터만 주도록 보내고 Vue.js가 받아서 화면을 그리도록 해준다.
- 데이터의 형식은? Json으로 주고 받도록 한다.


기존 Service vs REST API Service
- 기존 : 요청에 대한 처리 하고, 데이터 가공해서 View를 직접 만들었다. (ex. jsp 를 직접 만들었었다)
- REST : 데이터 처리만 한다거나, 처리 후 반환될 데이터 있으면 JSON, XML형식으로 전달. view에 대해 신경쓸 필요가 없으므로 Open API에서 사용.(화면을 만드는 게 아니라 데이터만 주면되니까!)

RESTful : Rest API로 구축된 웹서비스
서버에게 Request : URI, GET/POST/PUT/DELET 을 보내면
서버는 Response로 JSON, XML을 보내준다.

 

먼저 테스팅을 위한 환경을 설치해보자!

- Rest Client 설치 - 크롬 웹스토어 Talend API / POST Man

- 서버에서 요청을 보낼 때 별도의 프론트 단을 만들지 않고도 해당 url로 요청을 보낼 수 있게 도와주는 도구

cf) 요청을 보내는 것은 브라우저를 사용해서도 가능함

 

실습의 순서는 다음과 같다.

(1) @Controller + @ResponseBody
(2) @RestController
(3) @PathVariable
(4) @RequestBody
(5) @ResponseEntity

 

1. @Controller + @ResponseBody 사용 

@Controller
@RequestMapping("/rest1")
public class TestController1 {
..
http://localhost:8080/mvc/rest1/test1
	@GetMapping("/test1")
	public String test1() {
		return "hi rest";
	}​

 

- 결과 : 404 에러  (위 예시는 REST가 아니다!)

- DispatcherServlet이 경로 완성 >  /WEB-INF/views/hi rest.jsp > 해당 페이지 찾을 수 없음 > 404

- 그렇다면? @ResponseBody 를 사용해보자!

@ResponseBody : JSP 같은 뷰로 전달되는 게 아닌 데이터를 전달

 

 

 

 

 

 

 

http://localhost:8080/mvc/rest1/test2
	@GetMapping("/test2")
	@ResponseBody
	public String test2() {
		return "hi rest";
	}​

 

- @ResponseBody를 붙이는 순간 JSP 화면 같은 것이 아니라 반환값 그 자체를 데이터로 넘겨준다!

 

 

 

 

 

 

http://localhost:8080/mvc/rest1/test3
	@GetMapping("/test3")
	@ResponseBody
	public Map<String, String> test3() {
		Map<String, String> data = new HashMap<String, String>();
		data.put("id", "ssafy");
		data.put("name", "이수빈");
		data.put("password", "1234");
		return data;
	}​

- 결과 : 406 에러 

- 데이터를 넘길 땐 주로 JSON 형식으로 보내는데, return data 할 때 JSON을 처리해주지 않고 반환값을 데이터 그 자체로 보냈다.
- 데이터 형태를 알아서 json형태로 바꿔주는 jackson을 추가해서 해결하자.

 

https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind/2.13.3

<!-- pom.xml -->
		<dependency>
		    <groupId>com.fasterxml.jackson.core</groupId>
		    <artifactId>jackson-databind</artifactId>
		    <version>2.13.3</version>
		</dependency>

 

 

 

http://localhost:8080/mvc/rest1/test4
	@GetMapping("/test4")
	@ResponseBody
	public Member test4() {
		Member m = new Member();
		m.setId("ssafy");
		m.setName("이수비인");
		m.setPassword("1234");
		return m;
	}​

DTO로 반환하기

 

- 데이터를 바구니(DTO)에 담아서 반환해도 json 형태로 잘 반환된다

 

 

 

 

 

 

http://localhost:8080/mvc/rest1/test5
	@GetMapping("/test5")
	@ResponseBody
	public List<Member> test5() {
		List<Member> list = new ArrayList<>();
		for (int i = 0; i < 5; i++) {
			Member m = new Member();
			m.setId("ssafy");
			m.setName("이수비인");
			m.setPassword("1234");
			list.add(m);
		}
		return list;
	}​

리스트로 반환하기

 

 

 

2. @RestController

@RestController
@RequestMapping("/rest2")
public class TestController2 {
..

- @Responsebody 안 붙이면? viewResolver에게 화면 갖다 달라고 요청한다.
- @Responsebody 붙이면? 데이터 그 자체를 반환한다.
- @Restcontroller = @Controller + @ResponseBody 역할을 동시에 한다!

- 따라서 컨트롤러 클래스에 @Restcontroller만 달아주면, 메소드에 일일히 @ResponseBody 안 달아도 됨

 

@RestController : Controller가 REST방식을 처리하기 위한 것임을 명시

 

 

 

 

3. @PathVarable 

http://localhost:8080/rest4/board/1
http://localhost:8080/rest4/board/2
http://localhost:8080/rest4/board/999

... 
등등 board/숫자 모든 요청에 대한 페이지를 다 만들 수 없다. 
→ RESTful하게 작성하기 위해서 uri 자체가 자원이니까 그걸 가져다 쓰면 된다!

@PathVariable : URL경로에 있는 값을 파라미터로 추출

 

http://localhost:8080/mvc/rest4/board/2
	// 쿼리스트링으로 키값인 id가 있으면 그 값을 넣겠다
	@GetMapping("/board/{id}")
	public String test1(@PathVariable() int id) {
		return "PathVariable : " + id;
	}

	// 만약 이름이 다를 경우? 매핑을 해주자
	@GetMapping("/board/{id}")
	public String test1(@PathVariable("id") int no) {
		return "PathVariable : " + no;
	}​

 

 

 

 

4. @ResquestBody 

	@PostMapping("/test2")
	public String test2(Member m) {
		return m.toString();
	}

- Member 바구니에 알아서 매칭되려면 <form>태그에서 name속성의 값과 일치해야 한다.

- 위 예시는 데이터를 'application/x-www-form-urlencoded' 방식으로 보낸다

- 그렇다면 데이터를 <form>태그 이용해서 아니라,  json 형식으로 보내려고 하면? @RequestBody 를 사용하자!

 

	@PostMapping("/test3")
	public String test3(@RequestBody Member m) {
		return m.toString();
	}
@RequestBody : JSON 데이터를 원하는 타입으로 바인딩

 

 

 

 

4. @ResponseEntity 

- Talend에서 응답은 세가지 영역 ①응답 코드(status) ②응답 헤더 ③응답데이터로 넘어온다.

- @ResponseEntity : 응답하려는 데이터 + 응답코드 + 응답헤더 조작까지 가능하다.
- 즉, @ResponseEntity를 사용하여 각각의 상태를 보다 세밀하게 손을 댈 수 있다.
- ResponseEntity<T> : T는 Body에 들어갈 데이터 타입

	@GetMapping("/test4")
	public ResponseEntity<String> test4() {
		HttpHeaders headers = new HttpHeaders();
		headers.add("auth", "admin");

		return new ResponseEntity<String>("OK", headers, HttpStatus.OK);
	}