인프런 HTTP 웹 기본 지식을 수강하며 작성한 글입니다.
강의 링크 : https://www.inflearn.com/course/http-%EC%9B%B9-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC
강의 목표
- HTTP 전체 흐름 이해
- 실무에 필요한 핵심 내용
RFC 7230~7235 : https://www.rfc-editor.org/rfc/rfc7230
Section 1 : 인터넷 네트워크
인터넷 통신
클라이언트 - - - 서버
수많은 중간 node를 거쳐서 클라이언트 요청이 서버로 넘어가야한다
Q. 어떻게 넘어가는가?
IP(인터넷 프로토콜)
- IP 주소 부여
Ex) 클라이언트 IP 100.100.100.1
서버 IP 200.200.200.2
IP 프로토콜 역할
- 지정한 IP 주소(IP Address)에 데이터 전달
- 패킷(Packet)이라는 통신 단위로 데이터 전달 → https://enlqn1010.tistory.com/9
Client IP 패킷 정보
출발지 IP, 목적지 IP
Server 패킷 전달
출발 IP, 목적 IP, OK
IP 프로토콜의 한계
- 비 연결성
- 패킷을 받을 대상이 없거나 서비스 불능 상태여도 패킷 전송 - 비 신뢰성
- 중간에 패킷이 사라지면?
- 패킷이 순서대로 안오면?(패킷을 여러개 보냈을 때) - 프로그램 구분
- 같은 IP를 사용하는 서버에서 통신하는 애플리케이션이 둘 이상이면?
- 대상 서버가 패킷을 받을 수 있는 상황인지 모르는 상태로 요청을 보낸다
- 패킷 소실 여부를 알 수 없다
- 광케이블이 끊겨서 소실되는 등
- https://ko.myservername.com/what-is-packet-loss-how-test
패킷 손실 원인
- 네트워크 혼잡 : 네트워크 사용량이 많은 시간에는 네트워크의 트래픽이 최대 제한에 도달하고 네트워크 대역폭이 많이 사용되면 네트워크 정체 상태가 발생.
- 소프트웨어 버그 : 소프트웨어 업데이트 중에 시스템에 도입 된 데이터 패킷 손실의 가장 일반적인 원인 중 하나
- 네트워크 하드웨어 문제
1500 byte 초과 시 메세지를 끊어서 보낸다
Ex) 1. Hello 2. World 일 때
1번과 2번이 전송되는 경로가 달라 순서가 바뀔 수 있다.
인터넷 프로토콜 스택 4계층(이해 필요)
애플리케이션 계층 - HTTP, FTP
전송 계층 - TCP, UDP |
인터넷 계층 - IP |
네트워크 인터페이스 계층 |
프로토콜 계층
애플리케이션 - 웹 브라우저, 네트워크, 게임, 채팅 프로그램
Q: SOCKET 라이브러리 → 소켓에 대해서 잘 모르겠다 ex) 웹소캣 → 계속 listen 형태, ajax(비동기, 계속 요청) mta?!
Socket은 최근 프레임워크에서 거의 제공
Connection Pool 참고하기
https://velog.io/@imtaebari/Application-Layer-Socket ⭐
OS - TCP, UDP, IP(Internet Protocol)
네트워크 인터페이스 - LAN 드라이버, LAN 장비
Hello를 보낸다고 했을 때,
SOCKET 라이브러리를 통해 전달
TCP 정보 생성, 메시지 데이터 포함
IP 패킷 생성, TCP
Ethernet frame
랜카드에 등록한 맥주소 등 물리적인 정보 포함되어 있다.
IP 패킷 정보
출발지 IP, 목적지 IP, 기타…
Packet(package + bucket)
TCP 패킷 정보
출발지 PORT, 목적지 PORT, 전송 제어, 순서, 검증 정보… → IP 만으로 해결이 안됐던 순서 제어 등이 해결이 된다.
TCP 특징(Transmission Control Protocol 전송 제어 프로토콜) → 최근 거의 90% 점유
- 연결지향 - TCP 3 way handshake(가상 연결) - 연결을 한 다음에 요청을 보낸다.
- 데이터 전달 보증 - 메세지가 누락이 된 경우 알 수 있다. (ACK이 오지 않게 되어 알 수 있다.)
- 순서 보장
- 신뢰할 수 있는 프로토콜
- 현재는 대부분 TCP 사용
TCP 3 way handshake
<종료 시 4핸드>
1바이트를 보내도 실제로 더 많은 데이터가 전송된다.
syn : synchronize 접속 요청
ack : acknowledge 요청 수락
클라이언트도 서버를 믿을 수 있고 서버도 클라이언트를 믿을 수 있다 → 연결이 된 것을 인식할 수 있다.
서버가 꺼져있는 경우 2 return 이 돌아오지 않기 때문에 데이터를 전송하지 않는다.
개념적으로만 연결이 된 것(논리적으로)
데이터 전달 보증
- 데이터 전송
- 데이터 잘 받았음(return)
→ return 이 없을 시 연결이 안된 것을 알 수 있다.
순서 보장
- 패킷1, 패킷2, 패킷3 순서로 전송
- 패킷1, 패킷3, 패킷2 순서로 도착
- 패킷2부터 다시 보내라는 return → 질문
드라이버에서 모아놓았다가 최적화를 할 수 있다.
UDP(User Datagram Protocol) 사용자 데이터그램 프로토콜
- 기능이 거의 없음
- 연결지향 X
- 데이터 전달 보증 X
- 순서 보장 X
- 데이터 전달 및 순서가 보장되지 않지만, 단순하고 빠르다
- IP와 거의 같다. + PORT + 체크섬(데이터가 맞는지 검증해보는 정도?) 추가
- 애플리케이션에서 추가 작업 필요
PORT
내 IP에 여러 패킷이 오게되는데 포트를 통해 구별 가능
→ 최적화가 하고 싶은 경우 UDP 건드리기,,,,,,,,,,, 최근 각광을 받고 있다.
PORT
client 가 한번에 둘 이상 연결해야 하는 경우(게임 + 통화, 노래 등등)
packet이 날아올 때 이 패킷이 통화용 packet 인지, 게임용 패킷인지 구별해야한다.
해결방법!
TCP의 출발지, 목적지 PORT
IP는 목적지 서버를 찾는 것
서버안에서 돌아가는 애플리케이션을 구분하는 것이 PORT
PORT - 같은 IP 내에서 프로세스 구분
서버에서 어떻게 포트번호를 아는가?
TCP/IP 패킷에서 함께 보내주기 때문에 알 수 있다.
- 0 ~ 65535 할당 가능
- 0 ~1023: 잘 알려진 포트, 사용하지 않는 것이 좋다.
- FTP - 20, 21
- TELNET - 23
- HTTP - 80
- HTTPS - 443
DNS(Domain Name System)
IP는 기억하기 어렵다.
IP는 변경될 수 있다.
궁금한 점 : IP가 바뀔 때 마다 수동으로 도메인 IP 설정을 다시 해야하는지
Feedback
서버는 아이피가 잘 안 바뀐다. 바뀐 후 적용 시 소요시간 약 5분
dhcp static 알아보기
포트포워딩 공부하기
공유기 외부접근 가능
공유기로 요청이 들어오면 포트 번호에 따라 특정 IP와 연결을 할 수 있다
정리
- IP 만 가지고는 신뢰하기 어렵다.(도착 여부, 순서, 포트 등)
- TCP 를 통해 신뢰성을 올릴 수 있다.
- PORT 같은 IP 내에서 동작하는 애플리케이션을 구분하기 위하여 사용(ex 몇동 몇호)
- DNS IP는 변동되기 쉬운데 DNS를 통해 이를 컨트롤 할 수 있다.
Section 2: URI와 웹 브라우저 요청 흐름
URI(Uniform Resource Identifier)
- Uniform: 리소스 식별하는 통일된 방식
- Resource: 자원, URI로 식별할 수 있는 모든 것(제한 없음)
- Identifier: 다른 항목과 구분하는데 필요한 정보
리소스를 식별한다.
URI는 Locator, Name 또는 둘 다 추가로 분류될 수 있다.
- URL(Resource Locator) 리소스의 위치
- URN(Resource Name) 리소스의 이름 ex) urn:example:animal:ferret:nose → 찾기 어렵다, URN 이름만으로 실제 리소스를 찾을 수 있는 방법이 보편화 되지 않음
URL 분석 예시
scheme://[userinfo@]host[:port][/path][?query][#fragment]
https://www.google.com:443/search?q=hello&hi=ko
- https : 프로토콜
- http://www.google.com : 호스트명
- 443 : 포트번호
- /search : 패스
- q=hello&hi=ko : 쿼리 파라미터
schme
- 주로 프로토콜 사용
- 프로토콜: 자원 접근 방식 ex) http, https, ftp 등등
- http는 80 포트, https는 443 포트를 주로 사용, 기본포트는 생략 가능 → 정해져있어서(브라우저)
- https는 http에 보안 추가(HTTP Secure)
userInfo
- URL에 사용자 정보를 포함해서 인증
- 거의 사용하지 않음
host
- 호스트명
- 도메인명 또는 IP 주소를 직접 사용가능
port
- 접속 포트
- 일반적으로 생략, 생략시 http는 80, https는 443
path
- 리소스 경로(path), 계층적 구조
- /home/file1.jpg
- /members
- /members/100
query
- key=value 형태
- ?로 시작, &로 추가 가능
- query parameter, query string 등으로 불림, 웹서버에 제공하는 파라미터, 문자 형태
fragment
- html 내부 북마크 등에 사용
- 서버에 전송하는 정보는 아님
- https://velog.io/@roro/URL-%ED%94%84%EB%9E%98%EA%B7%B8%EB%A8%BC%ED%8A%B8-HASH
웹 브라우저 요청 흐름
- DNS 조회
- HTTP 요청 메시지 생성
GET /search?q=hello&hi=ko HTTP/1.1
Host: www.google.com
3. SOCKET 라이브러리를 통해 전달
- A: TCP/IP 연결(IP/PORT)
- B: 데이터 전달
4. TCP/IP 패킷 생성, HTTP 메시지 포함
5. HTTP 응답 메시지
Ex)
HTTP/1.1 200 OK
Content-Type: text/html;charset=UTF-8
Content-Length:3423 //실제 길이
<html>
<body>…</body>
</html>
Section 3: HTTP 기본
HTTP(HyperText Transfer Protocol)
- HTML, TEXT
- IMAGE, 음성, 영상, 파일
- JSON, XML(API)
- 거의 모든 형태의 데이터 전송 가능
- 서버간에 데이터를 주고 받을 때도 대부분 HTTP 사용
TCP 프로토콜을 이용해서 직접 전달하는 경우는 거의 없다
http > TCP
HTTP 역사
- HTTP1.1 1997년 가장 많이 사용, 우리에게 가장 중요한 버전
- RFC2068(1997) → RFC2616(1999) → RFC7230~7235(2014) - HTTP/2 2015년 성능 개선
- HTTP/3 진행중: TCP 대신에 UDP 사용, 성능 개선
HTTP 특징
- 클라이언트 서버 구조
- 무상태 프로토콜(stateless), 비연결성
- HTTP 메시지
- 단순함, 확장 가능
클라이언트 서버 구조
- Request - Response 구조
- 클라이언트는 서버에 요청을 보내고, 응답을 대기
- 서버가 요청에 대한 결과를 만들어서 응답
- 독립적으로 발전할 수 있다.(클라이언트와 서버를 분리함으로써 발전할 수 있다고 이해)
무상태 프로토콜(Stateless)
- 서버가 클라이언트의 상태를 보존X
- 장점: 서버 확장성 높음(스케일 아웃)
- 단점: 클라이언트가 추가 데이터 전송
Stateful, Stateless 차이
- 무상태는 응답 서버를 쉽게 바꿀 수 있다. → 무한한 서버 증설 가능(수평 확장 유리)
Stateless 실무 한계
- 모든 것을 무상태로 설계 할 수 있는 경우도 있고 없는 경우도 있다.
- 무상태
- Ex) 로그인이 필요 없는 단순한 서비스 소개 화면 - 상태 유지
- Ex) 로그인 - 로그인한 사용자의 경우 로그인 했다는 상태를 서버 유지
- 일반적으로 브라우저 쿠키와 서버 세션등을 사용해서 상태 유지
- 상태 유지는 최소한만 사용
비 연결성(Connectionless)
자원을 요청이 들어왔을 때만 연결하여 자원을 아낄 수 있다.
- HTTP는 기본이 연결을 유지하지 않는 모델
- 일반적으로 초 단위 이하의 빠른 속도로 응답
- 서버 자원을 매우 효율적으로 사용할 수 있음
비 연결성 한계
- TCP/IP 연결을 새로 맺어야 함 - 3 way handshake 시간 추가
- 웹 브라우저로 사이트 요청 시 HTML 뿐만 아니라 자바스크립트, css, 이미지 등 많은 자원 다운로드
- HTTP 지속 연결(Persistent Connections)로 문제 해결
- HTTP/2, HTTP/3에서 최적화
다 끝날 때 까지 상태를 유지한다(내부 메커니즘)
Stateless 설계를 기억하자
- 같은 시간에 딱 맞추어 발생하는 대용량 트래픽
- Ex) 선착순 이벤트, 명절 KTX 예약, 학과 수강 신청, 1000명 할인 이벤트 → 수만명 동시 요청
최대한 무상태성을 유지하여 대용량 트래픽이 올 때 서버를 증설하자 → 요청이 들어왔을 때 요청을 받아줄 IP가 여러개?!
어쩔 수 없는 부분에서만 상태를 유지하는 방향 → 쿠키, 세션
HTTP 메시지
start-line 시작 라인 (요청 메시지)
- 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
HTTP 메서드
- 종류 : GET, POST, PUT, DELETE…
- 서버가 수행해야 할 동작 지정
- ex) GET : 리소스 조회, POST: 요청 내역 처리
요청 대상
- absolute-path[?query](절대경로[?쿼리])
- 절대경로 = ”/”로 시작하는 경로
HTTP 버전
- HTTP/1.1
HTTP 상태 코드: 요청 성공, 실패를 나타냄
- 200 : 성공
- 400 : 클라이언트 요청 오류
- 500 : 서버 내부 오류
HTTP 헤더
- header-field = field-name “:” OWS field-value OWS (OWS : 띄어쓰기 허용)
- field-name은 대소문자 구분 없음
- HTTP 전송에 필요한 모든 부가 정보
- Ex) 메시지 바디의 내용(text/html), 메시지 바디의 크기(Content-Length), 압축, 인증, 요청 클라이언트(브라우저) 정보, 서버 애플리케이션 정보, 캐시 관리 정보…
- 표준 헤더가 너무 많음
- 필요시 임의의 헤더 추가 가능
https://en.wikipedia.org/wiki/List_of_HTTP_header_fields
HTTP 메시지 바디
- 실제 전송할 데이터
- HTML 문서, 이미지, 영상, JSON 등등 byte로 표현할 수 있는 모든 데이터 전송 가능
Section 4 HTTP 메서드
HTTP API
API URI 설계(Uniform Resource Identifier)
- 회원 목록 조회 /read-member-list → /mebers
- 회원 조회 /read-member-by-id → GET /members/{id}
- 회원 등록 /create-member → POST /members/{id}
- 회원 수정 /update-member → PUT /members/{id}
- 회원 삭제 /delete-member → DELETE /members/{id}
→ read-member-list : 리소스 식별이 안된다.
HTTP 메서드 종류
- GET : 리소스 조회
- POST : 요청 데이터 처리, 주로 등록에 사용
- PUT : 리소스를 대체, 해당 리소스가 없으면 생성
- PATCH : 리소스 부분 변경
- DELETE : 리소스 삭제
- 기타
헤더만 필요한 경우
url 다운로드 시 → 문서파일 이미지 파일만 다운로드받아야한다
헤더를 조회해와서 파일 형식을 알기 위해서
지원하는 곳
GET
- 리소스 조회
- 서버에 전달하고 싶은 데이터는 query(쿼리 파라미터, 쿼리 스트링)를 통해서 전달
- 메시지 바디를 사용해서 데이터를 전달할 수 있지만, 지원하지 않는 곳이 많아서 권장하지 않음
- 리소스 변경이 발생하는 곳에서 사용하면 안됨
POST
- 요청 데이터 처리
- 메시지 바디를 통해 서버로 요청 데이터 전달
- 서버는 요청 데이터를 처리
- 메시지 바디를 통해 들어온 데이터를 처리하는 모든 기능을 수행한다. - 전달된 데이터로 신규 리소스 등록, 프로세스 처리에 사용
→ 멤버 등록 성공시 201 Created response
Response Data → Location 알아보기 → POST 요청 후 멤버 등록 성공 시 /members/100 형식으로 location 포함해서 return OR json 데이터 내에 “id”: “100” 추가
POST 메서드는 대상 리소스의 고유한 의미 체계에 따라 요청에 포함된 표현을 처리하도록 요청한다.
리소스 URI에 POST 요청이 오면 요청 데이터를 어떻게 처리할지 리소스마다 따로 정해야 함 → 정해진 것이 없다
- 새 리소스 생성(등록)
- 서버가 아직 식별하지 않은 새 리소스 생성 - 요청 데이터 처리
- 단순히 데이터를 생성하거나, 변경하는 것을 넘어서 프로세스를 처리해야 하는 경우
- 예) 주문에서 결제완료 → 배달시작 → 배달완료 처럼 값 변경을 넘어 프로세스의 상태가 변경되는 경우
- POST의 결과로 새로운 리소스가 생성되지 않을 수도 있음
- 예) POST /orders/{orderId}/start-delivery (컨트롤 URI) → 리소스만으로 안되는 경우 동사도 사용한다. - 다른 메서드로 처리하기 애매한 경우 → 알아두기
- 예) JSON으로 조회 데이터를 넘겨야 하는데, GET 메서드를 사용하기 어려운 경우(body를 허용하지 않는 사이트가 많다)
- 애매하면 POST
조회의 Data는 웬만하면 GET을 사용해야한다. → 캐싱
POST 는 캐싱하기 어렵다??
PUT - 리소스 전체 덮어쓰기
- 리소스를 대체
- 리소스가 있으면 대체
- 리소스가 없으면 생성
- 쉽게 이야기해서 덮어버림
- 클라이언트가 리소스를 식별
- 클라이언트가 리소스 위치를 알고 URI 지정
- POST와 차이점
PATCH - 리소스 부분 변경
- 안되는 경우는 POST 로 보내기
DELETE - 리소스 제거
HTTP 메서드의 속성
안전(Safe)
- 호출해도 리소스를 변경하지 않는다.
멱등(Idempotent)
- f(f(x)) = f(x)
- 한 번 호출하든 두 번 호출하든 결과가 똑같다. - ‘요청의 효과’를 보고 판단,, 같은 행위를 여러 번 반복하더라도 같은 효과를 가져야 한다.
- 멱등 메서드 : GET, PUT, DELETE
- POST : 멱등이 아니다! 두 번 호출하면 중복 결제 된다.
- 활용
- 자동 복구 메커니즘
- 서버가 TIMEOUT 등으로 정상 응답을 못주었을 때, 클라이언트가 같은 요청을 다시 해도 되는가? 판단 근거
- Q: 재요청 중간에 다른 곳에서 리소스를 변경해버리면?
- 사용자1 : GET → username:A, age:20
- 사용자2: PUT → username:A, age:30
- 사용자1: GET → username:A, age:30 → 사용자2의 영향으로 바뀐 데이터 조회
- A: 멱등은 외부 요인으로 중간에 리소스가 변경되는 것 까지 고려하지 않는다. 바뀐 것을 서버가 체크를 해주어야 한다.
캐시가능(중요)
- 응답 결과 리소스를 캐시해서 사용해도 되는가?
- GET, HEAD, POST, PATCH 캐시가능
- 실제로는 GET, HEAD 정도만 캐시로 사용 - GET은 URL만 캐시로 잡고 캐싱하면 된다.
- POST, PATCH는 본문 내용까지 캐시 키로 고려해야 하는데 구현이 쉽지 않음
- 캐싱 → 백엔드 쪽 캐싱 디비 요청 단순한 DB 요청 일 시 캐싱 해놔서 자원 손실이 없도록 캐싱서버가 따로 있는 경우도 있다, 응답속도를 높히기 위해서
Section 5 HTTP 메서드 활용
클라이언트에서 서버로 데이터 전송
- 쿼리 파라미터를 통한 데이터 전송
- GET
- 주로 정렬 필터(검색어)
- 메시지 바디를 통한 데이터 전송
- POST, PUT, PATCH
- 회원 가입, 상품 주문, 리소스 등록, 리소스 변경
4가지 상황
- 정적 데이터 조회
- 이미지, 정적 텍스트 문서
- 동적 데이터 조회
- 검색, 게시판 목록 정렬 필터(검색어)
- HTML Form을 통한 데이터 전송
- 회원가입, 상품 주문, 데이터 변경
- HTTP API를 통한 데이터 전송
- 회원가입, 상품 주문, 데이터 변경
- 서버 to 서버, 앱 클라이언트, 웹 클라이언트(Ajax)
정적 데이터 조회
- 쿼리 파라미터 미사용, 리소스 경로로 단순하게 조회 가능
- 이미지, 정적 테스트 문서
- 조회는 GET 사용
동적 데이터 조회
- 주로 검색, 게시판 목록에서 정렬 필터(검색어)
- 조회 조건을 줄여주는 필터, 조회 결과를 정렬하는 정렬 조건에 주로 사용
- 조회는 GET 사용
- GET은 쿼리 파리미터 사용해서 데이터를 전달
HTML Form을 통한 데이터 전송(POST)
- Content-Type 참고 링크 : https://jw910911.tistory.com/117
- file 전송 시 multipart/form-data
- HTML Form submit POST 전송
- 예) 회원 가입, 상품 주문, 데이터 변경
- Content-Type: application/~
- form의 내용을 메시지 바디를 통해서 전송(key-=value(name 설정), 쿼리 파라미터 형식)
- 전송 데이터를 url encoding 처리
-
- HTML Form은 GET 전송도 가능하나 안하는 것을 권장
- Content-Type:multipart/form-data
- 파일 업로드 같은 바이너리 데이터 전송시 사용
- 다른 종류의 여러 파일과 폼의 내용 함께 전송 가능
HTTP API 데이터 전송
- 서버 to 서버
- 백엔드 시스템 통신
- 앱 클라이언트
- 아이폰, 안드로이드
- 웹 클라이언트
- HTML에서 Form 전송 대신 자바 스크립트를 통한 통신에 사용(Ajax)
- 예)React, VueJs 같은 웹 클라이언트와 API 통신
- POST, PUT, PATCH: 메시지 바디를 통해 데이터 전송
- GET: 조회, 쿼리 파라미터로 데이터 전달
- Content-Type: application/json을 주로 사용(사실상 표준)
- TEXT, XML, JSON 등등
HTTP API 설계 예시
- 회원 목록 /members → GET
- 회원 등록 /members → POST
- 회원 조회 /members/{id} → GET
- 회원 수정 /members/{id} → PATCH(부분 수정), PUT(기존 리소스를 삭제하고 덮어버린다, ex) 게시글 수정), POST
- 회원 삭제 /members/{id} → DELETE
POST - 신규 자원 등록 특징
- 클라이언트는 등록될 리소스의 URI를 모른다.
- 회원 등록 /members → POST
- POST /members
- 서버가 새로 등록된 리소스 URI를 생성해준다.
- HTTP/1.1 201 Created
- Location: /members/100
- 컬렉션(Collection)
- 서버가 관리하는 리소스 디렉토리
- 서버가 리소스의 URI를 생성하고 관리
- 여기서 컬렉션은 /members
파일 관리 시스템 API 설계 - PUT 기반 등록
- 파일 목록 /files → GET
- 파일 조회 /files/{filename} → GET
- 파일 등록 /files/{filename} → PUT
- 파일 삭제 /files/{filename} → DELETE
- 파일 대량 등록 /files → POST
PUT - 신규 자원 등록 특징
- 클라이언트가 리소스 URI를 알고 있어야 한다.
- 파일 등록 /files/{filename} → PUT → 기존에 있던 파일을 지우고 업로드이기 때문에 PUT을 사용하는 것이 어울린다.
- PUT /files/star.jpg
- 클라이언트가 직접 리소스의 URI를 지정한다.
- 스토어(Store)
- 클라이언트가 관리하는 리소스 저장소
- 클라이언트가 리소스의 URI를 알고 관리
- 여기서 스토어는 /files
HTML Form 사용
- HTML FORM은 GET, POST만 지원
- AJax 같은 기술을 사용해서 해결 가능 → 회원 API 참고
회원 등록 폼 == 회원 등록 uri를 맞추는 것을 추천
validation
POST의 최종결과를 다시 회원등록 폼으로 돌려보내야하는 경우가 있어서 맞춰두는 것이 좋다.
- 컨트롤 URI
- GET, POST만 지원하므로 제약이 있다.
- 동사로 된 리소스 경로 사용 → new, edit, delete
- HTTP 메서드로 해결하기 애매한 경우 사용(HTTP API 포함)
- 대체제로 사용하는 것이기 때문에 최대한 사용을 안하는 것이 좋다.
- 최대한 리소스라는 개념을 가져 설계하고 안될 때 대체제 느낌
대부분 collection
참고 사이트 : https://restfulapi.net/resource-naming/
Section 6 HTTP 상태코드
HTTP 상태코드 소개
클라이언트가 보낸 요청의 처리 상태를 응답에서 알려주는 기능
- 1XX (Informational) : 요청이 수신되어 처리증 - 거의 사용하지 않는다.
- 2XX (Successful) : 요청 정상 처리
- 3XX (Redirection) : 요청을 완료하려면 추가 행동이 필요
- 4XX (Client Error) : 클라이언트 오류, 잘못된 문법등으로 서버가 요청을 수행할 수 없음
- 5XX(Server Error) : 서버 오류, 서버가 정상 요청을 처리하지 못함
2XX(Successful)
클라이언트의 요청을 성공적으로 처리
200 OK
- 요청 성공
201 Created
- 신규자원 등록 요청(POST) - 서버에서 자원 생성
202 Accepted
- 요청이 접수되었으나 처리가 완료되지 않음
- 배치 처리 등에 사용
- Ex) 요청 접수 후 1시간 뒤에 배치 프로세스가 요청을 처리함 - 미리 받아놓는 상태
204 No Content
- 서버가 요청을 성공적으로 수행했지만, 응답 페이로드 본문에 보낼 데이터가 없음
- Ex) 웹 문서 편집기 save 기능
3XX(Redirection)
요청을 완료하기 위해 유저 에이전트의 추가 조치 필요
Redirection이란
- 웹 브라우저는 3XX 응답의 결과에 Location 헤더가 있으면, Location 위치로 자동 이동(리다이렉트)
- 종류
- 영구 리다이렉션 - 특정 리소스의 URI가 영구적으로 이동
- Ex) /members → /users
- /event → /new-event
- 일시 리다이렉션 - 일시적인 변경
- 주문 완료 후 주문 내역 화면으로 이동
- PRG: Post/Redirect/Get(POST 주문 → 새로고침 시 한번 더 중복 주문이 들어갈 수 있다.)
- 특수 리다이렉션
- 결과 대신 캐시를 사용
- 캐시기간이 만료된거 같다 → 생성일자와 함께 요청,,, → 캐시 사용 가능하니 캐시 사용하라는 리다이렉션
- 영구 리다이렉션 - 특정 리소스의 URI가 영구적으로 이동
영구 리다이렉션 - 301(Moved Permanently), 308(Permanent Redirect)
- 리소스의 URI가 영구적으로 이동
- 원래의 URL를 사용X, 검색 엔진 등에서도 변경 인지
- 301
- 리다이렉트시 요청 메서드가 GET으로 변하고, 본문이 제거될 수 있음(MAY)
- GET 으로 요청하기 때문에 입력했던 데이터가 사라지고 다시 작성을 해야하는 경우 발생
- 308 → 거의 사용하지 않는다. 아예 폼이 바뀌는 경우가 많기 때문
- 301과 기능은 같음
- 리다이렉트시 요청 메서드와 본문 유지(처음 POST를 보내면 리다이렉트도 POST)
- 301과 달리 바로 등록이 된다!
일시적인 리다이렉션 - 302(Found), 307(Temporary Redirect), 303(See Other)
- 리소스의 URI가 일시적으로 변경
- 따라서 검색 엔진 등에서 URL을 변경하면 안됨
- 302 → 많이 쓰인다
- 리다이렉트시 요청 메서드가 GET으로 변하고, 본문이 제거될 수 있음(MAY)
- 307
- 302와 기능은 같음
- 리다이렉트시 요청 메서드와 본문 유지(요청 메서드를 변경하면 안된다. MUST NOT)
- 303
- 302와 기능 같음
- 리다이렉트시 요청 메서드가 GET으로 변경
- 304 Not Modified
- 캐시를 목적으로 사용
- 클라이언트에게 리소스가 수정되지 않았음을 알려준다.
- 클라이언트는 로컬PC에 저장된 캐시를 재사용한다. (캐시를 리다이렉트 한다.)
- 304 응답은 응답에 메시지 바디를 포함하면 안된다.(로컬 캐시를 사용해야 하므로)
- 조건부 GET, HEAD 요청시 사용
- 예시
- POST로 주문후에 웹 브라우저를 새로고침하면?
- 새로고침은 다시 요청
- 중복 주문이 될 수 있다.
PRG: Post/Redirect/Get 일시적인 리다이렉션 - 예시
- POST로 주문후에 새로 고침으로 인한 중복 주문 방지
- POST로 주문후에 주문 결과 화면을 GET 메서드로 리다이렉트
- 새로고침해도 결과 화면을 GET으로 조회
- 중복 주문 대신에 결과 화면만 GET으로 다시 요청
4XX - 클라이언트 오류
- 클라이언트의 요청에 잘못된 문법등으로 서버가 요청을 수행할 수 없음
- 오류의 원인이 클라이언트에 있음
- 클라이언트가 이미 잘못된 요청, 데이터를 보내고 있기 때문에, 똑같은 재시도가 실패함
400 - Bad Request
- 클라이언트가 잘못된 요청을 해서 서버가 요청을 처리할 수 없음
- 요청 구문, 메시지 등등 오류
- 클라이언트는 요청 내용을 다시 검토하고, 보내야함
- 예) 요청 파라미터가 잘못되거나, API 스펙이 맞지 않을 때
- 백엔드 개발자들이 미리 다 막아줘서 405로 튕겨줘야한다. 철저하게 validation
401 Unauthorized
- 클라이언트가 해당 리소스에 대한 인증이 필요함
- 인증(Authentication) 되지 않음
- 401 오류 발생시 응답에 WWW-Authenticate 헤더와 함께 인증 방법을 설명
- 참고
- 인증(Authentication): 본인이 누구인지 확인, (로그인)
- 인가(Authorization): 권한부여 (ADMIN 권한처럼 특정 리소스에 접근할 수 있는 권한, 인증이 있어야 인가가 있음)
- 오류 메시지가 Unauthorized 이지만 인증 되지 않음(이름이 아쉬움)
403 Forbidden
- 서버가 요청을 이해했지만 승인을 거부함
- 주로 인증 자격 증명은 있지만, 접근 권한이 불충분한 경우
- 예) Admin 등급이 아닌 사용자가 로그인은 했지만, Admin 등급의 리소스에 접근하는 경우
404 Not Found
- 요청 리소스를 찾을 수 없음
- 요청 리소스가 서버에 없음
- 클라이언트가 권한이 부족한 리소스에 접근할 때 해당 리소스를 숨기고 싶을 때
5XX - Server Error
- 서버 문제로 오류 발생
- 서버에 문제가 있기 때문에 재시도
500 Internal Server Error
- 서버 내부 문제로 오류 발생
- 애매하면 500 오류
503 Service Unavailable
- 서버가 일시적인 과부하 또는 예정된 작업으로 잠시 요청을 처리할 수 없음
- Retry-After 헤더 필드로 얼마뒤에 복구되는지 보낼 수도 있음
Section 7 HTTP 헤더 - 일반 헤더
HTTP 헤더
- HTTP 전송에 필요한 모든 부가정보
- 예) 메시지 바디의 내용, 메시지 바디의 크기, 압축, 인증, 요청 클라이언트, 서버 정보, 캐시 관리 정보…
- 표준 헤더가 너무 많음
- 필요시 임의의 헤더 추가 가능
HTTP BODY
- 메시지 본문(message body)을 통해 표현 데이터 전달
- 메시지 본문 = payload
- 표현(Representation)은 요청이나 응답에서 전달할 실제 데이터
- 표현 헤더는 표현 데이터를 해석할 수 있는 정보 제공
- 데이터 유형(html, json), 데이터 길이, 압축 정보 등등
- 참고: 표현 헤더는 표현 메타데이터와, 페이로드 메시지를 구분해야 한다.
Representation
- Content-Type: 표현 데이터의 형식
- Content-Encoding: 표현 데이터의 압축 방식
- Content-Language: 표현 데이터의 자연 언어(한국어인지 영어인지 등)
- Content-Length: 표현 데이터의 길이 → 페이로드 헤더 검색해보기
- 표현 헤더는 전송, 응답 둘다 사용
Content-Type - 표현 데이터의 형식 설명
- 미디어 타입, 문자 인코딩
- text/html; charset=utf-8
- application/json - 기본이 utf-8
- image/png
Content-Encoding - 표현 데이터 인코딩
- 표현 데이터를 압축하기 위해 사용
- 데이터를 전달하는 곳에서 압축 후 인코딩 헤더 추가
- 데이터를 읽는 쪽에서 인코딩 헤더의 정보로 압축 해제
- gzip
- deflate
- identity - 압축 안한다
Content-Language - 표현 데이터의 자연 언어를 표현
- ko - 내용이 한국어
- en- 내용이 영어
- en-US
Content-Length - 표현 데이터의 길이
- 바이트 단위
- Transfer-Encoding(전송 코딩)을 사용하면 Content-Length를 사용하면 안됨
협상(Content-Negotiation) - 클라이언트가 선호하는 표현 요청(요청시에만 사용)
- 최대한 서버가 해달라고 요청하는 표현
- Accept: 클라이언트가 선호하는 미디어 타입 전달
- Accept-Charset: 클라이언트가 선호하는 문자 인코딩 - 있으면 주세요
- Accept-Encoding: 클라이언트가 선호하는 압축 인코딩
- Accept-Language: 클라이언트가 선호하는 자연 언어(한국 브라우저인데 Accept 설정이 되어있을 시 한국어 지원 사이트는 한국어 제공)
협상과 우선순위(Quality Values(q)
- Quality Values(q) 값 사용
- 0~1, 클수록 높은 우선순위
- 생략하면 1
- ex) 독일어 홈페이지가 독일어, 영어를 지원할 때 우선순위를 통해 영어를 제공받을 수 있다.
- 구체적인 것이 우선한다
- Accept: text/*, text/plain, text/plain;format=flowed, */ * 우선순위
- 1. text/plain; format=flowed
- 2. text/plain
- 3. text/*
- 4. */ *
전송 방식
- 단순 전송
- 압축 전송(gzip등으로 압축 → 절반이상 압축되는 경우가 많다), Content-Encoding:gzip 등의 헤더가 필요하다
- 분할 전송 - Transfer-Encoding: Chunked, Content-Length를 넣으면 안된다(예상이 안된다)
- 범위 전송 - Range, Content-Range
일반 정보
From - 유저 에이전트의 이메일 정보
- 일반적으로 잘 사용X
- 검색 엔진 같은 곳에서, 주로 사용
- 요청에서 사용
Referer - 이전 웹 페이지 주소
- 많이 사용한다.
- 현재 요청된 페이지의 이전 웹 페이지 주소
- A → B로 이동하는 경우 B를 요청할 때 Referer: A를 포함해서 요청
- Referer를 사용해서 유입 경로 분석 가능
- 요청에서 사용
- 검색했을 때 가입하라고 나오는 경우는 referer이 없어서 크롤링? html 긁어오는 검색어 데이터 수집 TI 팀 크롤링 → 샘플 수집, 악성 정보 수집
User-Agent - 유저 에이전트 애플리케이션 정보
- 클라이언트의 애플리케이션 정보(웹 브라우저 정보, 등등)
- 통계 정보
- 어떤 종류의 브라우저에서 장애가 발생하는지 파악 가능
- 요청에서 사용
- ex) 특정 웹 브라우저에서 문제가 생기는것을 파악할 수 있다.
Server - 요청을 처리하는 ORIGIN 서버의 소프트웨어 정보
- Server: Apache/2.2.22(Debian)
- server: nginx
- 응답에서 사용
Date - 메시지가 발생한 날짜와 시간
- Date: Tue, 15 Nov 1994 08:12:31 GMT
- 응답에서 사용 (과거에는 요청에도 사용했다)
특별한 정보
Host - 요청한 호스트 정보(도메인) 중요 ⭐⭐⭐⭐⭐
- 요청에서 사용
- 필수
- 하나의 서버가 여러 도메인을 처리해야 할 때
- 하나의 IP 주소에 여러 도메인이 적용되어 있을 때
- a.com으로 갈지, b.com 으로 갈지 알 수 없다. → Host 헤더 전달
Location - 페이지 리다이렉션
- 웹 브라우저는 3XX 응답의 결과에 Location 헤더가 있으면, Location 위치로 자동 이동(리다이렉트)
- 3XX 강의 참고
- 201(Created): Location 값은 요청에 의해 생성된 리소스 URI
- 3XX(Redirection): Location 값은 요청을 자동으로 리다이렉션하기 위한 대상 리소스를 가리킴
Allow - 허용 가능한 HTTP 메서드
- 서버에서 많이 구현되어 있지는 않다.
- 405(Method Not Allowed) 에서 응답에 포함해야함
- Allow: GET, HEAD, PUT → 이것을 보고 클라이언트가 POST를 지원하지 않는다는 것을 알 수 있다.
Retry-After - 유저 에이전트가 다음 요청을 하기까지 기다려야 하는 시간
- 사용하기가 쉽지 않다.
- 503 (Service Unavailable): 서비스가 언제까지 불능인지 알려줄 수 있음
- Retry-After: Fri, 31 Dec 1999 23:59:59 GMT (날짜 표기)
- Retry-After:120(초단위 표기)
인증
WWW-Authenticate - 리소스 접근시 필요한 인증 방법 정의
- 401 Unauthorized 응답과 함께 사용 → 401 Response 시 제공해주어야 한다.
쿠키
Stateless
- HTTP는 무상태(Stateless) 프로토콜이다.
- 클라이언트와 서버가 요청과 응답을 주고 받으면 연결이 끊어진다.
- 클라이언트가 다시 요청하면 서버는 이전 요청을 기억하지 못한다.
- 클라이언트와 서버는 서로 상태를 유지하지 않는다.
- 쿠키 미사용 시 모든 요청과 링크에 사용자 정보를 포함시켜야한다.
- 모든 요청에 사용자 정보가 포함되도록 개발 해야한다.
- 브라우저를 완전히 종료하고 다시 열면(web Storage??)
쿠키 로그인
- Set-Cookie 헤더 전송
- 요청시 Cookie 함께 전송
예) Set-Cookie: sessionId=abcde1234; expires=Sat, 26-Dec-2020 00:00:00 GMT; path=/;domain=.google.com;Secure
- 사용처
- 사용자 로그인 세션 관리
- 광고 정보 트래킹(이 웹브라우저를 사용하는 사람이 이런이런 광고를 주로 보는구나,,)
- https://support.google.com/adsense/answer/7549925?hl=ko
- 쿠키 정보는 항상 서버에 전송됨
- 네트워크 트래픽 추가 유발
- 최소한의 정보만 사용(세션 id, 인증 토큰[OAuth])
- 서버에 전송하지 않고, 웹 브라우저 내부에 데이터를 저장하고 싶으면 웹 스토리지(localStorage, sessionStorage) 참고, 필요할 때만 꺼내서 쓴다, 웹브라우저에 저장하지 않을 시 매번 요청할때마다 같이 보내기 때문에 부하가 가중된다.
- 주의
- 보안에 민감한 데이터는 저장하면 안됨(주민번호, 신용카드 번호 등등)
쿠키 생명주기 - Expires, max-age
- Set-Cookie: expires=Sat, 26-Dec-2020 00:00:00 GMT
- 만료일이 되면 쿠키 삭제
- Set-Cookie: max-age=3600(3600초)
- 0이나 음수를 지정하면 쿠키 삭제
- 유효기간이 지나면 삭제
- 세션 쿠키: 만료 날짜를 생략하면 브라우저 종료시 까지만 유지
- 영속 쿠키: 만료 날짜를 입력하면 해당 날짜까지 유지
쿠키 - 도메인
- 예) domain=example.org
- 명시: 명시한 문서 기준 도메인 + 서브 도메인 포함
- domain=example.org를 지정해서 쿠키생성
- example.org는 물론이고
- dev.example.org도 쿠키 접근
- 호스트 파일 → 로컬에서만 할 수 있도록(쿠키설정 연습)
- 생략: 현재 문서 기준 도메인만 적용
- example.org 에서 쿠키를 생성하고 domain 지정을 생략
- example.org에서만 쿠키 접근
- dev.example.org는 쿠키 미접근 - 하위 도메인에서는 접근 불가능
- example.org 에서 쿠키를 생성하고 domain 지정을 생략
쿠키 - 경로(Path)
- 예) path=/home
- 이 경로를 포함한 하위 경로 페이지만 쿠키 접근
- 일반적으로 path=/ 루트로 지정
- 예)
- path=/home 지정
- /home 가능
- /home/level1 가능
- /hello 불가능
쿠키 - 보안
- Secure
- 쿠키는 http, https를 구분하지 않고 전송
- Secure를 적용하면 https인 경우에만 전송
- HttpOnly
- XSS 공격 방지
- 자바스크립트에서 접근 불가(document.cookie)
- HTTP 전송에만 사용
- SameSite
- 브라우저 지원 확인해야 한다.
- CSRF 공격 방지
- 요청 도메인과 쿠키에 설정된 도메인이 같은 경우만 쿠키 전송
XSS(크로스 사이트 스크립팅)
공격자가 상대방의 브라우저에 스크립트가 실행되도록 해 사용자의 세션을 가로채거나, 웹사이트를 변조하거나, 악의적 콘텐츠를 삽입하거나, 피싱 공격을 진행하는 것
스크립트 언어와 취약한 코드를 공격 대상으로 한다.
Section 8 HTTP 헤더 - 캐시와 조건부 요청
캐시 기본 동작
캐시가 없을 때
- 데이터가 변경되지 않아도 계속 네트워크를 통해서 데이터를 다운로드 받아야 한다.
- 인터넷 네트워크는 매우 느리고 비싸다.
- 브라우저 로딩 속도가 느리다.
- 느린 사용자 경험
캐시 적용
- cache-control: max-age=60 → 캐시가 유효한 시간(초)
- 캐시 덕분에 캐시 가능 시간동안 네트워크를 사용하지 않아도 된다.
- 비싼 네트워크 사용량을 줄일 수 있다.
- 브라우저 로딩 속도가 매우 빠르다.
- 빠른 사용자 경험
캐시 시간 초과
- 캐시 유효 시간이 초과하면, 서버를 통해 데이터를 다시 조회하고 캐시를 갱신한다.
- 네트워크 다운로드가 발생
검증 헤더와 조건부 요청1
캐시 만료 후 서버에서 데이터 변경하지 않음
- 데이터를 전송하는 대신 저장해 두었던 캐시를 재사용 할 수 있다.
- 단 클라이언트의 데이터와 서버의 데이터가 같다는 사실을 확인할 수 있는 방법 필요
검증 헤더 추가
- Last-Modified Header
- 재요청을 했을 때 Last-Modified 비교를 통해 데이터가 바뀌었는지 안바뀌었는지 확인이 가능하다.
→ 수정이 안되었을 경우 Body 없이 전송
정리
- 캐시 유효 시간이 초과해도, 서버의 데이터가 갱신되지 않으면 304 Not Modified + 헤더 메타 정보만 응답(바디X)
- 클라이언트는 서버가 보낸 응답 헤더 정보로 캐시의 메타 정보를 갱신
- 클라이언트는 캐시에 저장되어 있는 데이터 재활용
- 네트워크 다운로드가 발생하지만 용량이 적은 헤더 정보만 다운로드
- 실용적
- 웹 브라우저는 대부분 적용하고 있다.
- 개발자도구에서 회색 글씨 → 캐시 이용
검증 헤더와 조건부 요청2
- 검증 헤더
- 캐시 데이터와 서버 데이터가 같은지 검증하는 데이터
- Last-Modifies, ETag
- 조건부 요청 헤더
- 검증 헤더로 조건에 따른 분기
- If-Modified-Since: Last-Modified 사용
- If-None-Match:ETag 사용
- 조건이 만족하면 200 OK
- 조건이 만족하지 않으면 304 Not Modified
If-Modified-Since: 이후에 데이터가 수정되었으면?
- 데이터 변경 예시
- 200 OK, 모든 데이터 전송(BODY 포함)
Last-Modified, If-Modified-Since 단점
- 1초 미만(0.X초) 단위로 캐시 조정이 불가능
- 날짜 기반의 로직 사용
- 데이터를 수정해서 날짜가 다르지만, 같은 데이터를 수정해서 데이터 결과가 똑같은 경우
ETag(Entity Tag)
- 캐시용 데이터에 임의의 고유한 버전 이름을 달아둠
- 데이터가 변경되면 이름을 바꾸어서 변경함(Hash 다시 생성)
- ETag만 보내서 같으면 유지, 다르면 다시 다운
ETag, If-None-Match
- 캐시 제어 로직을 서버에서 완전히 관리
- 클라이언트는 단순히 값을 서버에 제공
- 예)
- 배타 오픈 기간인 3일 동안 파일이 변경되어도 ETag를 동일하게 유지
- 애플리케이션 배포 주기에 맞추어 ETag 갱신
캐시와 조건부 요청 헤더
Cache-Control 캐시 지시어(directives)
- Cache-Control: max-age → 권장
- 캐시 유효 시간, 초 단위
- Cache-Control: no-cache
- 데이터는 캐시해도 되지만, 항상 원(origin) 서버에 검증하고 사용
- 캐시를 쓰기 전에 If-Modified-Since나 If-None-Match 조건부 요청을 해서 항상 서버에 검증을 하고 사용해야한다.
- 캐시 프록시 서버 등 중간 캐시 서버가 있을 수 있다. 그 뒤의 원 서버까지 가야한다는 얘기
- Cache-Control: no-store
- 데이터에 민감한 정보가 있으므로 저장하면 안됨(메모리에서 사용하고 최대한 빨리 삭제)
Expires - 캐시 만료일 지정(하위 호환)
- expires: Mon, 01 Jan 1990 00:00:00 GMT
- 캐시 만료일을 정확한 날짜로 지정
- HTTP 1.0 부터 사용
- 지금은 더 유연한 Cache-Control: max-age 권장
- Cache-Control: max-age와 함께 사용하면 Expires는 무시
프록시 캐시
Cache-Control - 기타
- Cache-Control:public
- 응답이 public 캐시에 저장되어도 됨
- Cache-Control:private
- 응답이 해당 사용자만을 위한 것임, private 캐시에 저장해야 함(기본값)
- Cache-Control:s-maxage
- 프록시 캐시에만 적용되는 max-age
- Age-60(HTTP 헤더)
- 오리진 서버에서 응답 후 프록시 캐시 내에 머문 시간(초)
Ex) 많은 한국사람들에게 자주 보여지는 유튜브 영상은 한국 캐시서버에 저장이 되어있어 로딩이 빠르다.
캐시 무효화 - 확실한 캐시 무효화
- Cache-Control: no-cache
- 데이터는 캐시해도 되지만, 항상 원 서버에 검증하고 사용(이름에 주의!)
- Cache-Control: no-store
- 데이터에 민감한 정보가 있으므로 저장하면 안됨(메모리에서 사용하고 최대한 빨리 삭제)
- Cache-Control: must-revalidate
- 캐시 만료 후 최초 조회 시 원 서버에 검증해야함
- 원 서버 접근 실패 시 반드시 오류가 발생해야함 - 504(Gateway Timeout)
- must-revalidate는 캐시 유효 시간이라면 캐시를 사용함
- Pragma: no-cache
- HTTP 1.0 하위 호환
확실한 캐시 무효화
'Network' 카테고리의 다른 글
웹소켓(Web Socket)이란? (3) | 2024.10.21 |
---|---|
[Network] SMTP (1) | 2022.12.07 |
MIME(Multipurpose Internet Mail Extensions) 타입 (0) | 2022.10.30 |
REST(Representational State Transfer) API (0) | 2022.09.18 |