[백엔드 로드맵] 인터넷 기초2

Gyubster·2022년 1월 31일
0

백엔드 로드맵

목록 보기
2/11

두번째로 알아볼 백엔드 지식은 HTTP이다. 인터넷에 대한 이해를 위해 꼬리잡기식 공부로 많은 양을 정리하였는데, 이번에는 적을 것으로 생각된다.


HTTP(HyperText Transfer Protocol)

: 텍스트 기반의 통신 규약으로 인터넷에서 데이터를 주고 받을 수 있는 프로토콜이다. 이러한 통신 규약을 만들었기 때문에 서로 정보를 쉽게 교환 할 수 있다.

이미지 출처: Hanomon.kr

HTTP는 1991년 부터 지금까지 계속 발전해왔다. 실험적인 성향을 띈 HTTP 0.9를 시작으로 HTTP 1.0, HTTP 1.1, HTTP 2를 걸쳐 HTTP 3까지 단점을 보완하며 변화하고 있다.

HTTP 구조

실제로 필자가 만든 로그인 API에 로그인 요청을 통해 HTTP 구조를 알아보자

HTTP Request와 Response의 구조는 위와 같다. (상단에 있는 것이 HTTP Request 하단에 있는 것이 HTTP Response)

HTTP Request

: HTTP Request는 크게 Start Line, Headers, Body로 나눠진다.

Start Line HTTP Method / Request Target/ HTTP version 순으로 작성된다. 위의 경우는 HTTP Method: POST 를 사용하고, Request Target: /api/puser/signin을 타겟으로 하고, HTTP version은 1.1로 HTTP Request에 대한 기본적인 정보를 확인한다.

Headers는 request에 대한 추가정보를 담고있다. 추가정보는 key:value 형태로 제공된다. General Headers(Date, Connection, Cache-Control, Pragma, Trailer), Requeset Headers(Host, User-Agent, From, Cookie, Referer, If-Modified-Since, Authorization, Origin, Accept-Encoding, Accept-Charset, Accept-Language), Entity Headers(Content-Type, Content-Language, Conetent-Encoding... Location,Last-Modified, Transfer-Encoding)로 나눠진다.

Body는 Request의 실제 메세지이다. 특정 메소드의 경우, Body가 비어있는 경우가 있다.(ex. GET)

HTTP Response

: HTTP Response는 크게 Status Line, Headers, Body로 나눠진다.

Status Line은 HTTP version, Status Code, Status Text로 이루어진다. 위의 경우, HTTP/1.1 버전을 사용하며 Status Code 200을 받았고, Status text는 OK이다.

Headers는 Request의 Headers와 같은 구조를 가진다. 단, Response에서만 가지는 Headers가 있다. Headers에는 Server(서버 소 프트웨어 정보), Accept-Range, Set-Cookie(세션 쿠키 정보 설정), Expires(응답 컨텐츠의 만료 시간), Age(캐시 응답), ETag(HTTP Content 바뀜 여부 확인), Proxy-authenticate, Allow(지원 가능한 Method들 나열), Access-Control-Allow-Origin(요청을 보내는 프론트와 요청을 받는 백엔드 주소가 다르면 *CORS Error 발생/ 헤더내에는 프론트 주소 기입)

Body는 Request의 Body와 동일하다.

HTTP 특징

각각의 특징을 알아보기 전에 공통적인 특징에 대해서 정리하자면,

  1. Client-Server Structure(클라이언트-서버 구조)

    이미지 출처: Hanomon.kr

    : Client에서 Server로 Request를 보내고 이에 따른 Response를 Server에서 Client로 보낸다.
  2. Stateless(무상태성)
    : Server가 Client 상태를 기억하지 못한다. 이때문에 매번 Client에서 Response를 보낼때 추가적인 데이터를 보내야하지만 Server는 높은 확장성을 가질 수 있게된다. 이는 *Scale Out으로 유지 및 보수가 가능하기 때문이다. 이와 반대인 Stateful Service의 경우, Client의 세션 정보를 모두 저장하게 됨으로 Scale Out으로 관리하기에는 부수적인 일들(새로 만든 서버에 세션 정보를 동기화 시키는 일 등)이 생긴다.
    하지만, Stateless 상태가 항상 유지되면 문제가 일어나는 부분도 있다. 대표적으로 로그인을 생각해보자. 로그인은 유저가 아이디와 비밀번호를 쳐서 확인이되면 그 상태를 유지 시켜야된다. 즉, 다른 페이지로 넘어가도 로그인한 정보가 유지 되어야한다는 것이다. 하지만 HTTP는 Stateless하기 때문에 다른 대안이 필요하다. 이를 해결하기 위해서, 쿠키나 서버 세션에 관련된 정보를 저장하는 등 상황에 맞춘 방법을 사용하고 있다.

이미지 출처: Hanomon.kr

  1. Connectionless(비연결성)
    Client에서 Server로 Response를 보내고 Reply를 받는 즉시 TCP/IP 연결을 끊는 것을 의미한다. 이는 Server가 항상 Client와 통신을 하는 과정에서 연결을 유지안해도 된다는 것이고, Client의 수가 많아져도 Server에 load가 적게 걸린다는 것을 의미한다(동시 처리하는 요청의 수가 적기 때문).
    하지만, 다시 연결을 하려고할 때 TCP/IP 연결을 새로 시도해야하기 때문에 3-Way Handshake와 같은 작업이 다시 이뤄져야하기때문에 부수적인 시간이 걸린다는 단점이 있다. 웹페이지의 경우를 생각해보자면 HTML을 뿐만아니라 CSS, JS, 이미지와 같은 다양한 파일들을 전달 받게 되는데, HTML 다운받고 연결 종료, JS 다운받고 연결 종료 ... 을 반복하게 된다. 따라서, 생각보다 Connectionless가 비효율적이게 적용이 된다. 이는 현재 *HTTP Persistent Connections(HTTP 지속 연결)을 통해 해결하고 있다.

Additional Information

  • Scale Out vs Scale Up
    : Scale Out: 수평적인 확장을 의미한다. 하나의 장비에서 처리하던 일을 여러 장비에서 나눠 처리할 수 있도록 설계를 변경하는 것이다. 장점으로는 지속적인 확장, 저렴한 서버 비용, 서버 부하로 인한 장애 영향도가 작음 등이 있다. 단점으로는 수평적인 확장이 많아 질수록 관리의 편의성이 떨어지고 운영 비용이 증가한다.
    Scale Up: 수직적인 확장을 의미한다. 더 좋은 하드웨어 장비로 교체하여 하드웨어 장비의 성능을 올리는 것을 의미한다. 장점으로는 관리 편의성과 운영 비용에 대한 변화는 없다는 점이 있다. 단점으로는 성능에 대한 비용 증가 폭이 크고, 서버 부하에 따른 장애 영향도가 크다는 점이 있다.
  • HTTP Persistent Connections(HTTP 지속 연결)
    : HTTP 1.X에서 나타났던 문제 중 하나이다. 웹의 초창기에는 현재와 비교하자면 많은 양의 데이터가 송수신 되지 않았다. 하지만, 시간이 지나게되고 TCP 재연결을 매번하는 것이 Server에 많은 부담을 주기 시작했다. 이를 해결하기 위해 TCP Header에 Connection과 관련한 정보(ex. Connection: Keep Alive, Conenction: Close)를 제공함으로써 TCP의 재사용을 하여 문제를 해결 하였다.
  • CORS(Cross-Origin Resource Sharing)란?
    : 직역하자면 교차 출처 리소스 공유를 의미한다. 컴퓨터 용어인데 교차?, 출처?라는 단어가 들어가서 이해가 되지 않을 수 있다. 따라서, 이를 좀 더 풀어서 이해해 보도록 하자.

    이미지 출처: https://evan-moon.github.io/2020/05/21/about-cors/


    Origin은 위의 그림에 나오는 주소와 포트 번호를 합친 주소를 말한다. 즉, 서버의 위치를 찾아가기 까지의 정확한 주소를 의미한다. 실제로, 크롬 개발자 도구에서 console.log(location.origin);를 입력하면 어플리케이션이 실행되고 있는 현 위치가 나타난다.
    그렇다면 이러한 Origin이 완벽히 일치해야 동일한 것일까? 이는 Scheme, Host, Port가 같아야 Origin이 일치한다고 할 수 있다. 예를 들어 설명하자면, Scheme은 https:// 혹은 http://가 되고, Host는 velog.io/@gyubster_shim이고, Port는 :80을 의미한다. 포트는 Origin에 보이지 않는다면 80으로 생각하면 된다.
    정리하자면, CORS는 출처가 다른 리소스를 공유한다는 것을 의미한다는 것을 알 수 있다. 웹상에서 출처가 다른 리소스를 공유한다는 것은 보안상으로 매우 위험하다. 웹에서 SOP(Same-Origin Policy)를 통해서 같은 출처에서만 리소스를 공유하는 것을 정책으로 삼았다.(웃긴 점은 CORS가 보다 SOP가 늦게 등장했다.) 하지만, 다른 출처에서의 리소스를 공유하는 것은 매우 흔한 일이기 때문에 CORS 정책을 지킨 리소스 요청만 허용하기로 하였다. 따라서 아래와 같은 과정이 가능한 것이다.

    이미지 출처: https://developer.mozilla.org/ko/docs/Web/HTTP/CORS


    Cors는 브라우저의 구현에 포함되는 정책이기 때문에 서버간 통신에서 적용이 되지 않는다. 대표적으로 Cors를 사용하지않는 Internet Explorer가 있다. 따라서, 서버에서는 통신을 제대로 하였지만 Cors 정책을 위반하여 리소스 요청에 오류가 나와 골머리를 아프게하는 경우가 많이 일어날 수 있다.
  • Cors 작동 원리
    웹클라이언트 어플리케이션은 출처가 다른 리소스를 사용하기위해 서버에 HTTP 요청 헤더 안에 Origin을 함께 담아보낸다. 서버는 이 요청에 응답할때 Access-Control-Allow-Origin이라는 값에 리소스 접근에 대한 허용된 출처를 보낸다. 이 응답을 받은 브라우저는 자신이 보낸 Origin과 서버가 보내준 Access-Control-Allow-Origin과 비교한 후 유효성을 체크한다.
    위는 Cors의 기본적인 흐름에 대해 이야기한 것이다. Cors의 동작방식은 총 3가지로 Preflight Request, Simple Request, Credentialed Request이다.


    1. Preflight Request
    : Preflight에 해당 되는 상황에서, 브라우저는 요청을 예비 요청과 본 요청으로 나누어 보낸다. 예비 요청에는 OPTIONS 메소드로 Origin을 보내 이에 대한 응답으로 Acess-Control-Allow-Origin에 대한 정보를 얻어 본 요청 전송 이전에 안전성을 점검한다. 이에 대한 부분은 아래의 그림을 보면 더 잘 알 수 있다.

    이미지 출처: https://evan-moon.github.io/2020/05/21/about-cors/


    2. Simple Request
    : 단순 요청을 직역할 수 있다. 간단히 이야기하자면, 예비 요청 없는 Preflight Request이다. 단, 이를 사용하기 위해서는 아래의 3가지 조건을 만족해야한다.
    1. 요청의 Method가 GET, HEAD, POST 중 하나여야한다.
    2. Accept, Accept-Language, Content-Language, Content-Type, DPR, Downlink, Save-Data, Viewport-Width, Width를 제외한 Header를 사용하면 안된다.
    3. Content-Type를 사용하는 경우에는 application/x-www-form-urlencoded, multipart/form-data, text/plain만 허용된다.
    위의 조건을 만족하는 상황을 마주하기는 정말 어렵다고한다.

    이미지 출처: https://evan-moon.github.io/2020/05/21/about-cors/
  1. Credential Request
    : 보안이 강화된 통신을 원할때 사용한다. 요청에 인증과 관련된 정보를 담을 수 있는 것이 특징이다. 옵션은 총 세가지이다.(same-origin: 같은 출처 간 요청에만 인증 정보를 담을 수 있다., include: 모든 요청에 인증 정보를 담을 수 있다., omit: 모든 요청에 인증 정보를 담지 않는다.) same-origininclude를 통해서 인증 정보를 담으려고 할때, Access-Control-Allow-Origin은 *를 사용할수 없다. 또한, Access-Control-Allow-Origin은 반드시 True이 여야한다.
  • HTTPS 란?
    : Hyper Text Transfer Protocol Secure를 의미한다. HTTP에 데이터 암호화가 추가된 프로토콜이다. HTTPS의 암호화는 대칭키 암호화(클라이언트와 서버가 동일한 키로 암호화 및 복호화/빠른 연산 속도지만 키가 노출되면 위험)와 비대칭키 암호화(1개의 쌍으로 구성된 공개키와 개인키를 암호화 및 복호화/느린 연산속도 키가 노출되어도 안위험)를 모두 사용한다.
    HTTPS는 처음 안전한 연결을 위해 비대칭키를 이용해 세션키를 공유하고, 이후에 데이터를 빠르게 공유하기 위해서 대칭키를 이용한다. 이러한 HTTPS는 자세한 과정은 아래와 같다. (이를 SSL Handshake라고 부른다.)

    이미지 출처:https://mangkyu.tistory.com/98
    HTTP와 HTTPS를 비교하면 아래와 같다. SSL이라는 것이 추가된 것을 확인 할 수 있다. 이는 CA(디지털 인증서 제공 공인업체)가 보증해주는 전자화된 인증서라고 생각하면된다. SSL의 역할은 1.통신 내용이 노출, 변경되는 것을 막는다., 2.클라이언트가 접속할 서버의 신뢰성을 확인한다., 3. SSL 통신에 사용할 공개키를 클라이언트에게 제공한다.

    이미지 출처: https://wayhome25.github.io/cs/2018/03/11/ssl-https/
  • HTTPS 대칭키 발급 방법
    : 서버는 클라이언트와 세션키를 공유하기 위한 공유키를 생성해야한다. 일반적으로는 Certificate Authority에 공개키를 전송하여 인증서를 발급받고있다.

    이미지 출처:https://mangkyu.tistory.com/98
profile
공부하는 예비 개발자

0개의 댓글