개발 R.I.P.

6.30 Dev.Feedback (HTTP/ Network)

편행 2021. 6. 30. 10:07
728x90

클라이언트 서버 아키텍쳐

상품 정보 혹은 금융 정보같은 리소스가 존재하는 곳과, 리소스를 사용하는 앱을 분리시킨 것을 2티어 아키텍처 또는, 클라이언트-서버 아키텍처라고 부른다. 리소스를 사용하는 앱이 바로 "클라이언트", 리소스를 제공(serve)하는 곳은 "서버"라고 부른다.

즉 상품 정보 자체를 전달하는 것에 초점이 맞춰진 것은 서버이며, 클라이언트에서는 그 리소스를 조회하는 것에 중점이 있다.

 

리소스에 접근하려는 앱은, 카페로 치면 손님과 같다. 손님은 아메리카노를 획득하기 위해, 리소스를 가지고 있는 점원에게 요청해야 한다. 손님의 요청에 따라, 점원은 리소스를 담아 응답한다. 이처럼 클라이언트와 서버는 요청과 응답을 주고 받는 관계이고, 클라이언트-서버 아키텍처에서는 요청이 선행되고, 그 후에 응답이 온다. 요청하지도 않았는데, 응답이 오는 경우는 없다.

 

그렇다면, 서버는 어떻게 그 많은 리소스를 다룰 수 있을까?

데이터베이스라는 창고를 만들어 저장을 해둠으로 다룰 수 있다. 이 데이터베이스 내부에 리소스에 대한 정보를 모두 저장하여, 클라이언트에서 요청이 들어왔을 때 데이터베이스에서 그 정보를 꺼내 전달을 해주는 것이다. 위와 같이 데이터베이스가 추가된 형태를 3티어 아키텍처라고 부른다.

 

클라이언트처럼 사용자가 직접 눈으로 보고, UI를 클릭 또는 터치하는 등의 상호작용을 할 수 있는 앱을 주로 개발하면 프론트엔드 개발자라고 할 수 있다. 반면, 사용자 눈에 보이지 않지만, 상품 정보를 API로 노출한다던지, 로그인/로그아웃, 권한 관리 등의 사용자 인증을 주로 다루는 개발자는 백엔드 개발자로 분류할 수 있다. (서버가 단순히 전달만 하는게 아니다!) 백엔드 개발자는 데이터베이스 등의 시스템 설계까지 도맡아서 하는 경우도 많다.

 

클라이언트와 서버의 종류

 

클라이언트는 보통 플랫폼에 따라 구분할 수 있다. 브라우저를 통해 주로 이용하는 웹(Web) 플랫폼에서의 클라이언트는 웹사이트 또는 웹 앱이라고 부른다. iOS나 안드로이드와 같은 스마트폰/태블릿 플랫폼, 그리고 윈도우와 같은 데스크탑 플랫폼에서 이용하는 앱 역시 클라이언트가 될 수 있다.

 

서버는 무엇을 하느냐에 따라 종류가 달라진다. 파일 서버는 파일을 제공하는 앱, 웹 서버는 웹사이트에서 필요로 하는 정보들을 제공하는 앱, 메일 서버는 메일을 주고 받을 수 있도록 도와주는 앱이다. 데이터베이스도 데이터 제공자로서 일하므로 일종의 서버라고 볼 수 있다.

 

클라이언트 서버 통신과 API

클라이언트와 서버 간의 통신을 알아보려면, 먼저 프로토콜이라는 개념을 이해해야 한다. 프로토콜은 통신 규약, 즉 약속이다. 손님이 주문을 받는 사람에게 대뜸 찾아가, 외계어로 주문을 할 수 없듯, 주문을 하기 위해서는 꼭 지켜야 하는 약속이 몇가지 존재한다.

 

웹 애플리케이션 아키텍처에서는 클라이언트와 서버가 서로 HTTP라는 프로토콜을 이용해서 서로 대화를 나눈다. HTTP를 이용해 주고받는 메시지는 "HTTP 메시지"라고 부른다.

 

프로토콜은 어떤 소통을 하기 위해 선택할 수 있는 방법이다. 그리고 소통을 하기 위해선 각각의 규약이 존재하기 마련이다.

예를 들면, 외교에서의 프로토콜은 국가 간에 작성한 외교 의정서(외교를 위한 룰북이라고 생각하면 쉬울 듯하다)를 토대로 진행되는 것을 의미하고 편지를 보내는 것도 하나의 프로토콜이고, 이때 송신자와 수신자의 위치를 적는 것도 그 프로토콜의 규약이라고 생각하면 된다.

그럼 HTTP라는 프로토콜에도 당연히 규약이 존재할 것이다.

클라이언트가 서버에 리소스를 요청을 할 때, 정확하게 서버에 요청하는 바를 전달해야 하는데 그 리소스를 잘 활용할 수 있도록 제공하는 것이 API(Application Programming Interface)다. 쉽게 이해하기 위해 API를 메뉴판에 비유하는 편이다.

HTTP API에는 Best Practice가 존재하는데, 아래 사이트에서 예시를 확인해볼 수 있다.

https://koreanjson.com

 

Korean JSON

{ Korean JSON } Super simple JSON API in Korean. Request GET, POST, PUT, DELETE actions and get JSON data in Korean back to get the most out of the look and feel of Korean language when prototyping your project. 한국어 데이터를 제공하는 초간

koreanjson.com

다양한 예시들 중 사용자 API에 대해서 정리해보면 아래와 같다.

위의 이미지와 같이 URL 디자인 자체는 비교적 단순하나 "메소드"라는 개념이 등장한다.

HTTP 요청에는 메소드라는 것이 존재한다. 

위의 이미지와 같이 각각의 목적에 맞는 정확한 메소드가 존재하며, 그 목적에 맞는 메소드를 꼭 사용해주어야 Client에서 정보를 조회할 때 혼동이 생기지 않게 된다.

URL

URL은 Uniform Resource Locator의 줄임말로, 네트워크 상에서 웹 페이지, 이미지, 동영상 등의 파일이 위치한 정보를 나타낸다.

이말은 CLI 환경에서 어떤 폴더 내에 진입해서 그 파일을 열었을 때, CLI 좌측에 표시되는 그 파일의 경로와 동일하다고 생각하면 된다. CLI에서 폴더와 파일의 위치를 찾아 이동하듯이, 슬래시(/)를 이용해 서버의 폴더에 진입하거나 파일을 요청할 수 있다. 

URI

URI는 Uniform Resource Identifier의 줄임말로, 일반적으로 URL의 기본 요소인 scheme, hosts, url-path에 더해 query, bookmark를 포함한다. query는 웹 서버에 보내는 추가적인 질문이라 생각하면 된다. 우리가 주소창에서 검색하면 나오는 것이 URI이며, URI가 URL의 상위 개념이다.

URL의 각 부분

프로토콜

http://, https://

 

프로토콜은 요청을 어떻게 전송을 할지 결정한다. 자주 쓰이는 프로토콜에는 file과 ftp가 존재한다.

 

HOST

localhost, google.com, www.naver.com

 

호스트는 서버이다. 로컬 컴퓨터(local host)나 로컬 네트워크에 있는 서버는 local host와 같은 단어 혹은 숫자 형태의 IP로 표현해준다. 인터넷에서 있는 서버들은 .com이나 .net같은 최상위 도메인으로 끝난다. 또한 호스트 이름 앞에 서브 도메인이 있을 수도 있다. 가장 널리 쓰이는 서브 도메인은 www이다. 다른 이름을 쓸 수도 있고, 생략 가능한 옵션이다.

 

PORT

:3000, :5000

 

각 서버에는 숫자 형태의 포트가 있다. 80, 443같은 일부 포트 번호는 특별한 용도로 사용된다. 포트를 생략해서 URL을 작성하면 HTTP 환경에서는 80을 기본 포트로 HTTPS에서는 443을 기본 포트로 사용한다. 일반적으로 기본 포트를 사용하지 않는다면 1023보다 큰 포트 번호를 사용해야하고, 일반적으로 3000, 5000, 8080같이 기억하기 쉬운 포트를 사용한다. 한 서버 내에서 중복된 포트번호를 사용할 수 없다. 1포트당 1서버

 

https://en.wikipedia.org/wiki/List_of_TCP_and_UDP_port_numbers

 

List of TCP and UDP port numbers - Wikipedia

 

en.wikipedia.org

각 포트 번호가 어떤 용도로 쓰이는지 확인할 수 있는 링크

Directory(경로)

/search, /blog

 

경로는 일반적으로 앱에서 가장 많이 사용하게 되는 URL 부분이다. 위에 작성한 프로토콜, 호스트, 포트만으로도 라우트를 결정할 수 있지만, 절대 좋은 방법이 아니다. 웹 앱에서 사용하는 페이지라거나 기타 리소스들은 모두 경로를 통해 유일하게 식별할 수 있어야 한다.

 

쿼리 스트링

?id=1, ?/type=post&returnURL

 

쿼리스트링은 일반적으로 이름 - 값의 쌍으로 이루어진 컬렉션이고 옵션이다. 쿼리스트링의 특징은 물음표(?) 기호로 시작한다. 이름-값 쌍은 각각 엠퍼샌드(&)로 구분을 한다. 이름과 값은 모두 URL 인코드를 사용해야 한다. 자바스크립트에서는 이 목적을 위해 내장함수 encodeURLComponent가 존재한다. 퀴리스트링을 검색 문자열(search string) 혹은 서치(search)라고 부르기도 한다.

 

encodeURLComponent 작동 방식

==> 스페이스는 + 기호로 변환, 다른 특스 문자들은 숫자형 문자 참조로 변환, 쿼리스트링을 검색 문자열

 

해시

#history, #q=express

 

해시(hash) 혹은 프래그먼트(fragment)는 서버로 전송되지 않으며 브라우저 단에서만 사용된다. 일부 단일 페이지 에플리케이션(SPA)은 해시를 에플리케이션 내부의 네비게이션 용도로 사용하기도 한다. 해시의 원래 목적은 브라우저가 문서의 <a id="비동기기초> 이런 특정 부분으로 이동하기 위해 사용되었다.

 

IP(Internet Protocol)

네트워크에 연결된 특정 PC의 주소를 나타내는 체계를 IP address(Internet Protocol address, IP 주소)라고 한다.

인터넷에 연결된 모든 PC는 IP 주소체계를 따라 닷(.)을 기준으로 네 덩이의 숫자로 구분된다. 이렇게 네 덩이의 숫자로 구분된 IP 주소체계를 IPv4라고 한다. IPv4는 Internet Protocol version 4의 줄임말로, IP 주소체계의 네 번째 버전을 뜻한다.

IPv4는 각 덩어리마다 0부터 255까지 나타낼 수 있다. 이 시스템을 따르면, 2^(32)인 약 43억 개의 IP 주소를 표현할 수 있다.

그 중 정해진 용도를 위한 IP도 있다.

  • localhost, 127.0.0.1 : 현재 사용 중인 로컬 PC를 지칭
  • 0.0.0.0, 255.255.255.255 : broadcast address, 로컬 네트워크에 접속된 모든 장치와 소통하는 주소, 서버에서 접근 가능 IP 주소를 broadcast address 로 지정하면, 모든 기기에서 서버에 접근할 수 있다.

최근 PC의 보급률이 늘어남에 따라 IPv6가 등장하게 됐다.

 

DOMAIN

Domain은 IP주소와 동일하게 주소를 나타내지만, 사용자가 조금 더 쉽게 이용할 수 있게 이름을 부여한 것이라고 보면 된다.

naver.com, google.com 같은 것들이 도메인의 한 종류이다.

예시를 들어보면 naver.com 과 125.209.222.142 위 아이피 주소는 동일하다. 인터넷 주소창에 적어보면 동일한 사이트로 이동하는 것을 볼 수 있다. 127.0.0.1localhost 로 사용할 수 있지만, 그 외의 모든 도메인 이름은 일정 기간 동안 대여하여 사용하게 된다.

 

 

DNS (Domain Name System)

위의 도메인 Name을 IP주소로 변환하여 사용자가 원하는 주소로 들어갈 수 있게 해주는 시스템이다.

네트워크 상에 존재하는 모든 PC는 IP 주소가 있다. 그러나 모든 IP 주소가 도메인 이름을 가지는 것은 아니다.

DNS는 Domain Name System의 줄임말로, 호스트의 도메인 이름을 IP 주소로 변환하거나 반대의 경우를 수행할 수 있도록 개발된 데이터베이스 시스템이다. 만약 브라우저의 검색창에 naver.com을 입력한다면, 이 요청은 DNS에서 IP 주소(125.209.222.142)를 찾는다. 그리고 이 IP 주소에 해당하는 웹 서버로 요청을 전달하여 클라이언트와 서버가 통신할 수 있도록 한다.

 

HTTP Messages

HTTP는 HyperText Transfer Protocol의 줄임말로, HTML과 같은 문서를 전송하기 위한 Application Layer 프로토콜이다. HTTP는 웹 브라우저와 웹 서버의 소통을 위해 디자인되었다. 전통적인 클라이언트-서버 모델에서 클라이언트가 HTTP messages 양식에 맞춰 요청을 보내면, 서버도 HTTP messages 양식에 맞춰 응답한다. HTTP는 특정 상태를 유지하지 않는 특징이 있다.

 

두가지의 유형이 있다.

  • 요청(Requests)
  • 응답(Responses)

HTTP messages는 몇 줄의 텍스트 정보로 구성되는데, 개발자는 이런 메시지를 직접 작성할 필요가 거의 없다.

구성 파일, API, 기타 인터페이스에서 HTTP messages를 자동으로 완성하게 된다.

요청과 응답은 다른 기능을 수행하지만, 비슷한 구조를 가지는 부분도 있다.

 

  1. start line : start line에는 요청이나 응답의 상태를 나타낸다. 항상 첫 번째 줄에 위치한다. 응답에서는 status line이라고 부른다.
  2. HTTP headers : 요청을 지정하거나, 메시지에 포함된 본문을 설명하는 헤더의 집합
  3. empty line : 헤더와 본문을 구분하는 빈 줄
  4. body : 요청과 관련된 데이터나 응답과 관련된 데이터 또는 문서를 포함, 요청과 응답의 유형에 따라 선택적으로 사용된다.

이 중 start line과 HTTP headers를 묶어 요청이나 응답의 헤드(head)라고 하고, payload는 body라고 한다.

 

요청(Requests)

Start line

 

HTTP 요청은 클라이언트가 서버에 보내는 메시지이다. Start line에는 세 가지 요소가 있다.

  1. 수행할 작업(GET, PUT, POST 등)이나 방식(HEAD or OPTIONS)을 설명하는 HTTP method를 나타낸다. 예를 들어 GET method는 리소스를 받아야 하고, POST method는 데이터를 서버로 전송한다.
  2. 요청 대상(일반적으로 URL이나 URI) 또는 프로토콜, 포트, 도메인의 절대 경로는 요청 컨텍스트에 작성된다. 이 요청 형식은 HTTP method 마다 다르다.
    • origin 형식 : ?와 쿼리 문자열이 붙는 절대 경로, POST, GET, HEAD, OPTIONS 등의 method와 함께 사용한다.

      예시 ) POST / HTTP 1.1 GET /background.png HTTP/1.0 HEAD /test.html?query=alibaba HTTP/1.1 OPTIONS /anypage.html HTTP/1.0

    • absolute 형식 : 완전한 URL 형식으로, 프록시에 연결하는 경우 대부분 GET method와 함께 사용

      예시) GET http://developer.mozilla.org/en-US/docs/Web/HTTP/Messages HTTP/1.1

    • authority 형식 : 도메인 이름과 포트 번호로 이루어진 URL의 authority component, HTTP 터널을 구축하는 경우, CONNECT와 함께 사용할 수 있다.

      예시) CONNECT developer.mozilla.org:80 HTTP/1.1

    • asterisk 형식 : OPTIONS 와 함께 별표(*) 하나로 서버 전체를 표현

      예시) OPTIONS * HTTP/1.1
  3. HTTP 버전은 메시지의 다른 구조를 결정한다. 이를 위해 HTTP 버전을 함께 입력해야 한다.

Headers

 

요청의 Headers는 기본 구조를 따른다.

  • 대소문자 구분 없는 문자열과 콜론(:), 값을 입력한다.
  • 값은 헤더에 따라 다르게 입력한다.

여러 종류의 헤더가 있고, 다음과 같이 그룹을 나눌 수 있다.

  • General headers : 메시지 전체에 적용
  • Request headers : User-Agent, Accept-Type, Accept-Language과 같은 헤더는 요청을 보다 구체화, Referer처럼 컨텍스트를 제공하거나 If-None과 같이 조건에 따라 제약을 추가할 수 있다.
  • Entity headers : Content-Length와 같은 헤더는 body에 적용, body가 비어있는 경우, entity headers는 전송되지 않는다.

Body

 

요청의 본문은 HTTP messages 구조의 마지막에 위치한다. 모든 요청에 body가 필요하지는 않다. GET, HEAD, DELETE, OPTIONS처럼 단순하게 서버에 리소스를 요청하는 경우에는 본문(body)이 필요하지 않다. POST나 PUT과 같은 일부 요청은 데이터를 업데이트하기 위해 본문을 사용한다. 

 

body는 다음과 같이 두 종류로 나눌 수 있습니다.

  • Single-resource bodies(단일-리소스 본문) : 헤더 두 개(Content-Type과 Content-Length)로 정의된 단일 파일로 구성
  • Multiple-resource bodies(다중-리소스 본문) : 여러 파트로 구성된 본문에서는 각 파트마다 다른 정보를 지님. 보통 HTML form과 관련이 있다.

응답(Responses)

Status line

 

응답의 첫 줄은 Status line이라고 부르며, 다음의 정보를 포함한다.

  1. 현재 프로토콜의 버전(HTTP/1.1)
  2. 상태 코드 - 요청의 결과를 나타냄 (200, 302, 404 등)
  3. 상태 텍스트 - 상태 코드에 대한 설명

Status line은 HTTP/1.1 404 Not Found. 처럼 작성된다.

 

Headers

 

응답에 들어가는 HTTP headers는 요청 헤더와 동일한 구조를 가지고 있다.

  • 대소문자 구분 없는 문자열과 콜론(:), 값을 입력
  • 값은 헤더에 따라 다르다.

 

요청의 헤더와 마찬가지로 몇 그룹으로 나눌 수 있다.

  • General headers : 메시지 전체에 적용됨
  • Response headers : Vary, Accept-Ranges와 같이 상태 줄에 넣기에는 공간이 부족했던 추가 정보를 제공
  • Entity headers : Content-Length와 같은 헤더는 body에 적용, body가 비어있는 경우, entity headers는 전송되지 않는다. 

Body(본문)

 

응답의 본문은 HTTP messages 구조의 마지막에 위치한다. 모든 응답에 body가 필요하지는 않다. 201, 204와 같은 상태 코드를 가지는 응답에는 본문이 필요하지 않다. 응답의 body는 다음과 같이 두 종류로 나눌 수 있다.

  • Single-resource bodies(단일-리소스 본문) :
    • 길이가 알려진 단일-리소스 본문은 두 개의 헤더(Content-Type, Content-Length)로 정의
    • 길이를 모르는 단일 파일로 구성된 단일-리소스 본문은 Transfer-Encoding이 chunked 로 설정되어 있으며, 파일은 chunk로 나뉘어 인코딩되어 있다.
  • Multiple-resource bodies(다중-리소스 본문) : 서로 다른 정보를 담고 있는 body

Stateless

Stateless는 말 그대로 상태를 가지지 않는다는 뜻이다. HTTP로 클라이언트와 서버가 통신을 주고 받는 과정에서, HTTP가 클라이언트나 서버의 상태를 확인하지 않는다. 

 

사용자는 쇼핑몰에 로그인하거나 상품을 클릭해서 상세 화면으로 이동하고, 상품을 카트에 담거나 로그아웃을 할 수도 있다. 클라이언트에서 발생한 이런 모든 상태를 HTTP 통신이 추적하지 않는데, 만약 쇼핑몰에서 카트에 담기 버튼을 눌렀을 때, 카트에 담긴 상품 정보(상태)를 저장해둬야 하지만 HTTP는 단순 통신 규약일 뿐이므로, 상태를 저장하지 않는다. 따라서, 필요에 따라 다른 방법(쿠키-세션, API 등)을 통해 상태를 확인할 수 있다.

 

지금은 Stateless(무상태성)이 HTTP의 큰 특징이라는 것을 기억하자.

 

'개발 R.I.P.' 카테고리의 다른 글

7.03 Dev.Feedback (Side Effect)  (0) 2021.07.03
7.01 Dev.Feedback (미들웨어)  (0) 2021.07.01
6.29 Dev.Feedback (Promise)  (0) 2021.06.29
6.28 Dev.Feedback (React #6 useEffect)  (0) 2021.06.28
6.27 Dev.Feedback (Node.js #2)  (0) 2021.06.27