HTTP는 최상위 계층인 application 계층에 동작
개념적으로만 봤을 때 HTTP는 TCP/IP 계층 위에 동작하는 거라고 볼 수 있다.
예를 들어서 클라이언트로부터 특정 URL로 요청이 들어오면 DNS 서버가 도메인에 매핑되는 IP 주소를 받아옵니다. TCP 계층에서 HTTP 메시지를 패킷으로 분해합니다. 그리고 IP 계층에서 전송 위치를 확인하고 네트워크를 통하여 전송합니다. 그리고 받는쪽은 위의 과정을 역순으로 진행하여 처리합니다.
추가로 소켓도 마찬가지로 TCP 기반으로 나온건데 HTTP와의 차이점은 연결지향 / 동기식 통신이 필요할 때는 소켓 통신을 이용하는게 더 유리하다는 점입니다.
HTTP: 웹에서 자주 사용되는 프로토콜
TCP/IP에서 쓰는 주소 : 물리주소(MAC 주소), 논리주소(IP 주소), 포트주소(port)
전송을 담당하는 IP
IP는 계층으로 따지면 네트워크 계층에 해당
IP의 역할은 각 패킷을 상대방에게 전달하는 것
목적지까지 중계를 해주는 도중의 컴퓨터 또는 라우터와 같은 네트워크 장비는 목적지에 도착하기 위한 대략적인 행선지만 알고있다. 이런 구조를 라우팅이라고 한다.
신뢰성을 담당하는 TCP
TCP는 전송계층에 해당하는 프로토콜로 신뢰성을 가진 바이트스트림을 사용
바이트 스트림은 커다란 데이터를 보내기 쉽도록 TCP세그먼트라고 하는 단위의 패킷으로 작게 나누어 전송
이때 각 패킷에는 번호가 붙기 때문에 누락된 패킷이 있는지 검증할 수 있고 신뢰도를 담보할 수 있다.
이름 변환을 담당하는 DNS
네트워크를 이용하는 컴퓨터는 IP주소와는 별개로 호스트 이름 www를 붙일 수 있다. DNS는 HTTP와 같은 응용프로그램 계층 시스템으로 주로 호스트 이름이나 도메인 이름 IP주소의 이름 변환을 제공한다. 이름 변환이란 사람이 쉽게 외우기 힘든 IP주소를 사람이 좀 더 외우기 쉬운 도메인 이름으로 변경하거나 반대로 도메인 이름을 IP주소로 변경하는 작업을 말한다.
TCP/IP 4계층을 통해서 네트워크 통신의 예시를 들면
1. 클라이언트 -> 서버, 특정 주소로 요청
2. DNS 상에서 IP 주소를 받아옴
3. HTTP 계층 -> HTTP 메시지 작성
4. TCP 계층 -> HTTP 메시지를 패킷으로 분해
5. IP 계층 -> 전송 위치를 확인
6. Ethernet 계층 -> 네트워크를 통해서 전송
7. 수신은 위의 과정의 역순으로 진행함.
HTTP 메시지를 전송할 때
다음과 같은 메시지가 client, server 사이에서 전송된다.
HTTP 메시지는 보통 header + body로 이루어지는데
이런 구조로 이루어져있다.
이 헤더에는
이렇게 Request와 Response로 나뉘어진다.
공통 헤더는 요청 및 응답의 메시지 모두에서 사용되지만 컨텐츠에는 적용되지 않는 헤더
General-Header: Data: <day-name>, <day> <month> <year> <hour>:<minute>:<second> GMT
// Date: Wed, 21 Oct 2015 07:28:00 GMT
Connection: keep-alive //지속 연결
Connection: close //연결 종료
Cache-Control
캐싱을 허용할지 허용하지 않을지를 정하기 위해 사용
Content-Encoding
HTTP 요청에서 사용되지만 메시지의 컨텐츠와 관련이 없는 HTTP 헤더
보통 Fetch될 리소스나 클라이언트 자체에 대한 정보를 포함하여 서버로 보내진다.
Host: <host>:<port_Optional>
// Host: blog.naver.com
User-Agent: <product> / <product-version> <comment>
// Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36
Accept: text/html
Accept-Charset : 원하는 Character Set
Accept-Language : 원하는 Lang
Accept-Encoding : 원하는 Encoding 방식
Authorization: <type> <credentials>
// Authorization: Basic YWxhZGRpbjpvcGVuc2VzYW1l
type : 인증 타입으로 보통 Basic과 Bearer을 사용한다.
credentials : 사용자명과 비밀번호, 다른 페이로드가 합처져 base64로 인코딩된 값
보통 JWT나 Bearer 토큰을 서버로 보낼 때 사용하며 자격이 증명되지 않을 경우 401 Unauthorized 상태를 알려준다.
Origin: null
Origin: <scheme> "://" <hostname> [ ":" <port> ]
// Origin: https://developer.mozilla.org
scheme : 사용하는 프로토콜
hostname : 서버의 이름 또는 ip
port : 서버에 열린 tcp 포트
위치 또는 서버 자체에 대한 정보(이름, 버전)과 같이 응답에 대한 부가적인 정보를 갖는 헤더
만약 프로토콜, 서브도메인, 도메인, 포트 중 하나라도 다르면 CORS 에러가 발생
Access-Control-Allow-Origin: * //주소를 일일지 지정하기 싫다면 *로 모든 주소에 CORS 요청을 허용가능 //그러나 보안이 취약해지는 점이 있기 때문에 해당 헤더를 사용해야한다.
Access-Control-Allow-Origin:
Access-Control-Allow-Origin: null
// Access-Control-Allow-Origin: https://developer.mozilla.org
- Allow
특정 메서드만 허용하겠다라는 것을 지정하는 헤더이다.
```c
Allow: <http-methods>
// Allow: GET, POST, HEAD
Content-Disposition: inline
Content-Disposition: attachment
Content-Disposition: attachment; filename="filename.jpg"
// ex)
POST /test.html HTTP/1.1
Host: example.org
Content-Disposition: form-data; name="field2"; filename="example.txt"
Location: <url>
// ex)
HTTP/1.1 302 Found
Location: /
Content-Security-Policy: <policy-directive>; <policy-directive>
// Content-Security-Policy: default-src https:
만얀 이 값을 self라고 지정한다면 자신과 같은 도메인의 파일만 가져 올 수 있다.
컨텐츠 길이나 MIME 타입과 같이 Entity Body에 대한 자세한 정보를 포함하는 헤더
MIME 타입이란 클라이언트에게 전송된 문서의 다양성을 알려주기 위한 메커니즘
MIME 종류 참고
Content-Language: ko-kr
Content-Length: 25907
Content-Type: text/html;charset=UTF-8
//Content-Type: multipart/form-data; boundary=something
Content-Type
개체의 미디어 타입(MIME)과 문자열 인코딩(UTF-8)을 지정하기 위해 사용
Content-Language
사용 언어
Content-Encoding
미디어 타입을 압축하기 위해서 사용
이 헤더가 존재한다면 그 값은어떤 방식으로 인코딩 되는지 알 수 있다.
우리가 gzip등의 알고리즘을 통해 encoding 해서 보낸다면 브라우저가 알아서 해제해서 사용한다.
Content-Encoding: gzip
Content-Encoding: compress
Content-Encoding: deflate
Content-Encoding: identity
Content-Encoding: br
1xx : 전송 프로토콜 수준의 정보 교환
2xx : 클라어인트 요청이 성공적으로 수행됨
3xx : 클라이언트는 요청을 완료하기 위해 추가적인 행동을 취해야 함
4xx : 클라이언트의 잘못된 요청
5xx : 서버쪽 오류로 인한 상태코드
2xx 번대의 상태 코드들은 서버가 클라이언트의 요청을 성공적으로 처리했다는 의미
클라이언트의 요청을 서버가 정상적으로 처리했다.
클라이언트에게 더 정확하고 자세한 정보를 제공하기 위해선 적절한 상태 코드를 보내는 것이 좋다.(2xx 상태 코드들은 각각 세분화된 목적을 갖는다.)
HTTP/1.1 200 OK
{
"result" : true
"status" : 200
}
클라이언트의 요청을 서버가 정상적으로 처리했고 새로운 리소스가 생겼다.
HTTP/1.1 201 Created
{
"id" : 1,
"name" : "hak"
}
HTTP 헤더의 Content-Location를 이용하여 만들어진 리소스 생성된 위치를 알려주면 좋다.
HTTP/1.1 201 Created Content-Location: /users/1 { "id" : 1, "name" : "hak" }
클라이언트의 요청은 정상적이나, 서버가 아직 요청을 완료하지 못했다.
202 상태 코드에서 중요한 것은 작업의 확인
비동기 작업은 해당 요청이 언제 완료되는지 알 수 없다.
클라이언트가 요청의 완료 여부를 확인할 수 있는 방법을 제공해야 한다.
Callback
콜백은 서버가 작업이 완료되면 클라이언트에게 알려주는 것
Polling
폴링은 클라이언트가 주기적으로 해당 작업의 상태를 조회하는 것
결론은 비동기 요청(202 상태 코드)은 콜백이든 폴링이든 클라이언트가 요청의 완료 여부를 확인할 수 있는 방법을 제공해야 한다는 것
클라이언트의 요청은 정상적이다. 하지만 컨텐츠를 제공하지 않는다.
PUT
자원 수정 요청의 결과가 기존의 자원 내용과 동일하여 변경된 내용이 없을 때 204로 응답할 수 있다.
만약 수정 요청으로 자원의 내용이 변경된다면 201로 응답할 것이다.
DELETE
삭제 요청으로 자원을 삭제하여 더 이상 존재하지 않고 그 자원을 참조하는 모든 자원도 삭제되어 더 이상 HTTP body를 응답하는 것이 무의미해졌을 때 사용한다.
클라이언트의 요청이 유효하지 않아 더 이상 작업을 진행하지 않는 경우
그러나, 400 상태 코드로 응답하는 것만으로는 부족하다.
오류 발생 시 파라미터의 위치(path, query, body), 사용자 입력 값, 에러 이유를 꼭 명시하는 것이 좋다.
HTTP/1.1 400 Bad Request
{
"errors": {
"message": "'name'(body) must be String, input 'name': 123",
"detail": [
{
"location": "body",
"param": "name",
"value": 123,
"error": "TypeError",
"msg": "must be String"
}
]
}
}
클라이언트가 권한이 없기 때문에 작업을 진행할 수 없는 경우
401은 비인증
- 비인증: Not
비인증은 아니다의 뜻이 강하다. 즉, 인증이 안된 상태다.- 미인증: Not enough
미인증은 부족하다의 뜻이 강하다. 즉, 권한이 부족한 상태다
클라이언트가 권한이 없기 때문에 작업을 진행할 수 없는 경우
클라이언트가 요청한 자원이 존재하지 않다.
REST API에선 크게 두 가지 경우
1. 경로가 존재하지 않음
대부분 API 프레임워크에선 경로(라우팅)에 대한 에러 처리를 해주기 때문에 존재하지 않는 경로는 쉽게 404로 응답할 수 있다.
ex)GET /users/abc/def/wow 경우 아예 존재하지 않는 경로
-- 404 오류의 경우 두 가지 모두 확인을 해야 한다는 설명을 위한 표현이다.
클라이언트의 요청이 허용되지 않는 메소드인 경우
메소드란 POST, GET, PUT, DELTE 등 HTTP Method를 말한다.
즉, 자원(URI)은 존재하지만 해당 자원이 지원하지 않는 메소드일 때 응답하는 상태 코드다.
클라이언트의 요청이 서버의 상태와 충돌이 발생한 경우
클라이언트가 일정 시간 동안 너무 많은 요청을 보낸 경우
ex)
DELETE /users/1 HTTP/1.1 X-TOKEN: password
- 자원(URI) /users/1에 존재하는 메소드고 Not 405
- /users/:id에서 :id가 유효한 형식이고 Not 400
- 1 사용자도 존재하고 Not 404
- 헤더의 인증(X-TOKEN)도 정확하고 Not 401
- 삭제 권한도 있는 경우 Not 403
클라이언트의 삭제 요청은 받아들여져서 200 혹은 204로 응답해야 하지만,
사용자의 게시물이 존재하는 경우 사용자를 삭제할 수 없다는 비지니스 로직이 있을 수 있다
이렇게 API 사용에 있어 비지니스 로직상 모순이 발생하여 처리가 불가능한 경우 응답하는 상태 코드다.
API 서버의 응답에서 5XX오류가 발생해서는 안된다.
보통 개발 과정에서 유효하지 않은 요청을 사전에 처리하지 않은 경우(400)에 많이 발생한다.
ex)요청에 대해 4XX 오류를 발생시킬 가능성이 있는데 사전에 확인 작업을 하지 않은 경우
메시지는 세 부분(공백 제외) 으로 구성되어 있습니다.
Start Line에는 HTTP 메소드, Request target, HTTP version이 있습니다.
HTTP 메소드는 요청의 의도를 담고 있는 GET, POST, PUT, DELETE 등이 있습니다. GET은 존재하는 자원에 대한 요청, POST는 새로운 자원을 생성, PUT은 존재하는 자원에 대한 변경, DELETE는 존재하는 자원에 대한 삭제와 같은 기능을 가지고 있습니다.
Request target은 HTTP Request가 전송되는 목표 주소입니다.
HTTP version은 version에 따라 Request 메시지 구조나 데이터가 다를 수 있어서 version을 명시합니다.
Header에는 HTTP Request 그 자체에 대한 정보를 담고 있습니다. key : value 형태로 이루어져 있습니다.
이 Header에 경우 Request, Response에만 있는 Header 외에 공통 Header도 있기에 여기선 우선 Request Header에 있는 정보만 알려드리겠습니다.
Host : 요청하려는 서버 호스트 이름과 포트번호
User-agent : 클라이언트 프로그램 정보. 이 정보를 통해 서버는 클라이언트 프로그램(브라우저)에 맞는 최적의 데이터를 보내줄 수 있다.
Referer : 바로 직전에 머물렀던 웹 링크 주소
Accept : 클라이언트가 처리 가능한 미디어 타입 종류 나열
If-Modified-Since : 여기에 쓰여진 시간 이후로 변경된 리소스 취득. 페이지가 수정되었으면 최신 페이지로 교체한다.
Authorization : 인증 토큰을 서버로 보낼 때 쓰이는 Header
Origin : 서버로 Post 요청을 보낼 때 요청이 어느 주소에 시작되었는지 나타내는 값. 이 값으로 요청을 보낸 주소와 받는 주소가 다르면 CORS(Cross-Origin Resource Sharing) 에러가 발생한다.
Cookie : 쿠키 값이 key-value로 표현된다.
HTTP Request가 전송하는 데이터를 담고 있는 부분입니다. 전송하는 데이터가 없다면 Body 부분은 비어있습니다.
보통 POST 요청일 경우, HTML 폼 데이터가 포함되어 있습니다.
Response의 Start Line에는 HTTP version, Status Code, Status Text가 있습니다.
-0 Staus Code는 Response 상태를 나타내는 코드입니다. 요청 정상 처리를 나타내는 200이나 페이지가 이동되거나 없어졌을 때를 나타내는 404와 같은 코드로 이 부분은 추후에 정리 하겠습니다.
Location : 301, 302 상태코드일 때만 볼 수 있는 Header로 서버의 응답이 다른 곳에 있다고 알려주면서 해당 위치(URI)를 지정합니다.
Server : 웹 서버의 종류
Age : max-age 시간내에서 얼마나 흘렀는지 초 단위로 알려주는 값
Referrer-policy : 서버 referrer 정책을 알려주는 값 ex) origin, no-referrer, unsafe-url
WWW-Authenticate : 사용자 인증이 필요한 자원을 요구할 시 , 서버가 제공하는 인증 방식
Proxy-Authenticate : 요청한 서버가 프록시 서버인 경우 유저 인증을 위한 값
HTTP Request 메시지의 Body와 동일합니다. 마찬가지로 전송하는 데이터가 없으면 비어있습니다.
참고
https://sanghaklee.tistory.com/61
https://livlikwav.github.io/study/rest,http,tcp,udp/
https://code-examples.net/ko/q/150e16a
[node.js REST API 서버 만들기] 3. 만들기
링크텍스트
Ulfius HTTP Framework
소켓 프로그래밍
HTTP Request / Response 메시지 구조