HTTP API를 만들어 보자
예를들어 회원 정보 관리 api를 만들어보자
혹시 넌 uri를 이렇게 만들거냐?
- 회원 목록 조회 /read-member-list
- 회원 조회 /read-member-by-id
- 회원 등록 /create-member
- 회원 수정 /update-member
- 회원 삭제 /delete-member
과연 이것이 좋은 URI 설계일까?
가장 중요한 것은 리소스 식별이다
그렇다면 리소스는 뭘까?
- 회원조회가 리소스가 아니라 “회원”이 리소스다
그럼 리소스를 어떻게 식별하는게 좋을까?
- “회원”이라는 리소스만 식별하면 된다 ⇒ “회원” 리소스를 URI에 매핑한다
이제 uri는 계층 구조를 활용해서 리소스를 리소스답게 설계 해볼까?
- 회원 목록 조회 /members
- 회원 조회 /members/{id} ..??
- 회원 등록 /members …??
- 회원 수정 /members/{id} …??
- 회원 삭제 /members/{id} …??
⇒ id: path variable
이렇게 되면 조회,등록,수정,삭제를 구분할 수 없을 것이다.
이때 필요한 것이 HTTP 메서드이다.
가장 중요한 것은 리소스 자체를 식별하는 것이다.
uri는 리소스만 식별한다!
리소스와 행위를 분리해야한다.
- 리소스(명사) ⇒ 회원
- 행위(동사) ⇒ 조회, 등록, 변경, 삭제
HTTP 메서드 - GET, POST, PUT, PATCH, DELETE
클라이언트가 서버에 뭔가 요청할 때 기대하는 행동이다.
- GET ⇒ 리소스 조회
- POST ⇒ 요청 데이터 처리, 주로 등록
- PUT ⇒ 리소스를 대체, 해당 리소스가 없으면 생성
- PATCH ⇒ 리소스 부분적으로 변경
- DELETE ⇒ 리소스 삭제
기타 메서드
- HEAD ⇒ GET과 동일. 메세지 부분 제외하고, 상태 줄과 헤더만 줘
- OPTIONS ⇒ 주로 CORS에서 사용
- CONNECT
- TRACE
GET
- 리소스 조회
- 검색엔진에 필요한(서버에 전달하고 싶은) 파라미터를 넘길때는 query를 통해 전달 ? &
- 메시지 바디를 사용해서 데이터를 전달할 수 있지만 지원하지 않는 곳이 많아서 권장하지 않음
과정
- 메세지를 전달한다
- 서버에 메세지가 도착한다
- 아 내부 데이터베이스 조회해서 json 등으로 만든다
- 서버에서 응답 메시지를 만들어서 클라이언트에 보낸다
- 그럼 데이터를 가지고 클라이언트에서 그린다
POST
- 요청 데이터 처리
- 메시지 바디를 통해 서버로 요청 데이터 전달
- 서버는 요청 데이터를 처리
- 메시지 바디를 통해 들어온 데이터를 처리하는 모든 기능을 수행
- 주로 신규 리소스 등록, 프로세스 처리에 사용
과정
- 메시지 전달
- 신규 리소스 생성
- 신규 리소스 식별자 생성
- 응답 데이터 전송
- 자원 생성 경로(locaiton)와 데이터 전송
POST는 요청 데이터를 어떻게 처리한다는 뜻일까?
- 스펙 : POST는 대상 리소스가 리소스의 고유 한 의미 체계에 따라 요청에 포함된 표현을 처리하도록 요청 ⇒ ???
- ex)
- html form 에서 회원가입, 주문 등
- 게시판 글쓰기, 댓글달기
- 신규 주문 생성
- 기존 자원 끝에 데이터 추가
- uri에 post 요청이 오면 데이터를 어떻게 처리할지 리소스마다 따로 정해야 함
-
새 리소스 생성(등록)
-
요청 데이터 처리
- 프로세스를 처리해야 하는 경우
- 결제 완료 ⇒ 배달 시작 ⇒ 배달 완료 등
- 결과로 새로운 리소스가 생성되지 않을 수 도 있다
- 컨트롤 uri ⇒ 동사로 시작하는 uri
-
다른 메서드로 처리하기 애매한 경우
- ex) json으로 조회 데이터를 넘겨야 하는데 get 메서드를 사용하기 어려운 경우
PUT
- 리소스를 대체 (덮어버림)
- 클라이언트가 리소소를 식별
- 클라이언트가 리소스 위치를 알고 uri 지정
- /members/100
- post와 차이점
과정
- 리소스가 있을 경우
- 클라이언트가 지정 ⇒ 서버에 있으면 리소스가 대체
- 리소스가 없는 경우
- 클라이언트가 리소스 전송 ⇒ 신규 리소스가 생성
PUT은 리소스를 완전히 대체한다!
- 만약 username 필드가 없는 상태로 전송한다면 없는 채로 리소스가 대체된다.
그래서 리소스를 부분 변경을 하고 싶다면 PATCH
를 사용하면 된다.
PATCH
- 리소스 부분 변경
- username만 변경하고 싶다면 부분적으로 변경된다
- 혹시 지원 안되는 서버가 있을 수도 있다
- 그런 경우는
POST
를 쓰면 된다
DELETE
HTTP 메서드의 속성
안전 (Safe)
- 호출해도 리소스를 변경하지 않는다 (해당 리소스만 고려)
멱등 (Idempotent)
- 한번 호출하든 100번 호출하든 결과가 똑같다
-
GET, PUT(똑같은 파일을 계속 보내도 결과는 같다), DELETE (여러번 요청해도 삭제함) ⇒ 멱등함
-
POST(여러번 결제하면 중복결제 된다) ⇒ 멱등하지 않다
멱등을 언제 쓰는가?
- 자동 복구 매커니즘
- 서버가 timeout 됐을 때 등….으로 정상 응답을 못 줬을 때 클라이언트가 같은 요청을 해도 되는지에 대한 판단 근거가 된다
- 같은 요청을 여러번 해도 된다면 멱등을 사용함
- ex) 재요청 중간에 다른 곳에서 리소스를 변경한다면?
캐시 가능(Cacheable)
- 응답 결과 리소스를 캐시해서 사용해도 되는가?
- GET, HEAD, POST, PATCH ⇒ 캐시 가능
- 실제로는 GET, HEAD 정도만 캐시로 사용
Reference.