Home HTTP 웹 지식 - HTTP 메서드, 메서드의 활용
Post
Cancel

HTTP 웹 지식 - HTTP 메서드, 메서드의 활용

HTTP API 설계

요구사항

  • 회원 목록 조회
  • 회원 조회
  • 회원 등록
  • 회원 수정
  • 회원 삭제

API URI 설계?

  • 회원 목록 조회 /read-member-list
  • 회원 조회 /read-member-by-id
  • 회원 등록 /create-member
  • 회원 수정 /update-member
  • 회원 삭제 /delete-member

이것이 좋은 URI 설계인가?

가장 중요한 부분은 리소스의 식별이다. 리소스에 대해 잘 생각해보자.

회원을 등록하고 수정하고 조회하는 것이 리소스가 아니다. 회원이라는 개념 자체가 리소스이다.

회원을 등록하고 수정하고 조회하는 것을 모두 배제하고 회원 리소스 식별에만 중점을 둬보자. -> 회원 리소스를 URI에 매핑.

API URI 재설계

  • 회원 목록 조회 /members
  • 회원 조회 /members/(id)
  • 회원 등록 /members/(id)
  • 회원 수정 /members/(id)
  • 회원 삭제 /members/(id)

이렇게 했을 때, members가 리소스인 것은 알 수 있다. 해당 id의 멤버를 수정한 다는 것도 안다. 하지만 조회, 등록, 수정, 삭제는 URI가 같은데 어떻게 구분할까?

리소스와 행위를 분리해야 한다.

URI는 리소스만 식별하고 행위를 판별하는데 사용하면 안된다. 이 때 행위 판별에 쓰이는 것이 HTTP 메서드인 것이다.

HTTP 메서드

클라이언트가 서버에 무언가 요청할 때 기대하는 행동이다. 예를 들어 간단히 GET은 무언가 달라는 것이고, POST는 내가 무언갈 줄테니 처리해달라의 느낌이다.

종류

  • GET : 리소스 조회
  • POST : 요청 데이터 처리, 주로 등록에 사용한다.
  • PUT : 리소스를 대체한다. 해당 리소스가 없으면 생성한다. 덮어쓰기 느낌.
  • PATCH : 리소스를 부분적으로 변경한다. 회원의 이름을 변경하는 등의 느낌.
  • DELETE : 리소스의 삭제.

기타 메서드

  • HEAD : GET과 동일하지만 메시지 부분을 제외하고 상태 줄과 헤더만 반환한다.
  • OPTIONS : 대상 리소스에 대한 통신 가능 옵션을 설명한다.
  • CONNECT, TRACE : 참고.

GET

리소스의 조회에 사용된다. 서버에 전달하고 싶은 데이터는 query(쿼리 파라미터, 쿼리 스트링)를 통해 전달한다. 메시지 바디를 사용해 데이터를 전달할 수는 있지만 지원하는 곳이 많지 않아 권장하지 않는다.

클라이언트가 /members의 100번 유저를 달라고 요청한다. 서버는 요청을 받고 내부 DB를 찾아 json 메시지 등으로 만들어 데이터를 만든다.

이후 서버에서는 응답메시지로 헤더에 데이터 정보, 바디에 데이터를 담아 클라이언트에 보낸다.

POST

요청 데이터를 처리한다. 메시지 바디를 통해 서버로 요청 데이터를 전달하고 서버는 요청 데이터를 처리한다.

메시지 바디를 통해 들어온 데이터를 처리하는 모든 기능을 수행한다. 주로 전달된 데이터로 신규 리소스를 등록하거나, 프로세스 처리에 사용한다.

클라이언트가 /members 라는 곳에 데이터를 전달한다. 단 약속이 되어있어야 한다. 클라이언트가 /members에 데이터를 보내면 서버는 데이터를 저장한다 혹은 ~~에 사용할거야 식의 약속.

서버는 리소스 식별자를 생성하고 처리한 후 응답한다.

POST의 정리

POST 메서드의 예를 들어보자.

  • 어떤 데이터 블록의 데이터 처리 프로세스에 제공
    • HTML FORM에 입력한 정보를 보내면 회원 가입, 주문 등에서 사용
  • 게시판, 뉴스 그룹, 메일링 리스트, 블로그 등등의 그룹에 메시지 게시
    • 게시판 글쓰기, 댓글 달기
  • 서버가 아직 식별하지 않은 새 리소스 생성
    • 신규 주문 생성
  • 기존 자원에 데이터 추가
    • 한 문서의 끝에 내용 추가하기.

위와 같이 어떤 리소스 URI에 POST 요청이 오면 요청 데이터를 어떻게 처리할지 리소스마다 따로 정해주어야 한다. 즉 정해진 것이 없는 것이다.

추가

단순히 데이터를 생성하거나, 변경하는 것을 넘어 프로세스를 처리해야 하는 경우에도 POST가 쓰인다.

예를 들어 주문에서 결제완료 -> 배달시작 -> 배달완료와 같이 단순히 값 변경을 넘어 프로세스의 상태가 변경되는 경우 POST의 결과로 새로운 리소스가 생기지 않을 수 있지만 변경에 사용할 수 있다.

다른 메서드로 처리하기 어려운 경우에도 쓰인다.

예를 들어 어떤 데이터를 조회하고 싶어서 GET 메서드를 썼는데 query 만으로 조회 데이터를 넘기기 어려워 JSON으로 조회 데이터를 넘기는 상황이 있을 수 있다. 이런 경우 조회 데이터를 POST로 넘기고 GET처럼 사용할 수도 있다.

참고

위의 프로세스 변경 예시에서 URI를 설계한다고 가정하자.

POST /orders/{orderID}/start-delivery 이것은 이상적이지 않다. 상태의 변경이 URI에 들어가있다. 하지만 실무에서는 리소스만 가지고 URI를 모두 설계할 수 있는 것이 아니다.

따라서 상황에 따라서는 이러한 컨트롤 URI를 만들어 사용할 수 있다.

PUT

리소스를 대체하는데 사용한다. /members/100에 대한 리소스가 없다면 아래의 데이터를 바탕으로 생성하고, 있다면 대체한다.

☆ 클라이언트가 리소스를 식별해야 한다.

  • 클라이언트가 /members/100과 같이 구체적인 리소스 위치를 알고 URI를 지정해야 한다.
  • 이것이 POST와의 차이이다. POST때는 단순히 /members에 POST를 했었다.

리소스가 있는 경우에는 단순 대체이다.

없는 경우에는 POST와 비슷하게 생성 역할을 할 수 있다.

★ 대체한다 라는 키워드에 주목해보자. username과 age 필드가 있는 데이터에 age필드만 PUT 한다면 username 필드가 사라진다. 완전히 대체하게 된다는 것이다. 즉, 수정하는데 사용하기는 적절치 않다. 이 때 사용하는 것은 PATCH이다.

PATCH

리소스를 부분 변경한다.

종종 PATCH를 허용하지 않는 서버가 있는데 이 때는 POST 사용하면 된다.

DELETE

리소스의 제거에 사용한다.

HTTP 메서드의 속성

안전?

호출해도 리소스를 변경하지 않는다. 당연히 POST, PUT, DELETE 같은 것들은 안전하지 않다.

계속해서 호출해 로그같은 것이 쌓여 장애가 발생해도 안전이라 할 수 있나?

안전은 해당 리소스의 변화에 집중한다. 이런 부분은 고려하지 않는다.

멱등(Idempotent)

  • f(f(x)) = f(x). 즉, 한번 호출하든 몇번을 호출하든 결과가 같다.

GET은 조회이기 때문에 당연히 결과가 같고, DELETE 또한 삭제이기 때문에 결과는 같다.

PUT은 결과를 대체하기 때문에 결과가 같다. 첫 번째 PUT 때 데이터가 없어 생성했다고 가정하고 두번째 PUT때 덮어씌웠다고 가정을 해도, 결국 최종 결과물은 같다.

POST의 경우 두 번 호출하면 결제 처리를 두 번 하는 등의 결과가 나온다.

PUT이 같은 데이터의 요청에 대해 멱등이면 PATCH도 멱등일거같은데..

PATCH는 멱등으로 설계할 수도 있지만, 멱등이 아니게도 설계할 수 있기 때문이다. {name: “kim”} 과 같은 PATCH 요청은 멱등이다. 하지만 {“operation”: “add”, “age”:10} 이렇게 설계한다면 +10 -> +10 이기 때문에 멱등이 아니게 된다.

재요청 중간에 다른 곳에서 리소스를 변경해도 멱등인가?

GET -> PUT으로 대체 -> GET 하면 첫 번째 GET과 두 번째 GET의 결과가 다르다.

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

캐시가능(중요)

응답 결과 리소스를 캐시해서 사용해도 되는가?

예를 들어 웹브라우저에 큰 이미지 파일을 요청한다고 가정하자. 이 파일을 이미 한번 받았는데 캐시하지 않으면 다시 받아야 하는 일이 발생한다. 이러한 부분을 내부에 저장해서 사용하는 것이 캐시이다.

  • GET, HEAD, POST, PATCH 캐시 가능. 실제로는 GET, HEAD 정도만 캐시로 사용.
  • POST, PATCH는 본문 내용까지 캐시 키로 고려해야 하는데 구현이 쉽지 않다. GET은 URL을 키로 사용하는 등의 간단한 처리 가능.

HTTP 메서드의 활용

클라이언트에서 서버로 데이터 전송하기

데이터의 전달 방식은 크게 2가지이다.

  • 쿼리 파라미터를 통한 데이터 전송 (GET)
    • 주로 정렬 필터에 사용한다. (검색어)
  • 메시지 바디를 통한 데이터 전송 (POST, PUT, PATCH)
    • 회원 가입, 상품 주문, 리소스 등록, 리소스 변경 등에 사용한다.

정적 데이터 조회 (쿼리 파라미터 미사용)

이미지나 정적 텍스트 문서를 조회하는 상황이다.

GET을 이용해 경로를 알고 그 경로 자체의 리소스를 반환하는 것이다.

일반적으로 쿼리 파라미터 없이 리소스 경로로 단순하게 조회하는 것이다.

동적 데이터 조회

/search 라는 검색 URL에 hello 쿼리를 포함시켜 쿼리를 전달하게 된다.

이러한 쿼리 파라미터를 기반으로 결과를 찾아 그 결과를 응답하게 된다.

  • 주로 검색, 게시판 목록에서 정렬 필터(검색어)
  • 조회 조건을 줄여주는 필터, 조회 결과를 정렬하는 정렬 조건에 주로 사용한다.
  • GET을 사용하고 GET은 쿼리 파라미터를 사용해 데이터를 전달한다.

HTML Form 데이터 전송

HTML Form 위의 전송을 누르면 (form의 submit이 적용된다.) form action의 /save를 POST로 전달하게 된다.

HTTP 메시지를 보면 username=kim&age=20 이런 식으로 쿼리파라미터와 비슷하게 생긴 HTTP 바디를 통해 내용을 서버에 POST로 전달하는 것이다.

위의 경우에 from method를 GET으로 한다면?

GET으로 하면 /save뒤에 쿼리 파라미터로 서버에 내용을 전달하게 된다. 그러나 GET은 이렇게 리소스 변경이 발생하는 곳에 사용하면 안된다. (암묵적인 룰)

이런식으로 Form을 이용해 조회하는 것은 허용하며 자주 쓰인다.

Form을 이용한 파일 전송

enctype을 multipart/from-data 라고 지정하면 HTTP 메시지의 Content-Type이 위의 POST 때와 다르게 위와 같이 바뀌고 boundary를 통해 각 데이터를 분리해 HTTP 바디에 담는다.

이렇게 여러 Content type의 데이터를 보낼 수 있게 되고 파일 업로드같은 바이너리 데이터 전송 시 사용된다.

** 참고 : HTML Form 전송은 GET, POST만 지원한다.

HTTP API 데이터 전송

예를 들어 안드로이드나 아이폰 애플리케이션에서 클라이언트에서 서버로 데이터를 바로 전송해야 하는 경우 사용한다.

직접 데이터를 만들어 넘기면 된다.

  • 서버 to 서버
    • 백엔드 시스템 통신
  • 앱 클라이언트
    • 아이폰, 안드로이드
  • 웹 클라이언트
    • HTML에서 Form 전송 대신 자바 스크립트를 통한 통신에 사용 (AJAX)
    • ex) React, Vue.js 같은 웹 클라이언트와 API 통신
  • POST, PUT, PATCH : 메시지 바디를 통해 전송
  • GET : 조회, 쿼리 파라미터로 데이터 전달
  • Content-Type : application/json을 주로 사용

HTTP API 설계 예시

HTTP API - 컬렉션

  • POST 기반 등록
  • ex) 회원 관리 API 제공
  1. 회원 목록 /members -> GET (검색을 하려하면 쿼리파라미터 이용)
  2. 회원 등록 /members -> POST
  3. 회원 조회 /members/(id) -> GET
  4. 회원 수정 /members/(id) -> PATCH, PUT, POST (PATCH가 베스트)
  5. 회원 삭제 /members/(id) -> DELETE

(게시글 수정을 한다 하면 PUT이 사용될 수 있다.)

컬렉션?

  • 서버가 관리하는 리소스 디렉토리
  • 클라이언트는 리소스 URI를 모른 채 단순히 /members에 POST 하게 되고 서버가 리소스의 URI를 생성하고 관리
  • 이 예시에서의 컬렉션은 /members

HTTP API - 스토어, 파일 관리 시스템

  • PUT 기반 등록
  • ex) 정적 컨텐츠 관리, 원격 파일 관리
  1. 파일 목록 /files -> GET
  2. 파일 조회 /files/(filename) -> GET
  3. 파일 등록 /files/(filename) -> PUT
  4. 파일 삭제 /files/(filename) -> DELETE
  5. 파일 대량 등록 /files -> POST

새로운 파일을 등록할 때 클라이언트가 filename을 알고 있기 때문에 PUT.

파일 등록을 PUT으로 지정하고 있기 때문에 /files의 POST 역할을 따로 지정할 수 있다. 따라서 파일 대량 등록과 같은 역할을 부여할 수 있는 것이다.

특징

  • 클라이언트가 리소스 URI를 알고 있어야 한다.
    • 서버가 URI를 생성하는 것이 아닌 클라이언트가 지정.
    • PUT /files/star.jpg

이러한 특징을 가진 것을 스토어 라고 한다.

스토어?

  • 클라이언트가 관리하는 리소스 저장소.
  • 클라이언트가 리소스의 URI를 알고 관리.
  • 이 예시에서의 스토어는 /files

대부분은 POST 기반의 컬렉션을 많이 사용한다.

HTTP FORM 사용

  • 웹 페이지 회원 관리
  • GET, POST만 지원.

물론 AJAX 같은 기술을 사용해 GET, POST만 사용할 수 있는 부분을 해결할 수 있지만 일단 순수 HTML, HTML FORM을 통한 것만 이야기한다.

  1. 회원 목록 /members -> GET
  2. 회원 등록 폼 /members/new -> GET
  3. 회원 등록 /members/new, /members -> POST (submit을 눌렀을 때.)
  4. 회원 조회 /members/(id) -> GET
  5. 회원 수정 폼 /members/(id)/edit -> GET
  6. 회원 수정 /members/(id)/edit, /members/(id) -> POST
  7. 회원 삭제 /members/(id)/delete -> POST

등록, 수정, 삭제 같은 경우 DELETE 라는 메서드를 사용할 수 있다면 /members/(id) URI를 사용하면 되겠지만 그럴 수 없기 때문에 위와 같이 /new, /edit 등등의 동사로 된 컨트롤 URI를 사용한다.

참고) 컬렉션, 스토어 그리고 문서?

문서란 단일 개념을 의미한다.

  • 파일 하나, 객체 인스턴스, 데이터베이스 row
  • ex) /members/100, /files/star.jpg
This post is licensed under CC BY 4.0 by the author.