no image
[HTTP] 캐시와 조건부 요청
이 글은 인프런 김영한님의 Spring 강의를 바탕으로 개인적인 정리를 위해 작성한 글입니다. 캐시를 사용하지 않는다면, 서버의 데이터가 변경되지 않았어도 클라이언트는 서버의 데이터를 다운로드 받아야 한다. 때문에 브라우저 로딩 속도가 느려진다. 이는 성질 급한 사용자가 참지 못하고 해당 사이트를 이탈할 수도 있다. 이는 SEO에 안좋은 영향을 미치기 때문에 장기적으로 사이트에 안좋은 영향을 끼칠 수 있다. 또한 인터넷 네트워크는 느리고 비싸기 때문에 캐시를 필수적으로 사용해야 한다. 캐시 기본 동작 캐시 시간 설정 브라우저에서 GET /star.jpg 첫번째 요청을 보내면, 서버는 HTTP 헤더(0.1M) + HTTP 바디=star.jpg 이미지(1.0M)를 담아 응답을 보낸다. 중요한 점은 HTTP ..
2024.02.12
no image
[HTTP] 일반 헤더
이 글은 인프런 김영한님의 Spring 강의를 바탕으로 개인적인 정리를 위해 작성한 글입니다. HTTP 헤더 개요 HTTP 전송에 필요한 메시지 바디의 내용, 메시지 바디의 크기, 압축, 인증, 요청 클라이언트, 서버 정보, 캐시 관리 등 모든 부가 정보를 헤더에 넣는다. 표준 헤더가 굉장히 많다. 필요시 임의의 헤더 추가가 가능하다. RFC2616 Header General 헤더: 요청/응답 메시지 전체에 적용되는 정보 (Connection: close 등) Request 헤더: 요청 정보 (User-Agent: Mozilla/5.0 등) Response 헤더: 응답 정보 (Server: Apache 등) Entity 헤더: 엔티티 바디 정보 (Content-Type: text/html, Content..
2024.02.11
no image
[HTTP] 상태코드
이 글은 인프런 김영한님의 Spring 강의를 바탕으로 개인적인 정리를 위해 작성한 글입니다. HTTP 상태코드 상태코드 1xx (Informational) : 요청이 수신되어 처리중 -> 거의 사용이 되지 않음 2xx (Successful) : 요청 정상 처리 3xx (Redirection) : 요청을 완료하려면 추가 행동이 필요 4xx (Client Error) : 클라이언트 오류, 잘못된 문법등으로 서버가 요청을 수행할 수 없음 5xx (Server Error) : 서버 오류, 서버가 정상 요청을 처리하지 못함 HTTP 상태 코드는 클라이언트가 서버로 요청을 보내면 요청이 잘 처리가 되어있는지 문제가 있는지 요청의 처리 상태를 응답에서 알려주는 기능이다. 만약 모르는 상태코드가 나타나면 클라이언트가..
2024.02.10
no image
[HTTP] HTTP 메서드 활용
이 글은 인프런 김영한님의 Spring 강의를 바탕으로 개인적인 정리를 위해 작성한 글입니다. 클라이언트에서 서버로 데이터 전송 데이터 전달 방식 쿼리 파라미터를 통한 데이터 전송 주로 GET 방식으로 많이 사용하고 검색어로 검색할 때, 게시판 리스트에 정렬 조건을 넣을 때 쿼리 파라미터를 이용해서 많이 사용한다. 메시지 바디를 통한 데이터 전송 클라이언트에서 서버로 전송할 때 HTTP 메시지 바디를 통해서 데이터를 전송한다. POST, PUT, PATCH 방식으로 주로 사용한다. 회원 가입, 상품 주문, 리소스 등록, 리소스 변경 등에 사용된다. 클라이언트에서 서버로 데이터 전송할 때 4가지 상황 정적 데이터 조회 : 이미지, 정적 텍스트 문서 동적 데이터 조회 : 주로 검색, 게시판 목록에서 정렬 필..
2024.02.09
no image
[HTTP] HTTP 메서드
이 글은 인프런 김영한님의 Spring 강의를 바탕으로 개인적인 정리를 위해 작성한 글입니다. HTTP API 예제 요구사항 및 API URI 설계 회원 정보 관리 API 설계 1. 회원 목록 조회 : /read-member-list 2. 회원 조회 : /read-member-by-id 3. 회원 등록 : /create-member 4. 회원 수정 : /update-member 5. 회원 삭제 : /delete-member 요구사항 기반으로 API를 만들게 되는게 위와 같이 현업에서 잘못된 API URI 설계를 한다. API URI 설계 분리 리소스 : 회원 행위 : 조회, 등록, 수정, 삭제 API URI 설계를 할 때 리소스와 해당 리소스를 대상으로 하는 행위를 분리해야 한다. 회원이라는 리소스만 식..
2024.02.08
no image
[HTTP] HTTP 기본
이 글은 인프런 김영한님의 Spring 강의를 바탕으로 개인적인 정리를 위해 작성한 글입니다. 모든 것이 HTTP HTTP(HyperText Transfer Protocol) 문서 간의 링크를 통해서 하이퍼텍스트 문서를 통해서 연결하는 프로토콜이다. HTTP 프토토콜에 HTML, TEXT, IMAGE, 음성, 영상, 파일, JSON, XML (API) 등 모든 형태의 데이터를 담아서 전송이 가능하다. 서버간에 데이터를 주고 받을 때도 사용한다. HTTP 역사 HTTP/0.9 (1991년) : GET 메서드만 지원, HTTP 헤더X HTTP/1.0 (1996년) : 메서드, 헤더 추가 HTTP/1.1 (1997년) : 가장 많이 사용하고 가장 중요한 버전이다. RFC2068 (1997년) -> RFC261..
2024.02.07
no image
[HTTP] URI와 웹 브라우저 요청 흐름
이 글은 인프런 김영한님의 Spring 강의를 바탕으로 개인적인 정리를 위해 작성한 글입니다. URI URI, URL, URN URI 내부에 URL, URN이 포함되어 있다. URI는 로케이터(Locator), 이름(Name) 또는 둘다 추가로 분류될 수 있다. URI (Uniform Resource Identifier) Uniform : 리소스 식별하는 통일된 방식이다. Resource : URI로 식별할 수 있는 모든 걸 자원이라고 한다. 웹 브라우저에 있는 HTML의 파일 것만 자원을 뜻하는 게 아니라 실시간 교통 정보 등등 이런것도 자원이라고 한다. Idenrifier : 다른 항목과 구분하는 데 필요한 정보이다. 사람을 식별할 때 주민등록번호를 식별 하는 것처럼 말한다. URL (Uniform ..
2024.02.06
no image
[HTTP] 인터넷 네트워크
이 글은 인프런 김영한님의 Spring 강의를 바탕으로 개인적인 정리를 위해 작성한 글입니다. 인터넷 통신 인터넷망에서 컴퓨터들은 어떻게 통신할까? 클라이언트가 한국에 있고 서버가 먼 곳에 있다면 한국에 있는 클라이언트가 'Hello, world'라는 메시지를 보내야 하는데 데이터의 출발지와 도착지 사이에 수많은 중간 노드라고 하는 서버들을 걸쳐서 다른 곳에 있는 서버에게 안전하게 메시지가 도착해야 한다. 어떤 규칙으로 다른 곳에 있는 서버에게 안전하게 도착할 수 있는지 이해를 하려면 IP 프로토콜을 알아야 한다. IP 인터넷 프로토콜 IP 주소 부여 IP(인터넷 프로토콜) 역할 지정한 IP 주소(Address)에 데이터 전달 패킷(Packet)이라는 통신 단위로 데이터 전달 클라이언트에게 IP 주소, ..
2024.02.05

이 글은 인프런 김영한님의 Spring 강의를 바탕으로 개인적인 정리를 위해 작성한 글입니다.


캐시를 사용하지 않는다면, 서버의 데이터가 변경되지 않았어도 클라이언트는 서버의 데이터를 다운로드 받아야 한다.

때문에 브라우저 로딩 속도가 느려진다. 이는 성질 급한 사용자가 참지 못하고 해당 사이트를 이탈할 수도 있다.

이는 SEO에 안좋은 영향을 미치기 때문에 장기적으로 사이트에 안좋은 영향을 끼칠 수 있다.

또한 인터넷 네트워크는 느리고 비싸기 때문에 캐시를 필수적으로 사용해야 한다.

 

캐시 기본 동작

캐시 시간 설정

 

브라우저에서 GET /star.jpg 첫번째 요청을 보내면, 서버는 HTTP 헤더(0.1M) + HTTP 바디=star.jpg 이미지(1.0M)를 담아 응답을 보낸다.

중요한 점은 HTTP 헤더에 cache-control로 캐시 유효 시간을 설정해서 응답한다는 것이다.

예시는 최대 캐시 유효 시간을 60초로 설정하였다.

 

캐시 유효 시간이 만료 되기 전에 다시 서버에 요청하면 아래의 그림과 같이 서버에 요청하기 전 브라우저 캐시에 요청을 보내고 캐시 유효 시간을 검증한다.

 

캐시 유효시간이 유효하다면 캐시에서 직접 조회하여 브라우저에 이미지를 표시한다.

 

캐시 시간 초과

만약 캐시 유효 시간을 검증했는데 유효 시간을 초과했다면 서버로 요청하게 된다.

서버는 이전과 동일하게 최대 캐시 유효시간을 설정하여  HTTP 헤더(0.1M) + HTTP 바디=star.jpg 이미지(1.0M)를 담아 응답을 보낸다. 

 

또한 클라이언트 웹 브라우저는 이전과 동일하게 브라우저 캐시에 60초 유효 상태로 응답 결과를 저장한다.

 

단순히 캐시의 시간만 설정하는 것은 비효율적일 수도 있다.

캐시 유효 기간이 지났지만, 서버의 데이터가 바뀌지 않았을 경우, 불필요한 데이터 다운로드가 있을 수 있기 때문이다.

이는 검증 헤더로 극복이 가능하다.

 

 

검증 헤더와 조건부 요청

검증 헤더 : 캐시 데이터와 서버 데이터가 같은지 검증하는 데이터

  1. Last-Modified
  2. ETag

 

조건부 요청 헤더 : 검증 헤더로 조건에 따른 분기시 사용

  • If-Modified-Since: Last-Modified를 사용
    If-Modified-Since <->If-Unmodified-Since
  • If-None-Match: ETag 사용
  • 조건이 만족하면 200 OK
  • 조건이 만족하지 않으면, 304 Not Modified

 

Last-Modified

캐시의 유효 시간이 초과된 이후에도 서버의 데이터가 동일하다면, 이미 다운로드된 데이터를 다시 다운로드 받지 않아도 된다.

브라우저 캐시와 서버의 데이터가 동일한지 아닌지를 판단할 수 있는 방법은 검증 헤더를 추가하는 것이다.

 

먼저 브라우저 캐시에 아무것도 없다고 가정하고, 서버에 요청을 보낸다.

그러면 서버는 헤더에 Last-Modified(데이터가 마지막에 수정된 시간)을 설정해서 클라이언트에 데이터를 전송한다.

 

클라이언트는 캐시 유효 시간과 데이터 최종 수정일을 함께 응답 결과를 캐시에 저장한다. 

 

Last-Modified - 캐시 시간 초과

클라이언트가 캐시 만료 후 요청을 보낸다.

요청을 보낼 때 헤더에 'if-modified-since:데이터 최종 수정일'을 붙여 서버에 요청을 보낸다.

데이터 최종 수정일은 GMT 기준으로 작성
Last-Modified: Thu, 04 Jum 2020 07:19:24 GMT

 

서버는 요청 받은 헤더의 if-modified-since 값과 데이터 최종 수정일을 비교하여 데이터가 바뀌었는지 검증한다.

 

만약 캐시의 데이터 최종 수정일과 서버의 데이터 최종 수정일이 같다면(데이터의 변경이 발생하지 않았다면)

(만약 데이터의 변경이 발생하였다면 200 상태 코드를 전달하게 된다. 따라서 서버의 데이터를 다운로드 받는다.)

 

서버는 데이터가 변경되지 않았다는 의미로 HTTP Body 없이, HTTP 헤더에 304 Not Modified를 전송한다.
HTTP Body 없이 HTTP Header 부분만 전송하기 때문에 라이트한 데이터를 보낸다.

 

클라이언트는 서버로부터 304 Not Modified를 응답받았으므로 캐시 데이터(응답 결과)를 재사용하고 헤더 데이터를 갱신한다.

300번대 메시지는 리다이렉트 응답이다.

따라서 캐시로 리다이렉트 된다.

 

클라이언트의 웹 브라우저와 서버의 데이터가 같으니 캐시에서 데이터를 조회하여 사용한다.

 

흐름을 정리하면 아래와 같다.

  1. 클라이언트가 서버에 데이터를 최초 요청한다.
  2. 서버는 cache-control, last-modified를 헤더에 붙여 캐시의 유효 기간, 데이터 최종 수정일을 설정하여 응답을 보낸다.
  3. 브라우저 캐시에 유효 기간과 데이터 최종 수정일과 함께 응답 결과를 저장한다.
  4. 클라이언트가 캐시의 유효기간이 만료된 데이터를 요청하면, 요청 헤더의 if-modified-since에 last-moidifed(데이터 최종 수정일)값을 설정하여 서버에 요청을 보낸다.
  5. 서버는 if-modified-since 값과 데이터의 최종 수정일을 비교하여 데이터 변경이 있는지 검증한다.
  6. 데이터 변경이 없었다면, 서버는 헤더 메타 정보, 304 Not Modified 를 붙여 응답을 보낸다. (메시지 바디 포함 X)
  7. 클라이언트가 304 응답을 받으면, 캐시의 메타 정보(캐시 유효기간 등)을 갱신하고, 캐시에 저장된 데이터를 조회하여 사용한다.

 

서버

  • 캐시가 만료되도 서버의 데이터가 변경되지 않았으면, 서버는 304 Not Modified + 헤더 메타 정보만 응답(HTTP bodyX)

 

클라이언트

  • 클라이언트는 서버가 보낸 응답 헤더 정보로 캐시의 메타 정보를 갱신(캐시 유효 기간도 갱신)
  • 클라이언트는 캐시에 저장된 데이터 재활용
    -> 네트워크 다운로드가 발생하지만 용량이 적은 헤더 정보만 다운로드하기 때문에, 매우 실용적

 

If-Modified-Since -> 데이터가 변경되었을 때와 변경되지 않았을 때

데이터 미변경 예시

  • 캐시: 2020년 11월 10일 10:00:00 vs 서버: 2020년 11월 10일 10:00:00
  • 304 Not Modified, 헤더 데이터만 전송한다. (body X)
  • 따라서 전송 용량 0.1MB (헤더 0.1MB)

데이터 변경 예시

  • 캐시: 2020년 11월 10일 10:00:00 vs 서버: 2020년 11월 10일 11:00:00
  • 200 OK, 모든 데이터 전송 (body O)
  • 따라서 전송 용량 1.1MB (헤더 0.1MB, 바디 1MB)

 

Last-Modified, If-Modified-Since의 단점

  • 1초 미만 단위로 캐시 조정이 불가능하다. (최근 갱신 일자의 단위가 초까지임)
  • 날짜 기반의 로직을 사용해야 한다

 

따라서 데이터를 수정해서 날짜가 달라졌지만, 실질적으로 같은 데이터를 수정해 결과가 똑같은 경우, 서버에서 별도의 캐시 로직을 관리하고 싶은 경우 예) 스페이스나 주석처럼 크게 영향이 없는 변경에서 캐시를 유지하고 싶은 경우

사용을 해야 한다.

 

ETag

ETag (Entity Tag)

  • 캐시용 데이터에 임의의 고유한 버전 이름을 달아두는 구조
    예) ETag: "v1.0", ETag: "a2jiodwjekjl3" , 버전으로 태그를 관리할 수도 있고, Hash 값으로 할 수도 있다.
  • 데이터가 변경되면, 이 이름을 바꾸는 것을 포함해 변경한다. (Hash를 다시 생성한다)
    예) ETag: "aaaaa" -> ETag: "bbbbb"
  • 단순하게 ETag만 보내서 깂이 같으면 유지하고, 다르면 다시 받는다.
  • If-Match <-> If-None-Match

클라이언트가 서버에 데이터를 요청한다.

서버는 ETag와 함께 데이터를 클라이언트에 보내준다.

 

응답 결과를 브라우저 캐시에 저장한다.

 

ETag - 캐시 시간 초과

설정하였던 캐시가 시간 초과가 될 경우, if-None-Match: ETag 로 서버에 데이터가 아직 변함 없는지 확인 요청을 보낸다.

 

데이터가 아직 수정되지 않았다면 304 Not Modified 상태 코드를 보낸다.

(만약 데이터가 수정되었다면, 200 OK 상태코드를 받게되고, 서버로부터 데이터를 다운로드 받는다. Body는 당연히 있다.)

이때 HTTP Body가 없이 헤더만 보낸다.

 

서버가 보낸 헤더를 클라이언트가 받고, 클라이언트는 브라우저 캐시에 있는 데이터를 재사용하게 되고 헤더 데이터를 갱신한다.

304 상태코드는 리다이렉트이다.

따라서 캐시된 페이지로 리다이렉트 된다.

 

단순하게 ETag만 서버에 보내서 같으면 유지하고, 다르면 다시 받는다.

캐시 제어 로직을 서버에서 완전하게 관리한다.

클라이언트는 단순히 이 값을 서버에 제공(클라이언트는 캐시 메커니즘을 모름)

예시)
서버는 배타 오픈 기간인 3일 동안 파일이 변경되어도, ETag를 동일하게 유지한다.
애플리케이션 배포 주기에 맞춰 ETag를 모두 갱신

이렇게 ETag와 If-None-Match를 사용할시, 클라이언트의 입장에서는 캐시 메커니즘이 완전히 블랙박스가 되어버린다.

 

프록시 캐시

클라이언트와 거리가 먼 서버로 요청과 응답은 당연히 느릴 수 밖에 없다.

이를 극복하기 위해 프록시 캐시 서버를 사용한다.

proxy cache라는 서버를 도입해서 브라우저(클라이언트의)가 원(origin) 서버가 아닌 proxy cache 서버를 거쳐오도록 만든다.

 

DNS에 요청을 하면 원 서버로 바로 가는 것이 아닌 프록시 서버로 요청을 1차적으로 보내게 되는 것이다.

원 서버는 미국에 있지만, 프록시 서버는 한국 아니면 미국보다 가까운 곳에 위치하기 때문에 훨씬 빠르다.

  • private cache: 내 로컬 환경이나 브라우저에 저장되는 캐시
  • public cache: 여러 유저가 공용해서 사용하는 캐시
CDN Contents Delivery Network 콘텐츠 전송 네트워크

지리적으로 분산된 여러개의 서버 네트워크를 두어  병목 현상을 방지하고 효율적인 네트워크 이동을 제공한다.
자주 사용하는 파일들을 Caching 하여 웹 서버의 부하를 줄인다.
Streaming 기술을 제공하여 실시간으로 많은 사용자가 원하는 콘텐츠를 전송해준다.
서버의 트래픽을 덜어주어 비용을 감소하는 효과가 있고, 공격 트래픽을 완화할 수 있어 Dos 공격에 대해서 어느정도 보호해줄 수 있다.

 

캐시와 조건부 요청 헤더

캐시의 제어와 관련된 헤더들은 아래와 같다.

  • Cache-Control: 캐시 제어
  • Pragma: 캐시 제어(하위 호환)
  • Expires: 캐시 유효 기간(하위 호환)

 

Cache-Control - 캐시 지시어(directives)

  • Cache-Control: max-age - 캐시 유효 시간, 초 단위로 작성
  • Cache-Control: no-cache - 데이터는 캐시해도 되지만, 항상 프록시 서버가 아닌 원(origin) 서버에 검증하고 사용
    (로컬 캐시에 있는 정보가 바뀌었는지 여부를 항상 서버에 검증을 받고 사용)
  • Cache-Control: no-store - 데이터에 민감한 정보가 있으므로 저장하면 안될때 사용.
    (메모리에서 사용하고 최대한 빨리 삭제)
  • Cache-Control: public : 응답이 public 캐시에 저장되어도 됨
  • Cache-Control: private : 응답이 해당 사용자만을 위한 것임, private 캐시에 저장해야 함(기본값)
  • Cache-Control: s-maxage : 프록시 캐시에만 적용되는 max-age
  • Age: 60 (HTTP 헤더) : 오리진 서버에서 응답 후 프록시 캐시 내에 머문 시간(초)

 

Pragma - 캐시 제어(하위 호환)

  • Pragma: no-cache - Cashe-Control의 no-cach와 기능 같음
  • HTTP 1.0 이하 버전일 때 사용

 

Expires - 캐시 만료일 지정(하위 호환)

  • expires: Mon, 01 Jan 1990 00:00:00 GMT
  • 캐시 만료일을 정확한 날짜로 지정할 수 있다.
  • HTTP 1.0부터 사용됨, 지금은 더 유연한 Cache-Control: max-age를 권장
  • 현재 버전에서 Cache-Control: max-age와 함께 사용하면 Expires는 무시된다.

 

캐시 무효화

캐시 데이터를 사용하면 안될 상황이 있다. 예를 들어 나의 통장 잔고 조회등이 있다.

따라서 캐시를 무효화할 필요가 있다.

이때 아래와 같이 캐시 무효화를 해주는 헤더 정보를 입력하면 캐시를 무효화할 수 있다.

  • Cache-Control: no-cache, no-store, must-revalidate 
  • Pragma: no-cache -> http 1.0 이하를 위해

 

  • Cache-Control: no-cache : 데이터는 캐시해도 되지만, 항상 원 서버에 검증하고 사용(이름에 주의!)
  • Cache-Control: no-store : 데이터에 민감한 정보가 있으므로 저장하면 안됨
    (메모리에서 사용하고 최대한 빨리 삭제)
  • Cache-Control: must-revalidate : 캐시 만료후 최초 조회시 원 서버에 검증해야함
    원 서버 접근 실패시 반드시 오류가 발생해야함 - 504(Gateway Timeout)
    캐시 유효 시간이라면 캐시를 사용함
  • Pragma: no-cache : HTTP 1.0 하위 호환

 

no-cache vs must-revalidate

no-cache는 프록시 캐시를 거쳐 원 서버에 검증을 요청하게 된다.

 

하지만 프록시 캐시와 원 서버가 통신 상태가 불량하다면, 오류를 발생하는 것이 아닌 프록시 캐시에 있는 캐시를 클라이언트로 응답하게 된다.

 

반면에 must-revalidate 는 프록시 캐시와 원 서버의 통신이 불량하다면 오류를 발생시킨다.

 

'네트워크 > HTTP' 카테고리의 다른 글

[HTTP] 일반 헤더  (1) 2024.02.11
[HTTP] 상태코드  (1) 2024.02.10
[HTTP] HTTP 메서드 활용  (1) 2024.02.09
[HTTP] HTTP 메서드  (1) 2024.02.08
[HTTP] HTTP 기본  (1) 2024.02.07

이 글은 인프런 김영한님의 Spring 강의를 바탕으로 개인적인 정리를 위해 작성한 글입니다.


HTTP 헤더 개요

HTTP 전송에 필요한 메시지 바디의 내용, 메시지 바디의 크기, 압축, 인증, 요청 클라이언트, 서버 정보, 캐시 관리 등 모든 부가 정보를 헤더에 넣는다. 표준 헤더가 굉장히 많다. 

필요시 임의의 헤더 추가가 가능하다. 

 

RFC2616

Header

  • General 헤더: 요청/응답 메시지 전체에 적용되는 정보 (Connection: close 등)
  • Request 헤더: 요청 정보 (User-Agent: Mozilla/5.0  등)
  • Response 헤더: 응답 정보 (Server: Apache  등)
  • Entity 헤더: 엔티티 바디 정보 (Content-Type: text/html, Content-Length: 3423  등)

 

BODY

메시지 본문을 통해 엔티티 본문을 전달 하는데 사용한다.

엔티티 헤더는 엔티티 본문의 데이터를 해석할 수 있는 데이터 유형, 데이터 길이, 압축 정보 등을 제공한다. 

 

표현(Representation) - RFC7230(최신)

  1. 1999년 RFC2616 폐기
  2. 2014년 RFC7230~7235 등장
  3. 엔티티(Entity) -> 표현(Representation)

 

HTTP BODY

  • 메시지 본문(message body)를 통해 표현 데이터 전달
  • 메시지 본문 = 페이로드(payload)
  • 표현 = 요청이나 응답에서 전달할 실제 데이터(표현 헤더 + 표현 데이터)
  • 표현 헤더는 표현 데이터를 해석할 수 있는 정보 제공

 

HTTP HEADER

Content-Type

  • Content-Type: 표현 데이터의 형식
  • Content-Encoding: 표현데이터의 압축 방식
  • Content-Language: 표현 데이터의 자연 언어
  • Content-Length: 표현 데이터의 길이

 

콘텐츠 협상

클라이언트가 선호하는 표현 요청

  • Accept : 클라이언트가 선호하는 미디어 타입 전달
  • Accept-Charset : 클라이언트가 선호하는 문자 인코딩
  • Accept-Encoding : 클라이언트가 선호하는 압축 인코딩
  • Accept-Language : 클라이언트가 선호하는 자연 언어

협상 헤더는 요청시에만 사용

 

Accept-Language 적용 전

클라이언트에서 서버로 요청을 보낼 때 한국어 정보를 원하는지 영어 정보를 원하는지 아무 정보가 없다.

그러면 서버는 기본값인 영어 관련된 내용으로 한국어 브라우저로 응답을 해준다. 

 

Accept-Language 적용 후

클라이언트가 선호하는 언어에 한국어 정보를 입력해서 서버에게 전달한다.

서버는 기본 언어가 영어지만 한국어도 지원하기 때문에 클라이언트가 원하는 한국어로 데이터를 전달한다.

 

Accept-Language  복잡한 예시

클라이언트가 선호하는 언어를 한국어 정보를 입력해서 서버에게 전달하는데, 서버가 기본은 독일어, 또 다른 언어로 영어만 지원한다.

서버가 한국어 지원을 하지 않아서 기본값인 독일어로 보내게 된다. 

 

협상과 우선순위

Quality Values(q) 값으로 사용한다. 0~1로 값이 클수록 우선순위가 높고 1은 생략이 가능하다.

GET /event
Accept-Language:ko-KR,ko;q=0.9,en-US;q=0.8,en;q=0.7
  1. ko-KR;q=1
  2. ko;q=0.9
  3. en-US;q=0.8
  4. en;q=0.7

위에 표현된 값으로 우선순위를 파악해서 어떤 언어를 클라이언트가 선호하는지 알 수 있다.

위 예시에서는 독일어보다 영어가 우선순위가 높기 때문에 영어로된 데이터를 전송하게 된다.


구체적일 수록 우선순위가 높다. 

GET /event
Accept: text/*text/plaintext/plain;format=flowed*/*
  1. text/plain;format=flowed
  2. text/plain
  3. text/*
  4. */*

구체적인 것을 기준으로 미디어 타입을 맞춘다.

클라이언트에서 요청한 text/html;level의 우선순위가 가장 높고 서버가 해당 미디어 타입을 지원하므로 text/html;level 미디어타입으로 응답한다.

 

전송 방식

단순 전송 (Content-Length)

데이터 전체를 한 번에 보낼 때 사용

 

압축 전송 (Content-Encoding)

전송해야하는 데이터가 커서 압축해서 보낼 때 사용(압축 방식은 다양함)

 

분할 전송 (Transfer-Encoding)

chunked는 덩어리라는 뜻이다.

덩어리로 쪼개서 전송을 한다.

5byte로 Hello를 서버에서 클라이언트로 보낸다.

또 5byte로 World를 보내고 마지막으로 0byte로 src를 보내면 끝이라는 걸 표현한다.

분할 전송할 때는 Content-Length를 넣으면 안된다.

 

범위 전송 (Content-Range)

Range 설정해서 요청 -> Content-Range 설정해서 응답

  • Range: bytes=클라이언트가 요청한 데이터의 범위
  • Content-Range: bytes 클라이언트가 요청한 데이터의 범위 / 전체 데이터의 길이
  •  Content-Length: 실제 전송된 데이터의 길이

어떠한 이유로 중간에 재요청해야할 때, 범위를 지정하여 사용

처음부터 다시 받지 않고, 이후 부분부터 받는다.

 

일반 정보

From

유저 에이전트의 이메일 정보이다. 일반적으로 잘 사용하지 않는다. 검색 엔진 담당자한테 사이트에 대해서 정보를 알려줄 때 연락할 수 있는 방법이 필요할 때 요청할 때 사용한다.

 

Referer(요청)

현재 요청된 페이지의 이전 웹 페이지 주소이다. A에서 B로 이동하는 경우 B를 요청할 때 Referer A를 포함해서 요청한다.

Referer를 사용해서 데이터 분석 할 때 유입 경로 분석을 가능하다. 

referer는 referrer의 오타

 

User-Agent(요청)

  • 유저 에이전트(클라이언트) 애플리케이션 정보 (웹 브라우저 정보..)
  • 장애가 발생하는 브라우저 파악, 통계 정보 사용

 

Server (응답)

  • 요청을 처리하는 ORIGIN 서버의 소프트웨어 정보
  • ORIGIN 서버: 실제로 응답을 보낸 서버(HTTP 요청을 보내면, 실제로 많은 프록시 서버를 거쳐 응답을 받게됨)

 

Date (응답)

  • 메시지가 발생한 날짜와 시간

 


특별한 정보

Host(요청)

요청에서 사용하고 필수값이다. 다른 헤더에서는 거의 없고 Host는 필수 헤더이다. 하나의 서버가 여러 도메인을 처리해야 할 때, 하나의 IP 주소에 여러 도메인이 적용되어 있을 때 구분해줘야 한다.

가상호스트를 통해서 하나의 서버가 지금 IP : 200.200.200.2 가 있는데 서버 안에 여러 개의 애플리케이션이 다른 도메인으로 구동되어 있다.

클라이언트가 /hello 로 GET 방식으로 요청을 했는데 서버 입장에서는 /hello 와 관련된 애플리케이션에 어디로 들어갈지 모른다. 

TCP/IP 통신으로 Host 헤더로 입력하면 서버에서 Host 헤더가 있기 때문에 요청에 맞는 도메인주소를 들어갈 수 있다.  

Q. Port와 Host는 비슷한 개념?
A.해당 IP에서 Host를 찾고 -> 그 안에서 Port로 구분

 

Location (응답)

페이지 리다이렉션

  • 3xx(Redirection)의 Location 값: 요청을 자동으로 리다렉션하기 위한 대상 리소스(이동할 위치)
  • 201(Created)의 Location 값: 요청에 의해 생성된 리소스의 URI

 

Allow (응답)

허용 가능한 HTTP 메서드

  • 405(Method Not Allowed) 에서 응답에 포함해야 함

 

Retry-After

유저 에이전트가 다음 요청을 하기까지 기다려야 하는 시간

  • 503 (Service Unavailable): 서비스가 언제까지 불가인지 알려줄 수 있음
  • 날짜, 초단위 표기

 

 

쿠키

 
  • Set-Cookie: 서버->클라이언트 쿠키 전달(응답)
  • Cookie: 클라이언트가 서버에서 받은 쿠키를 저장, 클라이언트->서버 쿠키 전달(요청)

 

로그인을 하면 서버에서는 Set-Cookie로 홍길동 정보를 쿠키로 만들어서 보내준다.

클라이언트의 웹 브라우저 내부에는 쿠키 저장소가 있는데 서버가 응답에서 만든 쿠키를 쿠키 저장소에 저장을 한다.

 

로그인 이후에 웹 브라우저가 /welcome에 들어오면 자동으로 웹 브라우저는 쿠키를 담아 서버에 요청한다.

 

지정한 서버 쿠키는 모든 요청 정보에 쿠키 정보를 자동으로 포함을 한다. 

 

  1. 웹 브라우저가 id, password를 담아 서버에 로그인을 요청함
  2. 서버는 id, password 검증에 성공하면, 해당 사용자에 대한 sessionId(쿠키)를 생성함
  3. 서버는 Set-Cookie에 sessionId를 담아 웹 브라우저에 로그인 성공을  응답함
  4. 웹 브라우저는 쿠키 저장소에 sessionId(쿠키)를 저장함
  5. 이후 웹 브라우저가 쿠키 접근가능한 도메인에 요청을 보낼 때마다 자동으로 쿠키 저장소에서 꺼낸 sessionId(쿠키)를 Cookie에 담아 서버에 요청을 보냄
  6. 서버는 sessionId(쿠키)의 유효성을 검사해 클라이언트를 식별함

 

쿠키 정보는 항상 서버에 전송된다.
-> 네트워크 트래픽 추가 유발
-> 최소한의 정보만 사용(세션 id, 인증 토큰)

보안에 민감한 데이터는 쿠키/웹스토리지에 저장하면 안된다.

 

생명주기

Set-Cookie: expires=Sat, 26-Dec-2020 04:39:21 GMT
  • expires : 쿠키를 무제한으로 보관할 수 없다. GMT기준으로 만료일이 되면 쿠키를 자동으로 삭제한다. 

 

Set-Cookie: max-age=3600
  • max-age :  초 단위로 구성되어 있고 0이나 음수를 지정하면 쿠키가 삭제한다. 

 

종류

  • 세션 쿠키 : 만료 날짜를 생략하면 브라우저가 종료할 때까지 유지
  • 영속 쿠키 : 만료 날짜를 입력하면 해당 날짜까지 유지(브라우저가 종료되어도 클라이언트 시간이 남아있는 한 유지)

 

도메인

  • 명시 : 도메인을 명시를 하면 명시한 문서 기준 도메인과 서브 도메인을 포함을 해서 다 전송
    - example.org 지정을 해서 쿠키를 생성하면 dev.example.org도 쿠키가 같이 접근할 수 있다.
  • 생략 :현재 문서 기준 도메인만 적용
    - example.org에서는 쿠키로 접근할 수 있고, dev.example.org는 쿠키로 접근할 수 없다.

 

경로

경로를 포함한 하위 경로 페이지만 쿠키를 접근 할 수 있다. 일반적으로 path=/ 루트로 지정한다

path=/home 지정

  • /home ->  가능
  • /home/level1 ->  가능
  • /home/level1/level2 ->  가능
  • /hello ->  불가능

 

보안

Secure, HttpOnly, SameSite

Secure

  • https인 경우메만 쿠키를 전송
  • 쿠키는 원래 http, https 를 구분하지 않고 쿠키를 서버에 전송함

 

HttpOnly

  • XSS 공격 방지 목적
  • 자바스크립트에서 쿠키 접근X(document.cookie), HTTP 전송에서만 쿠키 사용

 

SameSite

  • XSRF 공격 방지 목적
  • 요청 도메인과 쿠키에 설정된 도메인이 같은 경우만 쿠키 전송

'네트워크 > HTTP' 카테고리의 다른 글

[HTTP] 캐시와 조건부 요청  (0) 2024.02.12
[HTTP] 상태코드  (1) 2024.02.10
[HTTP] HTTP 메서드 활용  (1) 2024.02.09
[HTTP] HTTP 메서드  (1) 2024.02.08
[HTTP] HTTP 기본  (1) 2024.02.07

이 글은 인프런 김영한님의 Spring 강의를 바탕으로 개인적인 정리를 위해 작성한 글입니다.


HTTP 상태코드

상태코드

1xx (Informational) : 요청이 수신되어 처리중  ->  거의 사용이 되지 않음
2xx (Successful) : 요청 정상 처리
3xx (Redirection) : 요청을 완료하려면 추가 행동이 필요
4xx (Client Error) : 클라이언트 오류, 잘못된 문법등으로 서버가 요청을 수행할 수 없음
5xx (Server Error) : 서버 오류, 서버가 정상 요청을 처리하지 못함

HTTP 상태 코드는 클라이언트가 서버로 요청을 보내면 요청이 잘 처리가 되어있는지 문제가 있는지 요청의 처리 상태를 응답에서 알려주는 기능이다. 

 

만약 모르는 상태코드가 나타나면

클라이언트가 인식할 수 없는 상태코드를 서버가 반환하면 클라이언트는 상위 상태코드로 해석해서 처리하면 된다.

미래에 새로운 상태 코드가 추가되어도 클라이언트를 변경하지 않아도 된다.

299  -> 2xx (Successful)
451  ->  4xx (Client Error)
599  ->  5xx (Server Error)

 

100번대 - 정보

요청이 수신되어 처리 중이다. 거의 사용하지 않는다.

 

200번대 - 성공

200 OK 

  1. 클라이언트가 서버에  GET으로 리소스를 요청함
  2. 서버가 리소스를 조회함
  3. Stauts code: 200 과 리소스를 HTTP 응답 메시지를 만들어 클라이언트에 보냄

 

201 Created

요청 성공 후 새로운 리소스 생성됨

  1. 클라이언트가 서버에  POST로 신규 자원을 등록 요청함
  2. 서버가 리소스를 생성하고 리소스의 URI를 관리함
  3. Stauts code: 201, Location: 생성된 리소스의 URI 로 HTTP 응답 메시지를 만들어 클라이언트에 보냄

 

202 Accepted

요청이 접수되었으나 처리가 완료되지 않은 상태코드이다.

작업을 미뤄야할 때나 특수한 경우에 사용한다.

잘 사용하지 않는다. 

 

204 No Content

서버가 요청을 성공적으로 수행했지만 응답 페이로드 본문에 데이터가 없는 상태코드이다.

말 그대로 요청을 받고 정상적으로 수행을 했는데 보내줄 값, 함수로 따지면 return 할 값이 없다는 의미이다.

 

300번대 - 리다이렉션

300 : Multiple Choices
301 : Moved Permanently
302 : Found
303 : See Other
304 : Not Modified
307 : Temporary Redirect
308 : Permanent Redirect

 

리다이렉션 이해

웹 브라우저는 300번대 응답의 결과에 Location 헤더가 있으면 Location 위치로 자동으로 이동한다.

 

기존 /event 이벤트 페이지에서 /new-event 라는 페이지를 쓰기로 변경했다면 기존 경로를 북마크를 해둘 수 있고 기존의 링크가 여러 군데로 공유가 될 수 있다.

 

클라이언트가 /event 로 요청하면 서버 입장에서는 /event 를 더이상 쓰지 않으니까 /new-event 를 클라이언트에게 알려줄 때 301 상태코드로 알려준다.

 

 

클라이언트는 301 상태코드를 보고 /new-event 를 URL 서버에게 다시 요청을 한다.

 

정리를 하면, 기존의 경로로 요청을 하면 서버는 새로 만들어진 경로를 알려주게되고, 서버에게 받은 새로운 경로로 다시 요청을 하게 된다.

 

리다이렉션의 종류

1) 영구 리다이렉션: 특정 리소스의 URI가 영구적으로 이동
-> 이벤트 페이지 URI가 바뀌어 더이상 사용하면 안되거나 내부적으로 URI 경로가 아예 바뀐 경우
- /members -> /users
- /event -> /new-event

2) 일시 리다이렉션: 일시적인 변경
- 주문 완료 후 주문 내역 화면으로 이동
- PRG: Post/Redirect/Get

3) 특수 리다이렉션: 결과 대신 캐시를 사용

 

영구 리다이렉션

영구 리다이렉션은 상태코드가 301, 308이 있다.

리소스의 URI가 영구적으로 이동했다는 것 알려준다. 원래의 URI를 더 이상 하면 안된다.

검색 엔진들이 원래의 URI로 들어올 수 있지만 검색 엔진에서도 변경을 인지한다. 

 

301 Moved Permanently

리다이렉트시 요청 메서드가 GET으로 변하고, 본문이 제거될 수 있음(MAY)

 

  1. 클라이언트가 메세지 바디에 리소스를 담아 POST 방식으로 /event 를 서버에 요청하면
  2. 서버는 메세지 바디를 제거하고 301 코드와 Location에 /new-event를 담아 응답한다.
  3. 웹 브라우저의 URL이 자동 리다이렉트 되고
  4. 클라이언트는 메시지를 제거하고 GET방식으로 /new-event 를 서버에 요청한다.
  5. 서버는 200 코드와 /new-event 의 리소스를 응답한다.
  6. 이벤트 페이지에서 회원 정보를 등록하려고 했으나, 메시지 바디가 제거된 채로 자동 리다이렉트 되어 입력한 정보가 날라가서 처음부터 회원 정보를 다시 입력해서 등록해야 한다.

이러한 불편함 때문에 308이 나왔다.

 

308 Permanet Redirect

리다이렉트시 요청 메서드와 본문 유지

  • 클라이언트가 메세지 바디에 리소스를 담아 POST방식으로 /event 를 서버에 요청하면
  • 서버는 메세지 바디를 제거하고 308 코드와 Location에 /new-event를 담아 응답한다.
  • 웹 브라우저의 URL이 자동 리다이렉트 되고 클라이언트는 메시지를 유지해서 POST방식으로 /new-event 를 서버에 요청한다.
  • 서버는 200 코드와 /new-event 의 리소스를 응답한다.
    -> 이벤트 페이지에서 회원 정보를 등록하면 자동 리다이렉트 되어 입력한 정보가 유지되어 회원 정보가 정상 등록된다.

 

실무에서는 308을 거의 사용하지 않는다고 한다.

만약 /event 에서 /new-event로 URI가 바뀌면 내부적으로 전달해야하는 데이터 자체가 바뀌기 때문에, POST로 요청을 받아도 리다이렉트시 GET으로 바꾼다고 한다.

 

일시적인 리다이렉션

리소스의 URI를 일시적으로 변경한다.

검색 엔진 등에서 URI 변경하면 안될 때 사용한다.

 

302 Found

리다이렉트 시 요청 메서드가 GET으로 변하고 본문이 제거될 수 있다.

프레임워크나 기술 레벨에서 보면 라이브러리들이 기본값으로 302를 많이 쓰인다. 

 

307 Temporary Redirect

리다이렉트시 요청 메서드와 본문이 유지된다. 요청 메서드를 변경하면 안된다. 

 

303 See Other

리다이렉트 시 요청 메서드가 GET으로 변한다. 

 

302, 303, 307 정리

  • 302 - 메서드가 GET으로 변할 수 있음
  • 307 - 메서드가 변하면 안됨
  • 303 - 메서드가 GET으로 변경됨

현실적으로 307, 303을 권장하지만 이미 많은 애플리케이션 라이브러리들이 302를 기본값으로 사용한다.

자동 리다이렉션 시에 GET으로 변해도 되면 302를 사용해도 큰 문제가 없다.

 

PRG (Post/Redirect/Get)

POST로 주문 후에 웹 브라우저를 새로고침하면 중복 주문이 될 수 있다. 이러한 경우, PRG를 사용한다.

  • POST로 주문 후에 주문 결과 화면으로 리다이렉트
  • 새로고침해도 결과화면을 GET으로 서버에 요청
  • 중복 주문 대신에 결과 화면만 GET으로 다시 요청
새로고침(Refresh)는 마지막에 요청한 request를 재요청한다.

 

PRG 사용 전

1. 클라이언트가 마우스 1개를 POST로 주문 요청한다.
2. 서버는 주문 데이터(마우스 1개)를 DB에 저장한다.
3. 서버가 200 코드와 주문완료 html 리소스를 클라이언트에 응답한다.
4. 결과 화면을 새로고침하면 마지막 POST 요청을 새로고침 하게 된다.
5. 클라이언트가 마우스 1개를  POST로 중복 주문 요청을 한다.
6. 서버는 주문 데이터(마우스 1개)를 DB에 중복 저장한다.
7.  서버가 200 코드와 주문완료 html 리소스를 클라이언트에 응답한다.
-> 서버차원에서 중복 주문 방지: "잘못된 주문코드번호입니다"같은 응답으로 중복 주문을 방지해야 함

 

PRG 사용 후

클라이언트차원에서 중복 주문을 방지한다는 개념이다.

주문 요청을 할 때는 POST 메소드를 사용 하고 주문 완료창으로 리다이렉트 시킨다.

주문 완료창은 GET 메소드를 사용한다.

따라서 새로고침해도 GET으로 결과 화면만 조회한다.

 

기타 리다이렉션

300 Multiple Choice

안 쓴다.

 

304 Not Modified - 캐시 목적

클라이언트에게 리소스가 수정되지 않았음을 알려줌 -> 클라이언트는 로컬PC에 저장된 캐시 재사용(캐시로 리다이렉트

  • 응답에 메시지 바디를 포함하면 안됨(로컬 캐시를 사용해야하기 때문)
  • 조건부 GET, HEAD 요청 시 사용

 

400번대 - 클라이언트 오류

클라이언트의 요청에 잘못된 문법 등으로 서버가 요청을 수행할 수 없는 상태코드이다.

오류의 원인이 클라이언트에 있다.

클라이언트가 이미 잘못된 요청을 데이터를 보내고 있기 때문에 똑같이 재시도하면 실패한다. 

 

400 Bad Request

클라이언트가 잘못된 요청을 해서 서버가 요청을 처리할 수 없음

  • 요청 구문, 메시지 등 오류
  • 클라이언트는 요청 내용을 재검토 후 보내야 함
  • 요청 파라미터가 잘못되거나, API 스펙이 맞지 않을 때

 

401 Unauthorized 

클라이언트가 해당 리소스에 대한 인증이 필요하다.

오류 발생시 응답에 WWW-Authenticate라는 헤더와 함께 인증하는 방법을 설명을 해줘야 한다. 

인증(Authentication) : 본인이 누구인지 확인하는 과정
인가(Authorization) : 특정 리소스에 접근할 수 있는 권한이 있는 사람만 볼 수 있는 권한 부여
오류 메시지가 Unauthorized이지만 실제로는 인증이 되지않아 생긴 오류이다.

 

403 Forbidden

클라이언트가 보낸 요청을 서버가 이해했지만 승인을 거부하는 상태코드이다.

주로 인증 자격 증명은 있지만 접근 권한이 없을 때 볼 수 있다.

어드민 등급이 아닌 사용자가 다른 리소스로 로그인은 했지만 어드민 등급의 리소스에 접근할 때 오류가 나타난다.

 

404 Not Found

요청 리소스를 찾을 수 없는 상태코드이다.

클라이언트가 권한이 부족한 리소스에 접근할 때, 해당 리소스를 숨기고 싶을 때 사용할 수도 있다.

 

500번대 - 서버 오류

서버 오류

  • 오류의 원인 = 서버 ( NullPointerException, DB 접근 불가 등)
  • 서버에 문제가 있으므로 복구된 뒤 재시도하면 성공할 수도 있음

왠만하면 5xx 오류는 내면 안된다. 심각한 서버 오류가 있을 때만 500번대 오류를 내야 한다.

 

500 Internal Server Error

서버 내부 문제로 오류 발생한 상태코드이다.

애매한 오류는 500 상태코드이다.

 

503 Service Unavaliable

서버가 일시적인 과부하 되거나 예정된 작업으로 잠시 요청을 처리할 수 없는 것을 나타냄

Retry-After 헤더로 얼마 뒤에 복구되는지 예상 시간을 보낼수 있다.

'네트워크 > HTTP' 카테고리의 다른 글

[HTTP] 캐시와 조건부 요청  (0) 2024.02.12
[HTTP] 일반 헤더  (1) 2024.02.11
[HTTP] HTTP 메서드 활용  (1) 2024.02.09
[HTTP] HTTP 메서드  (1) 2024.02.08
[HTTP] HTTP 기본  (1) 2024.02.07

이 글은 인프런 김영한님의 Spring 강의를 바탕으로 개인적인 정리를 위해 작성한 글입니다.


클라이언트에서 서버로 데이터 전송

데이터 전달 방식

쿼리 파라미터를 통한 데이터 전송

주로 GET 방식으로 많이 사용하고 검색어로 검색할 때, 게시판 리스트에 정렬 조건을 넣을 때 쿼리 파라미터를 이용해서 많이 사용한다.

 

메시지 바디를 통한 데이터 전송

클라이언트에서 서버로 전송할 때 HTTP 메시지 바디를 통해서 데이터를 전송한다.

POST, PUT, PATCH 방식으로 주로 사용한다.

회원 가입, 상품 주문, 리소스 등록, 리소스 변경 등에 사용된다.

 

클라이언트에서 서버로 데이터 전송할 때 4가지 상황

  • 정적 데이터 조회 : 이미지, 정적 텍스트 문서
  • 동적 데이터 조회 : 주로 검색, 게시판 목록에서 정렬 필터
  • HTML Form을 통한 데이터 전송 : 회원가입, 상품 주문, 데이터 변경
  • HTTP API를 통한 데이터 전송 : 회원 가입, 상품 주문, 데이터 변경, 서버 to 서버, 앱 클라이언트 웹 클라이언트(Ajax)

 

데이터 조회

정적 데이터 조회 - 쿼리 파라미터 미사용

클라이언트에서 /static/star.jpg 인 경로만 입력하면 서버에서 star 이미지를 클라이언트에게 응답해준다.

정적 데이터를 조회할 때는 이미지나 정적 텍스트 문서를 조회하기 때문에 GET으로 사용한다.

일반적으로 정적 데이터는 쿼리 파라미터 없이 단순한 리소스 경로로 조회가 가능하다.

 

동적 데이터 조회 - 쿼리 파라미터 사용

검색할 때 검색어나 추가 조건을 데이터를 전달 할 때 쿼리 파라미터들을 사용해서 서버에게 요청한다.

쿼리 파라미터를 사용하기에 서버에서 key와 value를 볼 수 있다. 이에 대한 결과를 클라이언트에게 응답한다.

주로 검색을 하거나 게시판 목록에서 정렬하거나 필터할 때 추가 데이터들이 쿼리 파라미터로 요청한다.

조회이기 때문에 GET 방식으로 이용해서 쿼리 파라미터를 사용해서 데이터를 클라이언트에서 서버로 전달한다.

동적 데이터는 쿼리 파라미터를 사용해서 조회 가능하다.

 

HTML Form을 통한 데이터 전송

POST 전송의 저장

post method로 된 Form 태그의 submit 버튼을 누르면, 웹 브라우저가 HTML Form의 데이터를 읽어서 HTTP 요청 메시지를 생성해준다.

key - value 형태의 데이터를 HTTP 바디 메시지에 넣고 서버에 전송을 한다.

서버에서 POST 메시지를 받으면 데이터를 저장을 한다. 

htnl form 태그를 사용하여 post 방식으로 요청하거나, ajax 등의 요청을 할때 default Content-Type은 application/json이 아니라 application/x-www-form-urlencoded 이다.

전송 데이터를 url encoding 으로처리한다.

 

GET 전송의 저장

form을 통해서 데이터 전송할 때 GET 메서드로 변경하면 GET은 메시지 바디를 사용하지 않으므로 쿼리 파라미터 형식으로 서버에 전달한다.

리소스를 변경할 때 GET 메서드를 사용하면 안된다. GET은 조회할 때 사용한다

 

GET전송의 조회

get method로 된 Form 태그의 submit 버튼을 누르면, 웹 브라우저가 HTML Form의 데이터를 읽어서 HTTP 요청 메시지를 생성해준다.

쿼리 파라미터에 key-value 형태로 form 의 데이터를 넣어서 전송한다.

서버가 GET 메시지를 받으면 데이터를 필터링(조회)한 결과를 응답한다.

url에 key-value가 노출된다.

 

multipart/form-data

multipart/form-data는 파일(binary data)을 전송할 때 쓰는 인코딩 타입이다.

Content-type은 multipart/form-data로 지정되고 boundary는 웹으로 자동 생성해서 경계로 나눠진다.

HTML Form 태그의 enctype="multipart/form-data"로 설정하고 submit 버튼을 누르면 웹 브라우저가 username, age, file1 데이터를 분리하여 message-body에 담아 HTTP 요청 메시지를 생성해준다.

 

HTML Form을 통한 데이터 전송 정리

HTML Form submit 시 POST 전송

- 회원 가입, 상품 주문, 데이터 변경
▶ Content-Type: application/x-www-urlencoded 사용
form의 내용을 message-body에 담아 전송(key=value, 쿼리 파라미터 형식)
전송 데이터를 url encoding 처리
e.g. abc김 → abc%EA%B9%80

▶ Content-Type: multipart/form-data 사용
파일 업로드 같은 바이너리 데이터 전송시 사용
다른 종류의 여러 파일과 폼의 내용 함께 전송O 2) HTML Form submit 시 GET 전송
form의 내용을 쿼리 파라미터에 담아 전송

HTML Form 전송은 GET, POST 만 지원한다 다른 메서드들은 자바스크립트의 이벤트 핸들러를 통해 처리해야 한다.

 

HTTP API 데이터 전송

  • 서버 to 서버 : 백엔드 서버끼리 통신
  • 앱 클라이언트 : 아이폰, 안드로이드
  • 웹 클라이언트 : HTML Form이 아니라 자바스크립트를 통해서 Ajax로 통신
  • HTTP API는 메시지 바디를 통해 POST, PUT, PATCH로 데이터 전송 
  • GET도 마찬가지로 HTTP API로 쓸수 있지만 조회할 때는 항상 쿼리 파라미터 형식으로 전달해야 된다. 
  • Content-Type 으로 application/json을 주로 사용(TEXT, XML, JSON)
Form 태그에서 POST와 HTTP API에서의 POST
form 태그 - default Content-Type: application/x-www-form-urlencoded
HTTP API - default Content-Type: application/json

 

HTTP API 설계

<HTTP API 설계 예시 3가지>

POST 기반으로 등록, PUT기반으로 등록하는 2가지 경우의 특징을 아는 것이 중요
대부분 POST 기반 신규 자원 등록 방법(컬렉션)을 많이 사용한다.

1) HTTP API - 컬렉션 : POST 기반 등록
e.g. 회원 관리 API 제공

2) HTTP API - 스토어 : PUT 기반 등록
e.g. 정적 컨텐츠 관리, 원격 파일 관리

3) HTML FORM 사용 : 웹 페이지 회원 관리
- GET, POST 만 지원

POST 기반 등록

컬렉션 = /members

회원 관리 시스템
1. 회원 목록 : /members  ->  GET

2. 회원 등록 : /members  ->  POST
3. 회원 조회 : /members/{id}  ->   GET
4. 회원 수정 : /members/{id}  ->   PATCH, PUT, POST
5. 회원 삭제 : /members/{id}  ->   DELETE 
  • 클라이언트는 등록될 리소스의 URI를 모른다.
    서버가 알아서 회원을 식별해서 URI를 만들어준다.
회원 등록 : /members  -> POST
POST /memebers
  • 클라이언트가 결정하는 게 아니라 서버가 새롭게 등록된 리소스의 URI를 생성한다. 
HTTP/1.1 201 Created
Location : /members/100
  • 컬렉션(Collection)은 서버가 관리하는 리소스 디렉토리이다. 리소스의 URI를 생성하고 관리한다. 
/members
회원 수정은 PATCH, PUT, POST 중 무엇으로 구현해야 하나?

1) 개념적으로는 리소스 부분 변경인 PATCH로 하는 것이 가장 좋다.
2) 기존 리소스를 덮어써도 문제가 없는 경우, PUT을 사용할 수는 있지만 그런 경우는 거의 없다. 클라이언트에서 회원의 모든 데이터(id, 이름, email 등)을  다 보내야하기 때문이다.
- 게시글 수정같은 경우, 완전히 덮어써도 문제X
3) 애매한 경우, POST를 쓰면 된다.

 

PUT 기반 등록

스토어 = /files

파일 관리 시스템
1. 파일 목록 : /files  ->  GET
2. 파일 조회 : /files/{filename}  ->   GET
3. 파일 등록 : /files/{filename}  ->   PUT
4. 파일 삭제 : /files/{filename}  ->   DELETE
5. 파일 대량 등록 : /files  ->   POST 
  • 클라이언트가 리소스 URI를 알고 있어야 한다. 클라이언트가 직접 리소스의 URI를 지정해서 생성된 리소스를 관리해야 한다. 
파일 등록 : /file/{filename}  ->  POST
PUT /files/star.jpg
  • 스토어(Store)는 클라이언트가 관리하는 리소스 저장소이다. 
/files

파일 등록같은 경우는 해당 파일이 있으면 기존 것을 덮어써야하기 때문에, PUT을 쓴다.

 

HTML Form 사용

회원 관리 시스템
1. 회원 목록 : /members  ->  GET
2. 회원 등록 폼 : /members/new  ->   GET

3. 회원 등록 : /members/new, /members  ->   POST
4. 회원 조회 : /members/{id}  ->   GET
5. 회원 수정 폼 : /members/{id}/edit  ->   GET
6. 회원 수정 : /members/{id}/edit, /members/{id}  ->   POST
7. 회원 삭제 : /members/{id}/delete  ->   POST
  •  순수한 HTML과 HTML Form은 GET, POST만 지원하기 때문에 제약이 있다.
    -> AJAX 같은 기술을 사용해서 해결
  • 제약을 해결하기 위해 동사로 된 리소스 경로를 사용을 하는데 이걸 컨트롤 URI이라 한다. 
    -> HTML FORM은 GET, POST만 지원하기 때문에 어쩔 수 없이 컨트롤 URI를 써서 /members/{id}/delete
    POST로 설계

/members/new
/members/{id}/edit

/members/{id}delete

 

정리

1) HTTP API - 컬렉션
- POST 기반 등록
- 서버가 리소스 URI 결정

2) HTTP API - 스토어
- PUT 기반 등록
- 클라이언트가 리소스 URI 결정

3) HTML FORM 사용
- 순수 HTML + HTML form 사용
- GET, POST만 지원 → 컨트롤 URI로 해결

 

참고하면 좋은 URI 설계 개념

  • 문서(document) : 파일 하나, 객체 인스턴스, 데이터베이스 row 같은게 단일 개념이다.
/members/100
/files/star.jpg
  • 컬렉션(Collection) : 서버가 관리하는 리소스 디렉토리이다. 클라이언트는 요청만 하고 서버가 리소스의 URI를 생성하고 관리한다.
/members
  • 스토어(Store) : 클라이언트가 관리하는 자원 저장소이다. 클라이언트가 리소스의 URI를 알고 관리한다.
/files
  • 컨트롤러(Controller), 컨트롤 URI : 문서, 컬렉션, 스토어로 해결하기 어려운 추가 프로세스 실행할 때 동사를 직접 사용한다.
/members/{id}/delete

주로 컬렉션을 많이 사용하고, 파일 /게시판 같은 경우에 스토어를 사용할 수 있다.

문서, 컬렉션, 스토어로 해결하기 어려운 추가 프로세스를 실행할 때, 컨트롤 URI를 사용한다.

'네트워크 > HTTP' 카테고리의 다른 글

[HTTP] 일반 헤더  (1) 2024.02.11
[HTTP] 상태코드  (1) 2024.02.10
[HTTP] HTTP 메서드  (1) 2024.02.08
[HTTP] HTTP 기본  (1) 2024.02.07
[HTTP] URI와 웹 브라우저 요청 흐름  (1) 2024.02.06

이 글은 인프런 김영한님의 Spring 강의를 바탕으로 개인적인 정리를 위해 작성한 글입니다.


HTTP API 예제

요구사항 및 API URI 설계

회원 정보 관리 API 설계
1. 회원 목록 조회 :  /read-member-list
2. 회원 조회 :  /read-member-by-id
3. 회원 등록 : /create-member
4. 회원 수정 : /update-member
5. 회원 삭제 : /delete-member

요구사항 기반으로 API를 만들게 되는게 위와 같이 현업에서 잘못된 API URI 설계를 한다. 

 

API URI  설계 분리

리소스 : 회원
행위 : 조회, 등록, 수정, 삭제

API URI 설계를 할 때 리소스와 해당 리소스를 대상으로 하는 행위를 분리해야 한다.

회원이라는 리소스만 식별하고 회원 리소스를 URI에 매핑을 하면 된다. 

리소스를 식별하는 것이 가장 중요하다.

 

API URI 재설계

회원 정보 관리 API 재설계
1. 회원 목록 조회 :  /members
2. 회원 조회 :  /members/{id} 
3. 회원 등록 : /members/{id}
4. 회원 수정 : /members/{id}
5. 회원 삭제 : /members/{id}

API URI 재설계를 했지만 행위는 구분이 되지 않는다.

구분하는 방법은 URI 리소스만 식별해 놓으면 HTTP 메서드인 GET, POST, PUT, DELETE 이런 것들이 조회, 등록, 수정, 삭제 역할을 대신해준다

계층 구조상 상위를 컬렉션으로 보고 복수 단어 사용 권장(member  ->  members)


HTTP 메서드 - GET, POST

HTTP 메서드 종류

  • GET : 리소스를 조회
  • POST : 요청 데이터를 담아서 처리 
  • PUT : 리소스를 대체, 해당 리소스가 없으면 생성
  • PATCH : 리소스 부분 변경
  • DELETE : 리소스 삭제
  • HEAD : GET과 동일하지만 메시지 부분을 제외하고 상태 줄과 헤더만 반환
  • OPTIONS : 대상 리소스에 대한 통신 가능 옵션(메서드)를 설명 (주로 CORS에서 사용)
  • TRACE : 대상 리소스에 대한 경로를 따라 메시지 루프백 테스트를 수행

 

GET

리소스를 조회할 때 주로 사용한다.

서버에 전달하고 싶은 데이터는 쿼리 파라미터 또는 쿼리 스트링을 통해서 전달한다.

GET은 메시지 바디를 전달할 수 있지만 실무에서는 바디에 보통 데이터를 넣지 않는다.

지원하지 않는 서버들이 많아서 권장하지 않는다. 

 

예를들면 게시판의 게시물을 조회할 때 쓸 수 있다.

GET을 통한 요청은 URL 주소 끝에 파라미터로 포함되어 전송되며, 이 부분을 쿼리 스트링 (query string) 이라고 부른다.

방식은 URL 끝에 " ? " 를 붙이고 그다음 변수명1=값1&변수명2=값2... 형식으로 이어 붙이면 된다.

 

예를들어 다음과 같은 방식이다. 
http://www.example.com/show?name1=value1&name2=value2
서버에서는 name1 과 name2 라는 파라미터 명으로 각각 value1 과 value2 의 파라미터 값을 전달 받을 수 있다.

 

 

GET 요청과 응답

클라이언트가 /members/100 GET하고 요청하면 서버에서 GET 메시지가 도착한다.

서버에서는 /members/100 에서 데이터베이스를 조회해서 응답 메시지를 만들어서 클라이언트에게 보낸다. 

 

특징

  • 캐시 가능  : GET을 통해 서버에 리소스를 요청할 때 웹 캐시가 요청을 가로채 서버로부터 리소스를 다시 다운로드하는 대신 리소스의 복사본을 반환한다.
    HTTP 헤더에서 cache-control 헤더를 통해 캐시 옵션을 지정할 수 있다.
  • GET 요청은 브라우저 히스토리에 남는다.
  • GET 요청은 북마크 될 수 있다.
  • 길이 제한  : GET 요청의 길이 제한은 표준이 따로 있는건 아니고 브라우저마다 제한이 다르다고 한다. 
  • 보안 취약 : GET 요청은 파라미터에 다 노출되어 버리기 때문에 중요한 정보는 GET 방식을 사용하면 안된다.
  • GET은 데이터를 요청할때만 사용 된다.

 

POST

클라이언트에서 메시지 바디를 통해서 서버로 요청하고, 서버가 데이터를 처리하는 모든 기능을 수행한다.

주로 전달된 데이터로 신규 리소스 등록하거나 변경된 프로세스를 바꿀 때 많이 이용한다. 

 

POST는 클라이언트에서 서버로 리소스를 생성하거나 업데이트하기 위해 데이터를 보낼 때 사용 되는 메서드다.

예를들면 게시판에 게시글을 작성하는 작업 등을 할 때 사용할 된다.


POST는 전송할 데이터를 HTTP 메시지 body 부분에 담아서 서버로 보낸다

GET에서 URL 의 파라미터로 보냈던 name1=value1&name2=value2 가 body에 담겨 보내진다 생각하면 된다.

POST 로 데이터를 전송할 때 길이 제한이 따로 없어 용량이 큰 데이터를 보낼 때 사용하거나 GET처럼 데이터가 외부적으로 드러나는건 아니라서 보안이 필요한 부분에 많이 사용된다. (데이터를 암호화하지 않으면 body의 데이터도 결국 볼 수 있는건 똑같다.)

POST를 통한 데이터 전송은 보통 HTML form 을 통해 서버로 전송된다.

 

리소스를 /members POST로 전달하기전, 서버와 클라이언트는 그 데이터를 내부적으로 어떻게 쓸 것인지 미리 서로 약속되어있다.

따라서 클라이언트가 필요한 데이터를 전달하고 서버에서는 신규로 등록을 위해서  /members에 100 신규 리소스 식별자를 생성한다.

서버는 다시 클라이언트로 신규로 자원이 생성된 경로를 응답메시지로 보낸다.   

 

POST 예시

1. HTML 양식에 입력된 필드와 같은 데이터 블록을 데이터 처리 프로세스에 제공 

  • HTML 폼에 입력한 정보로 회원가입하거나 주문 문 등을 처리

2. 게시판, 뉴스 그룹, 메일링 리스트, 블로그 또는 유사한 기사 그룹에 메시지 게시

  • 게시판에 글쓰거나 댓글 달기
  • 게시판에 글을 쓰고 Submit 누르면 POST로 글이 서버로 전달하고 서버가 게시판에 글을 저장한다.

3. 서버가 아직 식별하지 않은 새 리소스 생성

  • 신규 주문을 생성하거나 신규 회원을 생성할 때 

4. 기존 자원의 끝에 데이터를 추가

  • 한 문서 끝에 내용 추가하기 

 

POST 정리

1. 새 리소스 생성(등록)

  • 서버가 아직 식별하지 않은 새 리소스 생성

2. 요청 데이터 처리

  • 단순히 데이터를 생성하거나 변경하는 것을 넘어서 프로세스를 처리할 때 서버에서 큰 변화가 일어남
  • 주문에서 결제완료 -> 배달 시작 -> 배달완료 처럼 단순히 값 변경을 넘어 프로세스의 상태가 변경되는 경우
  • POST의 결과로 새로운 리소스가 생성되지 않을 수 있음
  • 컨트롤 URI : POST /orders/{orderld}/start-delivery -> 실무에서 어쩔 수 없이 리소스만으로 URI 설계가 힘들 경우도 있다. 그때 동사만을 사용하여 URI를 구성

3. 다른 메서드로 처리하기 애매한 경우

  • JSON으로 조회 데이터를 넘겨야 하는데 GET 메서드를 지원하지 않는 서버가 있어서 사용하기 어려운 경우
  • 애매하면 POST 사용

 

특징

  • 캐시되지 않는다.
  • 브라우저 히스토리에 남지 않는다.
  • 북마크 되지 않는다.
  • 데이터 길이에 제한이 없다.

 

GET 과 POST 차이

  • 사용목적 : GET은 서버의 리소스에서 데이터를 요청할 때, POST는 서버의 리소스를 새로 생성하거나 업데이트할 때 사용한다.
    DB로 예시를 들면, GET은 SELECT 에 가깝고, POST는 Create 에 가깝다고 보면 된다.
  • 요청에 body 유무 : GET 은 URL 파라미터에 요청하는 데이터를 담아 보내기 때문에 HTTP 메시지에 body가 없다. POST 는 body 에 데이터를 담아 보내기 때문에 당연히 HTTP 메시지에 body가 존재한다.
  • 멱등성 (idempotent) : GET 요청은 멱등이며, POST는 멱등이 아니다.
멱등성
멱등의 사전적 정의는 연산을 여러 번 적용하더라도 결과가 달라지지 않는 성질을 의미한다.
GET은 리소스를 조회한다는 점에서 여러 번 요청하더라도 응답이 똑같을 것 이다.
반대로 POST는 리소스를 새로 생성하거나 업데이트할 때 사용되기 때문에 멱등이 아니라고 볼 수 있다. (POST 요청이 발생하면 서버가 변경될 수 있다.)

GET과 POST는 이런 차이들이 있기 때문에 사용하려는 목적에 맞는 확인한 후에 사용해야한다.

 

HTTP 메서드 - PUT, PATCH, DELETE

PUT

리소스가 있으면 완전히 대체(덮어쓰기)하고 리소스가 없으면 생성한다.

POST와 다른 점은 PUT은 클라이언트가 구체적인 리소스의 전체 위치를 알고 URI를 지정해서 서버에게 전달한다. 

 

PUT - 리소스가 있을 경우

클라이언트가 /members/100 리소스 지정해서 데이터를 서버에게 보내면 서버도 /members/100 리소스가 있다. 그러면 클라이언트가 보낸 리소스로 대체해버린다. 

 

PUT - 리소스가 없을 경우

클라이언트가 members/100 리소스 지정해서 데이터를 서버에게 보냈는데 서버에서 해당 리소스가 없으면 신규 리소스로 생성이 된다.

 

PUT 주의사항

클라이언트가 /members/100 데이터에 username이 없고 age로 지정해서 보내면 서버에서는 age를 업데이트를 하는데 username 자체가 날아가버린다.

기존 리소스를 새로운 리소스로 완전히 대체한다. 이렇게 되면 리소스를 수정하기 어렵다. 

 

PATCH

리소스를 부분 변경한다.

서버에 /members/100 데이터에 age가 없고, 클라이언트가 age로 지정해서 보내면 서버에서는 username은 남아있고 age만 변경한 것이다. 

 

DELETE

리소스를 삭제한다.

클라이언트가 /members/100 를 삭제해달라고 요청하면 서버에서 리소스를 삭제한다. 


HTTP 메서드의 속성

HTTP 메서드의 속성

 

안전(Safe)

호출해도 리소스가 변경하지 않는 특징

  • GET은 단순히 조회만 하기 때문에 안전하다.  한번 호출해도 여러번 호출해도 변경이 일어나지 않아서 안전하다.
  • POST, PUT, PATCH, DELETE는 안전하지 않다.
  • 만약에 그래도 계속 호출해서 서버에서 로그가 계속 쌓게되서 서버 장애가 일어날 때는 안전은 그런 부분까지 고려하지 않는다. 안전은 해당 리소스만 고려하기 때문이다. 

 

멱등(Idempotent)

한 번 호출해도 두 번 호출해도 100번 호출해도 결과는 동일한 특징

여러 번이라는 키워드를 중심으로 이해해야 한다.

  • GET은 한 번 조회하든 두 번 조회하든 같은 결과로 조회된다.
  • PUT은 결과를 대체하기 때문에 같은 요청을 여러 번 해도 최종 결과는 동일하다.
  • DELETE는 결과를 삭제하기 때문에 같은 요청을 여러 번 해도 삭제된 결과는 동일하다.
  • POST는 멱등이 아니다. 여러번 호출하면 같은 결제등이 중복으로 발생해서 새로운 리소스로 구별이 된다.
사용자 1 : GET -> username: A, age: 20
사용자 2 : PUT -> username: A, age: 30
사용자 1 : GET -> username: A, age: 30 -> 사용자2의 영향으로 바뀐 데이터 조회

멱등은 외부 요인으로 중간에 리소스가 변경되는 것까지 고려하지 않는다.

클라이언트가 동일한 요청을 똑같은 클라이언트가 동일한 요청했을 때만 멱등한다.

즉, 멱등은 동시성 문제까지 고려하지 않는다. 

 

멱등의 활용 

  • 자동 복구 매커니즘로 활용할 수 있다.
  • 클라이언트가 DELETE를 호출했는데 서버에서 잘 되고 있는지 안 되고 있는지 응답이 없을 경우, 클라이언트가 다시 재차 DELETE를 시도 해도 멱등하기 때문에 안전하다.

 

캐시가능(Cacheable)

웹 브라우저에 용량이 큰 이미지를 한번 요청을 하면 그 다음에 똑같이 용량이 큰 이미지를 요청할 필요없다.

똑같은 이미지를 서버에서 다운로드 받는 것은 불필요한 행동이기 때문이다.

그래서 로컬 PC에 웹 브라우저 저장을 하고 저장된 것을 이용한다.

 

캐시는 GET, HEAD, POST, PATCH 가 가능 하지만 실제로는 GET, HEAD 정도만 캐시로 사용한다.

POST, PATCH는 캐시를 하려면 본문 내용으로 리소스랑 캐시 키가 맞아아야 되는데 복잡해서 구현이 쉽지 않다.

GET, HEAD는 URI만 캐시 키로 캐시해서 간단하다. 

'네트워크 > HTTP' 카테고리의 다른 글

[HTTP] 상태코드  (1) 2024.02.10
[HTTP] HTTP 메서드 활용  (1) 2024.02.09
[HTTP] HTTP 기본  (1) 2024.02.07
[HTTP] URI와 웹 브라우저 요청 흐름  (1) 2024.02.06
[HTTP] 인터넷 네트워크  (1) 2024.02.05

이 글은 인프런 김영한님의 Spring 강의를 바탕으로 개인적인 정리를 위해 작성한 글입니다.


모든 것이 HTTP

HTTP(HyperText Transfer Protocol)

  • 문서 간의 링크를 통해서 하이퍼텍스트 문서를 통해서 연결하는 프로토콜이다.
  • HTTP 프토토콜에 HTML, TEXT, IMAGE, 음성, 영상, 파일, JSON, XML (API) 등 모든 형태의 데이터를 담아서 전송이 가능하다.
  • 서버간에 데이터를 주고 받을 때도 사용한다. 

 

HTTP 역사

  1. HTTP/0.9 (1991년) : GET 메서드만 지원, HTTP 헤더X
  2. HTTP/1.0 (1996년) : 메서드, 헤더 추가
  3. HTTP/1.1 (1997년) : 가장 많이 사용하고 가장 중요한 버전이다. 
    RFC2068 (1997년)  -> RFC2616 (1999년)  -> RFC7230~7235 (2014년)
  4. HTTP/2 (2015년) : 성능 개선
  5. HTTP/3 (진행중) : TCP 대신에 UDP 사용, 성능 개선

 

HTTP 기반 프로토콜

HTTP/1.1, HTTP/2 같은 경우에는 TCP 프로토콜 위에서 동작을 한다.

HTTP/3은 UDP 프로토콜 기반으로 개발이 되어 있다. TCP는 3 way handshake도 해야 되고 기본적으로 데이터도 많고 매커니즘 자체가 속도가 느린 편이다.

그래서 UDP 프로토콜 위에 애플리케이션 단계에서 성능을 최적화하도록 새로 설계한다. 

개발자 도구에서 Network 탭의 Protocol에서 어떤 버전의 HTTP를 사용하는지 알 수 있다.

HTTP/2, HTTP/3도 굉장히 급속도로 커지고 있다. 

 

HTTP 특징

HTTP 프로토콜은 기본적으로 클라이언트 서버 구조로 동작한다.

무상태 프로토콜(Stateless)이고 비연결성이라는 특징이 있다. HTTP 메시지를 통해서 통신을 하고 단순하고 확장 가능하다.

 

클라이언트 서버 구조

Request Response 구조

클라이언트와 서버 구조로 되어 있다.

HTTP는 클라이언트가 HTTP 메시지를 통해서 서버에 요청을 보내고 클라이언트는 서버에 응답이 올 때 기다린다.

서버가 요청에 대한 결과를 만들어서 응답이 오면 그 응답 결과를 열어서 클라이언트가 동작한다. 

 

역할의 분리

원래는 클라이언트와 서버가 하나로 되었다가 개념적으로 분리가 되면서 클라이언트는 UI, 사용성에 집중하고 서버는 비즈니스 로직이랑 데이터에 집중한다.

이슈가 발생해도 서로의 역할이 달라 이슈에 대한 영향을 미치지 않고 독립적으로 이슈를 대응하면서 진화했다.  

 

 

Stateful, Stateless

상태 유지 (Stateful)

서버가 클라이언트의 상태를 보존한다.

클라이언트가 상품을 구입할 때 상품 정보와 결제 정보를 매칭된 서버로 계속 유지해야 되서 서버를 바꿀 수가 없다.

중간에 유지해야할 서버가 장애가 발생하면 다른 서버로 바뀌게 되면 서버가 클라이언트에게 다시 정보를 요청을 해야 한다. 

 

무상태 (Stateless)

서버가 클라이언트의 상태를 보존하지 않는다.

클라이언트가 상품을 구입할 때 애초에 필요한 상품 정보와 결제 정보를 담아서 요청을 하면 서버에서는 상태를 보존하지 않고 응답만 한다.

중간에 서버가 장애가 발생해도 클라이언트가 필요한 정보들을 이미 담아 보내기 때문에 다른 서버에 요청 할 수 있다. 

 

HTTP는 무상태를 유지하되, 세션과 쿠키를 통해서 클라이언트의 필요한 정보를 알 수 있다.

 

무상태 스케일 아웃 

로그인 없이 검색만 할 경우 검색 서버에 트래픽이 많이 올라가도 검색 서버에 클라이언트의 상태를 유지되지 않아서 서버를 많이 늘릴 수 있다.

클라이언트, 서버 아키텍처에서는 엄청난 확장성이 가져와 무한한 서버 증식을 할 수 있다.

 

상태 유지와 무상태의 한계

상태 유지의 한계

  • 로그인 해야 되는 경우는 로그인한 사용자가 로그인했다는 상태를 서버에 유지해야 한다.
  • 서버에 세션이 날아가거나 세션 서버가 죽어버리면 전체적으로 로그인이 풀려버리게 된다.
  • 상태유지는 최소한으로만 사용해야한다. 

 

무상태의 한계

  • 로그인할 필요 없는 단순한 소개 페이지일 때는 상태를 유지할 필요가 없어서 설계하기가 쉽다.
  • 클라이언트가 전송할 때 필요한 정보를 담아야 하기 때문에 데이터량이 많다.

 

비 연결성(connectionless)

연결을 유지하는 모델

여러 클라이언트에서 서버로 응답을 요청하면 서버는 요청이 들어온 클라이언트 마다 연결을 유지해서 상태를 저장한다.

클라이언트가 많아 질수록 연결을 유지하는 서버의 자원이 계속 소모되는 단점이 있다.

 

연결을 유지하지 않는 모델

클라이언트가 요청할 때마다 서버는 응답만 보내주고 연결을 종료하기 때문에 서버가 최소한의 자원으로 유지할 수 있다.

 

비연결성

HTTP는 기본적으로 연결을 유지하지 않는 모델이다.

이로 인해서, 1시간 동안 수천명이 서비스를 사용해도 실제 서버에서 동시에 처리하는 요청은 적기 때문에 서버 입장에서는 자원의 가용성이 훨씬 높아진다.

 

비연결성의 한계

TCP/IP 연결을 새로 맺을 때 마다 3 way handshake 시간 추가가 되서 클라이언트 입장에서는 느리다.

웹 브라우저로 사이트를 요청하면 HTML, CSS, Javascript,  추가 이미지 등 수많은 자원이 함께 다운로드할 때 연결하고 끊고 또 연결하고 또 끊고 하면 비효율적이다. 

 

비연결성의 극복

HTTP는 기본적으로 지속 연결(Persistent Connection)로 문제 해결한다.

HTTP/2, HTTP/3 에서는 더 많은 최적화되어 있다. 

 

HTTP 초기

연결하고 요청, 응답 하고 종료 또 연결하고 요청, 응답 하고 종료 반복적으로 하면 속도가 느리다.

 

HTTP 지속 연결(Persistent Connections)

연결을 유지 하면서 종료하기 전까지 내부 매커니즘으로 요청하고 응답을 다 하고 종료하면 속도가 빠르다. 

 

Stateless를 기억하자

서버 개발자들이 어려워하는 업무가 같은 타이밍에 발생하는 대용량 트래픽발생할 때가 어렵다.

이럴 때는 Sateless하게 설계하는 게 제일 중요하다. 

 

 

HTTP 메시지

HTTP 메시지 구조

요청 메시지에도 message body가 있을 수 있다.

 

https://kotlinworld.com/98

 

HTTP 메시지 구조는 아래의 4가지 구조로 나눈다.

  • start-line : 한줄로 구성, 첫 번째 줄이 무조건 시작 라인이 되며 시작 라인은 두 줄 이상은 될 수 없음
  • header : 헤더는 첫 줄을 제외한 공백라인이 나오기 전까지의 줄이다. 헤더는 수십, 수백줄이 될 수 있음
  • empty line(CRLF)
  • message body : CRLF 뒤의 모든 라인

 

HTTP에서 요청 메시지와 응답 메시지는 구조가 조금 다르다.

 

Start Line(시작 라인)

  • 시작 라인은 요청 메시지인지 응답 메시지인지에 따라 다른 형식을 가진다.
  • 요청 메시지의 시작라인 (request-line) : http 메소드, 경로 및 질의정보(Path or Query), http 버전 (총 3개)
  • 응답 메시지의 시작라인 (status-line) : http 버전, 응답 메시지 (총 2개)

 

 

요청 메시지 시작라인

start-line : request-line

시작라인 : GET /search?q=hello&hl=ko HTTP/1.1
-> method SP Path or Query  SP HTTP-version CRLF
-> http메소드 SP 경로 및 질의정보 SP http버전 CRLF
SP : 공백, CRLF : 엔터
  • method (메서드)

HTTP method의 종류가 GET, POST, PUT, DELETE 등이 있고 서버가 수행해야 할 동작을 지정한다.

  • GET : 서버에게 리소스 조회
  • POST : 서버가 리소스를 요청 내역 처리 

 

  • 경로 및 질의정보(Path or Query)
/absolute-pate[?query]
/절대경로[?쿼리]

보통 절대경로로 ' / '로 시작하고 쿼리를 합친다.

http://...?x=y 같이 다른 유형의 경로지정 방법도 있다.

 

  •  HTTP-version (HTTP 버전)

 

응답 메시지 시작라인

start-line : status-line

HTTP/1.1 200 OK
HTTP-version SP status-code SP reason-phrase CRLF
  •  HTTP-version (HTTP 버전)
  • status-code (HTTP 상태 코드)

클라이언트가 보낸 요청이 성공했는지 실패했는지 나타내는 상태이다. 

  • 200 : 성공
  • 400 : 클라이언트 요청 오류
  • 500 : 서버 내부 오류

 

  • reason-phrase (이유 문구)

사람이 이해할 수 있는 짧은 상태 코드를 읽을 수 있는 글이다.

 

HTTP 헤더

왼쪽 : 요청, 오른쪽 : 응답

Content-Typetext/html;charset=UTF-8
Content-Length3423
field-name ":" OWS field-value OWS

OWS : 띄어쓰기 허용

헤더는 field-name와 field-value으로 이루어져 있다.

HTTP 헤더의 용도는 HTTP 전송에 필요한 메시지 바디의 내용, 메시지 바디의 크기, 압축, 인증, 요청 클라이언트(브라우저) 정보, 서버 애플리케이션 정보, 캐시 관리 정도 등 모든 부가 정보가 들어가 있다.

표준 헤더가 많다. 필요하면 임의의 헤더도 추가 가능할 수 있다. 

  • field-name : 대소문자 구분 X
  • field-value : 대소문자 구분 O

 

body

<html>
    <body> ... </body>
</html>

실제 전송할 데이터가 담아있다. HTML 문서, 이미지, 영상, JSON 등 byte로 표현할 수 있는 모든 데이터 전송이 가능하다.

'네트워크 > HTTP' 카테고리의 다른 글

[HTTP] 상태코드  (1) 2024.02.10
[HTTP] HTTP 메서드 활용  (1) 2024.02.09
[HTTP] HTTP 메서드  (1) 2024.02.08
[HTTP] URI와 웹 브라우저 요청 흐름  (1) 2024.02.06
[HTTP] 인터넷 네트워크  (1) 2024.02.05

이 글은 인프런 김영한님의 Spring 강의를 바탕으로 개인적인 정리를 위해 작성한 글입니다.


URI

URI, URL, URN 

URI 내부에 URL, URN이 포함되어 있다.

URI는 로케이터(Locator), 이름(Name) 또는 둘다 추가로 분류될 수 있다. 

URI (Uniform Resource Identifier) 

  • Uniform : 리소스 식별하는 통일된 방식이다. 
  • Resource :  URI로 식별할 수 있는 모든 걸 자원이라고 한다. 웹 브라우저에 있는 HTML의 파일 것만 자원을 뜻하는 게 아니라 실시간 교통 정보 등등 이런것도 자원이라고 한다.
  • Idenrifier : 다른 항목과 구분하는 데 필요한 정보이다. 사람을 식별할 때 주민등록번호를 식별 하는 것처럼 말한다.

 

URL (Uniform Resource Locator) 

  • Locator : 리소스가 있는 위치를 지정한다. 

 

URN (Uniform Resource Name)

  • Name : 리소스에 이름을 부여한다. 

 

위치는 변할 수 있지만 이름은 변하지 않는다.

 

URN이 이름으로 실제 리소스가 결과 나올수 있어야 하는데, 이름만으로는 찾기가 어렵다.

 

그래서 URN은 보통 잘 사용되지 않는다. 따라서 URI = URL 으로 통용되기도 한다.

 

URI 전체 문법

scheme://[userinfo@]host[:port][/path][?query][#fragment]
https://www.google.com:443/search?q=hello&hl=ko
  • scheme

주로  프로토콜 사용한다. 어떤 방식으로 자원에 접근할 것인가 하는 클라이언트와 서버 간의 약속 규칙이라고 보면 된다. 

http : 80 / https : 443 / ftp : 20, 21 주로 사용한다.

https는 http에 강력한 보안 추가로 적용된거다.  (HTTP Secure)

 

  • userinfo

URL에 사용자정보를 포함해서 인증해야 할 때 있는데 거의 사용하지 않는다.

 

  • host

호스트명이라고 한다. 보통 도메인명이나 IP 주소를 직접 사용 가능하다.

 

  • port

접속 포트이다. 일반적은 웹 브라우저에서는 생략을 많이 하지만 특정 서버에 따로 접근 할 때는 port를 입력을 한다.

 

  • path
/home/file1.jpg  -> home 이라는 경로에 file1.jpg가 있다.
/members  -> 회원들에 대한 정보를 보여주는 경로이다.
/members/100, /items/iphone12  -> 100번의 회원의 정보, 아이템 중에 아이폰12 정보 경로이다.

리소스가 있는 경로이자 계층적 구조로 되어 있다. 

 

  • query

key와 value 형태로 데이터가 들어가 있다.

?keyA=valueA&keyB=valueB

query는 ?로 시작하고 &로 추가적으로 query string를 입력한다.

숫자를 적어도 다 문자 형태로 넘긴다 해서 query string이라고 부르기도 한다. 

 

  • fragment
https://docs.spring.io/spring-boot/docs/current/reference/html/getting-
started.html#getting-started-introducing-spring-boot

HTML 내부에서 중간에 이동하고 싶을 때 북마크 등에 사용한다. 잘 사용하지 않고 서버에 전송하는 정보 아니다.

 

웹 브라우저 요청 흐름

1. URL을 입력한다. 

2. DNS 서버로 IP를 찾아내고 생략된 PORT는 scheme로 찾아낸다. 

3. 웹 브라우저가 HTTP 요청 메시지를 생성한다.

 

4. SOCKET 라이브러리를 통해서 TCP/IP로 IP와 PORT 정보를 찾은 것을 3 way handshake 방식으로 서버와 연결을 한다.

5. HTTP 요청 메시지는 OS에 있는 TCP/IP 계층으로 전달한다.

6. TCP/IP 계층에서 HTTP 요청 메시지에 패킷으로 감싼다.

7. 웹 브라우저가 만든 요청 패킷을 서버에서 도착하면 패킷을 열어서 HTTP 요청 메시지를 확인해서 서버가 해석한다.

 

8. 서버가 HTTP 응답 메시지를 만들어서 TCP/IP 패킷을 감싸서 클라이언트에게 도착하면 클라이언트는 패킷을 열어서 HTTP 응답 메시지를 확인해서 해석한다. 

 

9. 웹 브라우저가 HTML 렌더링을 해서 클라이언트가 HTML 결과를 볼 수 있다.

'네트워크 > HTTP' 카테고리의 다른 글

[HTTP] 상태코드  (1) 2024.02.10
[HTTP] HTTP 메서드 활용  (1) 2024.02.09
[HTTP] HTTP 메서드  (1) 2024.02.08
[HTTP] HTTP 기본  (1) 2024.02.07
[HTTP] 인터넷 네트워크  (1) 2024.02.05

이 글은 인프런 김영한님의 Spring 강의를 바탕으로 개인적인 정리를 위해 작성한 글입니다.


인터넷 통신

인터넷망에서 컴퓨터들은 어떻게 통신할까?

클라이언트가 한국에 있고 서버가 먼 곳에 있다면 한국에 있는 클라이언트가 'Hello, world'라는 메시지를 보내야 하는데 데이터의 출발지와 도착지 사이에 수많은 중간 노드라고 하는 서버들을 걸쳐서 다른 곳에 있는 서버에게 안전하게 메시지가 도착해야 한다.

어떤 규칙으로 다른 곳에 있는 서버에게 안전하게 도착할 수 있는지 이해를 하려면 IP 프로토콜을 알아야 한다.

 

IP 인터넷 프로토콜

IP  주소 부여

IP(인터넷 프로토콜) 역할

  • 지정한 IP 주소(Address)에 데이터 전달 
  • 패킷(Packet)이라는 통신 단위로 데이터 전달

클라이언트에게 IP 주소, 서버에게도 IP 주소가 있어야 하고 서버에게 'Hello, world!' 메시지를 보낼 때 최소한의 규칙이 있어야 보낼 수 있는데 패킷이라는 규칙으로 보내야 한다.

 

IP 패킷 정보

메시지에 패킷의 정보인 출발지 IP와 목적지 IP 등등을 넣고 보내는데 IP 프로토콜에 의해서 서버들이 규약을 따르고 있다. 

 

클라이언트 패킷 전달

인터넷망에서 내가 보낸 패킷을 서로 노드들끼리 출발지가 어디고 목적지가 어디인지 알고 서버 IP 주소인 200.200.200.2 까지 정확하게 도착한다.

 

서버 패킷 전달

 

서버도 마찬가지로 새로 메시지를 만들어서 메시지에 패킷의 정보인 출발지 IP와 목적지 IP 등등을 넣고 클라이언트에게 보내는데 클라이언트가 보낼 때랑 서버가 보낼 때랑 인터넷 망이 복잡하기 때문에 서로 다른 곳으로 전달 될 수 있다. 그래서 IP라는 패킷에 담는 방식으로는 한계가 있다. 

 

IP 프로토콜의 한계

비연결성

미국에 있는 서버가 PC가 꺼져 있는 것도 모르고 클라이언트는 계속 메시지를 보내게 된다.

 

그래서 패킷을 받을 대상이 없거나 서비스불능 상태여도 패킷은 계속 전송한다.

 

비신뢰성 

서버들이 전달하는 사이에서 한 서버가 문제가 생겨서 패킷이 유실 될 수 있다.

 

메시지를 한 번에 보낼 때 보통 1500byte가 넘어가게 되면 보통 나눠서 보낸다.


두 개의 패킷을 나눠서 보내는데 인터넷 망안에 있는 노드들을 통해서 패킷마다 노드를 각각 선택을 해서 따로 따로 보내게 되는 상황이 오다보니 클라이언트가 보낸 메시지 순서가 서버가 받은 메시지 순서와 상이하게 된다.

같은 IP 내에 프로그램 미 구분

  • 클라이언트에서 게임도 하고 음악도 듣고 여러가지 프로그램으로 같은 IP로 쓰고 있는데 어떤 프로그램에 필요한 데이터인지 구분되지 않아 한계가 있다.

 

TCP/ UDP

프로토콜 4계층

IP 프로토콜에서 중간에 패킷이 손실되고 순서가 상이한 문제들을 TCP 프로토콜이 해결해준다.

 

'Hello world!' 라는 메시지를 보낼 때 SOCKET 라이브러리를 통해서 OS계층에서 TCP 정보를 감싼다.

 

그 밑에 IP 패킷이 생성되서 IP와 관련된 정보도 있고 그 안에 TCP와 관련된 정보가 있다.

 

이 메시지를 랜카드를 통해서 나갈 때 Ethernet frame을 포함해서 나가게 된다. 

 

Ethernet frame : 램 카드에 등록된 맥주소의 물리적인 정보

 

TCP/IP 패킷 정보

TCP와 관련된 정보에는 출발지 PORT, 목적지 PORT, 전송 제어, 순서, 검증 정보 등이 들어 간다.

 

IP 프로토콜에서 해결이 안된 순서 제어 문제들이 TCP 프로토콜이 해결이 되고 전송 데이터를 넣게 된다.

 

TCP(Transmission Control Protocol)의 특징

TCP 3 way handshake (가상 연결)

  • SYN(synchronize) : 접속 요청
  • ACK(acknowledge) : 요청 수락

 

  1. 클라이언트에서 먼저 SYN 메시지를 서버에게 접속을 허락해달라고 요청한다.
  2. 서버는 접속을 수락하고 ACK 메시지를 클라이언트 한테 보낼 때 서버도 접속을 허락해달라고 SYN 메시지와 함께 보낸다.
  3. 클라이언트가 접속을 수락하고 서버에서 ACK 메시지를 보낸다.
    참고로 요즘 최적화가 잘 되서 마지막 ACK를 보낼 때 데이터도 전송한다.

 

이렇게 3단계를 거쳐 연결이 되고나면 데이터를 전송한다.  

 

위에 TCP 연결이 되었다고 연결이 된 게 아니라 논리적으로 연결되어 있을 뿐이다.

 

인터넷 망에 있는 수 많은 서버들은 이 둘이 연결되어 있는 건지 알 수 없다. 

 

데이터 전달 보증

메시지에 TCP 프로토콜이 포함되어 있으면 메시지를 전송할 때 서버에서 잘 받았다고 다시 보내는데 클라이언트가 메시지를 잘 전달 됐는지 안됐는지 알 수 있다. 

 

순서보장

메시지가 1500byte가 넘어서 패킷을 1번, 2번, 3번 순서로 나눠서 보냈다.

 

서버에서 1번, 3번, 2번 순서로 도착을 하면 내부적으로 최적화하는 로직에 따라서 2번부터 다시 보내라고 클라이언트에게 요청할 수 있다. 그렇기 때문에 순서가 보장이 된다.

 

또는 서버측에서 내부적으로 순서를 올바르게 정렬할 수도 있다.

 

순서대로 보낼 수 있는 이유는 TCP 정보 안에는 전송 제어, 순서, 검증 정보가 있어서 TCP 프로토콜이 신뢰할 수 있는 프로토콜이라고 한다.

 

UDP(User Datagram Protocol)의 특징

  • TCP 3 way handshake X
  • 데이터 전달 보증 X
  • 순서 보장 X
  • PORT 정보 O
  • 체크섬 정보 O

TCP는 데이터 양도 많고 3 way hands 때문에 전송 속도가 느린 반면에 UDP는 아무것도 없기 때문에 상대적으로 전송 속도가 빠르다.

 

클라이언트 PC에서 IP가 한 개만 할당되어 있어 있는데 게임용, 음악용 등 구분하기위해 PORT를 사용하고 메시지에 대해서 맞는지 검증해 주는 체크섬 특징이 있다.

 

PORT

클라이언트에서 게임도 하고 화상통화도 하고 웹 브라우저도 하고 있으면 여러 개의 서버랑 통신 해야 된다.

 

PORT 번호를 모르면, 클라이언트 IP에서 패킷이 올텐데 어떤 프로그램에게 온 패킷인지 알 수가 없다.

 

즉, IP 주소를 통해 아파트 앞까지는 왔는데 몇호인지 알 수 없는 것이다.

 

PORT 정보를 알면 어떤 프로그램에게 온지 알 수 있다.

 

즉, 몇호인지 알 수 있는 것이다.

 

TCP/IP 패킷 정보

위에 봤던 TCP/IP 패킷 정보에 TCP와 UDP에서 출발지 PORT와 목적지 PORT가 있다.

 

IP는 목적지 서버를 찾는 용도이고 서버 안에서 돌아가는 애플리케이션들을 구분하는게 PORT이다. 

 

같은 IP 내에서 프로세스 구분

같은 IP 내에서 프로세스를 구분하는 게 PORT 이다. 

  • [클라이언트] 게임 : 8090 ↔ [서버] 게임 : 11200
  • [클라이언트] 화상통화 : 21000 ↔ [서버] 화상통화 : 32202
  • [클라이언트] 웹 브라우저 : 10010 ↔ [서버] 웹 브라우저 : 80

 

위와 같이 예시처럼 각각 클라이언트와 서버 안에 맞는 PORT 번호를 찾아서 연결하면 된다.

여기서 패킷을 보낼 때 IP와 PORT를 포함해서 보낸다.

PORT 번호

  • 0 ~ 65535 : 할당 가능
  • 0 ~ 1023 : 잘 알려진 포트라 사용하지 않는 것이 좋음
  • FTP : 20, 21 / TELNET : 23 / HTTP : 80 / HTTPS : 443 

 

DNS

IP 주소의 문제점

IP를 가지고 서로 통신을 할 수 있지만 IP가 숫자로 되어 있어서 다 기억하기가 어렵다.

 

그리고 IP가 바뀌는 일이 많아져서 접속이 안되는 경우가 생긴다.

 

DNS (Domain Name System)

이러한 문제를 해결하기 위해 DNS 가 생겼다.

 

도메인을 사기 위해서 DNS 서버에 도메인을 등록을 할 수 있다.

 

클라이언트가 DNS 서버에다가 도메인에 맞는 IP를 달라고 요청을 하면 DNS 서버가 응답을 하고 클라이언트는 서버에 도메인으로 접속할 수 있다.

 

나중에 IP가 변경 되면 DNS 서버에 등록된 도메인에 IP를 변경을 할 수있다.

'네트워크 > HTTP' 카테고리의 다른 글

[HTTP] 상태코드  (1) 2024.02.10
[HTTP] HTTP 메서드 활용  (1) 2024.02.09
[HTTP] HTTP 메서드  (1) 2024.02.08
[HTTP] HTTP 기본  (1) 2024.02.07
[HTTP] URI와 웹 브라우저 요청 흐름  (1) 2024.02.06