이번 글에서는 HTTP의 가장 큰 특징인 비연결성, 무상태 그리고 HTTP 상태코드(status)와 메서드(method), 헤더(header)에 대해 알아보도록 하겠습니다.
비연결성은 클라이언트와 서버가 한 번 연결을 맺은 후, 클 라이언트 요청에 대해 서버가 응답을 마치면 맺었던 연결을 끊어 버리는 성질을 말합니다.
1) 비연결성의 장점
HTTP 프로토콜은 왜 한 번 맺은 연결을 끊어버리는걸까요?
HTTP는 인터넷 상에서 불특정 다수의 통신 환경을 기반으로 설계되었습니다.
만약 서버에서 다수의 클라이언트와 연결을 계속 유지해야 한다면, 이에 따른 많은 리소스가 발생하게 됩니다.
따라서 연결을 유지하기 위한 리소스를 줄이면 더 많은 연결을 할 수 있으므로 비연결적인 특징을 갖습니다.
2) 비연결성의 단점
물론 이로 인한 단점도 존재합니다.
서버는 클라이언트를 기억하고 있지 않으므로 동일한 클라이언트의 모든 요청에 대해, 매번 새로운 연결을 시도/해제의 과정을 거쳐야하므로 연결/해제에 대한 오버헤드가 발생한다는 단점이 있습니다.
3) KeppAlive
이에 대한 해결책으로 오버헤드를 줄이기 위해 HTTP의 KeepAlive 속성을 사용할 수 있습니다.
KeepAlive는 지정된 시간동안 서버와 클라이언트 사이에서 패킷 교환이 없을 경우, 상대방의 안부를 묻기위해 패킷을 주기적으로 보내는것을 말합니다.
이 때 패킷에 반응이 없으면 접속을 끊게 됩니다.
주기적으로 클라이언트의 상태를 체크한다는 것으로 미루어보아 KeepAlive 역시 완벽한 해결책은 아닙니다.
KeepAlive 속성이 On 상태라해도, 서버가 바쁜 환경에서는 프로세스 수가 기하급수적으로 늘어나기 때문에 KeepAlive로 상태를 유지하기 위한 메모리를 많이 사용하게 되므로 주의해야 합니다.
1) 무상태란?
Connectionless로 인해 서버는 클라이언트를 식별할 수가 없는데, 이를 Stateless라고 합니다.
클라이언트의 상태를 모른다는 것은 예를 들면 다음과 같습니다.
쇼핑몰에 접속
로그인
상품 클릭 -> 상세화면으로 이동
로그인
주문
로그인
....
즉, 매번 새로운 인증을 해야하는 번거로움이 발생하게 됩니다.
2) 상태를 기억하는 방법 - 쿠키
서비스를 운영하려면 서버가 클라이언트를 기억해야 할 경우가 많이 있는데, 클라이언트를 기억할 수 있는 방법은 없을까요?
HTTP는 이러한 문제점을 해결하기 위해 브라우저 단에서 쿠키라는 것을 저장하여 서버가 클라이언트를 식별할 수 있도록 합니다.
( HTTP 헤더 : set-cookie )
3) 상태를 기억하는 방법 - 세션
쿠키는 사용자 정보가 브라우저에 저장되기 때문에 공격자로부터 위변조의 가능성이 높아 보안에 취약합니다.
이와 달리 세션은 브라우저가 아닌 서버단에서 사용자 정보를 저장하는 구조입니다.
따라서 쿠키보다는 안전하다고 할 수 있습니다.
그런데 세션 정보도 중간에 탈취 당할 수 있기 때문에 보안에 완벽하다고 할 수 없습니다.
또한 세션을 사용하면 서버에 사용자 정보를 저장하므로, 서버의 메모리를 차지하게 되고, 만약 동시 접속자 수가 많은 서비스일 경우에는 서버 과부화의 원인이 됩니다.
4) 상태를 기억하는 방법 - 토큰을 사용하는 OAuth, JWT
쿠키와 세션의 문제점들을 보완하기 위해 토큰( Token )기반의 인증 방식이 도입되었습니다.
토큰 기반의 인증 방식의 핵심은 보호할 데이터를 토큰으로 치환하여 원본 데이터 대신 토큰을 사용하는 기술입니다.
그래서 중간에 공격자로부터 토큰이 탈취당하더라도 데이터에 대한 정보를 알 수 없으므로, 보안성을 높은 기술이라 할 수 있습니다.
대표적으로는 OAuth와 JWT이 있습니다.
그런데 꼭 토큰 기반의 인증이 좋다고는 할 수 없습니다.
서비스에 따라 기술의 특징을 잘 이해하여 때에 따라 쿠키, 세션, OAuth, JWT 등을 적절히 사용하는 것이 좋습니다.
위에서 언급한 기술들에 대해서는 아래의 링크를 참고해주시기 바랍니다.
쿠키와 세션 (링크)
OAuth (링크)
JWT ( 링크 )
클라이언트가 서버에 요청을 하면, 서버는 요청에 대한 처리 상태를 숫자로 반환하는데 이를 응답코드라 합니다.
흔히 웹 개발을 하다 보면 응답코드로 404를 많이 보셨을텐데요,
404 코드는 "웹 페이지를 찾을 수 없다"는 것을 알고 계실 것입니다.
이처럼 HTTP 응답에는 상태 코드를 헤더에 추가하여 응답을 합니다.
상태코드에 대한 자세한 정보는 링크를 참고해주시고, 상태 코드를 요약하면 다음과 같습니다.
100 - 109
메시지 정보
200 - 206
요청 성공
300 - 305
리다이렉션
400 - 415
클라이언트 에러
500 - 505
서버에러
API 개발 시 올바른 상태코드를 응답하는 것은 매우 중요합니다.
예를 들어, 사용자가 요청 파라미터를 잘못 입력한 경우
잘못된 파라미터로 인해 비즈니스 로직에서 에러가 발생했다고하여, 500 코드를 반환하면 안됩니다.
사용자가 잘못 입력한 경우이므로, 이 때는 403 코드를 반환해야 맞습니다.
이처럼 HTTP 응답 코드는 약속이며, 모두가 이해할 수 있는 올바른 코드를 응답하는 것이 중요합니다.
클라이언트가 서버로 요청을 할 때, 어떠한 목적을 갖는 행위인지 HTTP 메서드에 명시합니다.
다음은 HTTP Method를 정리한 것입니다.
GET
서버에게 리소스를 달라는 요청 ( 조회 )
HEAD
정확히 GET과 같지만, 서버는 응답으로 엔터티 본문 반환없이 헤더만을 반환.
클라이언트는 리소스를 가져올 필요 없이 헤더만을 통해 정보를 얻을 수 있습니다.
PUT
서버가 요청의 본문을 갖고 요청 URI의 이름대로 새 문서를 만들거나, 이미 URI가 존재한다면 요청 본문을 변경할 때 사용합니다. ( 수정 )
POST
서버에 입력데이터를 전송하며 요청 엔티티 본문에 데이터를 넣어 서버에 전송합니다. ( 삽입 )
DELETE
서버에서 요청 URI 리소스를 삭제하도록 요청합니다. ( 삭제 )
클라이언트는 항상 삭제된다고 생각하지만, 서버에서는 이 요청을 무시할 수도 있습니다.
TRACE
클라이언트와 목적지 서버 사이에 있는 모든 HTTP 애플리케이션의 요청/응답 연쇄를 따라가면서 자신이 보낸 메시지의 이상 유무를 파악합니다.
서버는 응답 메시지의 본문에 자신이 받은 요청메시지를 넣어 응답하며, 주로 진단을 위해 사용합니다.
OPTIONS
서버에게 특정 리소스가 어떤 메소드를 지원하는지 물어볼 수 있습니다.
1) REST
개발자라면 REST, REST API, Restful, Restful API 단어들을 많이 들어보셨을 것입니다.
REST란, 웹 초기에 "웹을 무너뜨리지 않고 어떻게 HTTP 프로토콜을 발전 시킬 수 있을까?"에 대한 고민으로 시작된 아키텍쳐입니다.
그리고 REST API는 REST 아키텍쳐를 따르는 API인 것이죠.
대부분의 API는 HTTP만 잘 따라도 어느정도 REST를 만족하는데요, 이를 Restful라고 표현합니다.
REST스럽다( Restful )라는 말로 미루어 볼 때, 진짜 REST가 되기 위해 부족한 것들이 있다는 뜻 같은데요.
REST의 특성 중 uniform interface에서 제약조건 self-descriptive messages, HATEOAS가 있습니다.
self-descriptive messages
메시지 자체만으로 스스로를 설명할 수 있어야 한다.
HATEOAS
애플리케이션의 상태는 하이퍼링크를 통해 전이되어야 한다.
위의 두 제약조건으로 인해, 대부분의 REST API라고 알려진 것들이 REST API가 아니라고 합니다.
지금까지의 얘기들은 영상의 내용들을 요약한 것 뿐입니다.
저도 이 영상을 보기 전까지 REST API 뭐 별거 아니고 아래의 내용만 만족시키면 된다고 생각했었습니다.
URI에 어떤 "자원에 대한 경로"인지를 명사로 작성
HTTP Method에 어떤 "행위"를 하고자 하는 것인지를 작성
이 조건은 REST가 되기 위한 조건의 일부이며,
이렇게 오해를 한 이유는 브라우저, HTML, 프레임워크 등에서 잘 처리를 해주기 때문에 REST하다(=> Restful)고 생각했던 것입니다.
영상을 보시면 REST API를 구현하는게 왜 어려운지, 잘 설명을 해주시는데요.
REST API가 무엇인지 알고 싶으시다면 꼭 시청하기를 권장드립니다.
2) Restful API
REST API를 만드는건 어렵고.. 그럼 Restful로 만드는건 어떻게 할까요?
예를 들어서 Restful 하지 않은 URI를 Restful 하게 바꿔보겠습니다.
먼저 Restful 하지 않은 URI입니다.
그 이유는 요청 행위를 URI에 명시하고 있기 때문입니다.
게시글 조회
http://example.com/showPost
게시글 추가
http://example.com/addPost
다음은 HTTP Method를 이용한 Restful API입니다.
게시글 조회
URI : http://example.com/post
HTTP 메서드 : GET
게시글 추가
http://example.com/post
HTTP 메서드 : POST
이렇게 Restful API로 설계하면, URI 매핑이 깔끔해지고 의미도 명확해진다는 장점이 있습니다.
HTTP 프로토콜 상에서 클라이언트와 서버는 데이터를 패킷 단위로 잘게 쪼개서 통신을 합니다.
데이터 전송 단위인 패킷에는 요청/응답에 대한 메시지가 담겨 있습니다.
패킷의 구조는 다음과 같이 구성되어 있습니다.
시작라인 ( Request Line )
헤더 ( Header )
본문 ( Body )
그 중에서 헤더에는 패킷에 대한 정보들을 담고 있습니다.
아래는 헤더에 대한 정보들을 간단하게 정리해본 것이며, 맛보기에 불과합니다.
헤더에는 어떤 정보들을 명시할 수 있는지에 대한 더 많은 자료는 여기를 참고해주세요.
Date
메시지가 언제 만들어졌는지
Via
메시지가 어떤 프락시를 거쳐왔는지
client-IP
클라이언트가 실행된 컴퓨터의 IP
Accept
서버가 보내도 되는 미디어의 종류
Accept-charset
서버가 보내도 되는 문자열셋
If-Modified-since
주어진 날짜 이후에 리소스가 변경되지 않았다면 요청을 제한 함
Authorization
서버에게 제공하는 인증 자체에 대한 정보
Cookie
쿠키 정보
Age
응답이 얼마나 오래 걸렸는지
Server
서버 정보
Allow
현재 엔티티에 대해 수행될 수 있는 요청 메서드 목록
Content-Encoding
본문에 적용된 인코딩
Content - type
본문의 내용이 어떤 형식인지 ( 텍스트, 이미지 등… )