쿼리 파라미터를 통한 데이터 전송(GET, 검색)
메시지 바디를 통한 데이터 전송(POST, PUT, PATCH)
정적 데이터 조회
쿼리 파라미터 미사용,
이미지, 정적 텍스트 문서
동적 데이터 조회
쿼리 파라미터 사용
주로 검색, 게시판 목록에서 정렬 필터, 조회는 GET 사용
html form을 통한 데이터 전송
POST 전송 - 저장용도로 주로 사용 (참고: html form 전송은 GET, POST만 지원함)
header content-type: application/x-www-form-urlencoded
POST면 자동으로 웹브라우저가 form data를 메세지 body에 넣고 GET이면 쿼리 파라미터로 넣어서 서버로 전송(GET은 당연히 조회 용도로만 가능)
multipart/form-data
http api를 통한 데이터 전송
서버 to 서버 (벡엔드 시스템 통신)
앱 클라이언트
html에서 form 전송 대신 자바스크립트를 통한 통신에 사용(ajax)
예시) react, vueJS 같은 웹클라이언트와 API 통신
POST, PUT, PATCH: 메시지 바디를 통해 데이터 전송
GET: 조회, 쿼리 파라미터로 데이터 전달
Content-Type: applocation/json을 주로 사용(사실상 표준)
POST 기반 등록 (회원관리 시스템)
• 회원 목록 /members -> GET
• 회원 등록 /members -> POST
• 회원 조회 /members/{id} -> GET
• 회원 수정 /members/{id} -> PATCH, PUT, POST
• 회원 삭제 /members/{id} -> DELETE
클라이언트는 등록될 리소스의 URI를 모르고, 서버가 새로 등록된 리소스 URI를 생성해준다.
컬렉션(collection) - 서버가 관리하는 리소스 디렉토리이고 서버가 리소스의 URI를 생성 관리
여기서 컬렉션은 /resource-name 을 가리킨다.
PUT 기반 등록 (파일 관리 시스템)
• 파일 목록 /files -> GET
• 파일 조회 /files/{filename} -> GET
• 파일 등록 /files/{filename} -> PUT
• 파일 삭제 /files/{filename} -> DELETE
• 파일 대량 등록 /files -> POST
클라이언트가 리소스 URI를 알고 있어야하고, 클라이언트가 직접 리소스의 URI를 지정한다.
스토어(Store) - 클라이언트가 관리하는 리소스 저장소로써, 리소스의 URI를 생성하고 관리
여기서 스토어는 /files를 가리킨다.
순수 HTML + HTML FORM 사용
• 회원 목록 /members -> GET
• 회원 등록 폼 /members/new -> GET
• 회원 등록 /members/new, /members -> POST
• 회원 조회 /members/{id} -> GET
• 회원 수정 폼 /members/{id}/edit -> GET
• 회원 수정 /members/{id}/edit, /members/{id} -> POST
• 회원 삭제 /members/{id}/delete -> POST
GET, POST만 지원하므로 제약이 있음
ajax같은 기술을 사용해서 해결 가능
컨트롤 URI로 해결
동사로된 리소스 경로사용
POST의 /new, /edit, /delete가 컨트롤 URI
http 메서드로 해결하기 애매한 경우 사용(HTTP API 포함)
• 문서(document)
• 단일 개념(파일 하나, 객체 인스턴스, 데이터베이스 row)
• 예) /members/100, /files/star.jpg
• 컬렉션(collection)
• 서버가 관리하는 리소스 디렉터리
• 서버가 리소스의 URI를 생성하고 관리
• 예) /members
• 스토어(store)
• 클라이언트가 관리하는 자원 저장소
• 클라이언트가 리소스의 URI를 알고 관리
• 예) /files
• 컨트롤러(controller), 컨트롤 URI
• 문서, 컬렉션, 스토어로 해결하기 어려운 추가 프로세스 실행
• 동사를 직접 사용
• 예) /members/{id}/delete
- 리소스만 가지고 설계를 완성하기 불가능한 경우, 추가적으로 설계에 필요해진다.
클라이언트가 보낸 요청의 처리 상태를 응답에서 알려주는 기능
• 1xx (Informational): 요청이 수신되어 처리중
• 2xx (Successful): 요청 정상 처리
• 3xx (Redirection): 요청을 완료하려면 추가 행동이 필요
• 4xx (Client Error): 클라이언트 오류, 잘못된 문법등으로 서버가 요청을 수행할 수 없음
• 5xx (Server Error): 서버 오류, 서버가 정상 요청을 처리하지 못함
200 OK - 요청 성공
201 created - 요청 성공해서 새로운 리소스가 생성됨
202 accepted - 요청은 접수 되었으나 처리가 완료되지 않음
204 No content - 서버가 요청을 성공적으로 수행했지만, 응답 페이로드 본문에 보낸 데이터가 없음
리다이렉션 이해
웹 브라우저는 3XX 응답의 경로가에 location 헤더가 있으면, location 위치로 자동 이동(리다이렉트)
• 영구 리다이렉션 - 특정 리소스의 URI가 영구적으로 이동
• 예) /members -> /users
• 예) /event -> /new-event
• 일시 리다이렉션 - 일시적인 변경
• 주문 완료 후 주문 내역 화면으로 이동
• PRG: Post/Redirect/Get
• 특수 리다이렉션
• 결과 대신 캐시를 사용
영구 리다이렉션(실무에서 많이 사용하진 않음, 그나마 301)
301, 308
원래의 URL을 사용하지 않는다, 검색엔진 등에서도 변경 인지
301 moved permanently, 308 permanet Redirect
차이: 같은 기능이나 301은 리다이렉트시 요청 메소드가 GET으로 변하면서 본문이 제거될 수 있으나, 308은 요청메서드와 본문이 유지 된다(post를 보내면 리다이렉트도 post)
일시적인 리다이렉션
리소스의 URI가 일시적으로 변경, 검색 엔진 등에서 URL을 변경하면 안됨
• 302 Found
• 리다이렉트시 요청 메서드가 GET으로 변하고, 본문이 제거될 수 있음(MAY)
• 307 Temporary Redirect
• 302와 기능은 같음
• 리다이렉트시 요청 메서드와 본문 유지(요청 메서드를 변경하면 안된다. MUST NOT)
• 303 See Other
• 302와 기능은 같음
• 리다이렉트시 요청 메서드가 GET으로 변경
일시적인 리다이렉션 - 예시
POST로 주문후에 웹브라우저를 새로고침하면 다시 요청하기때문에 중복 주문이 될 수 있다.
PRG 사용전 문제 발생
주문 요청 ->주문 데이터 저장 -> 응답 200 -> 새로고침 -> 중복 주문 요청 -> 주문데이터 저장 -> 응답 200
PRG 사용 방법
post로 주문후에 새로고침으로 인한 중복 주문 방지 목적
post로 주문후에 주문 결과 화면을 GET 메서드로 리다이렉트
새로고침해도 결과 화면을 GET으로 조회
중복 주문 대신에 결과 화면만 GET으로 다시 요청
주문 요청 -> 주문데이터 저장 -> 응답 302 -> 자동 리다이렉트 -> GET 요청 발생 -> 주문 데이터 조회 -> 200 응답 -> 새로고침 -> GET 요청 발생 -> 응답 200
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 Multiple Choices: 안쓴다
304 Not Modified
• 캐시를 목적으로 사용
• 클라이언트에게 리소스가 수정되지 않았음을 알려준다. 따라서 클라이언트는 로컬PC에
저장된 캐시를 재사용한다. (캐시로 리다이렉트 한다.)
• 304 응답은 응답에 메시지 바디를 포함하면 안된다. (로컬 캐시를 사용해야 하므로)
• 조건부 GET, HEAD 요청시 사용
클라이언트의 요청에 잘못된 문법등으로 서버가 요청을 수행할 수 없음
오류의 원인이 클라이언트에 있음
잘못된 요청이기에, 똑같은 제시도는 무조건 실패함.
400 bad Request
클라이언트가 잘못된 요청을 해서 서버가 요청을 처리 못함
예시) 요청 파라미터가 잘못되거나, API 스펙이 맞지 않을때
서버 쪽에서 스펙과 맞지 않는 요청은 무조건 400으로 튕겨줘야한다. (서버가 validation을 잘해줘야한다)
401 Unauthorized
클라이언트가 해당 리소스에 대한 인증이 필요함
401 오류 발생시 응답에 WWW-Authenticate 헤더와 함께 인증방법을 설명 해주어야 한다.
• 참고
• 인증(Authentication): 본인이 누구인지 확인, (로그인)
• 인가(Authorization): 권한부여 (ADMIN 권한처럼 특정 리소스에 접근할 수 있는 권한, 인증이 있어야 인가가 있음)
• 오류 메시지가 Unauthorized 이지만 인증 되지 않음 (이름이 아쉬움)
403 Forbidden
주로 인증 자격 증명은 있지만, 접근 권한이 충분하지 않은 경우
예시) 어드민 등급이 아닌 사용자가 로그인은 했지만, 어드민 등급의 리소스에 접근하는 경우
404 Not Found
요청 리소스가 서버에 없음
또는 클라이언트가 권한이 부족한 리소스에 접근할때 해당 리소스를 숨기고 싶을때
서버 문제로 오류 발생
서버에 문제가 있기 때문에 재시도 하면 성공할 수도 있음(복구가 되거나 등등)
500 Internal Server Error
서버 내부 문제로 오류 발생
503 Service Unavailable
서비스 이용 불가
서버가 일시적인 과부하 또는 예정된 작업으로 잠시 요청을 처리할 수 없음
Retry-After 헤더 필드로 얼마뒤에 복구되는지 보낼 수도 있음
500 에러는 서버에 정말 문제가 있을경우만 발생하도록 짜야된다. 비즈니스 로직상의 에러는 400 또는 200으로 해결하는것이 정석이다.