1. HTTP API를 만들어보자

📂 요구사항
'회원 목록 조회, 회원 조회, 회원 등록, 회원 수정, 회원 삭제' 기능이 들어있는 회원 정보 관리 API를 만들어라.


⌨️ 회원 정보 관리 API URI 설계

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

🧐 이것은 좋은 URL 설계일까?
URL 설계할 때 가장 중요한 것은 리소스를 식별하는 것이다.


📌 리소스란?
위 요구사항에서 회원을 등록하고 수정, 조회하는 게 리소스가 아니다. 예를 들어, '미네랄을 캐라'에서 리소스는 미네랄이다. 위 요구사항에서는 회원이라는 개념 자체가 리소스이다.


📌 그렇다면 리소스를 어떻게 식별하는 게 좋을까?

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

'회원을 등록하고 수정, 조회'와 같은 행위를 모두 배제하고 회원이라는 리소스만 식별한 다음, 회원 리소스를 URL에 매핑하면 된다. 그럼, 이제 위의 API를 재설계해보자.


⌨️ 회원 정보 관리 API URI 재설계

  1. 회원 목록 조회 : /members
  2. 회원 조회 : /members/{id}
  3. 회원 등록 : /members/{id}
  4. 회원 수정 : /members/{id}
  5. 회원 삭제 : /members/{id}

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

API URI를 재설계했지만 행위는 구분되지 않는다. 구분하는 방법은 URI 리소스만 식별해 놓으면 HTTP 메서드(GET, POST, PUT..)가 조회, 등록, 수정, 삭제 역할을 대신해준다.



2. HTTP 메서드 - GET, POST

📌 HTTP 메서드의 종류

    ⚡ 주요 메서드

  • GET : 리소스를 조회
  • POST : 요청 데이터를 담아서 처리
  • PUT : 리소스를 대체, 해당 리소스가 없으면 생성
  • PATCH : 리소스 부분 변경
  • DELETE : 리소스 삭제

    ⚡ 기타 메서드

  • HEAD: GET과 동일하지만 메시지 부분을 제외하고, 상태 줄과 헤더만 반환
  • OPTIONS: 대상 리소스에 대한 통신 가능 옵션(메서드)을 설명(주로 CORS에서 사용)
  • CONNECT: 대상 자원으로 식별되는 서버에 대한 터널을 설정
  • TRACE: 대상 리소스에 대한 경로를 따라 메시지 루프백 테스트를 수행
    (CONNECT와 TRACE는 거의 사용하지 않는다.)

📌 GET
리소스를 전달한다. 서버에 전달하고 싶은 데이터쿼리 파라미터이나 쿼리 스트링을 통해서 전달한다. GET도 메시지 바디를 사용해서 데이터를 전달할 수 있지만, 지원하지 않은 곳이 많아서 권장하지 않는다.

클라이언트가 /members/100 URI을 GET으로 요청하면, 서버에서는 /members/100에서 DB를 조회하고 응답 메시지를 만들어서 클라이언트에게 전달한다.


📌 POST

클라이언트에서 메시지 바디를 통해 서버로 요청 데이터를 전달하면 서버는 그 데이터를 처리하는 모든 기능을 수행한다. 주로 전달된 데이터로 신규 리소스를 등록하거나 변경된 프로세스 처리에 사용한다.

클라이언트가 POST로 데이터를 전달하면 서버에서는 /members에서 /100 신규 리소스 식별자를 생성한다. 신규로 자원이 생산된 경로를 응답메시지로 보낸다.

응답메시지에는 위 사진처럼 HTTP/1.1 뒤에 201 Created를 추가하고 Location을 추가해준다. (필수는 아님)



🧐 POST 예시_요청 데이터를 어떻게 처리한다는 뜻일까?

  1. HTML 양식에 입력된 필드와 같은 데이터 블록을 데이터 처리 프로세스에 제공
    > HTML 폼에 입력한 정보로 회원가입하거나 주문 등을 처리
  1. 게시판, 뉴스 그룹, 메일링 리스트, 블로그 또는 유사한 기사 그룹에 메시지 게시
    > 게시판에 글을 쓰거나 댓글 달기
    > 게시판에 글을 쓰고 Submit 누르면 POST로 글이 서버로 전달하고 서버가 게시판에 글을 저장한다.
  1. 서버가 아직 식별하지 않은 새 리소스 생성
    > 신규 주문을 생성하거나 신규 회원을 생성할 때
  1. 기존 자원의 끝에 데이터를 추가
    > 한 문서 끝에 내용 추가하기

📌 POST 정리

1. 새 리소스 등록(생성)
: 서버가 아직 식별하지 않은 새 리소스를 생성한다.

2. 요청 데이터 처리
📍 단순히 데이터를 생성하거나, 변경하는 것을 넘어서 프로세스를 처리해야 하는 경우
EX) '주문에서 결제완료 ➡️ 배달 시작 ➡️ 배달완료' 처럼 단순히 값 변경을 넘어 프로세스의 상태가 변경되는 경우

📍 POST의 결과로 새로운 리소스가 생성되지 않을 수도 있다.
EX) POST /orders/{orderld}/start-delivery (컨트롤 URI)
✔️ 위 내용대로라면 리소스인 orders만 적으면 되지만 실무에서는 어쩔 수 없이 리소스만으로 URL 설계가 안 될 경우도 있다.

3. 다른 메서드로 처리하기 애매한 경우
: JSON으로 조회 데이터를 넘겨야 하는데, GET 메서드를 지원하지 않는 서버가 있어서 사용하기 어려운 경우
➕➕ 애매하면 POST를 사용한다.



3. HTTP 메서드 - PUT, PATCH, DELETE

📌 PUT
리소스가 있으면 대체하고, 없으면 생성한다. 폴더에 파일을 추가할 때 같은 이름의 파일이 없으면 그대로 들어가고, 있으면 덮어쓰는 것처럼 이해하면 쉽다.


📌 POST와 PUT의 차이점
PUT은 클라이언트가 구체적인 리소스 위치를 알고 URL을 지정한다.
예시) POST /members HTTP/1.1
        PUT /members/100 HTTP/1.1


📌 PUT 리소스가 있을 경우

클라이언트가 /members/100 리소스 지정해서 데이터를 서버에게 보냈는데 서버도 /members/100 리소스가 존재한다.
👉 서버에 있는 리소스를 클라이언트가 보낸 리소스대체해버린다.

📌 PUT 리소스가 없을 경우

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


💡 PUT 주의사항

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

👉 PUT은 기존 리소스를 새로운 리소스로 완전히 대체하기 때문에 리소스를 수정하기 어렵다. 그렇다면 이제 부분 변경이 가능한 메서드를 알아보자.


📌 PATCH

리소스를 부분 변경한다. 클라이언트 /members/100 데이터에 username이 없고 age를 지정해서 보내면 서버username은 남아있고 age만 변경된다.


📌 DELETE

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



4. HTTP 메서드의 속성

📌 안전(Safe Methods)
호출해도 리소스를 변경하지 않는다.

Q. 그래도 만약 계속 호출해서, 로그 같은게 쌓여서 장애가 발생하게 된다면?
A. 안전은 해당 리소스만 고려하기 때문에 그런 부분까지 고려하지 않는다.

📌 멱등(Idempotent)
f(f(x)) = f(x). 즉, 한 번 호출하든 두 번 호출하든 100번 호출하든 결과가 똑같다.

⚡ 멱등 메서드

  • GET: 한 번 조회하든, 두 번 조회하든 같은 결과가 조회된다.
  • PUT: 결과를 대체한다. 따라서 같은 요청을 여러 번 해도 최종 결과는 같다.
  • DELETE: 결과를 삭제한다. 같은 요청을 여러 번 해도 삭제된 결과는 똑같다.
  • POST: 멱등이 아니다! 두 번 호출하면 같은 결제가 중복해서 발생할 수 있다

Q. 아래와 같이 재요청 중간에 다른 곳에서 리소스를 변경해버리면 어떻게 될까?

사용자 1 : GET ➡️ username: A, age: 20
사용자 2 : PUT ➡️ username: A, age: 30
사용자 3 : GET ➡️ username: A, age: 30

A. 멱등은 외부 요인으로 중간에 리소스가 변경되는 것까지 고려하지 않는다. 즉, 클라이언트가 동일한 요청을 했을 때만 고려한다.

📌 캐시가능(Cacheable Methods)
웹 브라우저에 대용량 이미지를 한 번 요청하고 나면, 다음에 동일한 이미지를 재요청할 필요가 없다. 동일한 이미지를 서버에서 다운받으면 시간이 오래 걸리기 때문에 이미지를 로컬 PC에 웹 브라우저가 저장을 하고 있다. 이것을 캐시라 한다.

GET, HEAD, POST, PATCH 모두 캐시가 가능하지만 실제로는 GET, HEAD 정도만 캐시로 사용한다. POST, PATCH는 캐시를 하려면 본문 내용까지 캐시 키로 고려해야 해서 복잡해서 구현이 쉽지 않다. GET, HEADURL만 캐시 키로 캐시해서 간단하다.

0개의 댓글