공부용 블로그 | seokmin100

혼공네트 - 5차시_응용 계층 본문

Network/혼자 공부하는 네트워크

혼공네트 - 5차시_응용 계층

seokmin100 2024. 9. 7. 00:44

DNS와 자원

도메인 네임과 네임 서버

일반적으로 사용자는 상대 호스트를 특정하기 위해 IP 주소보다는 도메인 네임(Domain Name)을 많이 사용한다. 도메인 네임은 호스트의 IP 주소와 대응되는 문자열 형태의 호스트 특정 정보이다.

IP 주소를 전화번호에 비유하면 도메인 네임은 전화번호에 대응하는 사용자 이름과 같다. 도메인 네임과 IP 주소는 네임 서버(Name Server)에서 관리한다. 도메인 네임을 관리하는 네임 서버는 DNS 서버라고 부른다.

 

네임 서버는 호스트의 도메인 네임과 IP 주소를 모아 관리하는 '공용' 전화번호부와 같은 역할을 한다. 도메인 네임을 네임 서버에 정의하면 해당 도메인 네임에 대한 IP 주소를 알려 주는 방식으로 도메인 네임을 통해 IP 주소를 알아낼 수 있다.

 

도메인 네임은 IP 주소에 비해 기억하기 쉬울뿐더러, IP 주소가 바꿔더라도 바뀐 IP 주소에 도메인 네임을 다시 대응하면 되므로 IP 주소만으로 호스트를 특정하는 것보다 더 간편하다. 도메인 네임은 점(.)을 기준으로 계층적으로 분류된다. 최상단에 루트 도메인(Root Domain)이 있고, 그 다음 단계인 최상위 도메인(TLD; Top-Level Domain)이 있으며, 계속 그다음 단계의 도메인이 있는 식이다.

 

일반적으로 알고 있는 도메인 네임의 마지막 부분을 최상위 도메인, 줄여서 TLD라고 한다. 최상위 도메인의 종류는 다양하지만, 대표적으로 com, net, org, kr, jp, cn, us 등이 있다.

 

흔히 최상위 도메인을 도메인 네임의 마지막 부분이라고 생각하기 쉽지만, 루트 도메인도 도메인 네임의 일부이다. 루트 도메인은 점(.)으로 표현되며 도메인 네임의 마지막에 점이 찍힌 형태로 표기된다. 일반적으로는 루트 도메인을 생략해서 표기하기에 대개 취상위 도메인을 '도메인 네임의 마지막 부분'으로 간주한다. 최상위 도메인의 하부 도메인은 2단계 도메인(Second-Level Domain)이라고 한다.

 

'www'는 3단계 도메인이다. 도메인의 단계는 이보다 더 늘어날 수도 있지마, 일반적으로는 3~5단계 정도이다. 그리고 도메인 네임을 모두 포함하는 도메인 네임을 전체 주소 도메인 네임(FQDN; Fully-Qualified-Domain-Name)이라고 한다.

 

3단계 도메인까지 고려하면 호스트를 식별할 수 있는 도메인 네임을 얻을 수 있다. 이런 점에서 FQDN의 첫 번째 부분(www)을 호스트 네임(Host Name)이라 부르기도 한다.

계층적인 도메인 네임을 효율적으로 관리하기 위해 네임 서버 또한 계층적인 형태를 이룬다. 또 네임 서버는 여러 개 존재하며 전 세계 여러 군데에 위치해 있다. 이렇게 계층적이고, 분산된 도메인 네임(Domain Name)에 대한 관리 체계(System)를 도메인 네임 시스템(Domain Name System), 줄여서 DNS라고 부른다. DNS는 호스트가 이러한 도메인 네임 시스템을 이용할 수 있도록 하는 애플리케이션 계층 프로토콜을 의미하기도 하다.

 

 

계층적 네임 서버

'IP 주소를 모르는 상태에서 도메인 네임에 대응되는 IP 주소를 알아내는 과정'을 흔히 '도메인 네임을 풀이(resolve)한다'라고 표현한다. 이 과정에서 다양한 네임 서버들이 사용되는데, 중요한 역할을 담당하는 네임 서버의 유형은 크게 네 가지가 있다. 각각 '로컬 네임 서버', '루트 네임 서버', 'TLD(최상위 도메인) 네임 서버', '책임 네임 서버'이다.

 

로컬 네임 서버(Local Name Server)는 클라이언트와 맞닿아 있는 네임 서버로, 클라이언트가 도메인 네임을 통해 IP 주소를 알아내고자 할 때 가장 먼저 찾게 되는 네임 서버이다. 로컬 네임 서버의 주소는 일반적으로 ISP에서 할당해 주는 경우가 많다. 다만 ISP에서 할당해 주는 경우가 많다. 다만 ISP에서 할당해 주는 로컬 네임 서버 주소가 아닌, 공개 DNS 서버(Public DNS Server)를 이용할 수도 있다. 공개 DNS 서버의 대표적인 예로는 구글의 8.8.8.8, 8.8.8.4와 클라우드플레어의 1.1.1.1이 있다.

 

만약 로컬 네임 서버가 대응되는 IP 주소를 모른다면 루트 네임 서버(Root Name Server)에게 해당 도메인 네임을 질의하게된다. 루트 네임 서버는 루트 도메인을 관장하는 네임 서버로, 질의에 대해 TLD 네임 서버의 IP 주소를 반환할 수 있다.

루트 네임 서버가 루트 도메인 을 관장하는 네임 서버인 것처럼, TLD 네임 서버는 TLD를 관리하는 네임 서버이다. 그리고 TLD 네임 서버는 질의에 대해 TLD의 하위 도메인 네임을 관리하는 네임 서버 주소를 반환할 수 있다. 하위 도메인 네임을 관리하는 네임 서버는 마찬가지로 그보다 하위 도메인 네임을 관리하는 네임 서버 주소를 반환할 수 있다.

 

책임 네임 서버(Authoritative Name Server)는 특정 도메인 영역(Zone)을 관리하는 네임 서버로, 자신이 관리하는 도메인 영역의 질의에 대해서는 다른 네임 서버에게 떠넘기지 않고 곧바로 답할 수 있는 네임 서버이다. 쉽게 말해, 책임 네임 서버는 로컬 네임 서버가 마지막으로 질의하는 네임 서버이다.

 

로컬 네임 서버가 네임 서버들에게 질의하는 방법에는 크게 '재귀적 질의'와 '반복적 질의'라는 두 가지 방법이 있다.

 

재귀적 질의

재귀적 질의(Recursive Query)는 클라이언트가 로컬 네임 서버에게 도메인 네임을 질의하면, 로컬 네임 서버가 루트 네임 서버에게 질의하고, 루트 네임 서버가 TLD 네임 서버에게 질의하고, TLD 네임 서버가 다음 단계에 질의하는 과정을 반복하며 최종 응답 결과를 역순으로 전달 받는 방식이다.

 

반복적 질의

반복적 질의(Iterative Query)란 클라이언트가 로컬 네임 서버에게 IP 주소를 알고 싶은 도메인 네임을 질의하면, 로컬 네임 서버는 루트 도메인 서버에게 질의해서 다음으로 질의할 네임 서버의 주소를 응답받고, 다음으로 TLD 네임 서버에게 질의해서 다음으로 질의할 네임 서버의 주소를 응답받는 과정을 반복하다가 최종 응답 결과를 클라이언트에게 알려 주는 방식이다.

 

실제로는 네임 서버들이 기존에 응답받은 결과를 임시로 저장했다가 추후 같은 질의에 이를 활용하는 경우가 많다. 이를 DNS 캐시(DNS Cache)라고 한다. DNS 캐시를 저장하는 용도로만 사용되는 서버도 있다. DNS 캐시를 활용하면 더 짧은 시간 안에 원하는 IP 주소를 얻어낼 수 있다.

DNS 캐시는 영원히 남아있는 것은 아니다. 임시 저장된 값은 TTL(Time To Live)이라는 값과 함께 저장되는데, 이 값은 캐시될 수 있는 시간을 뜻한다.

 

 

자원을 식별하는 URI

자원(Resource)이란 네트워크상의 메시지를 통해 주고받는 대상을 의미한다. 이는 HTML 파일이 될 수도 있고, 이미지나 동영상 파일이 될 수도 있으며, 텍스트 파일이 될 수도 있다. 즉, 두 호스트가 네트워크를 통해 서로 정보를 주고받을 때, 송수신하는 대상이 자원인 셈이다. 오늘날 인터넷 환경을 이루는 대부분의 통신은 HTTP를 기반으로 이루어지므로, 자원이라는 용어는 'HTTP 요청 메시지의 대상'이라고도 표현한다.

 

자원을 식별할 수 있는 정보를 URI(Uniform Resource Identifier)라고 부른다. 이름 그래도 자원(Resource)을 식별(Identifier)하는 통일된 방식(Uniform)이 URI인 셈이다.

URI는 위치를 이용해 자원을 식별할 수도 있고, 이름을 이용해 자원을 식별할 수도 있다. 전자를 URL(Uniform Resource Locator)이라 하고, 후자를 URN(Uniform Resource Name)이라 한다.

 

- URL

일반적인 URL 형식은 다음과 같다.

 

이 URL ;형태는 인터넷 표준 문서(RFC 3986)에서 소개하는 일반적인 URL 표기이다.

 

1. scheme

URL의 첫 부분은 scheme이다. scheme은 '자원에 접근하는 방법'을 의미한다. 일반적으로 사용할 프로토콜이 명시된다.

 

2. authority

authority에는 '호스트를 특정할 수 있는 정보', 이를테면 IP 주소 혹은 도메인 네임이 명시된다. 콜론(:) 뒤에 포트 번호를 덧붙일 수도 있다.

 

3. path

path에는 '자원이 위치한 경로'가 명시된다. 자원의 위치는 슬래시(/)를 기준으로 계층적으로 표현되고, 최상위 경로 또한 슬래시로 표현된다.

 

4. query

HTTP는 요청-응답 기반의 프로토콜이다. 클라이언트는 서버에게 URL(URL)가 포함된 HTTP 요청 메시지를 보내고, HTTP 서버는 이에 대해 HTTP 응답 메시지를 보낸다.

때로는 위에서 알아본 URL 구문만으로도 문제 없이 자원을 식별할 수 있는 경우도 있지만, 때로는 더 많은 정보가 필요할 수 있다. 이럴 때 사용할 수 있는 것이 쿼리 문자열(Query String)이다. 쿼리 파라미터(Query Parameter)라고도 부른다. 쿼리 문자열은 물음표(?)로 시작되는 <키=값> 형태의 데이터로, 앰퍼샌드(&)를 사용하여 여러 쿼리 문자열을 연결할 수 있다.

 

5. fragment

fragment는 '자원의 한 조각을 가리키기 위한 정보'이다. 흔히 HTML 파일과 같은 자원에서 특정 부분을 가리키기 위해 사용된다.

 

- URN

URN은 자원에 고유한 이름을 붙이는 이름 기반 식별자이기에 자원의 위치와 무관하게 자원을 식별할 수 있다는 장점이 있다. URN은 URL 만큼 널리 채택된 방식은 아니기에 자원을 식별할 URI로는 URN보다는 URL이 더 많이 사용된다.

 


 

HTTP

HTTP의 특성

HTTP(HyperText Tranfer Protocol)는 응용 계층에서 정보를 주고받는 데 사용되는 프로토콜이다. HTTP의 네 가지 주요 특성은 다음과 같다.

 

- 요청-응답 기반 프로토콜

HTTP는 '클라이언트-서버 구조 기반의 요청-응답 프로토콜'이다. HTTP는 클라이언트와 서버가 서로 HTTP 요청 메시지와 HTTP 응답 메시지를 주고받는 구조로 동작한다. 그렇기에 같은 HTTP 메시지일지라도 HTTP 요청 메시지와 HTTP 응답 메시지는 메시지 형태가 다르다.

 

- 미디어 독립적 프로토콜

클라이언트는 HTTP 요청 메시지를 통해 서버의 자원을 요청할 수 있고, 서버는 HTTP 응답 메시지로 요청받은 자원에 대해 응답할 수 있다. HTTP는 주고받은 자원의 특성과 무관하게 그저 자원을 주고받을 수단(인터페이스)의 역할만을 수행한다. 실제로 HTTP를 통해서 HTML, JPEG, PNG, JSON, XML, PDF 파일 등 다양한 종류의 자원을 주고받을 수 있다.

 

HTTP에서 메시지로 주고받는 자원의 종류를 미디어 타입(Media Type)이라 부른다. MIME 타입(Mutipurpose Internet Mail Extensions Type)이라고도 부른다. HTTP는 주고받을 미디어 타입에 특별히 제한을 두지 않고 독립적으로 동작이 가능한 미디어 독립적인 프로토콜이라 할 수 있다. 미디어 타입은 일종의 웹 세상의 확장자와 같은 개념이다. 일반적으로 파일의 종류를 .html, .png, .json .mp4와 같은 확장자로 나타낼 수 있듯이, HTTP를 통해 송수신하는 정보의 종류는 미디어 타입으로 나타낼 수 있다.

 

미디어 타입은 기본적으로 슬래시를 기준으로 하는 '타입/서브타입(Type/Subtype)' 형식으로 구성된다. 타입(Type)은 데이터의 유형을 나타내고, 서브타입(Subtype)은 주어진 타입에 대한 세부 유형을 나타낸다. 미디어 타입의 종류는 매우 다양하며, 필요에 따라 새로운 미디어 타입을 등록할 수도 있다. 그렇기에 모든 미디어 타입을 암기할 필요는 없고, 필요할 때마다 찾아보는 것이 일반적이다.

 

별표 문자(*)는 여러 미디어 타입을 통칭하기 위해 사용된다. */*는 모든 미디어 타입을 나타낸다.

미디어 타입에는 부가적인 설명을 위해 선택적으로 매개변수가 포함될 수도 있다. 매개변수는 모든 미디어 타입을 나타낸다.

 

- 스테이트리스 프로토콜

HTTP는 지속해서 발전 중인 프로토콜인 만큼, 여러 버전이 있다. 오늘날 많이 사용되는 HTTP 버전인 HTTP 1.1과 HTTP 2.0이 포함된다. 기본적으로 HTTP는 비연결형 프로토콜이지만, TCP는 연결형 프로토콜이다. 따라서 초기의 HTTP 버전은 쓰리 웨이 핸드셰이크를 통해 동작했습니다. 추가적인 요청-응답을 하기 위해서는 다시 TCP 연결을 수립해야 했다. 이러한 방식을 비지속 연결이라고 한다.

 

HTTP가 상태를 유지하는 프로토콜이었다면 클라이언트는 자신의 상태를 기억하는 특정 서버하고만 상호 작용할 수 있게 되어, 특정 클라이언트가 특정 서버에 종속될 수 있다. 이러한 상황에서 어느 한 서버에 문제가 발생하면 해당 서버에 종속된 클라이언트는 직전까지의 HTPTP 통신 내역을 잃어버리는 상황이 발생할 수도 있다.

 

HTTP가 처음 만들어졌을 때부터 오늘날까지 이어지는 중요한 설계 못표는 바로 확장성(Scalability)과 견고성(Robustness)이다. 상태를 유지하지 않고 모든 요청을 독립적인 요청으로 처리하는 것은 특정 클라이언트가 특정 서버에 종속되지 않도록 하며, 서버의 추가나 문제 발생 시 대처가 용이하도록 한다. 즉, 상태를 유지하지 않는 스테이트리스한 특성은 필요하다면 언제든 쉽게 서버를 추가할 수 있기 때문에 확장성이 높고, 서버 중 하나에 문제가 생겨도 쉽게 다른 서버로 대체가 가능하기 때문에 견고성이 높다.

 

- 지속 연결 프로토콜

HTTP는 지속해서 발전 중인 프로토콜인 만큼, 여러 버전이 있다. 오늘날 많이 사용되는 HTTP 버전인 HTTP 1.1과 HTTP 2.0이 포함된다. 기본적으로 HTTP는 TCP 상에서 동작하는데, HTTP는 비연결형 프로토콜이지만, TCP는 연결형 프로토콜이다. 따라서 초기의 HTTP 버전은 쓰리 웨이 핸드셰이크를 통해 TCP 연결을 수립한 후, 요청에 대한 응답을 받으면 연결을 종료하는 방식으로 동작했다. 추가적인 요청-응답을 하기 위해서는 다시 TCP 연결을 수립해야 하는데 이러한 방식을 비지속 연결이라고 한다.

 

 

HTTP 메시지 구조

HTTP 메시지는 시작 라인, 필드 라인, 메시지 본문으로 이루어져 있다. 필드 라인은 없거나 여러 개 있을 수 있고, 메시지 본문은 없을 수 있다. 또한 필드 라인과 메시지 본문 사이에는 빈 줄 바꿈이 있다.

 

시작 라인(Start-line)부터 보자. HTTP 메시지는 HTTP 요청 메시지일 수도 있고, HTTP 응답 메시지일 수도 있다. 이때, HTTP 메시지가 HTTP 요청 메시지일 경우 시작 라인은 '요청 라인'이 되고, HTTP 메시지가 HTTP 응답 메시지일 경우 시작 라인은 '상태 라인'이 된다.

 

HTTP 요청 메시지의 시작 라인인 요청 라인(Request-line)의 형식은 다음과 같다. 메서드, 요청 대상, HTTP 버전은 모두 공백으로 구분된다는 점에 유의해야 한다.

 

메서드(Method)란 클라이언트가 서버의 자원(요청 대상)에 대해 수행할 작업의 종류를 나타낸다. 대표적으로 GET, POST, PUT, DELETE 등이 있다. 요청 대상이 같아도 메서드가 다르면 각기 다른 요청으로 처리된다.

요청 대상(Requset-target)은 HTTP 요청을 보낼 서버의 자원을 의미한다. 보통 이곳에는 (쿼리가 포함된) URI의 경로가 명시된다.

HTTP 버전(HTTP-version)은 이름 그대로 사용된 HTTP 버전을 의미한다. 'HTTP/<버전>'이라는 표기 방식을 따르며, HTTP 버전 1.1은 HTTP/1.1로 표기된다.

 

HTTP 메시지가 HTTP 응답 메시지일 경우 시작 라인은 상태 라인(Status-line)이 된다. 강태 라인의 형식은 HTTP 버전, 상태 코드, 이유 구문 모두 공백으로 구분된다.

 

HTTP 버전은 사용된 HTTP의 버전을 나타내며 상태 코드(Status-line)는 요청에 대한 결과를 나타내는 세 자리 정수이다. 클라이언트는 상태 코드를 통해 요청이 어떻게 처리되었는지 판단할 수 있다. 이유 구문(Reason Phrase)은 상태 코드에 대한 문자열 형태의 설명을 의미한다.

 

필드 라인에는 0개 이상의 HTTP 헤더(HTTP Header)가 명시된다. 그래서 이를 헤더 라인(Header-line)이라고도 부른다. 여기서 HTTP 헤더란 HTTP 통신에 필요한 부가 정보를 의미한다. 필드 라인에 명시되는 각 HTTP 헤더는 콜론(:)을 기준으로 헤더 이름(Header-name)과 하나 이상의 헤더 값(Header-value)을 구성된다. HTTP 요청 혹은 응답 메시지에서 본문이 필요할 경우이는 메시지 본문(Message-body)에 명시된다. 메시지 본문은 존재하지 않을 수도 있고, 다양한 콘텐츠 타입이 사용될 수도 있다.

 

 

HTTP 메서드

HTTP 메서드의 종류에는 GET, POST, PUT, DELETE, CONNECT, OPTIONS, TRACE가 있다.

HTTP 메서드 설명
GET 자원을 습득하기 위한 메서드
HEAD GET과 동일하나 헤더만을 응답받는 메서드
POST 서버로 하여금 특정 작업을 처리하게끔 하는 메서드
PUT 자원을 대체하기 위한 메서드
PATCH 자원에 대한 부분적 수정을 위한 메서드
DELECT 자원을 삭제하기 위한 메서드
CONNECT 자원에 대한 양방향 연결을 시작하는 메서드
OPTIONS 사용 가능한 메서드 등 통신 옵션을 확인하는 메서드
TRACE 자원에 대한 루프백 테스트를 수행하는 메서드

 

-  GET - 가져다주세요

GET 메서드는 특정 자원을 조회할 때 사용되는 메서드이다. 클라이언트가 서버에게 '이것을 가져다주세요' 요청을 보내는 것과 같다. 여기서 '이것'은 조회하고자 하는 자원을 의미한다. GET은 가장 흔히 사용되는 메시지에 대한 응답이다. 이를 위해 사용되는 것이 요청 라인의 '요청 대상' 그리고 'Host 헤더'이다.

GET 요청 메시지가 성공적으로 처리되었다면 이에 대한 응답으로서 요청한 자원을 전달받게 된다.

 

- HEAD - 헤더만 가져다주세요

HEAD 메서드는 사실상 GET 메서드와 동일한 역할을 한다. 유일한 차이점은 응답 메시지에 메시지 본문이 포함되지 않는다는 것이다. 즉, HEAD 메서드를 사용하면 서버는 요청에 대한 응답으로 응답 메시지의 헤더만을 반환한다. 요컨대 HEAD 메서드는 클라이언트가 서버에게 '헤더만 가져다주세요'라고 요청을 보내는 것과 같다.

 

- POST - 처리해 주세요

POST 메서드는 서버로 하여금 특정 작업을 처리하도록 요청하는 매서드이다. POST는 '이것을 처리해 주세요'와 같은 메서드로 이해할 수 있다. POST는 메서드는 범용성이 매우 넓은 메서드이다. 웹과 관련된 개발을 하게 된다면 GET 다음으로 많이 접하게 될 메서드라고 볼 수 있다.

POST 메서드가 범용성 넓은 메서드라고는 하나, 많은 경우 '클라이언트가 서버에 새로운 자원을 생성하고자 할 때' 사용된다. 그리고 만약 성공적으로 POST 요청이 처리되어 새로운 자원이 생성되면 서버는 응답 메시지의 Location 헤더를통해 새로 생성된 자원의 위치를 클라이언트에게 알려 줄 수 있다.

 

- PUT - 덮어써 주세요

PUT 메서드는 쉽게 말해서 '덮어쓰기'를 요청하는 메서드이다. 요청 자원이 없다면 메시지 본문으로 자원을 새롭게 생성하거나, 이미 자원이 존재한다면 메시지 본문으로 자원을 완전히 대체하는 메서드이다.

 

- PATCH - 일부 수정해 주세요

PATCH 메서드는 PUT 메서드와의 차이와 비교하며 이해하는 것이 좋다. PATCH 매서드는 부분적 수정에 가깝다.

 

- DELETE - 삭제해 주세요

DELETE 메서드는 특정 자원을 삭제하고 싶을 때 사용하는 메서드이다.

 

같은 URL에 대한 요청일지라도 사용된 메서드가 다르면 각기 다른 요청으로 간주하기 때문에, 때로는 같은 URL에 대해 메서드별 동작을 여러개 구현할 수도 있다.

'어떤 URL로 어떤 요청을 받았을 때 서버는 어떻게 응답할 것인가?'는 서버를 개발하는 개발자들의 주된 고민 중 하나이다. 이를 가장 잘 보여주는 문서가 바로 API 문서이다.

 

 

HTTP 상태 코드

상태 코드는 요청에 대한 결과를 나타내는 세 자리 정수이다. 상태 코드의 종류는 200, 201, 304, 404, 505 등 다양한데, 백의 자리 수를 기준으로 유형을 구분할 수 있다. 즉, 100번대 상태 코드, 200번대 상태 코드, 300번대 상태 코드처럼 유사한 상태 코드는 같은 백의 자리 수를 공유한다.

상태 코드 설명
100번대(100~199) 정보성 상태 코드
200번대(200~299) 성공 상태 코드
300번대(300~399) 리다이렉션 상태 코드
400번대(400~499) 클라이언트 에러 상태 코드
500번대(500~599) 서버 에러 상태 코드

 

 

- 200번대: 성공 상태 코드

200번대 상태 코드는 '요청이 성공했음'을 의미한다. 주로 사용되는 상태 코드는 200(OK), 201(Created), 202(Accepted), 204(No Content)이다.

상태 코드 이유 구문 설명
200 OK 요청이 성공했음
201 Created 요청이 성공했으며, 새로운 자원이 생성되었음
202 Accepted 요청을 잘 받았으나, 아직 요청한 작업을 끝내지 않았음
204 No Content 요청이 성공했지만, 메시지 본문으로 표시할 데이터가 없음

 

 

- 300번대: 리다이렉션 상태 코드

300번대 상태 코드는 리다이렉션(Redirection)과 관련된 상태 코드이다. 리다이렉션은 클라이언트가 요청한 자원이 다른 곳에 있을 때, 클라이언트의 요청을 다른 곳으로 이동시키는 것을 의미한다.

클라이언트가 요청한 자원이 다른 URL에 있을 경우, 서버는 응답 메시지의 Location 헤더를 통해 요청한 자원이 위치한 URL을 안내해 줄 수 있다. 이를 수신한 클라이언트는 Location 헤더를 통해 요청한 자원이 위치한 URL을 안내해 줄 수 있다. 이를 수신한 클라이언트는 Location 헤더에 명시된 URL로 즉시 재요청을 보내어 새로운 URL에 대한 응답을 받게 된다.

 

리다이렉션의 유형은 크게 영구적인 리다이렉션과 일시적인 리다이렉션으로 구분된다.

영구적인 리다이렉션(Permanent Redirection)은 자원이 완전히 새로운 곳으로 이동하여 경로가 영구적으로 재지정되는 것을 의미한다. 따라서 이 경우 기존의 URL에 요청 메시지를 보내면 항상 새로운 URL로 리다이렉트된다. 서버가 도메인을 이전하는 등 웹 사이트의 큰 개편이 있을 때 이런 영구적인 리다이렉션을 접할 수 있다. 영구적인 리다이렉션과 관련한 상태 코드로는 301(Moved Permanently)과 308(Permanent Redirect)이 있다.

상태 코드 이유 구문 설명
301 Moved Permanently 영구적 리다이렉션; 재요청 메서드 변경될 수 있음
308 Permanent Redirect 영구적 리다이렉션; 재요청 메서드 변경되지 않음

 

일시적인 리다이렉션(Temporary Redirection)은 자원의 위치가 임시로 변경되있거나 임시로 사용할 URL이 필요한 경우에 주로 사용된다. 따라서 어떤 URL에 대해 일시적인 리다이렉션 관련 상태 코드를 응답받았다면 여전히 요청을 보낸 URL은 기억해야 한다. 일시적인 리다이렉션과 관련한 상태 코드는 302(Found), 303(See Other), 307(Temporary Redirect)이 있다.

상태 코드 이유 구문 설명
302 Found 일시적 리다이렉션; 재요청 메서드 변경될 수 있음
303 See Other 일시적 리다이렉션; 재요청 메서드 GET으로 변경
307 Temporary Redirect 일시적 리다이렉션; 재요청 메서드 변경되지 않음

 

 

- 400번대: 클라이언트 에러 상태 코드

400번대 상태 코드는 '클라이언트에 의한 에러가 있음'을 알려 주는 상태 코드이다. 서버가 처리할 수 없는 형태로 요청을 보냈거나, 존재하지 않은 자원에 대해 요청을 보내는 경우가 이런 경우에 속한다.

상태 코드 이유 구문 설명
400 Bad Request 클라이언트의 요청이 잘못되었음
401 Unauthorized 요청한 자원에 대한 유효한 인증이 없음
403 Forbidden 요청이 서버에 의해 거부됨
404 Not Found 요청받은 자원을 찾을 수 없음
405 Method Not Allowed 요청한 메서드를 지원하지 않음

 

상태코드 401(Unauthorized)와 403(Forbidden)을 혼동하기 쉬운데, 인증(Authentication) 여부와 권한 부여(Authorization) 여부는 다른 개념이다.

 

- 500번대: 서버 에러 상태 코드

400번대 상태 코드의 원인이 클라이언트라면, 500번대 상태 코드 원인은 서버이다. 즉, 500번대 오류는 클라이언트가 올바르게 요청을 보냈을지라도 발생할 수 있는 서버 에러에 대한 상태 코드이다.

상태 코드 이유 구문 설명
500 Internal Sever Error 요청을 처리할 수 없음
502 Bad Gateway 중간 서버의 통신 오류
503 Service Unavailable 현재는 요청을 처리할 수 없으나 추후 가능할 수도 있음

 


 

HTTP 헤더와 HTTP 기반 기술

HTTP 헤더

- 요청 시 활용되는 HTTP 헤더

1.  Host

Host는 요청을 보낼 호스트를 나타내는 헤더이다. 주로 도메인 네임으로 명시되며, 포트 번호가 포함되어 있을 수 있다.

 

2. User-Agent

User-Agent는 Host 헤더와 더불어 HTTP 요청 메시지에서 가장 흐히 볼 수 있는 헤더 중 하나이다.

유저 에이전트(User Agent)란 웹 브라우저와 같이 HTTP 요청을 시작하는 클라이언트 측의 프로그램을 의미한다.

User-Agent 헤더에는 이러한 정보, 즉 요청 메시지 생성에 관여한 클라이언트 프로그램과 관련된 다양한 정보가 명시된다. 운영체제, 브라우저 종류 및 버전, 렌더링 엔진과 같은 다양한 정보가 User-Agent 헤더에 포함되어 있다.

 

3. Referer

Referer는 개발 시 아주 유용한 헤더 중 하나이다. 이 헤더에는 클라이언트가 요청을 보낼 때 머무르고 있던 URL이 명시된다.

 

4. Authorization

Authorization 헤더는 클라이언트의 인증 정보를 담는 헤더이다. 이 헤더에는 인증 타입(Type)과 인증을 위한 정보(Credentials)가 차례로 명시된다. 인증 타입에 따라 인증 정보에 명시될 값이 달라진다.

[Authorization: <type> <credentials>]

 

인증 타입의 종류는 다양하지만, 가장 기본적인 HTTP 인증 타입은 Basic이라는 타입이다. Basic 타입 인증은 username:password와 같이 사용자 아이디(username)와 비밀번호(password)를 콘론을 이용해 합친 뒤, 이를 Base64 인코딩한 값을 인증 정보(credentials)로 삼는 방식이다. Base64 인코딩이란 '문자를 코드로 변환하는 방법'을 의미하는 인코딩(Encoding) 방식의 일종이다.

 

- 응답 시 활용되는 HTTP 헤더

1. Server

Server 헤더는 요청을 처리하는 서버 츠그이 소프트웨어와 관련된 정보를 명시한다.

 

2. Allow

Allow 헤더는 클라이언트에게 허용된 HTTP 메서드 목록을 알려 주기 위해 사용된다. 상태코드 405(Method Not Allowed)를 응답하는 메시지에서 Allow 헤더가 함께 사용된다.

 

3. Retry-After

Retry-After 헤더는 자원을 사용할 수 있는 날짜 혹은 시각을 나타낸다.

 

4. Location

Location 헤더는 클라이언트에게 자원의 위치를 알려주기 위해 사용되는 해더이다. 주로 리다이렉션이 발생했을 때나 새로운 자원이 생성되었을 때 사용된다.

 

5. WWW-Authenticate

WWW-Authenticate 헤더는 자원에 접근하기 위한 인증 방식을 설명하는 헤더이다.

 

Authorization과 WWW-Authenticate 헤더를 통해 인증되지 않은 클라이언트가 HTTP 인증(Basic 인증)을 수행하는 과정이다.

  1. 인증되지 않은 클라이언트가 서버에 GET 요청 메시지를 전송한다.
  2. 서버는 클라이언트에게 상태 코드 401(Unauthorized)과 함께 WWW-Authenticate 헤더를 통해 인증 방식을 알린다.
  3. 클라이언트는 사용자로부터 인증 정보(사용자 아이디와 비밀번호)를 전달받는다.
  4. "사용자 아이디:비밀번호"를 Base64 인코딩한 값을 인증 정보로 삼은 Authorization 헤더를 통해 다시 GET 요청 메시지를 전송한다.
  5. 서버는 인증 정보를 확인한다.
  6. 인증이 유효하면 상태 코드 200으로 응답하고, 인증되지 않았으면 상태 코드 401로 응답한다.

 

- 요청과 응답 모두에서 활용되는 HTTP 헤더

1. Date

Date는 메시지가 생성된 날짜와 시각에 관련된 정보를 담은 헤더이다. 클라이언트와 서버 모두에서 사용될 수 있는 헤더이다.

 

2. Connection

Connection 헤더는 클라이언트의 요청과 응답 간의 연결 방식을 설정하는 헤더이다. 'Connection: keep-alive' 헤더를 통해 상대방에게 지속 연결을 희망함을 알릴 수 있다. 또한 서버나 클라이언트가 연결을 종료하고 싶을 떄는 'Connection: close'를 통해 알릴 수 있다.

 

3. Content-Lengh

Content-Lengh 헤더는 본문의 바이트 단위 크기(길이)를 나타낸다.

 

4. Content-Type, Content-Lenguage, Content-Encoding

이 헤더들은 전송하려는 메시지 본문의 표현 방식을 설명하는 헤더이다. 이런 점에서 이 헤더들은 표현 헤더(Representation Header)의 일종이라고도 부른다. HTTP 요청-응답 메시지를 관찰하다 보면 자주 접하게 될 헤더들이다.

Content-Type 헤더는 메시지 본문에서 사용된 미디어 타입을 담고 있다.

Content-Language 헤더는 메시지 본문에 사용된 자연어를 명시한다.

Content-Encoding 헤더는 메시지 본문을 압축하거나 변환한 방식이 명시된다.

 

 

캐시

캐시(Cache)란 불필요한 대역폭 낭비와 응답 지연을 방지하기 위해 정보의 사본을 임시로 저장하는 기술이다. 이렇게 사본을 임시로 저장해 두면 동일한 요청에 대해 캐시된 데이터를 활용할 수 있기 때문에 불필요한 대역폭 남비를 줄일 수 있고, 더 빠르게 데이터에 접근할 수 있다.

캐시는 웹 브라우저에 저장되어 있기도 하고, 클라이언트와 서버 사이에 위치한 중간 서버에 저장되어 있기도 한다. 전자를 개인 전용 캐시(Private Cache)라 하고, 후자를 공용 캐시(Public Cache)라 부른다.

 

캐시는 원본이 아닌 사본을 저장하기 때문에 캐시를 했다면 항상 캐시한 이후로 원본 데이터가 변경되는 상황에 대비해야 한다. 캐시된 사본 데이터가 얼마나 최신 원본 데이터와 유사한지를 캐시 신선도(Cache Freshness)라고 표현하기도 한다.

신선도를 유지하는 가장 기본적인 방법은 '캐시된 데이터에 유효기간을 설정하는 방법'이다. 캐시된 데이터를 한 달 뒤, 1년 뒤, 10년 뒤 등 언제까지고 참조할 수 있다면 자연스레 신선도가 떨어질 확률이 높아진다. 따라서 캐시 데이터에 유효기간을 설정하고, 기간이 만료되었다면 원본 데이터를 다시 요청하는 방식으로 캐시 신선도를 유지할 수 있다. 캐시할 데이터에 유효 기간을 부여하는 방법으로 응답 메시지의 Expires 헤더(날짜)와 Cache-Control 헤더의 MAX-Age값(초)을 사용할 수 있다.

 

캐시가 만료되더라도 캐시된 자원이 여전히 최신 정보라면 클라이언트는 굳이 서버로부터 같은 자원을 응답받을 필요가 없다. 캐시된 자원을 이용하면 된다. 하지만 만일 서버의 원본 자원이 변경되었다면 클라이언트는 새로운 자원을 응답받아야한다. 캐시의 유효 기간이 만료되었다면 클라이언트는 캐시된 자원이 여전히 신선한지, 여전히 최신 상태의 정보인지 재검사해야 한다. 캐시의 신선도를 재검사하는 방법은 크게 두가지 방법이 있는데 '날짜를 기반으로 서버에게 물어보는 방법'이랑 '엔티티 태그를 기반으로 서버에게 물어보는 방법'이 있다.

 

날짜를 기반으로 재검사하는 방식으로 클라이언트는 If-Modified-Since 헤더를 통해 서버에게 특정 시점 이휴로 원본 데이터에 변경이 있었는지 물어볼 수 있다. If-Modified_Since 헤더의 값으로 특정 시점(날짜와 시각)이 명시되는데, 이 시점 이후로 원본에 변경이 있었다면 그때만 새 자원으로 응답하도록 서버에게 요청하는 헤더이다.

 

서버가 If-Modified-Since 헤더가 포함된 요청 메시지를 수신했다면 서버의 자원은 크게 셋 중 하나의 상황을 따르게 된다.

  1. 요청받은 자원이 변경되었음
  2. 요청받은 자원이 변경되지 않았음
  3. 요청받은 자원이 삭제되었음

첫째, 요청 받은 자원이 변경되었다면, 서버는 상태 코드 200(OK)과 함께 새로운 자원을 반환한다.

둘째, 요청받은 자원이 변경되지 않았다면, 서버는 메시지 본문 없는 상태 코드 304(Not Modified)를 통해 클라이언트에게 자원이 변경되지 않았음을 알린다. 이 경우 클라이언트는 캐시된 자원을 사용할 수 있다.

셋째, 만약 요청받은 자원이 삭제되었다면, 서버는 상태코듣 404(Not Found)를 통해 요청한 자원이 존재하지 않음을 알린다.

서버는 상태 코드 304(Not Modified)를 통한 자원은 '변경 여부'뿐만 아니라 자원의 '마지막 변경 시점'도 클라이언트에게 알려줄 수 있다. 이를 위한 헤더로 Last-Modified 헤더가 있다. 즉, Last-Modified 헤더는 특정 자원이 마지막으로 수정된 시점을 나타낸다.

 

앤티티 태그(Entity Tag)(이하 Etag)는 '자원의 버전'을 식별하기 위한 정보이다. 여기서 버전(Version)이란 '유의미한 변경 사항'을 의미한다. 즉, 자원이 변경될 때마다 자원의 버전을 식별하는 Etag 값이 변경된다. 반대로 자원이 변경되지 않았다면 Etag 값도 변경되지 않는다.

클라이언트가 Etag 값이 부여된 자원을 캐시할 때 캐시 신선도를 검사하기 위해 서버에게 '이 Etag 값과 일치하는 자원이 있니?'와 같이 물어볼 수 있다. 이를 위해 사용하는 헤더가 바로 If-None-Match이다.

 

이때도 서버의 자원은 크게 셋 중 하나의 상황을 따른다.

  1. 요청받은 자원이 변경되었음(Etag 값이 변경됨)
  2. 요청받은 자원이 변경되지 않았음(Etag 값이 동일함)
  3. 요청받은 자원이 삭제되었음

첫째, 요청한 자원이 변경되었다면 Etag 값도 변경되었을 것이다. 이 경우 서버는 상태 코드 200(OK)과 함께 변경된 데이터와 Etag 값을 응답한다.

둘째, 요청한 자원이 변경되지 않았다면 Etag 값도 변하지 않았을 것이다. 이때 서버는 메시지 본문 없는 상태 코드 304(Not Modified)를 응답한다.

셋째, 요청한 자원이 삭제되었다면 서버는 상태 코드 404(Not Found)를 응답하게 된다.

 

 

쿠키

HTTP는 기본적으로 상태를 유지하지 않는 스테이트리스 프로토콜이다.

쿠키(Cookie)란 서버에서 생성되어 클라이언트 측에 저장되는 데이터로, 상태를 유지하지 않는 HTTP의 특성을 보완하기 위한 수단이다. 서버가 클라이언트의 상태를 알 수 있게끔 하는 특별한 데이터이다. 쿠키를 이루는 정보는 기본적으로 <이름, 값> 쌍의 형태를 띠고 있고 추가로 적용 범위와 만료 기간 등 다양한 속성을 가질 수 있다.

 

서버는 쿠키를 생성하여 클라이언트에게 전송하고, 클라이언트는 전달받은 쿠키를 저장해 두었다가 추후 동일한 서버에 보내는 요청 메시지에 쿠키를 포함하여 전송한다. 서버는 쿠키 정보를 참고해 두 개의 요청이 같은 클라이언트에서 왔는지, 로그인 상태를 유지하고 있는지 등을 알 수 있다.

쿠키는 사용 가능한 도메인이 정해져 있다. 이는 응답 메시지 속 Set-Cookie 헤더의 'domain' 속성으로 정해진다.

 

같은 도메인 이라도 경로별로 쿠키를 구분하여 사용하고 싶을 때가 있을 수 있다. 그럴 때는 "path"로 쿠키가 정용될 경로를 명시하면 된다. 그러면 path로 지정된 경로와 그 앞부분이 일치하는 경로(하위 경로)에서 해당 쿠키 정보를 활용할 수 있게 된다.

 

Expires/Max-Age라는 열도 있다. 이는 쿠키의 유효 기간을 나타낸다. 쿠키마다 보통 유효 기간이 정해져 있다. Expires는 [요일, DD-MM-YY HH:MM:SS GMT] 형식으로 표기되는 쿠키 만료 시점을 의미하고, Max-Age는 초 단위 유효 기간을 의미한다. Expires로 명시된 시점이 지나거나 Max-Age로 명시된 유효 기간이 지나면 해당 쿠키는 상제되어 전달되지 않는다.

 

쿠키의 대표적인 한계는 바로 보안이다. 쿠키에 개인 정보를 비롯해 보안에 민감한 정보를 담아 송수신하고 저장하는 것이 바람직 하지 않다. 왜냐하면 쿠키 정보가 쉽게 노출되거나 조작될 수 있기 때문이다.

이를 보완하기 위한 속성으로 Secure와 HttpOnly라는 속성이 있다. Secure는 HTTPS 프로토콜이 사용되는 경우에만 쿠키를 전송되도록 하는 속성이다. HTTPS 프로토콜은 HTTP를 더 안전한 방식으로  전송할 수 있는 프로토콜이다.

 

HttpOnly는 HTTP 송수신을 통해서만 쿠키를 이용하도록 제한하는 속성이다. 다시 말해 쿠키와 관련한 데이터는 HTTP 송수신을 통해서만 확인이 가능했다. 그런데 사실 쿠키 관련 데이터는 자바스크립트라는 언어를 통해서도 접근 가능하다. 악의적 의도를 가진 해커는 자바스크립트로 쿠키를 중간에 가로채거나 위변조할 수 있다. HttpOnly는 이런 상황을 방지하기 위해 자바스크립트에서 쿠키에 접근하지 못하도록 하는 속성이다.

 

 

콘텐츠 협상과 표현

콘텐츠 협상(Content Negotiation)이란, 같은 URI에 대해 가장 적합한 '자원의 형태'를 제공하는 메커니즘을 의미한다. 같은 URI로 식별 가능한 HTML 문서라 해도, 영어로 요청하면 영어로 된 형태로 제공하고, 한국어로 요청하면 한국어로 된 형태를 제공하는 것이다. 이때, '송수신 가능한 자원의 형태'를 자원의 표현(Representation)이라고 한다. 즉, 콘텐츠 협상은 클라이언트에게 가장 적합한 자원의 표현을 제공하는 메커니즘을 의미한다.

 

GET 메서드를 조금 더 엄밀하게 정의할 수 있다. 자원에 대한 다양한 표현 중에서 클라이언트가 신호하는 표현을 반영하고자 콘텐츠 협상 관련 HTTP 헤더, 선호하는 언어를 나타내기 위한 Accept-Language 헤더, 선호하는 문자 인코딩과 압축 방식을 나타내기 위한 Accept-Charset 및 Accept-Encoding 헤더 등이 있다.

 

이러한 우선순위는 콘테츠 협상 관련 헤더의 q 값으로 표현된다. q는 Quality Value의 약자로, 특정 표현을 얼마나 선호하는지를 나타내는 값이다. 생략되었을 경우에는 1을 의미하고, 범위는 0부터 1까지이며, 값이 클수록 우선순위가 높다.