본문 바로가기

Spring

ch4 09. REST API Ajax

1. JSON이란?

- Java Script Object Notation - 자바 스크립트 객체 표기법

{속성명1: 속성값1, 속성명2: 속성값2, ... }

[{속성명:속성값,... } {속성명:속성값,...},...] // 객체 배열

{키1:{속성명:속성값,... }, 키2:{속성명:속성값,... },...} // Map

 

 

2. stringify()와 parse()

- JS객체를 서버로 전송하려면, 직렬화(문자열로 변환)가 필요

HTTP가 Text 기반 프로토콜로 요청 및 응답을 수행하므로, JS객체를 문자로 바꿔야 한다. 

JSON.stringify() - 객체를 JSON 문자열로 변환(직렬화, JS객체 -> 문자열)

 

 - 서버가 보낸 데이터(JSON문자열)를 JS객체로 변환할 때, 역직렬화가 필요

텍스트를 가지고 객체를 먼저 만들고, 그 값을 채우면 된다. 

JSON.parse() - JSON 문자열객체로 변환(역직렬화, 문자열 -> JS객체)

이런식으로 객체의 동적 생성 및 변경 가능 

이 객체를 문자열화 해서 저장.

parse 메서드를 사용해서 다시 객체로 변환

 

3. Ajax란?

- Asynshronous javascript and XML - 요즘은 JSON을 주로 사용

- 비동기 통신으로 데이터를 주고 받기 위한 기술

- 웹페이지 전체(data+UI)가 아닌 일부(data)만 업데이트 가능

 

ex) 주식사이트 그래프 같은 경우 전체 응답보다는 데이터만 JSON으로 받아서 그 부분만 갱신. 

주고받을 데이터 양도 적어지고, 갱신한 것도 더 빠르게 처리 가능

ex) 게시판 댓글 달 때 댓글 바뀌었다고 화면 전체를 가져오지 않고, 바뀐 댓글만 가져와서 보여준다. 

 

* 비동기 vs 동기

기본적으로 동기이지만, 비동기로 해서 효율을 높이려고 한다. 

- 동기 : 요청(호출)하면 서버가 처리하고 응답이 올 때까지 기다림. 메서드 호출하면, 메서드가 결과줄때까지 기다리는 것.

응답이 와야 수행 가능

- 비동기 : 요청해놓고 응답까지 기다리지 않아도 된다. 요청해놓고 다른 일 수행 가능.

처리가 끝난 걸 알기 위해 callback 함수 사용. 

 

 

4. jQuey를 이용한 Ajax

$(document).ready(function() {
	let person = {name:"abc", age:10}; // 객체 생성
    	let person2 = {}; // 빈 객체 
    
    $("#sendBtn").click(function() {
    $.ajax({ // 비동기 호출
    	type:'POST', // 요청 메서드
        url: '/ch4/send', // 요청 URI
        headers : {"content-type": "application/json"}, // 요청 헤더
        dataType : 'text', // 전송할 데이터의 타입
        data : JSON.stringify(person), // 서버로 전송할 데이터, stringify()로 직렬화 필요.
        success : function(result) {person2 = JSON.parse(result); // 서버로부터 응답이 도착하면 호출될 함수
        							alert(result);	}, // result는 서버가 전송한 데이터
        error : function() {alert("error")} // 에러가 발생했을 때, 호출될 함수
        }); // $.ajax()
        
        alert("the request is sent")
	});
});

콜백함수- 성공하면 success 호출, 실패하면 error 호출

요청해놓고 바로 다음으로 가서 응답이 안와도 alert문장으로 넘어간다. 그 다음 서버로부터 응답을 받는다.

 

 

<실습>

- SimpleRestController, Person 클래스, ajax.jsp 생성

SimpleRestController

 

[Person]

package com.fastcampus.ch4.domain;

public class Person {
    private String name;
    private int age;
    
    public Person() {}
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

[ajax.jsp]

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
  <title>Title</title>
  <script src="https://code.jquery.com/jquery-1.11.3.js"></script>
</head>
<body>
<h2>{name:"abc", age:10}</h2>
<button id="sendBtn" type="button">SEND</button>
<h2>Data From Server :</h2>
<div id="data"></div>
<script>
  $(document).ready(function(){
    let person = {name:"abc", age:10};
    let person2 = {};
    $("#sendBtn").click(function(){
      $.ajax({
        type:'POST',       // 요청 메서드
        url: '/ch4/send',  // 요청 URI
        headers : { "content-type": "application/json"}, // 요청 헤더
        dataType : 'text', // 전송받을 데이터의 타입
        data : JSON.stringify(person),  // 서버로 전송할 데이터. stringify()로 직렬화 필요.
        success : function(result){
          person2 = JSON.parse(result);    // 서버로부터 응답이 도착하면 호출될 함수
          alert("received="+result);       // result는 서버가 전송한 데이터
          $("#data").html("name="+person2.name+", age="+person2.age);
        },
        error   : function(){ alert("error") } // 에러가 발생했을 때, 호출될 함수
      }); // $.ajax()
      alert("the request is sent")
    });
  });
</script>
</body>
</html>

pom.xml 파일에 추가한다. 

데이터를 보내고 서버에게 받은 데이터가 표시되는걸 볼 수 있다. 

 

 

5. Ajax요청과 응답 과정

서버에 전송하기 위해 메모리에 있는 객체 {name:"abc", age:30} -> (JSON>stringift) -> '{"name":"abc","age":30}'문자열로

바꿔서 전송한다. 이 요청을 /send POST로 보내면, 서버가 '{"name":"abc","age":30}'를 받고 jackson-databind(라이브러리)가 이 문자열을 Java 객체로 변환해서  매개변수로 넘겨준다. 

컨트롤러에서 이걸 받아서 출력하고, 객체를 "ABC", 40으로 바꾸고 리턴한다. 

응답을 위해 jackson-databind가 자바 객체를 문자열 '{"name":"ABC","age":40}'로 바꿔서 전송하면 

클라이언트가 이걸 받고, JSON.parse() 메서드를 이용해서 자바 스크립트(JS) 객체로 문자열을 변환한다. 

 

이 때 무조건 되는게 아니라 @RequestBody, @ResponseBody가 있어야한다.

@RequestBody는 바디에 있는걸 자바 객체로 바꿔주는 것이다. 

응답 할때도 마찬가지로 @ResponseBody로 내용을 응답의 바디로 보내서 바꿔주는 일을 한다. 

뷰 이름이 아니라 객체를 반환한다.

 

 

6. RestController

- @ResponseBody대신 클래스에 @RestController 사용 가능

@Controller
public class SimpleRestController {
	@PostMapping("/send")
    @ResponseBody public Person test(@RequestBody Person p) {
    	System.out.println("p = " + p);
        p.setName("ABC");
        p.setAge(p.getAge() + 10);
        
        return p;
    }
}

객체를 반환할 때 JSON으로 변환해주는데 그럴 때 쓰는게 @ResponseBody이다. 

이런 메서드가 여러 개 있으면, 메서드마다 @ResponseBody를 계속 붙여줘야 한다. 

 

그래서 클래서 앞에 @Controller대신 @RestController 애너테이션을 붙이고, 원래는 @ResponseBody를

메서드 앞에 붙여야하지만 이걸 생략할 수 있도록 하게 한다. 

@RestController
public class SimpleRestController {
	@PostMapping("/send")
    public Person test(@RequestBody Person p) {
    	System.out.println("p = " + p);
        p.setName("ABC");
        p.setAge(p.getAge() + 10);
        
        return p; // 객체 반환
    } 
}

 

 

 

7. REST란?

- Roy Fielding이 제안한 웹서비스 디자인 아키텍쳐 접근 방식 

- 프로토콜에 독립적이며, 주로 HTTP를 사용해서 구현

- *리소스 중심의 API 디자인 - HTTP 메서드로 수행할 작업을 정의

리소스 POST GET PUT DELETE
/customers 새 고객 만들기 모든 고객 검색 고객 대량 업데이트 모든 고객 제거
/customers/1 Error 고객 1에 대한 세부 
정보 검색
고객 1이 있는 경우
고객 1의 세부 정보
업데이트
고객 1 제거
/customers/1/orders 고객 1에 대한 새 주문
만들기
고객 1에 대한 모든 
주문 검색
고객 1의 주문 대량
업데이트
고객 1의 모든 주문 제거

[출처] http://docs.microsoft.com/ko-kr/azure/architecture/best-practices/api-design 

 

웹 API 디자인 모범 사례 - Azure Architecture Center

플랫폼 독립성과 서비스 진화를 지원하는 웹 API 설계를 위한 모범 사례를 알아봅니다.

learn.microsoft.com

POST : 쓰기

GET : 읽기

PUT : 파일 업로드

DELETE : 파일 삭제

PATCH : 일부 수정

 

 

 

8. REST API란?

- Representational State Tansfer API : REST 규약을 준수하는 API

- REST is a set of architectural constraints, not a protocol or a standard.

API developers can implement REST in a variety of ways.

REST : 구조적 제약이나 규약. 특정 목적에 의한 방식 및 규칙들을 정의해놓은 것. 

여기서 제한한대로 디자인하면 그게 REST API이다. 

 

- API (Application Programming Interface)

An API is a set of definitions and protocols for building and integrating application software. It’s sometimes referred to as a contract between an information provider and an information user—establishing the content required from the consumer (the call) and the content required by the producer (the response). 

 

[출처] https://www.redhat.com/en/topics/api/what-is-a-rest-api

 

What is a REST API?

A REST API (also known as RESTful API) is an application programming interface that conforms to the constraints of REST architecture. REST stands for representational state transfer.

www.redhat.com

 

 

9. RESTful API 설계

작업 URI HTTP메서드 설명
읽기 /comment/read?cno=번호 GET 지정된 번호의 댓글을 보여준다.
쓰기 /comment/write POST 작성한 게시물을 저장한다.
삭제 /comment/remove POST 댓글을 삭제한다. 
수정 /comment/modify POST 수정된 게시물을 저장한다. 

이걸 이렇게 하지말고 RESTful하게 해보자!

 

 

작업 URI HTTP메서드 설명
읽기 /comments GET 모든 댓글을 보여준다. 
읽기 /comments/{cno} GET 지정된 번호의 댓글을 보여준다.
쓰기 /comments POST 새로운 댓글을 저장한다. 
삭제 /comments/{cno} DELETE 지정된 번호의 댓글을 삭제한다.
수정 /comments/{cno} PUT / PATCH 수정된 댓글을 저장한다. 

URI에 동사를 넣지말고, 이걸 HTTP메서드가 담당하게 하고, URI에 명사만 남긴다.