웹 개발을 위해서는 HTTP의 전체 흐름 이해가 필요하며, 좋은 API 설계를 하기 위해 <모든 개발자를 위한 HTTP 웹 기본 지식>을 보고 HTTP에 대한 지식을 정리하였다.

 

HTTP 란?

HTTP는 HyperText Transfer Protocol 로 하이퍼 미디어를 전송하기 위해 사용되는 프로토콜이다. 참조(ex. 링크)를 통해 사용자가 원하는 문서에 접근할 수 있는 텍스트를 하이퍼 텍스트라고 하며, 문서/영상/오디오 등 다양한 하이퍼텍스트의 집합을 하이퍼 미디어라고 한다.

 

HTTP의 특징

  • 애플리케이션 프로토콜 : OS 계층 중 최상위에 있는 애플리케이션 단에서 사용하는 프로토콜이다.
  • 클라이언트-서버 모델 : 클라이언트에서 전달하는 요청과 서버에서 전달하는 응답으로 이루어져 있다.
  • 무상태 : 클라이언트와 서버간의 데이터를 유지하지 않으며, 기존 요청에 대한 정보를 저장하지 않음을 의미한다.

 

HTTP에 대해서 간단하게 알아보았으니, HTTP가 동작하는 생태계인 인터넷에 대헤서 정리해본다.

 

1. 인터넷 네트워크의 구성

인터넷은 인터넷 프로토콜 제품군을 사용하는 네트워크와 장치 간에 통신하기 위해 구성된 시스템을 의미한다. 인터넷 통신을 할때는 인터넷 망이라는 복잡한 네트워크를 사용하며, 클라이언트(사용자)가 서버(다른 사용자)에게 접근하기 위해 IP주소를 사용한다.

 

IP(Internet Protoco, 인터넷 프로토콜)

  • IP는 지정한 IP주소에 데이터를 전달하는 통신규약으로, 패킷(Package+bucket의 합성어)이라는 통신 단위로 데이터를 전달
  • IP 주소를 통해 클라이언트와 서버를 식별
  • IP의 한계
    1. 비연결성 : 패킷을 받을 대상이 없거나, 서비스가 불능인 경우에도 패킷을 전송
    2. 비신뢰성 : 중간에 패킷이 사라지거나 순서를 유지하지 않는 경우가 발생 가능
    3. 애플리케이션 구분 : 같은 IP주소를 사용하는 서버에서 통신하는 애플리케이션이 둘 이상인 경우 구분이 불가능 
  • IP의 한계를 극복하고자 TCP/UDP 프로토콜이 새롭게 등장

TCP/UDP

TCP(Transmission Control Protocol, 전송 제어 프로토콜)은 신뢰할 수 있는 프로토콜로 대부분의 애플리케이션에서 사용한다.

  • 3way handshake를 통해 연결성을 보장하며, IP의 비신뢰성을 극복
    SYN: 접속 요청(클라이언트) -> SYN+ACK : 요청 수락(서버) -> ACK : ACK와 데이터 전송(클라이언트)
  • TCP 세그먼트(전송 계층의 데이터 단위)의 순서를 보장할 수 있는 전송 제어, 순서, 검증 정보 등이 포함됨 -> IP의 비신뢰성 극복
  • 애플리케이션 별 port를 지정하여 사용 -> 애플리케이션 구분 가능

UDP(User Datagram Protocol)은 IP에서 Port와 체크섬이 추가된 프로토콜로, 단순하고 빠르다는 특징이 있다.

추가 기능이 없음에도 불구하고 UDP가 있는 이유는 사용자가 메뉴얼하게 전송계층의 프로토콜을 활용하기 위해서이다.

 

 

2. 인터넷의 자원

인터넷에서의 자원(Resource)는 애플리케이션(대표적으로 웹브라우저)를 통해 접근할 수 있는 곳을 의미한다. 이러한 자원을 식별하기 위해서 URI를 만들었으며, 인터넷 주소창에 작성하는 양식이 URI의 예로 볼 수 있다.

 

URI(Uniform Resource Identifier)

URI는 자원(식별할 수 있는 모든 것)을 식별하는 통일된 식별자이다.

URI의 구조 : <scheme>://<userinfo@><host><:port></path><?query><#fragment>

  • scheme : 프로토콜을 입력하며, http/https/ftp 등을 사용
  • userinfo : 사용자 정보를 포함해서 인증할 때 사용
  • host : 도메인 명 혹은 IP 주소를 입력하는 부분
  • port : 접속하는 포트로 약속된 프로토콜 포트(ex. http-80/https-443)는 생략 가능
  • path : 리소스 경로로 계층적으로 구성되어 있음
  • query : key=value 형태로 입력되며, ?로 시작하고 &로 쿼리를 추가하여 사용 가능(ex. ?keyA=valueA&keyB=valueB)
  • fragment : html 내부 북마크 등에 사용되며, 서버에 전송되지 않는 정보

 

3. HTTP(HyperText Transfer Protocol)

클라이언트-서버 간에 데이터를 주고 받을 때는 대부분 HTTP를 사용하며, HTTP/1.1이 가장 중요하고 맣이 사용되는 버전이며 이후 나온 HTTP/2,3은 성능 개선에 초점이 맞추어져 있다. 웹브라이주에서 개발자도구를 통해 각 패킷 별로 HTTP 버전을 확인할 수 있다. TCP는 HTTP/1.1 & HTTP/2를 활용하고, UDP는 HTTP/3을 기반으로 구현되어 있다.

네이버 메인 페이지 접속 시 HTTP 통신 (HTTP/1.1 -> http/1.1, HTTP/2 -> h2, HTTP/3 -> h3를 의미)

 

HTTP의 특징 

  • 클라이언트/서버 구조로 클라이언트는 서버에 요청을 전송 & 서버 응답을 대기하고, 
    서버는 요청에 대한 결과 생성 & 클라이언트에 응답한다.
  • 무상태 프로토콜(stateless)이다. 
    • 이전 상태에 대한 정보를 유지하지 않는 프로토콜
    • 수평 확장에 용이 - 무상태 프로토콜이면 어떠한 요청이 와도 여러 대의 서버 중에 한 곳에서 처리를 수행하면 되지만, 상태유지 프로토콜의 경우 기존에 요청해주던 서버에서 처리를 수행해야한다. 무상태 프로토콜는 처리 성능 향상= 서버 증설이지만, 상태유지 프로토콜은 처리 성능 향상 = 서버 증설 + 클라이언트-서버 세션 관리 가 있기 때문에 무상태 프로토콜이 수평 확장에 용이하다.
    • 중복 데이터를 많이 보내야한다는 단점이 존재
    • 특정 시간에 대용량 트래픽 발생하는 경우(ex. 수강신청,티켓팅) stateless 하게 만들어야하며, 트래픽을 낮출 수 있는 방법(ex. 사용자 입력 대기)을 생각해야함 
  • 비연결성 
    • HTTP는 연결을 유지하지 않는 모델이다.
    • 연결 유지를 사용하지 않음으로써 서버의 자원을 효율적으로 사용할 수 있음
    • TCP/IP 매 요청마다 새로 맺어야하며, 요청시 마다 자원을 함께 다운로드 받아야함
      -> HTTP 지속 연결(Persistent Connections)을 사용하여 최적화 진행 
  • 단순함, 확장성 - HTTP 스펙과 구조는 매우 단순함

 

HTTP 메시지 구조

기본 구조는 <start-line> - <header-file> - <empty line> - < message body> 로 구성되며, start-line의 구조는 요청메시지와 응답메시지가 달라짐

  • start-line(요청) : [method] SP(공백) [request-target] SP [HTTP-version] CRLF(엔터)
    • method : 서버가 수행해야할 행위를 지정 (GET, POST, DELETE 등)
    • request-target : 요청 메시지로 요청 대상이 됨, 절대경로(/로 시작하는 경로)를 사용
    • HTTP-version : HTTP 버전 
  • start-line(응답) : [HTTP-version] SP [status-code] SP [reason-phrase] CRLF
    • HTTP-version : HTTP 버전
    • status-code : 상태 코드
    • reason-phrase : 사람이 이해할 수 잇는 상태 코드에 대한 짧은 설명
  • header-file : [field-name] ":" [OWS] [field-value] [OWS] (OWS: 띄어쓰기 허용)
    • HTTP 전송에 필요한 모든 부가 정보가 들어 있음
    • field-name : 대소문자 구문이 없으며 field-name과 : 사이에 띄어쓰기가 있으면 안됨
  • message-body : 실제 전송할 데이터가 모두 포함되며, 다양한 데이터 형태도 전송 가능

 

HTTP 메서드

클라이언트가 서버에 요청의 목적이나 종류를 알리는 수단이다.

 

주요 메서듸 종류

  •  GET : 리소스 조회 
    • 서버에 전달하고 싶은 데이터는 URI 뒤에 query를 붙여 전달하며, message-body를 사용해 전달할 수도 있지만 권장하지 않음 
  • POST : 새 리소스 생성 / 요청 데이터 처리 / 다른 메서드로 처리하기 애매한 경우 사용
    • message-body를 통해서 서버로 요청 데이터를 전달
  • PUT : 리소가 있는 경우 대체하고, 해당 리소스가 없으면 생성
    • PUT과 POST의 둘다 리소스를 생성하는데 사용할 수 있지만
      PUT의 경우 클라이언트가 URI를 알고 있는 경우 사용하고, POST는 URI를 모르는 경우 사용한다는 차이점이 있다.
    • 기존 리소스가 있는 겨웅 완전 대체되며, 기존에 있는 정보는 모두 사라짐
  • PATCH : 리소스 부분 변경
  • DELETE : 리소스 삭제
  • HEAD : GET과 동일하지만 메시지 부분을 제외하고, 사앹줄과 헤더만 반환
  • OPTION : 대상 리소스에 대한 통신 가능 옵션을 설명

 

메서드의 속성

  • 안전(Safe) : 호출해도 리소스를 변경하지 않는 경우 안전하다고 함
  • 멱등(Idempotent) : 여러번 호출해도 동일한 결과를 얻는 경우 멱등하다고 함
    • HTTP API를 어떻게 설계하느냐에 따라서 같은 메소드라도 멱등하게 혹은 멱등하지 않게 사용될 수 있다. 예를 들어 PACTH의 경우 PUT과 같이 일부 내용을 지정 문자로 바꾸면 멱등하게 사용할 수 있지만, 원래 값을 증가시키며 사용하면 멱등하지 않을 수 있다. 
    • 멱등하지 않을 수 있는 경우가 있는 메소드인 경우 멱등하지 않다라고 한다. (ex. POST, PATCH)
    • 외부 요인으로 중간에 리소스가 변경되는 것을 고려하지 않음
    • 자동 복구 메커니즘에 활용 (정상 응답을 못받은 경우, 같은 요청을 다시 해도되는지의 판단 근거로 사용)
  • 캐시가능(Cacheable) : 응답 결과 리소스를 캐시해서 사용해도 되는지 여부
    • GET, HEAD 정도만 캐시로 사용

 

메서드의 활용 

  • 클라이언트에서 서버로 데이터 전송하는 방식은 (쿼리 vs 바디 vs 컨텐츠 타입)에 따라 다름
    • 정적 데이터 조회 - 이미지,텍스트 문서를 조회할 때 사용
    • 쿼리 파라미터 통한 데이터 전송 -동적 데이터 조회시, 쿼리 파라미터를 사용해서 데이터를 전달
    • 메시지 바디를 통한 데이터 전송 (POST,PUT,PATCH 메서드 사용)
    • HTML FORM 데이터 전송 - GET/POST 메서드만 지원하며, URI 지정이 어려울 경우 동사로 된 리소스 경로인 컨트롤 URI를 사용
      • GET 전송(Content-Type가 별도로 없음) : 리소스를 조회할 경우 사용함
      • POST 전송(Content-Type: multipart/form-data) : 메시지 바디로 전송됨
      • 파일 전송(Content-Type: multipart/form-data) : 여러 컨텐트를 보낼 때 사용하며, 바이너리 데이터 전송시 사용
    • HTTP API 데이터 전송 - 좋은 HTTP API는 리소스 와 행위를 분리하여, 리소스 정의를 명확히한 것이다. 
      • 데이터 전송(Content-Type: /application/json) : 서버 to 서버 통신 및 앱 클라이언트, 웹 클라이언트(Ajax) 에서 사용

 

참고하면 좋은 URI 설계 개념 : htps://restfulapi.net/resource-naming 참고

  • 문서 : 단일 개념
  • 컬렉션 : 서버가 관리하는 리소스 디렉터리
  • 스토어 : 클라이언트가 관리하는 자원 저장소
  • 컨트롤러, 컨트롤 URI : 리소스(문서, 컬렉션, 스토어) 기준으로 해결하기 어려운 경우 행위를 포함하여 uri를 선언한 것(동사를 직접 사용)

 

HTTP 상태 코드

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

  • 1XX(Informational) : 요청이 수신되어 처리중
  • 2XX(Successful) : 요청 정상 처리(성공)
    • 200 : OK
    • 201 : Created (생성된 리소스는 응답의 Location 필드에 추가됨)
    • 202 : Accepted (배치 처리 같은 곳에서 사용)
    • 204 : No Content (요청은 성공적으로 수행했지만, 본문에 보낼 데이터가 없는 경우)
  • 3XX(Redirection) : 요청을 완료하려면 클라이언트에서 추가 행동이 필요
    • 리다이렉션 : 웹 브라우저는 3XX 응답 결과에 Location 헤더가 있으면, 자동으로 해당 위치로 이동함
    • 영구 리다이렉션 : 리소스 URI가 영구적으로 이동햇으며, 원래의 URI를 사용하지 않음
      • 301 : Moved Permanently (리다이렉트시 요청 메서드가 GET으로 변하고, 본문이 제거될 수 있음)
      • 308 : Permanent Redirect (요청 메서드와 본문 유지)
    • 일시 리다이렉션 : PRG(Post/Redirect/Get) 패턴을 사용할 때 많이 사용 ( POST 로 주문 -> 주문 결과 화면을 GET 메서드로 리다이렉트 -> 새로 고침을 해도 GET으로 조회 )
      • 302 : Found (리다이렉트 시에 요청 메서드가 GET으로 변하고, 본문이 제거될 수 있음 - 301과 유사)
      • 307 : Temporary Redirect (요청 메서드와 본문 유지, - 308과 유사)
      • 303 : See Other (리다이렉트시에 요청 메서드를 GET로 의무적으로 변경)
    • 캐시 리다이렉션
    • 304 : Not Modified (리소스가 수정되지 않았음을 알려주며, 로컬 PC에 저장된 캐시를 재사용)
  • 4XX(Client Error) : 클라이언트 오류 ( 클라이언트의 요청에 잘못된 문법 등으로 서버가 요청을 수행할 수 없음)
    • 400 : Bad Request (클라이언트가 잘못된 요청을 해서 서버가 요청을 처리할 수 없는 경우)
    • 401 : Unauthorized (클라이언트가 해당 리소스에 대한 인증이 필요함)
      • Authentication(인증) : 본인이 누구인지 확인 vs  Authorization(인가) : 권한 부여
    • 403 : Forbidden (접근 권한이 없는 경우)
    • 404 : Not Found (요청 리소스를 찾을 수 없는 경우 or 권한이 부족한 리소스를 숨기는 경우)
  • 5XX(Server Error) : 서버 오류 (서버 내의 에러 시에만 발생해야되며, 비지니스 로직의 문제는 500으로 나타나면 안)
    • 500 : Internal Server Error (서버 내부 문제로 오류 발생)
    • 503 : Service Unaailable (서비스 이용 불가)
  • 클라이언트가 인식할 수 없는 상태코드를 서버가 반환하면 상위 코드로 해석해서 처리

 

표현(Representation) 이란?

요청이나 응답에서 전달할 실제 데이터로, 표현 메타데이터 + 표현 데이터로 구성된다. 

  • 표현 메타데이터 : 표현 데이터를 해석할 수 있는 정보를 제공
    • Content-Type : 미디어 타입, 문자 인코딩 (ex. text/html; charset=utf-8, application/json, image/png)
    • Content-Encoding : 표현 데이터의 압축하기 위해 사용하며, 데이터를 읽는 쪽에서 인코딩 헤더의 정보로 압축해제를 수행 (ex. gzip, deflate, identity)
    • Content-Language : 표현 데이터의 자연 언어를 표현 (ex. ko,en, en-Us)
    • Content-Length: 바이트 단위로 표현된 요청의 길이
    • 협상(Content Nagotiation) 헤더 
      협상의 우선순위는 구체적일수록/Quality Value(q) 값이 높을수록 우선순위가 높음(0~1 사이 값)
      • Accept : 클라이언트가 선호하는 미디어 타입 전달
      • Accept-Charset : 클라이언트가 선호하는 문자 인코딩
      • Accept-Encoding : 클라이언트가 선호하는 압축 인코딩
      • Accept-Language : 클라이언트가 선호하는 자연 언어
        (ex. Accept-Language: ko-KR,ko;q=0.9,en-US;q=0.8,en;q=0.7)
    • 일반 정보 헤더
      • from(요청) : 유저 에이전트의 이메일 정보
      • referer(요청) : 현재 요청된 페이지의 이전 웹 페이지 주소 ( 유입 경로 분석을 위해 사용함)
      • user-Agent(요청) : 클라이언트 애플리케이션 정보(통계정보 및 특정 브라우저에 대한 장애 대응에 사용)
      • server(응답) : 요청을 처리하는 ORIGIN 서버의 소프트웨어 정보
      • date(응답) : 메시지가 발생한 시간
    • 특별한 헤더 
      • host : 요청한 호스트 정보
      • location : 3XX 대의 상태 응답코드에서는 리다이렉션의 위치로 사용하며, 201 상태 응답 코드에서는 생성한 URI로 사용
      • allow : 405 상태 응답 코드에서 포함됨
      • retry-after : 유저 에이전트가 다음 요청을 하기까지 기다려야하는 시간
    • 인증 헤더
      • authorization : 클라이언트 인증 정보를 서버에 전달
      • www-authentication : 401 상태 응답 코드 발생 시, 리소스 접근에 필요한 인증 방법을 전달하기 위해 사용
    • 쿠기 관련 헤더
      • HTTP는 무상태 프로토콜이기 대문에 클라이언트와 서버는 이전 상태에 대해서 기록하지 않음
        -> 상태를 유지하기 위해 사용하는 기법
      • 로그인 시에 set-cookie 필드를 설정하여 웹브라우저의 쿠키 저장소에 저장
      • 모든 요청에 대해서 쿠기 정보가 자동으로  포함되기 때문에 최소한의 정보만 사용해야함
      • 보안에 민감한 데이터는 저장하면 안되며, 웹 브라우저 내부에 데이터를 저장하고 싶다면 웹 스토리지(localStorage, sessionStorage)를 참고
      • 쿠키의 종류는 세션 쿠키(브라우저 종료시 까지만 사용) / 영속 쿠기(특정 시간 기준으로 쿠기만료)가 있음
      • Set-Cookie: expire - 쿠키의 만료일(GMT)을 설정할 수 있음
        ex. Set-Cookie: expire=Sat, 26-Dec-2020 04:39:21 GMT
      • Set-Cookie: max-age - 쿠키를 보관할 시간(초)으로 사용 (0이나 음수 지정시 쿠키 삭제)
        ex. Set-Cookie: max-age=3600
      • domain - 명시 시에 서브 도메인 까지 쿠기 사용 가능, 미기입 시 현재 도메인만 사용 가
      • path - 경로를 포함한 하위 경로 페이지만 쿠키 접근 
      • Secure - 적용시 https인 경우에만 전송 가능
      • HttpOnly - XSS 공격을 방지할 수 있으며, 자바스크립트에서 접근 불가
      • SameSite - XSRF 공격을 방지할 수 있음 (요청 도메인과 쿠기에 설정된 도메인이 가능 경우에만 쿠키 전)
    • 캐시 관련 헤더
      • 캐시가 없는 경우 데이터가 변경되지 않아도 계속 네트워크 통신이 필요함
      • 캐시를 적용하면 네트워크를 사용하지 않아도 되고, 빠르게 실행가능
      • 캐시 유효 시간이 초과하면, 서버를 통해 데이터를 다시 조회하고 캐시를 갱신해야함 
        -> 변경되지 않은 경우에도 다시 전송해야되는 문제가 있음
        -> 검증 헤더와 요청 헤더를 통해 캐시 유효기간이 초과해도 재사용 가능 
        • 검증 헤더
          • ETag : 데이터에 고유 식별자를 붙여서 사용
          • last-modified : 데이터 수정일 기준의 식별자 사용
        • 조건부 요청 헤더
          • if-match, if-none-match : ETag 값 사용 시 요청에 추가
          • if-modified-since, if-unmodified-since : last-modified 값 사용 시 요청에 추가
      • cache-control : https://developer.mozilla.org/ko/docs/Web/HTTP/Headers/Cache-Control
  • 표현 데이터 : 메시지 본문을 의미

 

 

+ Recent posts