이 글은 인프런 김영한님의 Spring 강의를 바탕으로 개인적인 정리를 위해 작성한 글입니다.


HTTP API 예제

요구사항 및 API URI 설계

회원 정보 관리 API 설계
1. 회원 목록 조회 :  /read-member-list
2. 회원 조회 :  /read-member-by-id
3. 회원 등록 : /create-member
4. 회원 수정 : /update-member
5. 회원 삭제 : /delete-member

요구사항 기반으로 API를 만들게 되는게 위와 같이 현업에서 잘못된 API URI 설계를 한다. 

 

API URI  설계 분리

리소스 : 회원
행위 : 조회, 등록, 수정, 삭제

API URI 설계를 할 때 리소스와 해당 리소스를 대상으로 하는 행위를 분리해야 한다.

회원이라는 리소스만 식별하고 회원 리소스를 URI에 매핑을 하면 된다. 

리소스를 식별하는 것이 가장 중요하다.

 

API URI 재설계

회원 정보 관리 API 재설계
1. 회원 목록 조회 :  /members
2. 회원 조회 :  /members/{id} 
3. 회원 등록 : /members/{id}
4. 회원 수정 : /members/{id}
5. 회원 삭제 : /members/{id}

API URI 재설계를 했지만 행위는 구분이 되지 않는다.

구분하는 방법은 URI 리소스만 식별해 놓으면 HTTP 메서드인 GET, POST, PUT, DELETE 이런 것들이 조회, 등록, 수정, 삭제 역할을 대신해준다

계층 구조상 상위를 컬렉션으로 보고 복수 단어 사용 권장(member  ->  members)


HTTP 메서드 - GET, POST

HTTP 메서드 종류

  • GET : 리소스를 조회
  • POST : 요청 데이터를 담아서 처리 
  • PUT : 리소스를 대체, 해당 리소스가 없으면 생성
  • PATCH : 리소스 부분 변경
  • DELETE : 리소스 삭제
  • HEAD : GET과 동일하지만 메시지 부분을 제외하고 상태 줄과 헤더만 반환
  • OPTIONS : 대상 리소스에 대한 통신 가능 옵션(메서드)를 설명 (주로 CORS에서 사용)
  • TRACE : 대상 리소스에 대한 경로를 따라 메시지 루프백 테스트를 수행

 

GET

리소스를 조회할 때 주로 사용한다.

서버에 전달하고 싶은 데이터는 쿼리 파라미터 또는 쿼리 스트링을 통해서 전달한다.

GET은 메시지 바디를 전달할 수 있지만 실무에서는 바디에 보통 데이터를 넣지 않는다.

지원하지 않는 서버들이 많아서 권장하지 않는다. 

 

예를들면 게시판의 게시물을 조회할 때 쓸 수 있다.

GET을 통한 요청은 URL 주소 끝에 파라미터로 포함되어 전송되며, 이 부분을 쿼리 스트링 (query string) 이라고 부른다.

방식은 URL 끝에 " ? " 를 붙이고 그다음 변수명1=값1&변수명2=값2... 형식으로 이어 붙이면 된다.

 

예를들어 다음과 같은 방식이다. 
http://www.example.com/show?name1=value1&name2=value2
서버에서는 name1 과 name2 라는 파라미터 명으로 각각 value1 과 value2 의 파라미터 값을 전달 받을 수 있다.

 

 

GET 요청과 응답

클라이언트가 /members/100 GET하고 요청하면 서버에서 GET 메시지가 도착한다.

서버에서는 /members/100 에서 데이터베이스를 조회해서 응답 메시지를 만들어서 클라이언트에게 보낸다. 

 

특징

  • 캐시 가능  : GET을 통해 서버에 리소스를 요청할 때 웹 캐시가 요청을 가로채 서버로부터 리소스를 다시 다운로드하는 대신 리소스의 복사본을 반환한다.
    HTTP 헤더에서 cache-control 헤더를 통해 캐시 옵션을 지정할 수 있다.
  • GET 요청은 브라우저 히스토리에 남는다.
  • GET 요청은 북마크 될 수 있다.
  • 길이 제한  : GET 요청의 길이 제한은 표준이 따로 있는건 아니고 브라우저마다 제한이 다르다고 한다. 
  • 보안 취약 : GET 요청은 파라미터에 다 노출되어 버리기 때문에 중요한 정보는 GET 방식을 사용하면 안된다.
  • GET은 데이터를 요청할때만 사용 된다.

 

POST

클라이언트에서 메시지 바디를 통해서 서버로 요청하고, 서버가 데이터를 처리하는 모든 기능을 수행한다.

주로 전달된 데이터로 신규 리소스 등록하거나 변경된 프로세스를 바꿀 때 많이 이용한다. 

 

POST는 클라이언트에서 서버로 리소스를 생성하거나 업데이트하기 위해 데이터를 보낼 때 사용 되는 메서드다.

예를들면 게시판에 게시글을 작성하는 작업 등을 할 때 사용할 된다.


POST는 전송할 데이터를 HTTP 메시지 body 부분에 담아서 서버로 보낸다

GET에서 URL 의 파라미터로 보냈던 name1=value1&name2=value2 가 body에 담겨 보내진다 생각하면 된다.

POST 로 데이터를 전송할 때 길이 제한이 따로 없어 용량이 큰 데이터를 보낼 때 사용하거나 GET처럼 데이터가 외부적으로 드러나는건 아니라서 보안이 필요한 부분에 많이 사용된다. (데이터를 암호화하지 않으면 body의 데이터도 결국 볼 수 있는건 똑같다.)

POST를 통한 데이터 전송은 보통 HTML form 을 통해 서버로 전송된다.

 

리소스를 /members POST로 전달하기전, 서버와 클라이언트는 그 데이터를 내부적으로 어떻게 쓸 것인지 미리 서로 약속되어있다.

따라서 클라이언트가 필요한 데이터를 전달하고 서버에서는 신규로 등록을 위해서  /members에 100 신규 리소스 식별자를 생성한다.

서버는 다시 클라이언트로 신규로 자원이 생성된 경로를 응답메시지로 보낸다.   

 

POST 예시

1. HTML 양식에 입력된 필드와 같은 데이터 블록을 데이터 처리 프로세스에 제공 

  • HTML 폼에 입력한 정보로 회원가입하거나 주문 문 등을 처리

2. 게시판, 뉴스 그룹, 메일링 리스트, 블로그 또는 유사한 기사 그룹에 메시지 게시

  • 게시판에 글쓰거나 댓글 달기
  • 게시판에 글을 쓰고 Submit 누르면 POST로 글이 서버로 전달하고 서버가 게시판에 글을 저장한다.

3. 서버가 아직 식별하지 않은 새 리소스 생성

  • 신규 주문을 생성하거나 신규 회원을 생성할 때 

4. 기존 자원의 끝에 데이터를 추가

  • 한 문서 끝에 내용 추가하기 

 

POST 정리

1. 새 리소스 생성(등록)

  • 서버가 아직 식별하지 않은 새 리소스 생성

2. 요청 데이터 처리

  • 단순히 데이터를 생성하거나 변경하는 것을 넘어서 프로세스를 처리할 때 서버에서 큰 변화가 일어남
  • 주문에서 결제완료 -> 배달 시작 -> 배달완료 처럼 단순히 값 변경을 넘어 프로세스의 상태가 변경되는 경우
  • POST의 결과로 새로운 리소스가 생성되지 않을 수 있음
  • 컨트롤 URI : POST /orders/{orderld}/start-delivery -> 실무에서 어쩔 수 없이 리소스만으로 URI 설계가 힘들 경우도 있다. 그때 동사만을 사용하여 URI를 구성

3. 다른 메서드로 처리하기 애매한 경우

  • JSON으로 조회 데이터를 넘겨야 하는데 GET 메서드를 지원하지 않는 서버가 있어서 사용하기 어려운 경우
  • 애매하면 POST 사용

 

특징

  • 캐시되지 않는다.
  • 브라우저 히스토리에 남지 않는다.
  • 북마크 되지 않는다.
  • 데이터 길이에 제한이 없다.

 

GET 과 POST 차이

  • 사용목적 : GET은 서버의 리소스에서 데이터를 요청할 때, POST는 서버의 리소스를 새로 생성하거나 업데이트할 때 사용한다.
    DB로 예시를 들면, GET은 SELECT 에 가깝고, POST는 Create 에 가깝다고 보면 된다.
  • 요청에 body 유무 : GET 은 URL 파라미터에 요청하는 데이터를 담아 보내기 때문에 HTTP 메시지에 body가 없다. POST 는 body 에 데이터를 담아 보내기 때문에 당연히 HTTP 메시지에 body가 존재한다.
  • 멱등성 (idempotent) : GET 요청은 멱등이며, POST는 멱등이 아니다.
멱등성
멱등의 사전적 정의는 연산을 여러 번 적용하더라도 결과가 달라지지 않는 성질을 의미한다.
GET은 리소스를 조회한다는 점에서 여러 번 요청하더라도 응답이 똑같을 것 이다.
반대로 POST는 리소스를 새로 생성하거나 업데이트할 때 사용되기 때문에 멱등이 아니라고 볼 수 있다. (POST 요청이 발생하면 서버가 변경될 수 있다.)

GET과 POST는 이런 차이들이 있기 때문에 사용하려는 목적에 맞는 확인한 후에 사용해야한다.

 

HTTP 메서드 - PUT, PATCH, DELETE

PUT

리소스가 있으면 완전히 대체(덮어쓰기)하고 리소스가 없으면 생성한다.

POST와 다른 점은 PUT은 클라이언트가 구체적인 리소스의 전체 위치를 알고 URI를 지정해서 서버에게 전달한다. 

 

PUT - 리소스가 있을 경우

클라이언트가 /members/100 리소스 지정해서 데이터를 서버에게 보내면 서버도 /members/100 리소스가 있다. 그러면 클라이언트가 보낸 리소스로 대체해버린다. 

 

PUT - 리소스가 없을 경우

클라이언트가 members/100 리소스 지정해서 데이터를 서버에게 보냈는데 서버에서 해당 리소스가 없으면 신규 리소스로 생성이 된다.

 

PUT 주의사항

클라이언트가 /members/100 데이터에 username이 없고 age로 지정해서 보내면 서버에서는 age를 업데이트를 하는데 username 자체가 날아가버린다.

기존 리소스를 새로운 리소스로 완전히 대체한다. 이렇게 되면 리소스를 수정하기 어렵다. 

 

PATCH

리소스를 부분 변경한다.

서버에 /members/100 데이터에 age가 없고, 클라이언트가 age로 지정해서 보내면 서버에서는 username은 남아있고 age만 변경한 것이다. 

 

DELETE

리소스를 삭제한다.

클라이언트가 /members/100 를 삭제해달라고 요청하면 서버에서 리소스를 삭제한다. 


HTTP 메서드의 속성

HTTP 메서드의 속성

 

안전(Safe)

호출해도 리소스가 변경하지 않는 특징

  • GET은 단순히 조회만 하기 때문에 안전하다.  한번 호출해도 여러번 호출해도 변경이 일어나지 않아서 안전하다.
  • POST, PUT, PATCH, DELETE는 안전하지 않다.
  • 만약에 그래도 계속 호출해서 서버에서 로그가 계속 쌓게되서 서버 장애가 일어날 때는 안전은 그런 부분까지 고려하지 않는다. 안전은 해당 리소스만 고려하기 때문이다. 

 

멱등(Idempotent)

한 번 호출해도 두 번 호출해도 100번 호출해도 결과는 동일한 특징

여러 번이라는 키워드를 중심으로 이해해야 한다.

  • GET은 한 번 조회하든 두 번 조회하든 같은 결과로 조회된다.
  • PUT은 결과를 대체하기 때문에 같은 요청을 여러 번 해도 최종 결과는 동일하다.
  • DELETE는 결과를 삭제하기 때문에 같은 요청을 여러 번 해도 삭제된 결과는 동일하다.
  • POST는 멱등이 아니다. 여러번 호출하면 같은 결제등이 중복으로 발생해서 새로운 리소스로 구별이 된다.
사용자 1 : GET -> username: A, age: 20
사용자 2 : PUT -> username: A, age: 30
사용자 1 : GET -> username: A, age: 30 -> 사용자2의 영향으로 바뀐 데이터 조회

멱등은 외부 요인으로 중간에 리소스가 변경되는 것까지 고려하지 않는다.

클라이언트가 동일한 요청을 똑같은 클라이언트가 동일한 요청했을 때만 멱등한다.

즉, 멱등은 동시성 문제까지 고려하지 않는다. 

 

멱등의 활용 

  • 자동 복구 매커니즘로 활용할 수 있다.
  • 클라이언트가 DELETE를 호출했는데 서버에서 잘 되고 있는지 안 되고 있는지 응답이 없을 경우, 클라이언트가 다시 재차 DELETE를 시도 해도 멱등하기 때문에 안전하다.

 

캐시가능(Cacheable)

웹 브라우저에 용량이 큰 이미지를 한번 요청을 하면 그 다음에 똑같이 용량이 큰 이미지를 요청할 필요없다.

똑같은 이미지를 서버에서 다운로드 받는 것은 불필요한 행동이기 때문이다.

그래서 로컬 PC에 웹 브라우저 저장을 하고 저장된 것을 이용한다.

 

캐시는 GET, HEAD, POST, PATCH 가 가능 하지만 실제로는 GET, HEAD 정도만 캐시로 사용한다.

POST, PATCH는 캐시를 하려면 본문 내용으로 리소스랑 캐시 키가 맞아아야 되는데 복잡해서 구현이 쉽지 않다.

GET, HEAD는 URI만 캐시 키로 캐시해서 간단하다. 

'네트워크 > HTTP' 카테고리의 다른 글

[HTTP] 상태코드  (1) 2024.02.10
[HTTP] HTTP 메서드 활용  (1) 2024.02.09
[HTTP] HTTP 기본  (1) 2024.02.07
[HTTP] URI와 웹 브라우저 요청 흐름  (1) 2024.02.06
[HTTP] 인터넷 네트워크  (1) 2024.02.05