HTTP 메서드 관련 정리

    HTTP API를 만들어보기


    요구 사항 (회원 정보 관리 API를 만들어라)

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

    위와 같은 API 요구 사항이 있다면, API 설계는 어떻게 해야할까?

     

    API URI 설계 (URI : Uniform Resource Identifier)

    URI는 계층 구조를 써야함. (read/member/list 형식)

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

    API URI 설계를 할 때, 위처럼 계층 구조를 활용해서 만들 수도 있다. 그런데 이렇게 하는 것이 정말 좋은 것일까? 그렇지 않다. API의 URI 설계는 리소스와 행위가 동시에 나오는 것이 아니라 '행위를 식별하는 것'이다. 

     

    API URI 고민

    리소스의 의미는 뭘까?

    • 회원을 등록하고 수정하고 조회하는게 리소스가 아니다.
      1. 리소스는 '회원'이다.
      2. 등록, 수정, 조회는 '행위'이다.
    • 리소스를 어떻게 식별하는게 좋을까?
      1. 등록, 수정, 조회 행위들을 모두 배제한다.
      2. 회원이라는 리소스만 식별하도록 한다. → URI에 회원 리소스만 맵핑하면 됨. 

    API를 설계할 때 가장 중요한 것은 '리소스만 식별'되게 하는 것이다. 위의 방침을 반영해서 다시 한번 요구사항에 대한 URI를 다시 작성해보면 아래와 같다. 

    • 회원 목록 조회 → /members
    • 회원 조회 → /members/{id}
    • 회원 등록 → /members/{id}
    • 회원 수정 → /members/{id}
    • 회원 삭제 → /members/{id}
    • 참고 : 계층 구조 상 상위를 컬렉션으로 보고 복수단어를 사용하는 것을 권장한다(member → members)

    위의 URI를 보면 리소스가 members인것은 너무너무 쉽게 알 수 있다. 그런데 한 가지 문제가 생긴다. 조회, 등록, 수정, 삭제에 대한 URI가 동일하다. 그렇다면 이 '행위'는 도대체 어떻게 식별하면 좋을까? 

     

    API URI의 설계

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

    • 리소스, 행위를 분리한다.
      1. 리소스 : 회원
      2. 행위 : 조회, 등록, 삭제, 변경
    • 리소스는 명사로 표기해서 URI에 바로 보일 수 있게 한다.
    • 행위는 HTTP 메서드로 구분한다. 만약 HTTP 메서드로 구분이 안된다면, URI에 동사로 표기한다.

     

     

    HTTP 메서드


    클라이언트가 서버가 해주었으면 하는 것들.

     

    HTTP 메서드의 종류

    HTTP 메서드는 여러 가지가 있는데, 주로 사용하는 메서드는 아래 메서드이다. 

    • GET : 리소스 조회
    • POST : 요청 데이터 처리, 주로 등록에 사용. 사실 만능임.
    • PUT : 기존에 있던 리소스 지우고, 덮어씌움. 없으면 새로 만듬.
    • PATCH : 리소스의 일부분만 수정한다.
    • DELETE : 리소스를 지움.
    • HEAD : GET과 동일. 메시지 부분을 제외하고, 상태 + 헤더만 반환함. 

     

     

    HTTP 메서드, GET

    • 리소스를 조회하는데 사용함
    • 서버에서 조회하고 싶은 리소스는 쿼리를 통해서 전달함.
    • 바디를 사용해서 데이터를 전달할 수 있지만, 지원하지 않는 서버가 많아 권장하지 않음. 

     

    GET 메서드의 동작 방식

    좌 : 리소스 GET 요청 / 우 : 응답 메세지 작성해서 반환

    1. 먼저 클라이언트에서 GET으로 HTTP 요청을 보낸다. "멤버의 100번 정보를 주세요"라고 보냄
    2. 서버에서는 이 메세지를 받는다. 서버가 내부의 DB를 조회하고, JSON 형식으로 가공함.
    3. 서버에서는 JSON 데이터를 응답 메세지 형태로 만들어서 클라이언트에게 다시 쏴줌.

     

     

    HTTP 메서드, POST 

    • 요청 메세지에 있는 데이터 처리가 가장 큰 목적
    • 바디에 데이터 넣어서 서버에 데이터 전달함. 서버에서 이 데이터를 처리해줬으면 함.
    • 바디를 통해 들어온 데이터를 처리하는 모든 기능을 수행함.
    • 주로 전달된 데이터로 신규 등록, 프로세스 처리에 사용

     

    POST의 동작 방식

    1. 클라이언트는 요청 메세지를 만들어 서버에 전달함. 이 때 /members라는 곳에 데이터를 전달한다는 의미다. (서버 입장에서는 이 데이터가 들어오면 어떤 행위를 할지 이미 약속되어있음.)
    2. 서버는 요청메세지를 받은 후, members/100에 신규 리소스 식별자를 생성하고 DB에 저장을 한다. (members/100에 아무것도 없는 상태)
    3. 서버는 응답 메세지를 만들어서 전달함. 신규로 자원이 생성되면 보통 201 created로 보낸다. 

     

    POST 메서드의 다양한 의미

    • SPEC : POST 메서드는 대상 리소스가 고유한 의미 체계에 따라 요청에 포함된 표현을 처리하도록 요청합니다. 
    • POST가 사용되는 기능
      1) HTML 양식에 입력된 필드과 같은 데이터 블록을 데이터 처리 프로세스에 제공
      → HTML FORM에 입력한 정보로 회원 가입, 주문 등에서 사용
      2) 게시판, 뉴스 그룹, 메일링 리스트, 블로그 또는 유사한 기사 그룹에 메시지 게시
      → 게시판 글쓰기, 댓글 달기. 게시판의 글쓰고 SUMMIT → 서버로 넘어가서, 서버가 게시판에 글을 저장
      3) 서버가 아직 식별하지 않은 새 리소스 생성
      → 신규 주문 생성
      4) 기존 자원에 데이터 추가
      → 한 문서 끝에 내용을 추가한다.

     

    POST 메서드에 대한 정리

    특정 URI에 POST 요청이 오면, 여러 일을 수행할 수 있다. 정해진 것이 없기 때문에, 각 리소스마다 어떤 행위를 해야할지 정해야함.

    1. 새 리소스를 생성
      서버가 아직 식별하지 않은 새 리소스를 생성
    2. 요청 데이터 처리
      ● 단순히 데이터를 생성하거나, 변경하는 것을 넘어 프로세스 처리해야할 때
      → 주문에서 결제완료 →  배달시작 →  배달완료처럼 단순히 값 변경을 넘어 프로세스의 상태가 변경되는 경우. 예를 들어 결제가 완료되면, 배달시작 버튼을 눌러줘야하는데.. 이 때 호출을 POST로 보낸다.
      ● POST의 결과로 새로운 리소스가 생성되지 않을 수도 있음)
      → POST/orders/{orderId}/start-delivery (Control URI) 이런 걸 만들 수 있다. 리소스만으로 URI을 설계를 할 수 없는 경우에는 Control URI를 설계하고, 이 때 POST 메서드를 주로 사용함.
    3. 다른 메서드로 처리하기 애매한 경우가 있음. 애매하면 POST 쓰자.
      → JSON으로 조회 데이터를 넘겨야 하는데, GET 메서드를 사용하기 어려운 경우. (서버에서 GET 메서드의 Body 영역을 잘 허용하지 않음).이 경우는 조회지만 POST를 한다. 

    POST는 사실 모든 것을 할 수 있다. 그렇지만 그 기능을 위해 주어진 메서드를 먼저 사용하고, 애매한 경우에만 POST를 사용하는 것이 좋다. 예를 들어 GET 경우를 들면, GET은 캐싱이 가능하기 때문에 좀 더 효율적으로 사용할 수 있다. 

     

    HTTP 메서드, PUT

    • PUT은 리소스를 대체한다. 
      리소스가 없으면 생성하고, 있으면 그걸 삭제하고 덮어쓴다.
    • 중요! 클라이언트가 리소스를 식별한다 (members/100으로 지정
      1. 클라이언트가 리소스 위치를 알고 URI를 지정해야한다.
      2. POST와 차이점.  POST는 POST /members. 이 때 클라이언트는 만들어질 URI를 모름.

     

    PUT의 동작 방식

    1. 먼저 100번에 넣을꺼야라고 지정하고, 만들어서 보낸다. (PUT members/100)
    2. 서버에서는 미리 리소스가 있으면 완전히 대체가 되어버린다. 나이가 20에서 50으로 바뀌어버린다. 
    3. 리소스가 없으면, 그냥 신규 리소스가 하나 생성이 된다. 

     

    '리소스는 완전히 대체됨'의 의미

    위의 경우, username 필드 없이 age만 있는 것을 Body에 넣어서 보내면, username 필드가 아예 삭제되어버림. 이런 이유 때문에 Put은 Resource를 수정하는데 사용하기가 까다롭다. PUT은 리소스를 완전히 덮어버린다고 봐야한다. 그렇다면 일부만 수정한다면 어떤 메서드를 써야할까? 

     

     

    HTTP 메서드, PATCH

    • PATCH는 리소스의 부분 변경에 사용됨.
    • PATCH로 값을 보내면, 보낸 값만 수정됨. 기존 저장 값들 중 다른 값은 안 건드리고, 부분 변경만 일어남.
    • PATCH 지원하지 않는 서버가 있음. 이 때는 POST를 씀. 

     

    HTTP 메서드, DELETE

    리소스를 제거할 때 사용하는 메서드다.

     

    HTTP 메서드의 속성

    • 안전(Safe Methods)
    • 멱등(Idempotent Methods)
    • 캐시가능(Cacheable Methods)

    HTTP 메서드의 속성은 위의 안전, 멱등, 캐시가능으로 분류를 한다.

     

    안전 속성 → 리소스만 고려해야함.

    • 안전은 메서드 호출에 따른 리소스가 변경이 없음.
    • GET은 안전.  POST / DELETE / PUT / PATCH 안전하지 않음.
    • 계속 호출해서, 로그가 많이 쌓여 장애가 발생하면? → 안전은 해당 리소스만 고려함. 이런 부분 고려 X

     

    멱등(외부 요인 고려X. 나만 동일한 요청했을 때, 멱등한지만 본다)

    • f(f(x)) = f(x)
      똑같은 호출을 한 번 호출하든, 두 번 호출하든, 100번 호출하든 결과가 똑같다.
    • 멱등 메서드 
      1) GET : 한번 조회하든, 100번 조회하든 같은 결과가 조회.
      2) PUT : 결과를 대체한다. 동일 상태에서 같은 요청을 여러 번 해도 최종 결과 같음.
      3) DELETE : 결과를 삭제. 같은 요청을 여러 번 해도 삭제된 결과는 똑같다. 
      4) POST : 멱등이 아님. 두 번 호출하면, 같은 결제가 중복해서 발생할 수 있음. (DB에 결제 2번 올라감)
    • 활용(클라이언트가 같은 요청을 해도 되는지에 대한 판단 근거)
      자동 복구 메커니즘
      → 예를 들어 DELETE를 호출했는데 서버에서 응답이 없음. 실행 유무를 알 수 없는 상황이다. 이 때, DELETE는 멱등 메서드이기 때문에 클라이언트가 다시 한번 시도를 할 수 있다. 
    • 재요청 중간에 다른 곳에서 리소스를 변경해버리는 경우는 멱등 케이스로 보는지?
      사용자1 : GET A/20 , 사용자2 : PUT A/30
      → 사용자1 : GET A/30 → 사용자 2의 영향으로 바뀐 데이터 조회하게 된다.
      멱등은 외부 요인으로 중간에 리소스가 변경되는 것은 고려하지 않음. 오로지 나만 호출하는 경우, 똑같은 결과가 나오는지를 봄

     

    캐시가능(Cacheable)

    • 응답 결과 리소스를 캐시해서 사용해도 되는가? (웹 브라우저가 내부에 이걸 저장할 수 있는지?)
    • 웹브라우저에 이미지 굉장히 큰 것을 요청한다고 하면, 그 다음에 또 요청하면 시간, 자원 낭비다. 내 PC에 저장하고, 이걸 다시 이용할 수 있는 것을 캐시가능이라고 함.
    • 이론상 GET, HEAD, POST, PATCH 캐시 가능
    • 실제는 GET, HEAD만 캐시로 사용한다. (GET,HEAD는 URL만 캐시 키로 만들면 됨.)
      → POST, PATCH는 본문 내용까지 캐시 키로 고려해야하는데 구현이 어려움. (본문 내용으로 캐시 키 만들기 어렵)

     

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

    HTTP 메서드 활용  (0) 2021.12.06
    HTTP 상태 코드 정리  (0) 2021.12.04
    HTTP의 Stateless, 비연결성  (0) 2021.12.04
    URI와 웹 브라우저 요청 흐름  (0) 2021.12.04
    인터넷 네트워크 구조 (IP, TCP, UDP, DNS, PORT)  (0) 2021.10.11

    댓글

    Designed by JB FACTORY