2022.11.17 HTTP1.1 체험하기
https://www.postman.com/downloads/
HTTP(Hyper Text Transfer Protocol)은 HTML 문서와 같은 리소스들을 가져올 수 있도록 해주는 프로토콜 입니다.
웹 브라우저와 웹 서버간의 통신을 위해 디자인 되었습니다.
HTTP 요청이 발생하면 브라우저는 HTTP 요청 메시지를 생성하고 TCP/IP 프로토콜을 이용하여 웹 서버에 요청을 전달합니다.
이후 브라우저는 웹 서버로부터 HTTP 응답을 전달 받습니다.
A(Client) ---------------> B(Server) 요청(Request)
A(Client) <--------------- B(Server) 응답(Response)
요청(Request) 방법 4가지
HTTP 엔 여러 특징이 있는데 그 중 중요한 특징으로 무상태(Stateless) 가 있다. 이 무상태라는 특징은 무엇인가? 그리고 무상태 특징을 왜 사용하는가? 에 대해서 알아보도록 한다.
클라이언트와 서버 관계에서 서버가 클라이언트의 상태를 보존하지 않음을 의미한다.
장점 : 서버의 확장성이 높기 때문에 대량의 트래픽 발생 시에도 대처를 수월하게 할 수 있다.
단점 : 클라이언트의 요청에 상대적으로 Stateful 보다 더 많은 데이터가 소모된다.
무상태 단어 그대로 생각해보면 “상태가 없는 것” 이다. 그 반대의 경우 “상태가 있는 것” 이라 생각할 수 있으며 이는 상태 유지(stateful) 라 한다. 무상태를 이해하기 위해 우선 상태가 있는 경우를 먼저 살펴보도록 하자.
상태 유지라 함은 클라이언트와 서버 관계에서 서버가 클라이언트의 상태를 보존함을 의미한다. 단순히 말하면 클라이언트의 이전 요청이 서버에 전달되었을 때, 클라이언트의 다음 요청이 이전 요청과 관계가 이어지는 것을 의미한다. 단순히 말하자곤 했지만, 이렇게 봐도 무슨 말인지 이해하기 어렵다. 역시 실제 사례를 바탕으로 이해하는 것이 빠르다. 예를 들어보자.
A : 자전거 사려합니다
X : 자전거 커스텀 재료를 골라주세요 (자전거를 사려한다는 것을 기억한다)
A : 휠은 검정색, 핸들은 검정색, 바디는 흰색, 안장은 흰색으로 해주세요
X : 배송은 어디로 해드릴까요? (자전거를 사려했다는 것을 기억하고 있다)
A : 집으로 보내주세요
X : 결제는 무엇으로 해드릴까요? (자전거를 사려했다는 것, 커스텀을 어떻게 했는지 알고 있다)
A : 카드로 결제할게요
X : 결제 완료 되었습니다. (위의 모든 사용자가 요구했던 사항을 기억하고 있다)
대화를 보면 판매하는 X서버는 사용자의 이전 요청을 모두 기억하며 진행한다는 것을 알 수 있다. 이것이 상태 유지이며 지극히 정상적인 대화 처럼 보인다. 하지만 여기엔 함정이 있다. 바로 판매하는 서버 X가 바뀔 경우다. 만약 대량의 트래픽이 몰려들어서 서버를 긴급하게 늘렸다고 생각해보자. 그러면 판매자 서버 X가 아닌 증가된 어떤 서버 Y가 될 수도 있다. 현실에서도 마트에서 너무 바쁘면 담당자가 바뀌기도 하지 않은가? 같은 의미로 생각할 수 있다. 다음은 X가 바뀌었을 경우의 상황이다. 서로간의 대화는 다음과 같이 진행된다.
A : 자전거 사려합니다
X : 자전거 커스텀 재료를 골라주세요
A : 휠은 검정색, 핸들은 검정색, 바디는 흰색, 안장은 흰색으로 해주세요
Y : 네? 어떤걸 말씀하시는거죠?
A : 집으로 보내주세요
Z : ?
A : 카드로 결제할게요
X : 네?
말이 안통한다. 이게 바로 상태 유지의 문제이다. 이러한 문제를 해결하기 위해 무상태가 등장한다.
상태 유지를 이해했다면 무상태는 생각보다 쉽게 이해할 수 있다. 바로 무상태의 예를 보도록하자. 위와 같은 상황을 가정한다.
자전거 판매를 하는 서버 X, 대체 가능한 서버 Y, Z
자전거 사려는 클라이언트 A
A : 자전거 사려합니다.
X : 자전거 커스텀 재료를 골라주세요. (서버는 아무것도 기억하지 않는다)
A : 자전거를 사려합니다. 휠은 검정색, 핸들은 검정색, 바디는 흰색, 안장은 흰색으로 해주세요.
Y : 배송은 어디로 해드릴까요? (서버는 아무것도 기억하지 않는다)
A : 자전거를 사려합니다. 휠은 검정색, 핸들은 검정색, 바디는 흰색, 안장은 흰색으로 해주세요. 배송은 집으로 보내주세요.
Z : 결제는 무엇으로 해드릴까요? (서버는 아무것도 기억하지 않는다)
A : 자전거를 사려합니다. 휠은 검정색, 핸들은 검정색, 바디는 흰색, 안장은 흰색으로 해주세요. 배송은 집으로 보내주세요. 결제는 카드로 할게요.
Y : 결제 완료 되었습니다. (서버는 들어온 요청을 처리한다)
이 대화에서 아마 손뼉을 치신 분이 있으리라 생각한다. 이게 바로 무상태이다. 이전의 클라이언트의 요청(상태)을 유지하지 않는 서버. 그것이 핵심이다. 무상태는 기존의 서버가 혼잡해져서 새로운 서버를 가져다 놓아도 기존의 비즈니스 로직을 그대로 구현하고 있다면 이전의 사용자 요청이 어떤지에 관계없이 계속 일을 처리할 수 있다. 단점은 클라이언트가 하고자하는 최종 목적을 위해 지나는 과정마다 점점 전달해야하는 내용이 많아진다는 것이다.
HTTP는 이 무상태를 특징으로 기본적으로 가지고 있다. 특별한 일이 없다면 무상태를 지향해야하며 정말 필요한 경우에만 상태 유지를 해야한다.
출처
https://developer.mozilla.org/ko/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types
✨
@Controller
사용자가 요청 -> 응답(HTML) 하는 컨트롤러
@RestController
사용자가 요청 -> 응답(Data) 하는 것이 컨트롤러
<script>
public class HttpControllerTest {
//http://localhost:8080/http/get(select)
@GetMapping("/http/get")
public String getTest() {
return "get 요청";
}
//http://localhost:8080/http/post(insert)
@PostMapping("/http/post")
public String postTest() {
return "post 요청";
}
//http://localhost:8080/http/put(update)
@PutMapping("/http/put")
public String putTest() {
return "put 요청";
}
//http://localhost:8080/http/delete(delete)
@DeleteMapping("/http/delete")
public String deleteTest() {
return "delete 요청";
}
}
</script>
인터넷 브라우저 요청은 무조건 get 요청밖에 할 수 없다.
New -> HTTP Request -> url 적고 Send -> 응답
Get 뿐만 아니라 post,put,delete 다 요청이 가능하다.
url에 쿼리스트링으로 데이터 보내기
✨ Query String 쿼리스트링이란?
사용자가 입력 데이터를 전달하는 방법중의 하나로, url 주소에 미리 협의된 데이터를 파라미터를 통해 넘기는 것을 말한다.
http://host:port/path?querystring
query parameters( 물음표 뒤에 = 로 연결된 key value pair 부분)을 url 뒤에 덧붙여서 추가적인 정보를 서버 측에 전달하는 것이다. 클라이언트가 어떤 특정 리소스에 접근하고 싶어하는지 정보를 담는다.
1) Test 용 Member 클래스 생성
public class Member {
private int id;
private String username;
private String password;
private String email;
public int getId() {
return id;
}
public Member(int id, String username, String password, String email) {
this.id = id;
this.username = username;
this.password = password;
this.email = email;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
...
}
2) url 쿼리스트링 값에 맞게 HttpControllerTest.java 수정
@RequestParam 타입 이름
http://localhost:8080/http/get?id=1&username=won
@GetMapping("/http/get")
public String getTest(@RequestParam int id, @RequestParam String username) {
return "get 요청"+id+","+username;
}
3) 데이터 따로 받지 않고 한꺼번에 받을때
파라미터를 따로 적지 않고 클래스를 적어주면
클래스내에 변수값이 알아서 맵핑된다.
@GetMapping("/http/get")
public String getTest(Member m) {
return "get 요청"+m.getId()+","+m.getUsername()+","+m.getPassword();
}
회원가입을 진행해보자.
post 방식은 url에 데이터를 보내는 것이 아닌 Body에 담아보낸다.
여러 방식 중 몇 가지만 사용해보자.
1) x-www-form-urlencoded(form 태그방식)
//http://localhost:8080/http/post(insert)
@PostMapping("/http/post")
public String postTest(Member m) {
return "post 요청"+m.getId()+","+m.getUsername()+","+m.getPassword()+","+m.getEmail();
}
2) text MIME 타입 : text/plain
post text 방식은 @RequestParam이 아니라 @RequestBody로 받아준다.
@PostMapping("/http/post")
public String postTest(@RequestBody String text) {
return "post 요청"+text;
}
3) JSON MIME 타입 : application/json
raw 선택 후 오른쪽에 JSON으로 변경
@PostMapping("/http/post")
public String postTest(@RequestBody String text) {
return "post 요청"+text;
}
@PostMapping("/http/post")
public String postTest(Member m) {
return "post 요청"+m.getId()+","+m.getUsername()+","+m.getPassword()+","+m.getEmail();
}
@PostMapping("/http/post")
public String postTest(Member m) {
return "post 요청"+m.getId()+","+m.getUsername()+","+m.getPassword()+","+m.getEmail();
}
id가 1인 것의 passwork를 5555로 변경
@PutMapping("/http/put")
public String putTest(@RequestBody Member m) {
return "put 요청"+m.getId()+","+m.getUsername()+","+m.getPassword()+","+m.getEmail();
}