HTTP 메소드,메소드 활용, 상태코드

gustjtmd·2022년 3월 7일

HTTP 메소드

HTTP API를 만들어 보자

'요구사항 -> 회원 정보 관리 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

'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

HTTP 메소드 - PUT, PATCH, DELETE

'PUT' 
			PUT/members/100 HTTP/1.1 Content-Type: application/json
				{
					"username": "hello", "age": 20
				}
                
* '리소스를 대체'
	- 리소스가 있으면 대체
    - 리소스가 없으면생성
    - 쉽게 이야기해서 덮어버림
* '중요! 클라이언트가 리소스를 식별'
	- 클라이언트가 리소스 위치를 알고 URI 지정
    - POST와 차이점

'PATCH'

* 리소스 부분 변경

'DELETE'

* 리소스 제거


HTTP 메소드의 속성

'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 메소드 활용

* 클라이언트에서 서버로 데이터 전송
* HTTP API 설계 예시

클라이언트에서 서버로 데이터 전송 (데이터 전달 방식은 크게 2가지)

* 쿼리 파라미터를 통한 데이터 전송
	- 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 설계 예시

* 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/

HTTP 상태 코드

HTTP 상태코드 소개

상태코드 - 클라이언트가 보낸 요청의 처리 상태를 응답에서 알려주는 기능

* 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 - 성공

2xx(Successful) 클라이언트의 요청을 성공적으로 처리

- 200 OK
- 201 Created
- 202 Accepted
- 204 No Content


202 Accepted - 요청이 접수되었으나 처리가 완료되지 않았음

- 배치 처리 같은 곳에서 사용
예) 요청 접수 후 1시간 뒤에 배치 프로세스가 요청을 처리함

204 No Content 
	- 서버가 요청을 성공적으로 수행했지만, 응답 페이로드 본문에 보낼 데이터가 없음
예) 웹 문서 편집기에서 save 버튼
- save 버튼의 결과로 아무 내용이 없어도 된다.
- save 버튼을 눌러도 같은 화면을 유지해야 한다.
- 결과 내용이 없어도 204 메시지(2xx)만으로 성공을 인식할 수 있다.

3xx - 리다이렉션

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 - 클라이언트 오류, 5xx - 서버 오류

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 헤더 필드로 얼마뒤에 복구되는지 보낼 수도 있음
profile
반갑습니다

0개의 댓글