요구사항
회원 목록 조회
회원 등록
회원 수정
회원 삭제
회원 조회
API URI 설계
먼저 요구사항에 대한 이름 만들기
(CRUD)
위와 같은 설계가 좋은 URI 설계일까?
-> 가장 중요한 것은 리소스 식별 !
리소스의 의미는 ?
미네랄
이다회원을 등록, 수정, 삭제, 조회 하는것을 모두 배제한다
오직 회원이라는 리소스만 식별하면된다 -> 회원 리소스를 URI에 매핑
따라서 다음과 같이 API URI를 설계
리소스 식별, URI 계층 구조 활용
(CRUD)
참고 : 계층 구조상 상위를 컬렉션으로 보고 복수형 단어 사용을 권장한다 (members)
id는 부여했는데 4개의 CRUD끼리 어떻게 구별할지 의문점이 든다
HTTP 메서드를 통해 위의 역활을 수행한다
http 메서드 : http메시지의 header에 포함되어있다
GET, POST, PUT, PATCH, DELETE
주요 메서드
기타 메서드
GET /search?q=hello&hl=ko HTTP/1.1
클라 -> 서버 (메시지 전달)
GET /members/100 HTTP/1.1
Host :localhost:8080
(개행)
{
"username":"woonsik",
"age":20"
}
메시지 서버 도착
서버가 메시지를 확인해서 응답데이터를 응답메시지로 만들어서 클라에게 전달
서버 -> 클라 (응답 데이터 전달)
응답 데이터
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 34
{
"username":"woonsik",
"age":20"
}
클라 -> 서버 (메시지 전달)
메시지
POST /members HTTP/1.1
Content-Type: application/json
{
"useranme":"woonsik",
"age":"20"
}
미리 클라이언트-서버간에 데이터 처리에 대해 약속을 해놓는다
만약 클라이언트가
POST
로/members
에 데이터를 보내면 서버는 전달받은 해당 데이터를 저장 혹은 내부적인 프로세스로 사용하는데 쓰겠다 라는 식이다
신규 리소스 생성
/members -> /members/100 신규 리소스 식별자 생성
{
"useranme":"woonsik",
"age":"20"
}
서버 -> 클라이언트 (응답 데이터 전달)
응답 데이터
HTTP/1.1 201(200도 가능) Created
Content-Type: application/json
Content-Length: 34
Location: /members/100
{
useranme":"woonsik",
"age":"20"
}
서버는 요청 데이터를 어떻게 처리할까?
POST 정의 : POST 메서드는 대상 리소스가 리소스의 고유한 의미 체계에 따라 요청에 포함된 표현을 처리하도록 요청한다
POST의 기능 예시)
즉, 이 리소스 URI에 POST 요청이 오면 요청 데이터를 어떻게 처리할지 리소스마다 따로 정해야한다 -> 정해진 것이 없다
POST /orders/{orderID}/start_delivery
(컨트롤 URI) 리소스만으로 설계를 못하는 경우도 존재PUT /members/100 HTTP/1.1 (100번 리소스를 지정)
Content-Type: application/json
{
useranme":"woonsik",
"age":"20"
}
즉 지정한 리소스에 위의 데이터를 주는 것, 따라서 미리 약속이 필요없다
서버에 리소스가 존재한다면, members/100
이 이미 있다면 전달하는 데이터로 완전히 대체한다
따라서 기존 데이터에 추가적인 데이터가 있더라도 다 지우고 새로 쓰게 된다. 그러므로 수정개념이 아니라 새롭게 만드는 개념이다
없다면 해당 데이터를 새로 생성
그렇게 결과적으로는 요청한 데이터로 새로만든 리소스를 클라이언트에게 반환 데이터로 전달
위와 같이 PUT이 리소스의 수정에 힘들다 보니 새로 추가된 메소드가 PATCH이다
PATCH의 경우 put과 똑같이 리소스의 URI를 지정하고 데이터를 전달하며, 해당 데이터가 서버의 리소스에도 있다면 변경(업데이트)해주고, 없다면 추가해준다 (기존 리소스의 데이터를 건들지 않는다)
그렇게 변경(수정)된 리소스를 반환 데이터로 클라이언트에게 전달
따로 클라에서 메시지를 보낼때 http body의 내용은 없고 리소스의 URI를 지정해서 해당 리소스를 클라이언트에서 지운다
DELETE /members/100 HTTP/1.1 (100번 리소스를 지정)
Content-Type: application/json
호출해도 리소스를 변경하지 않는다
Q. 지속적으로 호출해서 로그같은게 쌓여서 장애가 발생한다면?
A. 안전은 해당 리소스의 안전만을 고려한다. 그외의 부분은 고려하지 않는다
몇번을 호출해도 결과가 동일하다
조회를 몇번해도, 같은 데이터로 계속 덮어 씌어도, 같은 데이터를 계속 지워도 결과는 동일하다
POST의 경우 두번이상 호출하면 같은 행위가 중복해서 발생 할 수 있다
왜 멱등 기능이 필요할까?
활용
Q. 재요청 하는 중간에 다른곳에서 서버의 리소스를 변경한다면 멱등한 메소드라도 다른 리소스를 변경하게 되는데?
A. 외부 요인은 따지지 않는다. 단지 지금 사용하는 메서드의 관점에서만 따진다
Q. PATCH는 왜 멱등하지 않을까?
A. PATCH는 멱등할 수도 있고, 않할 수도 있다. 만약 이름을 a에서 b로 변경해라 와 같은 경우에는 지속적으로 불려도 결과가 동일하겠지만, 만약 나이가 10세 이하인 경우 특정값을 5 증가시켜라 와 같은 쿼리이면 반복했을때 지속적으로 값이 변경되는 결과를 낳을수 있다
예를 들어서 json데이터가 {"name":"kim"}
인 경우는 멱등하겠지만 {"operation":"add", "age":"1"}
인 경우에는 나이가 계속 1씩 더해지는 것이므로 멱등하지 않는 것
응답 결과 리소스를 캐시해서 사용해도 되는가
웹을 리롤드 할 경우 이미 다운받은 웹의 구성요소들이 있을 텐데 굳이 다시 다운받지 않고 로컬의 웹브라우저의 캐시메모리에 저장을 할수 있다
캐시가능 (웹브라우저가 해당 요청의 이미지를 저장하고 있을수 있는가 없는가)
실제로는 GET, HEAD 정도만 캐시를 사용한다
POST, PATCH의 경우 본문 내용도 캐시 키(key)로 고려해야하는데 구현이 쉽지 않다
캐시를 하기위해서는 key가 맞아야 value를 가져오는데 POST, PATCH의 경우 http 메시지의 body가 있으므로 해당 내용들까지 key로 고려하기가 쉽지 않다
정리
http api를 설계할때 자원, 리소스를 식별하는 구조로 해야한다. 동사가 아닌 명사(식별자, id)로 구분하고 동사는 http의 메서드를 활용하자
메서드로는 GET, POST, PUT, PATCH, DELETE 등 존재
위 메서들의 특징으로 Safe, Idempotent, Cacheable이 존재한다
해당 메소드를 써도 서버의 리소스가 안전한가?
해당 메소드를 반복적으로 불러도 서버의 리소스의 결과가 동일한가?
해당 메소드의 결과를 cache해도 되는가?