'요구사항 -> 회원 정보 관리 API를 만들어라'
1. 회원 목록 조회 /read-member-list
2. 회원 조회 /read-member-by-id
3. 회원 등록 /create-member
4. 회원 수정 /update-member
5. 회원 삭제 /delete-member
-> '이것은 좋은 URI 설계일까?'
'가장 중요한것은 리소스 식별'
API URI 고민(URI(Uniform Resource Identifier))
* 리소스의 의미는 뭘까?
* 회원을 등록하고 수정하고 조회하는게 리소스가 아니다
* 예) 미네랄을 캐라 -> 미네랄이 리소스
* '회원이라는 개념 자체가 바로 리소스이다.'
* 리소스를 어떻게 식별하는게 좋을까?
* 회원을 등록하고 수정하고 조회하는 것을 모두 배제
* '회원이라는 리소스만 식별하면 된다. -> 회원 리소스를 URI에 매핑'
'API URI 설계'
* 리소스 식별, URI 계층 구조 활용
1. 회원 목록 조회 /members
2. 회원 조회 /members/{id} -> 어떻게 구분하지?
3. 회원 등록 /members/{id} -> 어떻게 구분하지?
4. 회원 수정 /members/{id} -> 어떻게 구분하지?
5. 회원 삭제 /members/{id} -> 어떻게 구분하지?
'참고: 계층 구조상 상위를 컬렉션으로 보고 복수단어 사용 권장(member -> members)'
------------------------------------------------------------------------
'리소스와 행위를 분리'
* 가장 중요한 것은 리소스를 식별하는 것
* 'URI는 리소스만 식별!'
* 리소스와 해당 리소스를 대상으로 하는 '행위'를 분리
리소스 : 회원
행위 : 조회, 등록, 삭제, 변경
* 리소스는 명사, 행위는 동사 (미네랄을 캐라)
* 행위(메소드)는 어떻게 구분?
'HTTP 주요 메소드 종류'
* GET : 리소스 조회
* POST : 요청 데이터 처리, 주로 등록에 사용
* PUT : 리소스를 대체, 해당 리소스가 없으면 생성
* PATCH : 리소스 부분 변경
* DELETE : 리소스 삭제
'기타 메서드'
* HEAD: GET과 동일하지만 메시지 부분을 제외하고, 상태 줄과 헤더만 반환
* OPTIONS: 대상 리소스에 대한 통신 가능 옵션(메서드)을 설명(주로 CORS에서 사용)
* CONNECT: 대상 자원으로 식별되는 서버에 대한 터널을 설정
* TRACE: 대상 리소스에 대한 경로를 따라 메시지 루프백 테스트를 수행
'GET'
GET /search?q=hello&hl=ko HTTP/1.1
Host: www.google.com
* 리소스 조회
* 서버에 전달하고 싶은 데이터는 query(쿼리 파라미터, 쿼리 스트링)를 통해서 전달
* 메세지 바디를 사용해서 데이터를 전달할 수 있지만, 지원하지 않는곳이 많아서 관장하지 않음



'POST'
POST /members HTTP/1.1
Content-Type: application/json
{
"username": "hello", "age": 20
}
* 요청 데이터 처리
* '메세지 바디를 통해 서버로 요청 데이터 전달'
* 서버는 요청 데이터를 처리
* 메세지 바디를 통해 들어온 데이터를 처리하는 모든 기능을 수행한다.
* 주로 전달된 데이터로 신규 리소스 등록, 프로세스 처리에 사용



'POST 요청 데이터를 어떻게 처리한다는 뜻일까? 예시'
* 스펙 : POST 메서드는 대상 리소스의 고유 한 의미 체계에 따라 요청에 포함된 표현을 처리하
도록 요청합니다(구글 번역)
* 예를 들어 POST는 다음과 같은 기능에 사용됩니다
* HTML 양식에 입력된 필드와 같은 데이터 블록을 데이터 처리 프로세스에 제공
예) HTML FORM에 입력한 정보로 회원 가입, 주문 등에서 사용
* 게시판, 뉴스 그룹, 메일링 리스트, 블로그 또는 유사한 기사 그룹에 메세지 게시
예) 게시판 글쓰기, 댓글 달기
* 서버가 아직 식별하지 않은 새 리소스 생성
예) 신규 주문 생성
* 기존 자원에 데이터 추가
예) 한 문서 끝에 내용 추가하기
* 정리 : '이 리소스 URI에 POST 요청이 오면 요청 데이터를 어떻게 처리할지 리소스마다 따로'
'정해야 함 -> 정해진 것이 없음'
1. 새 리로스 생성(등록)
* 서버가 아직 식별하지 않은 새 리소스 생성
2. 요청 데이터 처리
* 단순히 데이터를 생성하거나, 변경하는 것을 넘어서 프로세스로 처리해야 하는 경우
예) 주문에서 결제완료 -> 배달시작 -> 배달완료 처럼 단순히 값 변경을 넘어서 프로세스의
상태가 변경되는 경우
* POST의 결과로 새로운 리소스가 생성되지 않을 수도 있음
예) POST /orders/{orderId}/start-delivery(컨트롤 URI)
3. 다른 메소드로 처리하기 애매한 경우
예) JSON으로 조회 데이ㅓ를 넘겨야 하는데 GET 메소드를 사용하기 어려운 경우
애매하면 POST
'PUT'
PUT/members/100 HTTP/1.1 Content-Type: application/json
{
"username": "hello", "age": 20
}
* '리소스를 대체'
- 리소스가 있으면 대체
- 리소스가 없으면생성
- 쉽게 이야기해서 덮어버림
* '중요! 클라이언트가 리소스를 식별'
- 클라이언트가 리소스 위치를 알고 URI 지정
- POST와 차이점






'PATCH'
* 리소스 부분 변경


'DELETE'
* 리소스 제거


'HTTP 매소드의 속성'
* 안전(Safe Methods)
* 멱등(Idempotent Methods)
* 캐시가능(Cacheable Methods)

'안전'
* 호출해도 리소스를 변경하지 않는다.
Q : 그래도 계속 호출해서, 로그 같은게 쌓여서 장애가 발생하면?
A : 안전은 해당 리소스만 고려한다 그런 부분까지 고려하지 않는다.
'멱등'
* f(f(x)) = f(x)
* 한 번 호출하든 두 번 호출하든 100번 호출하든 결과가 똑같다.
* 멱등 메서드
- GET : 한 번 조회하든, 두 번 조회하든, 같은 결과가 조회된다.
- PUT : 결과를 대체한다. 따라서 같은 요청을 여러번 해도 최종 결과는 같다.
- DELETE : 결과를 삭제한다. 같은 요청을 여러번 해도 삭제된 결과는 똑같다.
- 'POST' : 멱등이 아니다! 두 번 호출하면 같은 결제가 중복해서 발생할 수 있다.
* 활용
- 자동 복구 메커니즘
- 서버가 TIMEOUT 등으로 정상 응답을 못주었을때, 클라이언트가 같은 요청을 다시해도
되는가? 판단 근거.
Q : 재요청 중간에 다른 곳에서 리소스를 변경해버리면?
예) 사용자1 : GET -> username: A, age :20
사용자2 : PUT -> username:A, age : 30
사용자1 : GET -> username:A, age : 30 -> 사용자2의 영항으로 바뀐 데이터 조회
A : 멱등은 외부 요인으로 중간에 리소스가 변경되는 것 까지는 고려하지 않는다.
'캐시가능'
* 응답 결과 리소스를 캐시해서 사용해도 되는가?
* GET, HEAD, POST, PATCH 캐시가능
* 실제로는 GET, HEAD 정도만 캐시로 사용
* POST, PATCH는 본문 내용까지 캐시 키로 고려해야 하는데 구현이 쉽지 않음.
* 클라이언트에서 서버로 데이터 전송
* HTTP API 설계 예시
* 쿼리 파라미터를 통한 데이터 전송
- GET
- 주로 정렬 필터(검색어)
* 메시지 바디를 통한 데이터 전송
* POST, PUT, PATCH
* 회원 가입, 상품 주문, 리소스 등록, 리소스 변경
클라이언트에서 서버로 데이터 전송(4가지 상황)
* 정적 데이터 조회
- 이미지, 정적 테스트 문서
* 동적 데이터 조회
- 주로 검색, 게시판 목록에서 정렬 필터(검색어)
* HTML Form을 통한 데이터 전송
- 회원 가입, 상품 주문, 데이터 변경
* HTTP API를 통한 데이터 전송
- 회원 가입, 상품 주문, 데이터 변경
- 서버 to 서버, 앱 클라이언트, 웹 클라이언트(Ajax)

'정적 데이터 조회 정리'
- 이미지, 정적 텍스트 문서
- 조회는 GET 사용
- 정적 데이터는 일반적으로 쿼리 파라미터 없이 리소스 경로로 단순하게 조회 가능

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




'HTML Form 데이터 전송 정리'
* HTMl Form submit시 POST 전송
예) 회원가입, 상품주문, 데이터 변경
* Content-Type : application/x-www-form-urlencoded 사용
* form의 내용을 메시지 바디를 통해서 전송(key = value, 쿼리 파라미터 형식)
* 전송 데이터를 url encoding 처리
예) abc김 -> abc%EA%B9%80
* HTML Form은 GET 전송도 가능
* Content-Type : multipart/form-data
* 파일 업로드 같은 바이너리 데이터 전송시 사용
* 다른 종류의 여러 파일과 폼의 내용 함께 전송 가능(그래서 이름이 multipart)
* 참고 : HTML Form 전송은 'GET,POST만 지원'

'HTTP API 데이터 전송 정리'
* 서버 to 서버
- 백엔드 시스템 통신
* 앱 클라이언트
- 아이폰, 안드로이드
* 웹 클라이언트
- HTML에서 Form 전송 대신 자바 스크립트를 통한 통신에 사용(AJAX)
예) React, VueJs 같은 웹 클라이언트와 API 통신
* POST, PUT, PATCH : 메시지 바디를 통해 데이터 전송
* GET : 조회, 쿼리 파라미터로 데이터 전달
* Content-Type : application/json을 주로 사용 (사실상 표준)
* TEXT, XML, JSON 등등
* HTTP API - 컬렉션
* POST 기반 등록
* 예) 회원 관리 API 제공
* HTTP API - 스토어
* PUT 기반 등록
* 예) 정적 컨텐츠 관리, 원격 파일 관리
* HTML FORM 사용
* 웹 페이지 회원 관리
* GET,POST만 지원
'회원 관리 시스템 API 설계 - POST 기반 등록'
* 회원 목록 /members -> GET
* 회원 등록 /members -> POST
* 회원 조회 /members/{id} -> GET
* 회원 수정 /members/{id} -> PATCH, PUT, POST
* 회원 삭제 /members/{id} -> DELETE
'회원 관리 시스템 POST - 신규 자원 등록 특징'
* 클라이언트는 등록될 리소스의 URI를 모른다.
- 회원 등록 /members -> POST
- POST /members
* 서버가 새로 등록된 리소스 URI를 생성해준다.
- HTTP/1.1 201 Created
Location: /members/100
* 컬렉션
- 서버가 관리하는 리소스 디렉토리
- 서버가 리소스의 URI를 생성하고 관리
- 여기서 컬렉션은 /members
'파일 관리 시스템 API 설계 - PUT 기반 등록'
* 파일 목록 /files -> GET
* 파일 조회 /files/{filename} -> GET
* 파일 등록 /files/{filename} -> PUT
* 파일 삭제 /files/{filename} -> DELETE
* 파일 대량 등록 /files -> POST
'파일 관리 시스템 PUT - 신규 자원 등록 특징'
* 클라이언트가 리소스 URI를 알고 있어야 한다.
- 파일 등록 /files/{filename} -> PUT
- PUT /files/star.jpg
* 클라이언트가 직접 리소스의 URI를 지정한다.
* 스토어
- 클라이언트가 관리하는 리소스 저장소
- 클라이언트가 리소스의 URI를 알고 관리
- 여기서 스토어는 /files
'HTML FORM 사용'
* HTML FORM은 GET, POST만 지원
* AJAX 같은 기술을 사용해서 해결 가능 -> 회원 API 참고
* 여기서는 순수 HTML, HTML FORM 이야기
* GET, POST만 지원하므로 제약이 있음.

* HTML FORM은 'GET, POST'만 지원
* 컨트롤 URI
- GET, POST만 지원하므로 제약이 있음
- 이런 제약을 해결하기 위해 동사로 된 리소스 경로 사용
- POST의 /new, /edit, /delete가 컨트롤 URI
- HTTP 메소드로 해결하지 애매한 경우 사용(HTTP API 포함)
'정리'
* HTTP API - 컬렉션
- POST 기반 등록
- 서버가 리소스 URI 결정
* HTTP API - 스토어
- PUT 기반 등록
- 클라이언트가 리소스 URI 결정
* HTML FORM 사용
- 순수 HTML + HTML form 사용
- GET, POST만 지원
'참고하면 좋은 URI 설계 개념'
* 문서(document)
- 단일 개념(파일 하나, 객체 인스턴스, 데이터베이스 row)
예) /members/100, /files/star.jpg
* 컬렉션(collection)
- 서버가 관리하는 리소스 디렉터리
- 서버가 리소스의 URI를 생성하고 관리
예) /members
* 스토어(store)
- 클라이언트가 관리하는 자원 저장소
- 클라이언트가 리소스의 URI를 알고 관리
예) /files
* 컨트롤러(controller), 컨트롤 URI
- 문서, 컬렉션, 스토어로 해결하기 어려운 추가 프로세스 실행
- 동사를 직접 사용
- 예) /members/{id}/delete
참고 주소 : https://restfulapi.net/resource-naming/
상태코드 - 클라이언트가 보낸 요청의 처리 상태를 응답에서 알려주는 기능
* 1xx(Informational) : 요청이 수신되어 처리중
* 2xx(Successful) : 요청 정상 처리
* 3xx(Redirection) : 요청을 완료하려면 추가 행동이 필요
* 4xx(Client Error) : 클라이언트 오류, 잘못된 문법등으로 서버가 요청을 수행할 수 없음
* 5xx(Server Error) : 서버 오류, 서버가 정상 요청을 처리하지 못함
'만약 모르는 상태 코드가 나타나면?'
* 클라이언트가 인식할 수 없는 상태코드를 반환하면?
* 클라이언트는 상위 상태코드로 해석해서 처리
* 미래에 새로운 상태 코드가 추가되어도 클라이언트를 변경하지 않아도 됨
예)
299 ??? -> 2xx(Successful)
451 ??? -> 4xx(Client Error)
599 ??? -> 5xx(Server Error)
1xx(Informational)
'요청이 수신되어 처리중'
- 거의 사용하지 않으므로 생략
2xx(Successful) 클라이언트의 요청을 성공적으로 처리
- 200 OK
- 201 Created
- 202 Accepted
- 204 No Content


202 Accepted - 요청이 접수되었으나 처리가 완료되지 않았음
- 배치 처리 같은 곳에서 사용
예) 요청 접수 후 1시간 뒤에 배치 프로세스가 요청을 처리함
204 No Content
- 서버가 요청을 성공적으로 수행했지만, 응답 페이로드 본문에 보낼 데이터가 없음
예) 웹 문서 편집기에서 save 버튼
- save 버튼의 결과로 아무 내용이 없어도 된다.
- save 버튼을 눌러도 같은 화면을 유지해야 한다.
- 결과 내용이 없어도 204 메시지(2xx)만으로 성공을 인식할 수 있다.
3xx(Redirection) - 요청을 완료하기 위해 유저 에이전트의 추가 조치 필요
* 300 Multiple Choices
* 301 Moved Permanetly
* 302 Found
* 303 See Other
* 304 Not Modified
* 307 Temporary Redirect
* 308 Permane Redirect
'리다이렉션 이해'
- 웹 브라우저는 3xx 응답의 결과에 Location 헤더가 있으면, Location 위치로 자동 이동
(리다이렉트)

'리다이렉션의 종류'
* 영구 리다이렉션 - 특정 리소스의 URI가 영구적으로 이동
예) /members -> /users
예) /event -> /new-event
* 일시 리다이렉션 - 일시적인 변경
- 주문 완료 후 주문 내역 화면으로 이동
- PRG : Post/Redirect/Get
* 특수 리다이렉션
- 결과 대신 캐시를 사용
'영구 리다이렉션' - 301, 308
* 리소스의 URI가 영구적으로 이동
* 원래의 URL를 사용X, 검색 엔진 등에서도 변경 인지
* 301 Moved Permanently
- 리다이렉트시 요청 메소드가 GET으로 변하고, 본문이 제거될 수 있음 (MAY)
* 308 Permanent Redirect
- 301과 기능은 같음
- 리다이렉트시 요청 메소드와 본문 유지(처음 POST를 보내면 리다이렉트도 POST 유지)


'일시적인 리다이렉션' - 302, 307, 303
- 리소스의 URI가 일시적으로 변경
- 따라서 검색 엔진 등에서 URL을 변경하면 안됨
- 302 Found
- 리다이렉트시 요청 메소드가 GET으로 변하고, 본문이 제거될 수 있음(MAY)
- 307 Temporay Redirect
- 302와 기능은 같음
- 리다이렉트시 요청 메소드와 본문 유지(요청 메소드를 변경하면 안된다. MUST NOT)
- 303 See Other
- 302와 기능은 같음
- 리다이렉트시 요청 메소드가 GET으로 변경
'PRG : Post/Redirect/Get 일시적인 리다이렉션 - 예시'
* POST로 주문후에 웹 브라우저를 새로고침하면?
* 새로고침은 다시 요청
* 중복 주문이 될 수 있다.

* POST로 주문후에 새로 고침으로 인한 중복 주문 방지
* POST로 주문후에 주문 결과 화면을 GET 메소드로 리다이렉트
* 새로고침해도 결과 화면을 GET으로 조회
* 중복 주문 대신에 결과 화면만 GET으로 다시 요청

* PRG 이후 리다이렉트
- URL이 이미 POST -> GET으로 리다이렉트 됨
- 새로 고침 해도 GET으로 결과 화면만 조회
'그래서 뭘 써야 하나요?' - 302,307,303
* 잠깐 정리
- 302 Found -> GET으로 변할 수 있음
- 307 Temporary Redirect -> 메소드가 변하면 안됨
- 303 See Other -> 메소드가 GET으로 변경
* 역사
- 처음 302 스펙의 의도는 HTTP 메소드를 유지하는 것
- 그런데 웹 브라우저들이 대부분 GET으로 바꾸어버림(일부는 다르게 동작)
- 그래서 모호한 302를 대신하는 명확한 307,303이 등장함(301 대응으로 308도 등장)
* 현실
- 307, 303을 권장하지만 현실적으로 이미 많은 애플리케이션 라이브러리들이 302를 기본
값으로 사용
- 자동 리다이렉션시에 GET으로 변해도 되면 그냥 302를 사용해도 큰 문제 없음
'기타 리다이렉션' - 300, 304
* 300 Multiful Choices : 안쓴다
* 304 Not Modified
- 캐시를 목적으로 사용
- 클라이언트에게 리소스가 수정되지 않았음을 알려준다. 따라서 클라이언트는 로컬PC에
저장된 캐시를 재사용한다(캐시로 리다이렉트 한다.)
- 304 응답은 응답에 메시지 바디를 포함하면 안된다.(로컬 캐시를 사용해야 하므로)
- 조건부 GET,HEAD 요청시 사용
4xx(Client Error) - 클라이언트 오류
* 클라이언트의 요청에 잘못된 문법등으로 서버가 요청을 수행할 수 없음
* '오류의 원인이 클라이언트에 있음'
* 중요! 클라이언트가 이미 잘못된 요청, 데이터를 보내고 있기 때문에, 똑같은 재시도가
실패함
'400 Bad Request - 클라이언트가 잘못된 요청을 해서 서버가 요청을 처리할 수 없음'
* 요청 구문, 메시지 등등 오류
* 클라이언트는 요청 내용을 다시 검토하고 보내야함
예) 요청 파라미터가 잘못되거나, API 스펙이 맞지 않을때
'401 Unauthorized - 클라이언트가 해당 리소스에 대한 인증이 필요함'
* 인증(Authentication) 되지 않음
* 401 오류 발생시 응답에 WWW-Authenticate 헤더와 함께 인증 방법을 설명
* 참고
- 인증(Authentication): 본인이 누구인지 확인,(로그인)
- 인가(Authorization) : 권한 부여(Admin 권한처럼 특정 리소스에 접근할 수 있는 권한,
인증이 있어야 인가가 있음)
- 오류 메시지가 Unauthorized 이지만 인증 되지 않음(이름이 아쉬움)
'403 Forbidden - 서버가 요청을 이해했지만 승인을 거부함'
* 주로 인증 자격 증명은 있지만, 접근 권한이 불충분한 경우
예) 어드민 등급이 아닌 사용자가 로그인은 했지만, 어드민 등급의 리소스에 접근하는 경우
'404 Not Found - 요청 리소스를 찾을 수 없음'
* 요청 리소스가 서버에 없음
* 또는 클라이언트가 권한이 부족한 리소스에 접근할 때 해당 리소스를 숨기고 싶을때
5xx(Server Error) - 서버 오류
* 서버 문제로 오류 발생
* 서버에 문제가 있기 때문에 재시도 하면 성공할 수도 있음(복구가 되거나 등등)
'500 Interna Server Error - 서버 문제로 오류 발생, 애매하면 500 오류'
* 서버 내부 문제로 오류 발생
* 애매하면 500 오류
'503 Service Unavailable - 서비스 이용 불가'
* 서버가 일시적인 과부하 또는 예정된 작업으로 잠시 요청을 처리할 수 없음
* Retry-After 헤더 필드로 얼마뒤에 복구되는지 보낼 수도 있음