HTTP 웹 기본 지식

seul·2023년 2월 9일
0

공부

목록 보기
7/13

모든 개발자를 위한 HTTP 웹 기본 지식

인프런 강의를 다 듣고, 복습 겸 간단하게 정리해서 올린다.
자세한 내용은 개인 노션에 정리해두었다.

🧤 인터넷 네트워크

IP (인터넷 프로토콜)

클라이언트와 서버 사이를 연결해주는 것이 인터넷,
클라이언트에서 서버로 메시지를 보내려면 각각의 ip address가 필요하다.
패킷이라는 통신 단위로 각각의 노드를 타다가 도착을 원하는 서버에 도착~

근데 IP는 한계가 있음

비연결성: 데이터 유실, 서버가 존재하지 않는 등의 문제
비신뢰성: 끊어서 보내면 순서를 지킬 수가 없음

TCP, UDP

TCP 등장

전송 제어 프로토콜이다.
IP 패킷에 있는 정보 외에 출발지 port, 목적지 port, 전송 제어, 순서, 검증 정보 등을 담고 있다.

TCP 3 way handshake

클라이언트가 서버에 연결하는 방법
1. 클라이언트가 서버에게 SYN: synchronize 메시지 보냄
2. 서버가 확인하고 ACK: 왔네? ㅇㅋㅇㅋ 라는 메시지를 SYN과 함께 보냄
3. 클라이언트가 서버의 SYN을 받고 다시 ACK 보냄
이렇게 '논리적으로' 보장 후 전송

-> 이렇게 하니까 데이터 전달 보증도 되고, 순서 보증도 되더라

UDP?

연결 지향도 아니고, 순서도 보장하지 않지만 port가 있다.
요즘 뜨는 이유는?
Http3에서 그나마 속도를 개선해보겠다고 UDP 프로토콜을 써본대요


🦊 URI와 웹 브라우저 요청 흐름

URI = URL + URN

Uniform Resource Identifier: 리소스를 식별하는 통합된 방법

문법

scheme://[userinfo@]host[:port][/path][?query][#fragment]
해석은 노션 보자

웹 브라우저 요청 흐름

  1. url을 작성해서 보내면, 웹 브라우저에서 DNS 서버 조회
    1. ip 찾고, port는 보통 생략이지만 아무튼 정보 찾아옴
  2. HTTP 요청 메시지 생성 (method, path, query, http 버전 정보, host 정보)
  3. SOCKET 라이브러리를 통해 전달
    1. TCP/IP 연결
    2. 데이터 전달
  4. TCP/IP 패킷 생성, HTTP 메시지 포함
  5. 서버가 패킷의 TCP/IP 패킷 까서 버리고 HTTP 메시지 보고 해석
  6. 서버에서 HTTP 응답 메시지 생성 (나중에 더 자세히..)
  7. 응답 메시지에 TCP/IP 씌워서 다시 웹 브라우저로 전달
  8. 웹 브라우저가 까서, 데이터 렌더링 해서 보기~

🐽 HTTP 기본

HTTP: HyperText Transfer Protocol

  • HTTP/1.1: 가장 많이 사용, 우리에게 가장 중요한 버전
  • HTTP/2: 성능 개선
  • HTTP/3: TCP 대신 UDP 사용, 성능 개선

특징

  1. 클라이언트-서버 구조
  2. 무상태 프로토콜, Stateless
  3. 비연결성: 서버 자원 효율적으로 사용 가능

HTTP 메시지

start-line
header
empty-line
message body
와 같이 구성됨!
(여기서 참고 SP: 공백, CRLF: 엔터, OWS: 띄어쓰기 허용)

start-line: 시작 라인

요청일 때는 request-line, 응답일 때는 status-line

  • request-line = method SP request-target SP HTTP-version CRLF
  • status-line = HTTP-version SP status-code SP reason-phrase CRLF

설명은... 노션에서

header: 헤더

header-field = field-name “:” OWS field-value OWS
http 전송에 필요한 모든 부가 정보 (ex. 메시지 바디의 내용, 크기, 클라이언트 정보 등)

message body

실제 전송할 데이터 (byte로 표현할 수 있는 모든 데이터 전송 가능)


🍀 HTTP 메서드

가장 중요한 것은 리소스 식별!!!
(리소스 → Representation)

  • GET: 리소스 조회
  • POST: 요청 데이터 처리, 주로 등록에 사용
  • PUT: 리소스를 대체, 해당 리소스가 없으면 생성
  • PATCH: 리소스 부분 변경
  • DELETE: 리소스 삭제

HTTP 메서드 - GET, POST

GET

리소스 조회
서버에 전달하고 싶은 데이터는 query(파라미터, 스트링)를 통해서 전달
메시지 바디를 전달할 수 있지만(ㅇ0ㅇ), 지원하지 않는 곳이 많아서 권장하지 않음

POST

요청 데이터 처리
메시지 바디를 통해 서버로 요청 데이터 전달

  • 서버가 식별하지 않은 새 리소스 생성
  • 기존 자원에 데이터 추가

HTTP 메서드 - PUT, PATCH, DELETE

PUT

리소스를 대체 (있으면 대체, 없으면 생성)
클라이언트가 리소스의 위치를 알고 URI를 지정함 (ex. seq)

리소스를 완전히 대체한다
값이 없는 컬럼은 지워버리는..
진짜 새 거로 대체한다고 생각하면 된다

PATCH

리소스 부분 변경
PUT이 앞뒤 안 보고 대체해버려서 생긴 메서드
변경된 부분만 변경한다
→ 근데 이게 지원이 안 되는 서버도 있다 (그런 경우에는 POST..)

DELETE

리소스 제거 ㅎ

HTTP 메서드의 속성

안전 Safe

호출해도 리소스를 변경하지 않는다
(GET은 조회만 하기 때문에 안전함, 그 외는 안전하지 않음)

멱등 Idempotent

f(f(x)) = f(x) 이게 먼 소리고?
한 번 호출하든 두 번 호출하든 100번 호출하든 결과가 똑같다.

멱등 메서드

  • GET: 한 번 조회하든, 두 번 조회하든 같은 결과가 조회된다
  • PUT: 결과를 대체한다. (기존 거를 날리고 내가 보낸 걸 덮으니까 항상 같음)
  • DELETE: 결과를 삭제한다. 같은 거 계속 삭제하니까~
  • POST (X): 멱등 아님!!

이런 개념 왜 있어요?

자동 복구 매커니즘… 이런 곳에 쓰인댑니다.
DELETE 호출했는데 응답이 없으면? 또 호출해 → 괜찮음! 멱등하니까


✨ HTTP 메서드 활용

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

  • 쿼리 파라미터를 통한 데이터 전송
    • GET
    • 주로 정렬 필터
  • 메시지 바디를 통한 데이터 전송
    • POST, PUT, PATCH

HTML Form 데이터 전송

POST 전송 - 저장

HTML 폼 태그에 action, post 넣고 input에 name 설정하고 넣고 싶은 변수 세팅
→ Content-Type을 application/x-www-form-urlencoded로 보냄, messageBody에 값을 넣고 쿼리 파라미터 형식으로 전달함

(데이터를 인코딩 해서..)

GET 전송 - 저장

쿼리 파라미터에 값을 넣고 전달함 (근데 get은 조회에만 사용하니까 저장에는 사용하지 맙시다)

multipart/form-data

만약 파일도 같이 전송한다면? (다른 종류의 데이터를 같이 전송해야 할 때)

form의 enctype에 multipart/form-data라고 넣는다
그러면 Content-Type이 multipart/form-data로 들어가고 알아서 데이터를 경계로 잘라줘서 들어감

HTTP API 데이터 전송

서버 to 서버, 앱 클라이언트, 웹 클라이언트
Content-Type: application/json을 주로 사용 (사실상 표준)

HTTP API 설계 예시

회원 관리 시스템

API 설계 - POST 기반 등록

클라이언트는 등록될 리소스의 URI를 모른다.

등록할 거야, 라고 클라이언트가 데이터를 보낼 때까지 ‘리소스 식별자’를 알지 못 한다.
서버가 등록을 한 뒤에야 식별자가 생기고 리소스 URI를 생성한다.

→ 이런 형식을 컬렉션 (Collection) 이라고 부른다. (서버가 리소스 URI 생성하는 거)

파일 관리 시스템

API 설계 - PUT 기반 등록
파일 업로드 시, 기존 파일을 지우고 다시 올려야 하니까 PUT 사용

클라이언트가 리소스 URI를 알고 있어야 한다.

클라이언트가 어떤 파일을 올릴지 아니까 URI를 알고 있음

  • 예시: /file/{filename}
    → 이런 형식을 스토어 (Store) 라고 부른다. (클라이언트가 관리하는 리소스 저장소)

참고하기 좋은 URI 설계 개념

은 노션에...


🍕 HTTP 상태 코드

상태코드 소개

클라이언트가 보낸 요청의 처리 상태를 응답에서 알려주는 기능

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

2xx - 성공

200 OK

요청 성공

201 Created

클라이언트의 요청 성공해서 새로운 리소스가 생성됨
(생성된 리소스는 응답의 Location 헤더 필드로 식별~)

202 Accepted

요청이 접수되었으나 처리가 완료되지 않았음
ex. 배치, 요청 접수 후 1시간 뒤에 배치 프로세스가 요청을 처리함

204 No Content

서버가 요청을 성공적으로 수행했지만, 응답 페이로드 본문에 보낼 데이터가 없음

3xx - 리다이렉션

요청을 완료하기 위해 유저 에이전트(웹 브라우저)의 추가 조치 필요
웹 브라우저는 3xx 응답의 결과에 Location 헤더가 있으면, Location 위치로 자동 이동 (=리다이렉트)

영구 리다이렉션 301, 308

리소스의 URI가 영구적으로 이동

원래의 URI를 사용 X, 검색 엔진 등에서도 변경 인지

  • 301 Moved Permanetly
  • 308 Permanent Redirect

일시적 리다이렉션 302, 307, 303

리소스의 URI가 일시적으로 변경
검색 엔진에서 URL을 변경하면 안 됨

PRG: Post/Redirect/Get (일시적인 리다이렉션)

POST로 주문 후에 웹 브라우저에서 새로고침을 하면? → 중복 주문이 될 수 있다.

  1. POST로 주문 후에 주문 결과 화면을 GET 메서드로 리다이렉트
  2. 새로고침을 해도 결과 화면을 GET으로 조회
  3. 중복 주문 대신에 결과 화면만 GET으로 다시 요청

기타 리다이렉션

304 Not Modified

  1. 캐시를 목적으로 사용
  2. 클라이언트에게 리소스가 수정되지 않았음을 알려준다. 따라서 클라이언트는 로컬 PC에 저장된 캐시를 재사용한다.
  3. 응답에 메시지 바디를 포함하면 안 된다.

4xx 클라이언트 오류

클라이언트의 요청에 잘못된 문법으로 서버가 요청을 수행할 수 없음
오류의 원인이 클라이언트에게 있음
이미 잘못된 요청을 보냈기에 똑같은 재시도가 실패함

400 Bad Request

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

401 Unauthorized

인증되지 않음

  • 인증(Authentication): 본인이 누구인지 확인, 로그인
  • 인가(Authorization): 권한 부여 (특정 리소스에 접근할 수 있는 권한, 인증이 있어야 함)

403 Forbidden

서버가 요청을 이해했지만 승인을 거부함
인증 자격 증명은 있지만, 접근 권한이 불충분한 경우

404 Not Found

요청 리소스를 찾을 수 없음
또는 해당 리소스를 숨기고 싶을 때

5xx 서버 오류

서버 문제로 오류 발생
재시도 하면 성공할 수도 있음 (복구 됐을 때)

500 Internal Server Error

서버 내부 문제로 오류 발생, 애매하면 다 500

503 Service Unavailable

서비스 이용 불가
서버가 일시적인 과부하 또는 예정된 작업으로 잠시 요청을 처리할 수 없음
Retry-After 헤더 필드로 얼마 뒤에 복구되는지 보낼 수도 있음


🎨 HTTP 헤더 1

header-field = field-name “:” OWS field-value OWS (OWS: 띄어쓰기 허용)
(field-name은 대소문자 구분 없음)

표현

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

콘텐츠 협상 (콘텐츠 네고시에이션)

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

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

일반 정보

From

유저 에이전트의 이메일 정보

Referer (많이 씀)

이전 웹 페이지 주소

User-Agent (얘도 많이 씀)

유저 에이전트 애플리케이션 정보 (클라이언트의 정보, 웹 브라우저 정보 등)

통계 정보
어떤 종류의 브라우저에서 장애가 발생하는지 파악 가능

Server

요청을 처리하는 ORIGIN 서버의 소프트웨어 정보
요청을 할 때 여러 프록시 서버를 거치게 돼서 나의 요청이 있는 마지막 서버 정보를 갖고 있음

Date

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

특별한 정보

Host

요청한 호스트 정보 (도메인)
요청에서 사용, 필수 값!!
하나의 서버가 여러 도메인을 처리해야 할 때

Location

페이지 리다이렉션

Allow

허용 가능한 HTTP 메서드
405 (Method Not Allowed)로 응답할 때 사용 가능한 메서드를 적어서 응답 한다

Retry-After

유저 에이전트가 다음 요청을 하기까지 기다려야 하는 시간
503 (Service Unavailable): 서비스가 언제까지 불능인지 알려줄 수 있음

인증

Authorization

클라이언트 인증 정보를 서버에 전달
인증 매커니즘에 관계 없이 그 값을 헤더에 넣어주면 된다

WWW-Authenticate

리소스 접근 시 필요한 인증 방법 정의
401 Unauthorized 응답과 함께 사용

쿠키

내가 만든 쿠키~
두 개의 헤더를 사용함

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

사용법

로그인을 했으면, 서버에서 클라이언트에 응답 헤더에 Set-Cookie: user=홍길동 과 같이 보낸다
그럼 클라이언트는 쿠키 저장소에 user=홍길동 을 저장한다
그리고 로그인 이후 다른 페이지에 접근하면 서버에 요청을 보낼 때마다 자동으로 쿠키 저장소를 뒤져서 쿠키로 헤더를 만들어서 요청한다.

쿠키 - 생명 주기

Set-Cookie: expires=어쩌고(날짜)
만료일을 넣어준다, 만료일 되면 쿠키 삭제

Set-Cookie: max-age=어쩌고 (초 단위)
0이나 음수를 지정하면 쿠키 삭제

쿠키 - 도메인

ex) domain=example.org

방법

  • 명시: 명시한 문서 기준 도메인 + 서브 도메인 포함
  • 생략: 현재 문서 기준 도메인만 적용 → 하위 도메인은 쿠키 접근 불가능

쿠키 - 경로

ex) path=/home

이 경로를 포함한 하위 경로 페이지만 쿠키 접근 가능
일반적으로 path=/ 루트로 지정

쿠키 - 보안

  • Secure
  • HttpOnly
  • SameSite
    자세한 설명은 노션에

⛱️ HTTP 헤더 2

계속해서 같은 요청을 반복할 때 캐시가 없으면 네트워크를 통해서 데이터를 다운로드 받아야 하고 네트워크는 느리고 비싸다

캐시를 적용하면?

헤더에 cache-control: max-age=60를 넣어준다
(캐시가 유용한 시간, 60초 간은 캐시가 유효하다)

→ 웹 브라우저에서 응답 결과를 캐시에 저장한다
→ 두 번째 요청 시 캐시를 먼저 뒤지고, 아직 유효하다면 캐시에서 값을 가져온다

캐시가 시간 초과가 되었다면?

다시 요청한다
요청 결과를 다시 웹 브라우저에 저장한다

검증 헤더와 조건부 요청 1

캐시 시간 초과

  1. 서버가 데이터를 변경하지 않음
  2. 다만, 데이터가 변경되지 않음을 확인할 수 있는 방법은?

응답 시 Last-modified 추가

Last-modified: 2020년 11월 10일 10:00:00
이 데이터가 마지막으로 수정된 시간을 가져온다

→ 응답 결과를 캐시에 저장하면서 데이터 최종 수정일을 갖고 있는다

요청 시 if-modified-since 추가

요청을 보낼 때 Last-modified가 존재하면, if-modified-since: 날짜를 추가한다
해당 데이터의 최종 수정일을 같이 보내는 것

→ 서버에서 요청을 받고 서버 데이터와 요청된 데이터의 최종 수정일을 검증한다

수정일이 같으면 304 Not Modified 리턴

변경된 게 없다고 리턴
HTTP Body가 없음 (응답이 매우 가벼워짐)

검증 헤더와 조건부 요청 2

검증 헤더

캐시 데이터와 서버 데이터가 같은지 검증하는 데이터 (Last-modified, ETag)

조건부 요청 헤더

검증 헤더로 조건에 따른 분기

If-Modified-SInce: Last-modified

  • 이후에 데이터가 수정되었으면?
  • 미변경: 304 Not Modified, 헤더 데이터만 전송
  • 변경: 200 OK, 모든 데이터 전송

If-None-Match: ETag

Last-Modified, If-Modified-Since 단점

1초 미만 단위로 캐시 조정 불가능
날짜 기반의 로직 사용

ETag, If-None-Match

Entity Tag

  • 캐시용 데이터에 임의의 고유한 버전 이름을 달아둔다

캐시와 조건부 요청 헤더

Cache-Control: 캐시 제어

  • max-age: 유효 시간, 초 단위
  • no-cache: 데이터는 캐시해도 되지만, 항상 origin 서버에 검증하고 사용
  • no-store: 데이터에 민감한 정보가 있어서 저장하면 안 된다~ 사용하고 빨리 삭제해

Pragma: 캐시 제어
Expires: 캐시 제어

검증 헤더와 조건부 요청 헤더

  • 검증 헤더: ETag, Last-Modified
  • 조건부 요청 헤더
    • If-Match, If-None-Match: ETag 값 사용
    • If-Modified-Since, If-Unmodified-Since: Last-Modified 값 사용

프록시 헤더

멀리 있는 원 서버에서 데이터를 가져오려면 한참 걸리잖아요?
그걸 모두가 원한다면 각자 계속 기다려야 하고 응답이 느리니까..
한국 어딘가에 있는 프록시 캐시 서버를 거쳐서 요청이 오도록 한다.

  • Cache-Control
    • public: public 캐시에 저장 되어도 된다
    • private: 프록시 캐시에 저장 되면 안 된다
    • s-maxage: 프록시 캐시에만 적용되는 max-age
    • Age: 60: 오리진 서버에서 응답 후 프록시 캐시 내에 머문 시간 (먼 소리고)

캐시 무효화

확실한 캐시 무효화 응답
이 페이지는 진짜 캐시 되면 안 돼!! 라고 한다면 이렇게 넣어준다

Cache-Control: no-cache, no-store, must-revalidate
Pragma: no-cache

profile
자존감은 일상의 성실함으로부터 온다

0개의 댓글