HTTP란?
정의
- 웹(WWW, Wolrd Wide Web)에서 Client와 Server간에 데이터를 주고받기 위해 등장한 프로토콜로, 원활하고 일관성있는 통신을 위한 규칙이다
- 서로 다른 시스템 간 통신에서 요청과 응답의 형식, 처리 방식에 대한 공통 규칙이 없다면, 일관성있고 원활한 통신이 어렵기 때문에 이를 표준화하기 위해 정의되었다
- 현재는 웹을 포함한 다양한 분산환경의 API 통신에서도 사용된다
특징
- 무상태(Stateless) 프로토콜 -> 따라서 각 요청은 독립적이고, 이전 요청을 기억하지 않는다
- 요청-응답 모델 -> 클라이언트가 API 요청을 보내면, 서버에서 응답을 해주는 방식
- 전송 가능한 데이터에는 다양한 종류가 있다 -> html, css, java script, png, gif, mp4, ...
동작
- 일반적으로 TCP/IP 프로토콜 기반으로 동작한다
- HTTP/1.0 -> 연결을 수립하고 끊는 과정을 매 요청마다 반복
- HTTP/1.1 이상 -> 'keepalive'를 사용하여, 데이터 교환이 모두 끝날때까지 연결을 끊지 않는다
보안
- 데이터를 평문으로 전송해, 도청 및 데이터 변조의 위험이 있다
- 중간에서 패킷을 가로채 내용을 엿볼 수 있고, 필요에 따라 수정할수도 있기에 보안이 좋지 못함
- 따라서 이를 해결하고자 HTTPS(HTTP Secure)가 등장
- HTTPS : HTTP에 SSL(Secure Socket Layer)/TLS(Transport Layer Security) 프로토콜을 통해 데이터를 암호화시켜 전송하는 프로토콜
HTTP Method
정의
- 클라이언트가 서버로 API 요청을 보낼 때, 해당 요청이 '무엇을 하고 싶은 요청인지'를 명확하게 나타내는 수단
- 종류
- GET -> "가져오기", 서버의 리소스를 조회만 하고 변경하지 않는다
- POST -> "생성하기", 새로운 데이터를 서버에 보내서 생성한다
- PUT -> "전체 교체하기", 기존 리소스를 완전히 새로운 내용으로 바꾼다
- PATCH -> "부분 수정하기", 기존 리소스의 일부분만 변경한다
- DELETE -> "삭제하기", 기존 리소스를 서버에서 제거한다(물리적 삭제와 논리적 삭제 모두 포함. 클라이언트에서 알 필요는 없음)
HTTP Method의 멱등성
정의
- HTTP에서 멱등성이란, "같은 요청을 여러 번 보내도 서버의 상태가 동일하다" 라는 의미
- Method별 멱등성 여부
- GET (멱등하다) -> 동일한 uri로 여러번 호출해도, 단순 조회이기 때문에 서버의 상태가 변하지 않는다
- POST (멱등성을 보장하지 않는다) -> 동일한 uri로 동일한 resource를 요청하더라도, 요청시마다 서버에 새로운 데이터가 생성되므로 서버의 상태가 변한다. 하지만 '멱등 키(Idempotency Key)'를 사용하여 멱등성을 보장하도록 처리할 수도 있다
- PUT (멱등하다) -> 대상 자원의 값을 '덮어씌우는' 행동이므로, 몇 번을 호출하더라도 최초 1회를 제외하고는 서버 상태가 변하지 않는다
- PATCH (설계에 따라 다르다) -> 기본적으로는 멱등성을 가지지 않지만, 구현 자체를 PUT처럼 대상 리소스를 덮어씌우는 방식으로 구현한다면 멱등성을 가지게 된다. 즉, 설계에 따라 멱등성 여부가 달라진다
- ex) PATCH { likeCount : +1 } -> 해당 api의 경우 서버에 저장된 likeCount가 1씩 계속 증가하므로 서버 상태가 변한다
- ex) PATCH { likeCount : k } -> 반대로 likeCount를 k로 지정해버리면, k로 덮어씌워지므로 서버 상태가 변하지 않는다
- DELETE (멱등하다) -> 대상 자원을 삭제하는 행동이므로, PUT과 마찬가지로 최초 1회를 제외하고는 서버 상태가 변하지 않는다
'GET'과 'POST'의 차이
핵심
- '단순 목적'만이 아니라, '멱등성 여부'도 신경을 써야한다
GET
- 본질적으로 '안전'하고 '멱등성'이 보장되기에 서버 상태를 변경하지 않는다
- 따라서 '재시도'에 대해 서버 상태가 변하지 않는 특성을 가진다
- 이 특성 덕분에 브라우저에서 '캐시'되고 히스토리에 '저장'될 수 있다
- 또한 주로 'URL에 정보'를 담아 보내기에 북마크 할 수 있으며, 공유가 가능하다
- 하지만 URL 길이에 제한이 있어서 담을 수 있는 정보량에 한계가 있고, 보안상 민감한 정보가 노출될 위험이 존재한다
POST
- 본질적으로 '안전'하지 않고, '멱등성'을 보장하지 않는다
- 따라서 재시도시 중복 처리 위험이 있기에, 보수적으로 접근해야한다
- GET과 다르게, 필요한 정보를 요청 본문(Body)에 포함시킨다
- 덕분에 대용량 데이터를 전송할 수 있다
- 하지만 Body에 저장한다해도, TLS가 없으면 민감한 정보가 노출될 수 있다
'GET' 요청의 Body 사용은 왜 안티패턴일까?
- 일관성 & RESTful API 설계 원칙 문제
- 'GET'의 본래 의도와 맞지 않아 일관성이 깨진다
- 본래 의도는 '리소스 가져오기'로, 최초 설계시 URL에 명시된 경로의 리소스를 가져오도록 되어있었다
- 따라서 Body에 데이터를 넣으면 ‘무엇을 조회하는가(URI)’와 ‘조회 조건(Body)’이 분리되어, API 의미가 불명확해지고 일관성이 떨어진다
- 캐싱 문제
- HTTP 캐싱은 URL을 기준으로 작동하기에, Body의 데이터 변경을 캐싱 시스템에서 구분할 수 없다
- 따라서 의도와 다르게 동일한 캐싱 데이터를 반환할 위험이 존재한다
- 호환성 문제
- 일부 네트워크 시스템(ex. Http 클라이언트, 프록시, 로드밸런서 등)에서 'GET'요청의 Body를 비표준으로 판단하여 무시하거나 제거하도록 구현되어 있는 경우가 있다
- 따라서 의도와 다르게 동작할 위험성이 존재한다
- 로깅 문제
- 웹 서버의 엑세스 로그는 보통 URL만을 기록한다
- 따라서 'GET' 요청시 Body에 데이터가 들어있다면, 별도 설정이 없다면 로그를 보더라도 디버깅이 어렵다