HTTP 간단 총 정리( 프로토콜, HTTP METHOD, 상태코드, Header, body, 캐쉬 값)
들어가며
HTTP는 웹 개발자 중 백엔드 개발자는 물론 프론트엔드 개발자에게도 필수적으로 알아야할 지식 중 하나라고 생각합니다. 웹을 사용하려면 웹 브라우저를 사용하고 이 웹 브라우저에서 일어나는 일련의 과정들에 HTTP가 필수적인 요소이기 때문입니다. 저는 이 HTTP의 개념에 대해 대강 알고 있는 수준이었습니다. 실무에서 필요한 부분만 그때그때 익혀 사용하는 수준이었어요. 그래서 이번 기회에 총 정리하는 느낌으로 개념을 잡아놓으면 업무에 큰 도움이 될 것이라 판단했습니다. 사실 왜 미리 하지 않았을까 하는 후회가 더 큽니다. 참고로 공부는 인프런의 김영한 선생님의 강의를 들었습니다. 어떤 기술에 대한 설명을 스토리처럼 이해하기 쉽게 설명해주셔서 추천하는 강의입니다!
말그대로 넓은 범위의 과목을 간단 정리한 것이라 가독성이 매우 떨어지는 것 같습니다.(다시 읽어보는데 저야 강의를 들은지 얼마 안돼서 괜찮은데 처음 보신 분들은 혼란 그 자체일듯..) 공부한 내용을 상기시키는 목적으로 작성하였으니 만약 아래 내용을 읽으신다면 가볍게 흐름을 훑는 정도로 보시는 것을 추천합니다..
TCP
TCP 특징은 다음과 같은 특징을 가집니다.
- 연결지향 - TCP 3 way handshake : 상대방과 연결이 되어있는지 확인함.
- 데이터 전달 보증 - 메시지 전달이 안되면 알 수 있게 해줌
- 순서 보장
- TCP 3 way handshake
- SYN
- ‘야 너 잘 있냐, 연결해도 되냐?(connect, 연결 과정 정보)’
- SYN + ACK
- ‘어 잘 있다, 연결할게~’
- ACK
- ‘어 알았다, 나도 연결할게~’
- 데이터 전송( 요새는 3과4 동시에)
- 잘못된 순서가 있으면 다시 보내라고 요청해서 순서 보증
UDP
- UDP
- 기능 없음(IP와 거의 동일)
- 대신 포트가 추가됨(+체크섬)
- 포트 존재이유 : 하나의 IP로 여러개의 프로그램을 실행하기 위해 포트를 구분
- 체크섬은 메시지가 맞는지 검증해주는 데이터.
- 데이터 전달 및 순서가 보장되지 않지만 단순하고 빠름.
- 대부분 TCP가 점유를 했는데 최적화를 진행하면서 빠르게 하기 위해 UDP를 쓰기도함.
- TCP 패킷 정보(출발, 도착 port 정보)
- 0~1023 : 잘 알려진 포트로 사용하지 않은 것이 좋음
- 65535가 최대
- DNS
- IP는 외우기 어렵고 변경될 수 있다. 바뀌면 접근할 수 없음.
- 그래서 DNS서버에서 도메인명을 등록해놓으면 아이피 주소가 바뀌거나 해도 찾아갈 수 있다.
- URI
- resource locater와 name을 동시에 갖고 있음. 자원 자체를 식별
- resource locater만 있는 것은 url
- resource name만 있는 것은 urn
- 프로토콜 : 어떤 방식으로 자원에 접근할 것인가 하는 약속, 규칙
- ex) http, https, ftp …
- 웹 브라우저에서 도메인 주소를 입력했을때
- DNS 조회
- IP와 PORT 조회
- HTTP 요청 메시지 생성
- socket 라이브러리로 전달(포트,ip 번호)
- tcp/ip에서 패킷 생성
- 서버에서 http 메시지 해석
- http 응답 메시지 생성(http status, content-type, content-length, content)
- tcp 패킷과 함께 전송
- HTTP
- html 전송하는 프로토콜로 처음에 시작했으나 이제는 모든 형태의 데이터를 전송하는 프로토콜을 사용
- 1.1v를 가장 많이 사용하고 이후 2,3버전은 성능 개선용
- 1, 1/2 - TCP, 3 - UDP
- 클라이언트/서버 구조
- request/response 구조
- 클라이언트가 서버에 요청 보내고 응답을 대기
- 서버는 요청에 대한 결과를 만들어 응답
- 클라이언트는 UI대한 것만 집중, 서버는 비즈니스 로직에 대한 것으로 구분하는게 독립적으로 진화하는데 중요
- 무상태 프로토콜
- 서버가 클라이언트의 상태를 유지하지 않음(stateless)
- 차이를 보면 과거의 문맥을 보존하는 것과 항상 처음보는 상태로 요청을 보내는 것
- stateful하게 되면 ‘점원’ 이 바꼈을 때 이해하지 못함. 그래서 다른 ‘점원’ 으로 바뀌면 안됨.(점원 a한테 가서 이거 주세요, 그리고 점원 b한테 가서 카드로 계산할게요, 하면 점원 b는 카드로 계산하는 거만 알고 뭘 사는지 모름)
- stateless하게 되면 ‘점원’ 이 바껴도 이해함. → 서버를 막 늘려도 관리가 가능.(점원 a한테 가서 이거 주세요, 점원 b한테 가서 이거 주시고 카드로 계산할게요, 하면 점원 b도 이해가능)
- 한계 : 모든 것을 무상태로 하기 힘들다, 데이터 전송량의 차이.
- 비연결성
- 장점
- 요청, 응답을 보낼때만 연결을 유지함. → 서버의 자원을 효율적으로 유지 가능
- 초 단위 이하의 빠른 속도로응답
- 수천명이 서비스를 이용해도 실제 서버의 처리 요청은 작을 수 있음.
- 단점
- TCP 연결을 새로 맺어야 해서 3 way handshake 시간 추가
- 웹 브라우저로 사이트를 요청하면 html 뿐만 아니라 css, javascript, image등이 함께 다운로드됨.
- 그래서 지속 연결로 문제 해결
- 연결 후 html 요청 응답하는 과정 계속 유지하다가 마지막에 종료
- HTTP 메시지로 구성
- 시작라인, 헤더, 공백라인, 메시지 바디로 구성
- 시작라인
- request-line : 메서드(get/post), target, http version
- status-line : http version, status code, reason
- header-field : field-name : value(메시지 바디에 없는 메타데이터 정보), 임의로 추가가능
- message body : 실제 전송할 데이터(모든 종류 가능)
- 단순함, 확장 가능
- HTTP 메서드
- http api 만들기
- 이름을 지을 때 - 리소스의 의미만 담아라.(회원 조회,등록,수정,삭제 - member로)
- URI는 리소스만 식별하고 행위는 분리한다. 행위는 Http Method로(get,post,put,delete)
- GET
- 리소스 조회
- query 파라미터로 전달
- POST
- 요청 데이터를 처리하는 역할
- 주로 신규 데이터 등록, 프로세스 처리에 사용
- 클라이언트가 메시지 바디에 담아 전달
- 응답 데이터에 등록 결과와 어떤 경로에 등록했는지 정보를 담아 전달
- 요청 데이터를 처리하는데(프로세스의 변화가 일어날때), 리소스가 생성되지 않아도 사용
- uri는 리소스명만으로 하는 것이 좋지만 불가능한 경우 컨트롤 URI를 사용하기도 한다.
- JSON으로 조회 데이터를 넘겨야 하는데 GET METHOD를 사용하기 어려운 경우
- PUT
- 기존 리소스를 ‘완전히’ 대체
- 리소스가 없으면 생성
- 클라이언트가 리소스의 구체적 위치를 알고있음.( ex /members/100)
- PATCH
- 기존 리소스를 부분만 대체
- 지원이 안되는 서버가 있을 수 있음.(POST로 대체)
- DELETE
- 제거
- http api 만들기
- HTTP METHOD 속성
- 안전 : 여러번 호출했을때 리소스 변경이 일어나면 안전하지 않다고 판단.
- 멱등(Idempotent)멱등하지 않은 것은 POST METHOD. 따라서 두번 호출하면 안된다.
- 활용
- 자동 복구 매커니즘(장애 발생 시 똑같은 호출을 반복해도됨)
- 활용
- : 1,2,100 호출하든 최종 결과는 항상 똑같은 것.
- 캐시가능
- 응답 결과 리소스를 캐시해서 사용해도 되나? GET, HEAD 정도만 캐시로 사용
- POST, PATCH는 사용은 가능하지만 본문 내용까지 캐시 키로 고려해야 해서 구현이 쉽지 않음.
- 클라이언트에서 서버로 데이터 전송
- 쿼리 파라미터로 전달해서 사용(GET)
- 검색어에서 정렬 필터
- 메시지 바디를 통한 전송(POST, PUST, PATCH)
- 정적 데이터 조회(image, text)
- 쿼리 파라미터 미사용, 단순 조회
- 동적 데이터 조회(쿼리 파라미터)
- 파라미터 기반으로 동적 데이터를 조회해서 응답
- POST 전송 - 저장전송 데이터는 url encoding처리
- Content-type form 설정 후 body 에 message request
- 파일 전송(multipart/form-data)
- 텍스트 뿐만 아니라 파일을 전송할때 Content-type을 바꾸고 각 파트의 경계를 자르고 각각의 데이터를 분리해서 넣어준다.
- form data 전송은 get, post만
- 서버 to 서버
- 앱 클라이언트
- 데이터 전달 표준은 json이다. 과거에는 xml이었으나 용량도 더 크고 보기 어려움
- 쿼리 파라미터로 전달해서 사용(GET)
정리 : 정적 데이터 조회(그냥 이미지같은), 동적 데이터 조회(쿼리 파라미터), 폼 데이터(회원가입, 상품주문, 데이터변경), HTTP API(회원가입, 상품주문, 데이터변경, 서버to서버, 앱,웹클라이언트(ajax, android)
- 컬렉션
- 서버가 관리하는 디렉토리
- 서버가 리소스를 생성하고 관리
- 회원등록 시 POST /member로 API 보낼 경우 컬렉션은 /member가 된다.
- POST 등록의 경우 서버가 url을 관리하지만 PUT 등록의 경우 클라이언트가 url을 알고 관리해야한다.
- 스토어
- 클라이언트가 url을 관리하는 것
- URL 설계 개념
- https://restfulapi.net/resource-naming
- 상태코드
- 1xx : 요청이 수신되어 처리중
- 2xx: 요청 정상 처리
- 3xx: 요청을 완료하려면 추가 행동 필요
- 302,307,303 : 일시적 리다이렉션, new-url로 저장하지 않음
- 300, 304 : 기타 리다이렉션, 304는 캐시에 있는 데이터를 쓰라고 알려주는 것(메시지 바디 포함 안함)
- 301, 308 : 영구 리다이렉션, 301은 POST로 보내면 GET으로 바꾸고 본문을 지우지만 308은 POST로 하고 데이터 보존
- 301 : url이 과거에서 바꼈을때 new-url과 301코드를 줘서 클라이언트가 다시 new-url로 보냄.
- 4xx: 클라이언트 오류, 잘못된 문법으로 서버가 요청을 수행할 수 없을때
- 401인증(Authentication) : 본인이 누구인지
- 404 : 잘못되 url 호출
- 403: 권한 오류 401은 미확인 사용자이고 403은 권한의 차이가 있음.
- 5xx: 서버 오류, 정상 요청을 처리하지 못할 때
- 500 서버 문제 오류PRG(POST-REDIRECT-GET) : POST로 프로세스 처리 후 GET으로 리다이렉트함
- 503 서비스 이용불가(뭔가 점검이나 장애)
- 재실행했을때 성공할 가능성이 있음.
- HTTP 헤더
- 표현 헤더
- content-type: 형식
- content-Encoding: 압축 방식(서버에서 해당 스펙으로 압축 해제)
- content-Language: 자연 언어
- content-Length: 길이
- 컨텐츠 네고시에이션
- 클라이언트가 선호하는 표현으로 요청
- Accept: 클라이언트가 선호하는 미디어 타입(xml, json..)
- Accept-Charset : 문자 인코딩
- Accept-Encoding: 압축 인코딩
- Accept-Language: 자연 언어
- 우선순위의 배율을 맞춘다(1, 0.9, 0.8…)
- 우선순위 : 원하는 것의 순서를 정해줌.(사이트 방문 시 사이트가 다중 언어를 지원하면 네고시에이션을 통해 1순위 한국어 2순위 영어를 판단)
- 클라이언트가 선호하는 표현으로 요청
- 데이터를 전송하는법
- 단순전송
- 압축전송(content-encoding 필요)
- 분할전송(transfer-encoding 필요, content-length 노필요)
- 범위전송
- From
- 유저 에이전트의 이메일 정보(요청에서 사용)
- Referer : 어디서 유입된건지 파악 가능
- 현재 요청된 페이지의 이전 웹 페이지 주소(많이씀)
- User-Agent : 어디서 장애가 발생하는지, 혹은 분석에 도움
- 클라이언트의 애플리케이션 정보(web,app,android,…)
- Server
- 요청을 처리하는 origin 서버(데이터를 만들어주는 진짜 서버)의 소프트웨어 정보
- Host(필수)
- 도메인 정보를 입력(서버가 해당 호스트 정보를 확인할 수 있음)
- Allow
- 허용 가능한 HTTP 메서드(잘 쓰지 않음)
- Retry-After
- 유저 에이전트가 다음요청을 하기까지 기다리는 시간(서버 오류로 인해)
- 인증
- Authorization : 인증에 관련된 값을 전달(OAuth, jwt)
- 캐시
- 캐시 적용 - 헤더에 cache-control(캐시 유효 시간)
- 서버에 최초 요청 후 → 브라우저 캐시에 유효 시간만큼 저장 → 다음 요청 시 캐시 먼저 조회(네트워크 탈 필요 없음)→브라우저 로딩 속도 빠름, 빠른 사용자 경험
- 캐시 시간 초과 되었을때는 서버 조회 후 시간 갱신.
- Last-Modified : 최종 수정 시간을 기록.
- 캐시가 만료된 경우 이 값을 헤더에 보내면 서버에서 자신이 갖고 있는 파일과 최종 수정 시간을 비교한다. 만약 이 값이 같다면 서버는 304응답값(수정 안됨)과 함께 바디 없이 보낸다. 클라이언트는 이 값을 받고 캐시 데이터를 사용한다. 이 경우 용량을 많이 줄일 수 있다.
- 검증 헤더(Last-Modifed)와 조건부 요청(if-modifed-since)를 함께 사용
- 조건부 요청 단점 : 데이터를 수정했는데 같은 데이터로 수정해서 데이터 자체는 똑같은 경우, 내가 임의로 캐시 로직을 짜고 싶을 경우 짤 수 없다.
- if-modified-since - 변경이 안됐으면 304(캐시로 리다이렉션 해라.), 변경이 됐으면 200(모든 데이터 전송)
- ETag - 캐시용 데이터에 임의의 고유한 버전 이름을 담음. 변경되면 이 이름을 바꿔 변경, Etag가 같은지 다른지 판단해서 조건부 요청(If-None-Match)
- cache-controlno-cache : 데이터는 캐시해도 되지만 항상 origin 서버에 검증하고 사용
- no-store : 데이터를 저장하지 않음(메모리에서 사용하고 최대한 빨리 삭제)
- max-age : 캐시 유효 시간, 초단위
- 프라그마, Expires - 캐쉬의 하위호환
- 캐시가 없을때 - 똑같은 정보를 계속 서버에서 다운로드 받아야함.(느린 사용자 경험)
- 캐시 컨트롤
- 프록시 캐시
- 웹 브라우저가 원 서버까지 도달하기 너무 머니까 프록시 캐시 서버를 두어 요청속도를 향상
- 로컬 캐시는 private cash, proxy cash는 public cash
- 개인적인 정보들은 프라이빗에다 저장
- 프록시 캐시
- 확실한 캐시 무효화 응답
- no-cache, no-store, must-revalidate
- pragma : no-cache(옛날 브라우저에서 가끔사용해서 넣어줘야 확실하게 무효화 가능)
- 표현 헤더
마치며
넓은 범위이지만 HTTP의 전체적인 데이터 흐름을 파악할 수 있는 뜻깊은 시간이었습니다. 까먹기 쉬운 내용들이라 여러번 복습이 필요할 듯 하고 필요한 부분은 더 깊게 파서 볼 기회를 가져야겠다고 생각했습니다.(캐시, HTTP Method 라던가...)