241105 에이콘 아카데미 수업을 기반하여 작성되었음을 알립니다.
RESTful
AJAX를 운영하고 있다면 RESTful을 필수적으로 알아야 한다.
RESTful 하나의 프로그래밍 기법이다. 웹의 장점을 최대한 활용할 수 있는 아키텍처, 하나의 스타일인 것이다.
모바일, 웹 프로그래밍, 클라우드와 소통할 수 있는 아키텍처
하지만 REST를 사용했다 하여 모두가 RESTful 한 것은 아니다. REST API의 설계 규칙을 올바르게 지킨 시스템을 RESTful 하다고 할 수 있다.
클라이언트가 요청할 때 GET/POST 방식만 써왔다. 서버도 마찬가지로 GET으로 요청이 왔을 때 GET 방식으로 응답, POST 방식으로 요청이 왔을 때 POST 방식으로 응답해왔다.
GET / POST 방식으로 모든 CRUD가 가능하긴하다.
RESTful 시스템에서는 모든 것이 자원이다. 자원은 URI(Uniform Resource Identifier)를 통해 식별된다.
예를 들어, 사용자의 정보를 얻으려면 /users라는 URI를 사용할 수 있다.
내가 작업하려는 것을 URI에 적어준다. /users, /products, /buser ...
REST는 자원(Resource), 행위(Verb), 표현(Representations) 세 가지 구성요소를 가지고 있다.
자원은 접근 대상을 의미, HTTP URI이다.
행위는 메소드를 의미, HTTP Method (GET(select/조회), POST(insert/생성), DELETE(delete/삭제), PUT, PATCH (update/수정,기존에 데이터가 없다면 추가로도 쓸 수 있다.))
// PUT은 리소스의 모든 것을 업데이트, PATCH는 리소스의 일부를 업데이트
표현은 메세지를 의미, HTTP Message PayLoad( 전송되는 데이터 )
표현의 주요 개념자원은 여러 가지 형식으로 표현될 수 있다.
가장 일반적인 형식은 JSON(JavaScript Object Notation)과 XML(Extensible Markup Language)이다.
예를 들어, 사용자 자원은 JSON 또는 XML 형식으로 표현될 수 있다.
서버는 응답할 때 Content-Type 헤더를 사용하여 표현의 형식을 명시한다.
예: Content-Type: application/json은 응답이 JSON 형식임을 나타낸다.
클라이언트는 요청할 때 Accept 헤더를 사용하여 원하는 표현 형식을 지정할 수 있다.
예: Accept: application/json은 클라이언트가 JSON 형식의 응답을 원함을 나타낸다.
서버는 클라이언트의 요청에 따라 자원을 적절한 형식으로 변환하여 응답할 수 있다.
자원 자체는 변하지 않지만, 표현 형식은 클라이언트의 요구에 맞게 변경다.
예를 들어 "상품명이 진라면인 상품을 생산한다."
자원 : 상품
행위 : POST
메세지 : 상품명이 진라면
HTTP POST(메소드), https://localhost/products (URI) 이런식으로 날아가게 된다.
{"name" : "진라면", "price" : "5000"}(메세지)
<form method="post" action="/products"></form> 이런 식으로 해주고 submit해주면 된다.
URI 예시:
GET /users: 모든 사용자 목록을 가져온다.
GET /users/{id}: 특정 ID를 가진 사용자의 정보를 가져온다. 패스배리어블로 받아준다., ?로 넘어오는 데이터는 리퀘스트 파람으로 받음
POST /users: 새로운 사용자를 생성한다.
PUT /users/{id}: 특정 ID를 가진 사용자의 정보를 업데이트한다. 기존에 데이터가 없다면 추가,
DELETE /users/{id}: 특정 ID를 가진 사용자를 삭제한다.
server 측에서는 각 요청명에 맞게 매핑된다. @get, @post, @put, @patch, @delete
URI 설계 시 주의할 점
동사보다는 명사를! 대문자 보다는 가급적 소문자를! 사용하자.
언더바(_)보다 하이픈(-)은 URI 가독성을 높이는데 사용하자. Path에 띄어쓰기가 들어가는 경우 %20이 들어가 가독성이 떨어진다. 한글보다는 영문이 좋음 아스키코드 문자가 좋다.
확장자를 사용하지 말자.
마지막에 슬래시 (/)를 포함하지 않는다.
행위를 포함하지 않는다.
REST의 장점 : Open API를 제공하기 쉽다.
REST의 단점 : 사용할 수 있는 Method가 제한적이다. 하지만 CRUD 만 사용하게 될 것이기에 큰 문제가 없다.
REST API 디자인 가이드 : https://bcho.tistory.com/914를 읽어보면서 정확하게 이해하고 설명할 수 있어야
보통, 리액트나 뷰로 많이 쓴다.
위의 REST의 특징은 실습 없이는 잘 이해되지 않는다.
Postman tool 사용
Postman 툴을 이용해 요청 처리 (API 테스트) 확인, 서버 사이드 개발자들은 유용하게 사용 가능!
클라이언트가 없어도 바로 확인 가능 AJAX 사용 시 반드시 필요한 툴이다.
Tabbed Postman - REST Client 확장프로그램 추가
RESTful 실습 1 (GET)
의존성 추가
Spring Boot DevTools / Spring Web
application.properties
spring.application.name=sprweb33restful
server.port=80
Controller
package pack.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController // @Controller + @ResponseBody 두 개를 합친 것
public class GetController {
@GetMapping(value = "/hello") // 행위 GET
public String abc() {
System.out.println("요청 1 접수");
return "Hello 안녕하세요"; // 메세지
}
@GetMapping(value = "/hello/{info}") // 함께 넘어오는 데이터가 있다.
public String abc2(@PathVariable("info")String info) {
System.out.println("요청 2 접수 : " + info);
return "반환 값 : " + info;
}
@GetMapping(value = "/world") // /world?변수=값&변수=값
public String abc2(@RequestParam("name")String irum,
@RequestParam("age")String nai) {
System.out.println("요청 3 접수 : ");
return "반환 값 : " + irum + " " + nai;
}
}
test1
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script type="text/javascript">
function func1(){
//alert("aa"); // fetch then then catch 세트!
fetch("/hello",{method:"GET"})
.then(response => {
if(!response.ok){
throw new Error("response 오류");
}
return response.text();
})
.then(data => {
document.querySelector("#result").innerText = data;
})
.catch(error => {
document.querySelector("#result").innerText = "err : " + error;
});
}
function func2(){
const info = document.querySelector("#infoInfut").value;
fetch(`/hello/${info}`,{method:"GET"}) // 자바스크립트에서 `` 사용하면 ${} 사용 가능, 자주 사용해주면 편함
.then(response => {
if(!response.ok){
throw new Error("response 오류2");
}
return response.text();
})
.then(data => {
document.querySelector("#result").innerText = data;
})
.catch(error => {
document.querySelector("#result").innerText = "err2 : " + error;
});
}
function func3(){
const name = document.querySelector("#name").value;
const age = document.querySelector("#age").value;
// 인코딩해서 넘겨주기
const url = `/world?name=${encodeURIComponent(name)}&age=${encodeURIComponent(age)}`;
console.log(url);
fetch(url,{method:"GET"})
.then(response => {
if(!response.ok){
throw new Error("response 오류3");
}
return response.text();
})
.then(data => {
document.querySelector("#result").innerText = data;
})
.catch(error => {
document.querySelector("#result").innerText = "err3 : " + error;
});
}
</script>
</head>
<body>
<h2>RESTfull API TEST</h2>
<button onclick="func1()">GET 요청1</button>
<br/>
<input type="text" id="infoInfut" placeholder="info 입력">
<button onclick="func2()">GET 요청2</button>
<br/>
<input type="text" id="name">
<input type="text" id="age">
<button onclick="func3()">GET 요청3</button>
<hr/>
<div id="result"></div>
</body>
</html>
결과
사용자 개발 도구에서 각각의 상태를 확인할 수 있다.
Postman 결과
url과 함께 넘어오는 데이터
파라미터로 넘어오는 데이터
RESTful 실습 2 (POST)
Controller
package pack.controller;
import java.util.Map;
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;
@RestController
public class PostController {
@PostMapping(value = "/hipost")
public String post1() {
System.out.println("post 요청 접수 1");
return "post 요청1 결과";
}
@PostMapping(value = "/hiform") // form tag로 전송한 자료를 수신
public String post2(@RequestParam("name")String name,
@RequestParam("addr")String addr) {
System.out.println("post 요청 접수 2 : 파라미터 값으로 insert 진행한다고 생각해야 함");
return name + " " + addr;
}
@PostMapping(value = "/hiform2") // json 형식으로 전송한 자료를 수신
// 전달 받을 데이터 예시 {name:name, addr:addr}
public String postJson(@RequestBody Map<String, String> postData) {
String name = postData.get("name");
String addr = postData.get("addr");
System.out.println("post 요청 접수 3 : json 형식으로 insert 진행한다고 생각해야 함");
return "이름 : " + name + ", 주소 : " + addr;
}
@PostMapping(value = "/hiform3") // 폼빈 형식으로 전송한 자료를 수신
public String postJson2(PostDataBean postData) {
String name = postData.getName();
String addr = postData.getAddr();
System.out.println("post 요청 접수 4");
return "이름은 " + name + ", 주소는 " + addr;
}
}
test2
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script type="text/javascript">
function func1() {
fetch("/hipost",{
method:"POST"
})
.then(response => {
if(!response.ok){
throw new Error("response 오류");
}
return response.text();
})
.then(data => {
document.querySelector("#result").innerText = data;
})
.catch(error => {
document.querySelector("#result").innerText = "err : " + error;
});
}
function func2() {
const name = document.querySelector("#name").value;
const addr = document.querySelector("#addr").value;
fetch("/hiform",{
method:"POST",
headers:{
"Content-Type":"application/x-www-form-urlencoded"
},
body:`name=${encodeURIComponent(name)}&addr=${encodeURIComponent(addr)}`
//body:`name=${name}&addr=${addr}` 굳이 안줘도 안 깨짐
})
.then(response => {
if(!response.ok){
throw new Error("response 오류2");
}
return response.text();
})
.then(data => {
document.querySelector("#result").innerText = data;
})
.catch(error => {
document.querySelector("#result").innerText = "err2 : " + error;
});
}
function func3(event) {
event.preventDefault();
const formData = new FormData(document.querySelector("#frm"));
//console.log(formData);
fetch("/hiform",{
method:"POST",
body:formData
})
.then(response => {
if(!response.ok){
throw new Error("response 오류3");
}
return response.text();
})
.then(data => {
document.querySelector("#result").innerText = data;
})
.catch(error => {
document.querySelector("#result").innerText = "err3 : " + error;
});
}
function func4(event) {
event.preventDefault();
const formData = new FormData(document.querySelector("#frm2"));
//console.log(formData);
fetch("/hiform3",{
method:"POST",
body:formData
})
.then(response => {
if(!response.ok){
throw new Error("response 오류4");
}
return response.text();
})
.then(data => {
document.querySelector("#result").innerText = data;
})
.catch(error => {
document.querySelector("#result").innerText = "err4 : " + error;
});
}
function func5(event) {
event.preventDefault();
const name = document.querySelector("#name2").value;
const addr = document.querySelector("#addr2").value;
const jsondata = JSON.stringify({name:name, addr:addr}); // JSON 형식을 문자열로 변환
//console.log(jsondata);
fetch("/hiform2",{
method:"POST",
headers:{
"Content-Type":"application/json"
},
//body:jsondata
body:JSON.stringify({name:name, addr:addr})
})
.then(response => {
if(!response.ok){
throw new Error("response 오류4");
}
return response.text();
})
.then(data => {
document.querySelector("#result").innerText = data;
})
.catch(error => {
document.querySelector("#result").innerText = "err4 : " + error;
});
}
</script>
</head>
<body>
<h2>RESTfull API TEST : POST</h2>
<button onclick="func1()">POST 요청1</button>
<br/>
<input type="text" id="name">
<input type="text" id="addr">
<button onclick="func2()">POST 요청2 (form X)</button>
<br/>
<form id="frm" onsubmit="func3(event)">
<input type="text" name="name" value="라라라">
<input type="text" name="addr" value="성동구 성수동">
<button type="submit">POST 요청3 (form 전송)</button>
</form>
<form id="frm2" onsubmit="func4(event)">
<input type="text" name="name" value="타타타">
<input type="text" name="addr" value="성동구 왕십리">
<button type="submit">POST 요청4 (form 전송)</button>
</form>
<form id="frm3" onsubmit="func5(event)">
<input type="text" id="name2" value="나나나">
<input type="text" id="addr2" value="성동구 행당동">
<button type="submit">POST 요청5 (json 전송)</button>
</form>
<hr/>
<div id="result"></div>
</body>
</html>
에러
🚨 Failed to load resource: the server responded with a status of 400 ()
POST 방식 form tag로 넘길 때 form 태그 안에는 id를 주고 input에는 name을 주어야 함!
<form id="frm" onsubmit="func3(event)">
<input type="text" id="name" value="라라라">
<input type="text" id="addr" value="성동구 성수동">
<button type="submit">POST 요청3(form 전송)</button>
</form>
▼
<form id="frm" onsubmit="func3(event)">
<input type="text" name="name" value="라라라">
<input type="text" name="addr" value="성동구 성수동">
<button type="submit">POST 요청3(form 전송)</button>
</form>
결과
Postman 결과
form tag로 전송한 자료를 수신
JSON 형식으로 전송한 자료를 수신, Headers에 Content-Type:apllication/json 적어주기
폼빈 형식으로 전송한 자료를 수신
'Study > Acorn' 카테고리의 다른 글
241107 RESTful / AOP (3) | 2024.11.07 |
---|---|
241106 RESTful (CRUD/문제) (1) | 2024.11.07 |
241105 RESTful (PUT/DELETE/문제) (0) | 2024.11.05 |
241104 AJAX (DB연동/문제) (0) | 2024.11.04 |
241101 AJAX (jQuery/fetch then/AXIOS) (0) | 2024.11.04 |