Post

[1% network] Ch01. 웹 브라우저가 메시지를 만든다

Ch01. 웹 브라우저가 메시지를 만든다

학습할 것

  • HTTP 리퀘스트 메시지를 작성한다.
  • 웹 서버의 IP 주소를 DNS 서버에 조회한다.
  • 전 세계의 DNS 서버가 연대한다.
  • 프로토콜 스택에 메시지 송신을 의뢰한다.

HTTP 리퀘스트 메시지를 작성한다.

1. 탐험 여행은 URL 입력부터 시작한다.

브라우저는 웹 서버 액세스 및 파일을 다운로드/업로드하는 FTP의 클라이언트 기능이나 메일의 클라이언트 기능 등 여러 기능이 있어 어떤 기능을 사용하여 데이터에 액세스할지를 명시하는 여러 종류의 URL이 있다.

url은 맨 앞에 문자열에 http:, ftp:, file:, mailto: 등을 사용하여 액세스 방식을 명시한다.

(이 때 프로토콜이 아닌 액세스 방식이라고 한 이유는 file: 의 경우는 액세스할 때 네트워크를 사용하지 않으므로 프로토콜이라고 단언할 수 없기 때문이다.)

이후 문자열에는 웹 서버나 FTP 서버에 액세스하는 경우 서버의 도메인명이나 액세스하는 파일의 경로 등을 URL에 포함시키며 메일의 경우 보내는 상대의 메일 주소를 URL에 포함시킨다.

각종 URL 형식

  • HTTP 프로토콜로 웹 서버에 액세스 하는 경우
    • http://www.cyerco.kr:80/dir/file1.htm

      http://{ 웹 서버의 도메인 명 } : { 포트 } / { 파일 경로명 }

  • FTP 프로토콜로 파일을 다운로드하거나 업로드하는 경우
    • ftp://ftp.cyber.co.kr:21/dir/file1.htm

      ftp://{ ftp 서버의 도메인 명 } : { 포트 } / { 파일 경로명 }

  • 클라이언트 PC 자체의 파일에서 데이터를 읽어오는 경우
    • file://localhost/c:/path/dir/file1.zip

      file://{ 컴퓨터명 } / { 파일 경로명 }

  • 메일을 송신하는 경우
    • mailto:tone@cyber.co.kr

      mailto:{ 메일 주소 }

2. 브라우저는 먼저 URL을 해독한다.

브라우저는 가장 먼저 웹 서버에 보내는 리퀘스트 메시지를 작성하기 위해 URL을 해독한다.

http://lab.cyber.co.kr/dir1/file1.html

  • http: -> 데이터 출처에 액세스하는 방법
  • www.lab.cber.co.kr -> 웹 서버 명
  • /dir/file1.html -> 데이터 출처의 경로명

URL을 해독할 때는 다음과 같이 요소를 분해하여 URL 의미를 찾는다.

위의 예시의 URL은 www.lab.cyber.co.kr이라는 웹 서버에 있는 /dir/file1.html 경로의 파일에 액세스한다는 의미이다.

3. 파일명을 생략한 경우

http://lab.cyber.co.kr/dir1/

다음과 같이 /로 끝나는 URL의 경우는 /dir/ 다음에 써야할 파일명을 쓰지 않고 생략한다는 것이다.

이럴 경우 어느 파일에 액세스해야 할지 모르므로 index.html과 같이 파일명을 미리 서버측에 설정해둔다.

4. HTTP의 기본 개념

리퀘스트 메시지 (URI와 메서드)

HTTP 프로토콜의 경우 클라이언트에서 서버를 향해 리퀘스트 메시지를 보낸다. 이 때 메시지 안에는 ‘무엇을(URI)’ , ‘어떻게 해서(메서드)’ 라는 내용이 있다.

이 때 무엇을에 해당하는 것을 URI라고 하는데 보통 페이지 데이터를 저장한 파일의 이름이나 CGI 프로그램의 파일명을 URI로 쓴다.

어떻게해서에 해당하는 것은 메서드로 웹서버에 특정 동작을 요구한다.

응답 메시지 (스테이터스 코드)

응답 메시지의 맨 앞에는 실행 결과의 상태를 나타내는 스테이터스 코드가 있다. 그리고 헤더 파일과 페이지의 데이터를 포함하여 클라이언트에 반송한다.

메서드

| 메서드 | 버전 1.0 | 버전 1.1 | 의미 | | —– | :—: | :—: | —– | | GET | o | o | URI로 지정한 정보를 도출한다. | | POST | o | o | 클라이언트에서 서버로 데이터를 송신한다. | | HEAD | o | o | GET과 유사하나 HTTP 메시지 헤더만 반송한다. | | OPTIONS | | o | 통신 옵션을 통지하거나 조사한다. | | PUT | | o | URI로 지정한 서버의 파일을 있으면 치환, 없으면 생성한다. | | DELETE | △ | o | URI로 지정한 서버의 파일을 삭제한다. | | TRACE | △ | o | 서버측에서 받은 리퀘스트 라인과 헤더를 그대로 클라이언트에 반송한다. | | CONNECT | | o | 암호화한 메시지를 프록시로 전송한다. |

5. HTTP 리퀘스트 메시지를 만든다.

URL을 해독하고 웹 서버와 파일 명을 판단하면 브라우저는 이것을 바탕으로 HTTP 리퀘스트 메시지를 만든다.

HTTP 메시지 포맷

브라우저는 URL을 해독하고 웹 서버와 파일명을 판단한 후 이를 바탕으로 HTTP의 리퀘스트 메시지를 만든다.

리퀘스트 메시지

리퀘스트 메시지

리퀘스트 메시지의 형식은 다음과 같다.

  • 리퀘스트 라인
    • <메서드>
  • 메시지 헤더
    • <필드명> : <필드값>
    • Host, Cookie, User-Agent, Referer 등 리퀘스트의 부가적인 정보를 ‘이름 : 값’형식으로 보낸다.
  • 메시지 본문
    • 클라이언트에서 서버에 송신하는 데이터이다. POST 메서드에서 사용한다.

응답 메시지

응답 메시지

응답 메시지의 형식은 다음과 같다.

  • 스테이터스 라인
    • <상태 코드=""> <응답 문구="">
  • 메시지 헤더
    • Server, Set-Cookie, Content-Type, Content-Length 등 데이터를 담고있다.
  • 메시지 본문
    • 클라이언트가 요청한 리소스 혹은 요청한 작업 상태에 대한 일부 정보를 포함한다.

6. 리퀘스트 메시지를 보내면 응답이 되돌아온다.

응답 메시지의 경우 리퀘스트의 실행 결과를 나타내는 스테이터스 코드와 응답 문구를 첫번째 행에 쓴다.

스테이터스 코드는 숫자로 쓰여있어 주로 프로그램 등에 실행 결과를 알려주는 것이 목적이고 응답 문구는 문장으로 쓰여있어 사람에게 실행 결과를 알리는 것이 목적이다.


웹 서버의 IP 주소를 DNS 서버에 조회한다

1. IP 주소의 기본

HTTP의 메시지를 만들면 이 메시지를 OS에 의뢰하여 액세스 대상의 웹 서버에 송신한다.

이 때 URL 안에 쓰여있는 서버의 도메인 명에서 IP 주소를 조사해야한다.

IP 주소의 구성 (네트워크 부와 호스트 부)

IP 주소는 어느 네트워크의 어느 호스트라는 것을 식별하는 주소이다.

따라서 **IP 주소는 호스트가 속한 네트워크 주소인 네트워크 부 (Network PartNetwork ID)와 호스트의 주소인 호스트 부 (Host PartHost ID)** 로 구성된다.

즉 네트워크 부는 어떤 네트워크인지를 나타내 다른 네트워크와 구분하는 역할을 하고, 호스트 부는 해당 네트워크의 어느 호스트인지를 나타내 다른 호스트와 구분하는 역할을 한다.

(이 때 호스트는 컴퓨터와 IP주소를 할당하는 라우터를 포함한다)

2. 도메인명과 IP 주소를 구분하여 사용하는 이유

실행 효율 관점에서 IP 주소 대신 이름으로 통신하는 것은 좋은 방법이 아니다.

IP 주소라면 32비트 (4바이트)에 해당하는 개수 밖에 없지만 도메인명은 최대 255 바이트까지의 문자를 취급해야 하므로 그만큼 데이터를 운반하는 동작에 더 많은 시간이 걸리기 때문이다.

그래서 이름을 알면 IP 주소를 알 수 있다거나 IP주소를 알면 이름을 알 수 있다는 원리를 사용한 DNS가 나오게 되었다.

DNS의 구성 요소

DNS는 세가지 요소로 구성되어 있다.

  • 도메인 네임 스페이스
    • 도메인 이름 저장을 분산한다.
  • 네임 서버 (= 권한 있는 DNS 서버)
    • 해당 도메인 이름의 IP 주소를 찾는다.
  • 리졸버 (= 권한 없는 DNS 서버)
    • DNS 클라이언트 요청을 네임 서버로 전달하고 찾은 정보를 클라이언트에게 제공하는 기능을 수행한다.

3. Socket 라이브러리가 IP 주소를 찾는 기능을 제공한다.

DNS 서버에 조회한다는 것은 DNS 서버에 조회 메시지를 보내고 거기에서 반송되는 응답 메시지를 받는 것이다.

DNS 클라이언트에 해당하는 것을 DNS 리졸버라고 부른다. 그리고 DNS 원리를 사용하여 IP 주소를 조사하는 것을 네임 리졸루션이라고 한다.

리졸버의 실체는 Socket 라이브러리에 들어가 있는 프로그램 부품 중 하나이다. ( Socket 라이브 러리 : 네트워크의 기능을 호출하기 위한 프로그램 부품 모음 )

4. 리졸버를 이용하여 DNS 서버를 조회한다.

리졸버는 Socket 라이브러리 안에 들어가 있어 애플리케이션 프로그램을 만들 때 리졸버의 프로그램명(gethostbyname)과 웹 서버의 이름을 써서 리졸버를 호출할 수 있다.

1
< 메모리 영역 > = gethostbyname(" { 조회하는 서버의 도메인 명 } ")

5. 리졸버 내부의 작동.

  1. 리졸버를 호출하여 리졸버에 제어가 넘어가면 여기서 DNS 서버에 문의하기 위한 메시지를 만든다. (‘www.lab.cyber.co.kr’ 서버의 IP 주소를 알려주세요)
  2. 메시지를 DNS 서버에 보낸다.
  3. OS 내부에 포함된 프로토콜 스택을 호출하여 송신을 의뢰한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<애플리케이션 프로그램>

< 메모리 영역 > = gethostbyname(" { 조회하는 서버의 도메인 명 } ")

----------------------------------

<Socket>
gethostByName {
  
  DNS 서버에 조회하는 메시지 생성
  조회 메시지를 DNS 서버에 보냄 -> (OS 내부의 프로토콜 스택 호출)
  
  DNS 서버에서 응답한 메시지 수신
  응답 메시지로 IP 주소 호출하여 <메모리 영역>에 저장 후 애플리케이션으로 돌아감
}

----------------------------------

<OS 내부의 프로토콜 스택>
UDP 메시지 송신 {
  송신 동작 (-> LAN 어댑터 -> DNS 서버)
}
UDP 메시지 수신 {
  수신 동작 (<- LAN 어댑터 <- DNS 서버)
}


전 세계의 DNS 서버가 연대한다

1. DNS 서버의 기본 동작

DNS 서버의 기본 동작은 클라이언트에서 조회 메시지를 받고 조회 내용에 응답하는 형태이다.

조회 메시지 구성 요소

조회 메시지는 다음 세가지 정보를 포함한다.

  • 이름
    • 서버나 메일 배송 목적지이다.
  • 클래스
    • 인터넷 외의 네트워크 이용을 식별하기 위해 존재하나 지금은 인터넷 외의 네트워크가 소멸되었으므로 클래스는 항상 인터넷을 나타내는 ‘IN’을 사용한다.
  • 타입
    • 이름에 어떤 타입의 정보가 지원되는지를 나타낸다.

DNS 서버의 기본 동작

  • 서버의 IP를 조사할 때 클라이언트는 이름, 클래스, 타입 정보를 포함한 조회 메시지를 DNS 서버에 보낸다.
  • DNS 서버는 등록된 정보를 찾아서 세가지 항목이 일치하는 것을 찾아 등록된 회답할 값을 클라이언트에 회답한다.

동작 예시

| 이름 | 클래스 | 타입 | 클라이언트에 회답 | | ——————- | —– | —- | —————– | | www.lab.cyber.co.kr | IN | A | 192.0.2.226 | | cyber.co.kr | IN | MX | 10 mail.cyber.co.kr | | mail.cyber.co.kr | IN | A | 192.0.2.227 |

예를 들어 조회 메시지 항목이 이름 cyber.co.kr / 클래스 IN / 타입 MX 와 같을 경우 DNS 서버는 10과 mail.cyber.co.kr 이라는 두개의 항목에 회답한다.

이 때 MX의 경우 회답 뿐 아니라 mail.cyber.co.kr이라는 메일 서버의 IP 주소(192.0.2.227)도 함께 회답한다.

2. 도메인의 계층 구조

도메인의 체계적인 분류와 관리를 위해 도메인 이름은 몇 개의 짦은 영문자를 ‘. (닷, 점)’으로 연결한 계층 구조를 갖고 있다.

도메인

출처: https://better-together.tistory.com/128?category=887984

그림과 같이 도메인의 계층 구조는 나무를 거꾸로 한 것 같은 모양으로 되어 있어 ‘역 트리(Inverted tree) 구조’라고 하며 트리 구조의 정점을 루트(root, 뿌리)라고 한다.

루트 아래로 갈라지는 가지를 단계별로 구분하여 ‘kr’과 같이 국가를 나타내는 국가 코드 도메인(ccTLD, country code Top Level Domain)이나 ‘com’같이 등록인의 목적에 따라 사용되는 일반 도메인(gTLD, generic Top Level Domain)을 1단계 도메인(또는 최상위 도메인, 탑레벨 도메인, Top Level domain, TLD)이라고 한다.

1단계 도메인의 하위 도메인인 2단계 도메인(또는 서브 도메인, Sub domain)에는 조직의 속성을 구분하는 ‘co’(영리 기업), ‘go’(정부 기관), ‘ac’(대학)과 같은 도메인이 있다.

2단계 도메인 아래 3단계 도메인은 조직이나 서비스의 이름을 나타내는 도메인 이름으로 도메인 사용자가 원하는 문자열을 사용할 수 있다.

그리고 마지막은 컴퓨터의 이름을 나타내는 호스트(Host)가 위치한다.

도메인을 표기할 때는 낮은 단계부터 표현하여 최상위 도메인이 가장 뒤에 나타난다.

3. 담당 DNS 서버를 찾아 IP 주소를 가져온다.

액세스 대상의 웹 서버가 어느 DNS 서버에 등록되어있는지 찾아내는 방법을 알아보자.

사용자가 www.google.com을 입력하는 것을 예시로 알아보자.

예시

출처 : https://better-together.tistory.com/128?category=887984

사용자가 도메인 이름 www.google.com을 입력하면 사용자의 컴퓨터는 DNS 서버에 도메인 이름의 IP 주소를 찾는다.

- 로컬 DNS 확인 (캐싱)

브라우저에서 요청을 보내면 먼저 해당 컴퓨터에 있는 로컬 DNS (이미지의 DNS resolver)에서 hosts 파일에 해당 도메인의 IP 주소가 저장되어 있는지 찾아본다.

이미 로컬 DNS가 알고 있다면 (캐시 되어 있다면) IP 주소를 바로 응답한다.

- 루트 네임 서버 확인

로컬에 주소가 없으면 로컬 DNS는 먼저 루트 네임 서버에 IP 주소를 조회한다.

루트 네임 서버는 해당 도메인의 최상위 도메인 즉 여기서는 com 도메인을 관리하는 com 네임서버의 IP주소를 로컬 DNS에게 응답한다.

- com 네임 서버 확인

로컬 DNS 서버는 루트 네임 서버가 알려준 com 네임 서버의 IP 주소로 가서 www.google.com의 IP 주소를 조회한다.

com 네임 서버는 google.com 네임서버의 IP 주소를 응답한다.

- google.com 네임서버

이 google.com 네임 서버에는 요청한 도메인에 대한 IP 주소가 등록되어 있으므로 IP 주소를 클라이언트에게 회답한다.

위에서 아래로 DNS 서버를 따라가는 동작을 반복해서 원하는 DNS 서버에 도달하게 되고 클라이언트는 웹 서버의 IP 주소를 받아 거기에 액세스 할 수 있게 된다.

4. DNS 서버는 캐시 기능으로 빠르게 회답할 수 있다.

DNS 서버는 한 번 조사한 이름을 캐시에 기록할 수 있는데 조회한 이름에 해당하는 정보가 캐시에 있으면 그 정보를 회답한다.

그러면 그 위치에서 계층 구조를 아래로 향하여 찾을 수 있다.

이 때 캐시에 정보를 저장한 후 등록 정보가 변경되는 경우도 있으므로 캐시 안에 정보는 정확하다고 할 수 없다.


프로토콜 스택에 메시지 송신을 의뢰한다

1. 데이터 송수신 동작의 개요

IP 주소를 조사한 이후 IP 주소의 상대 (액세스 대상 웹 서버)에 메시지를 송신하도록 OS 내부에 있는 프로토콜 스택에 의뢰한다.

여기서도 마찬가지로 Socket 라이브러리에 들어있는 프로그램 부품을 이용한다.

소켓이란

소켓은 데이터의 출입구 역할을 한다. 데이터를 주고 받기 위해서 소켓을 만들고 열어 소켓에 데이터를 써보내거나 소켓으로부터 데이터를 읽을 수 있다.

즉 네트워크를 이용해 데이터를 송수신 하고 싶은 프로그램들은 소켓을 거쳐야한다.

아래 그림과 같은 위치에 소켓 레이어가 놓이게 된다.

소켓 레이어

출처 : https://bnzn2426.tistory.com/52?category=770232

즉 OSI 7 계층의 어플리케이션 계층(application Layer)에 존재하는 네트워크 응용 프로그램들은 데이터를 송수신 하기 위해 소켓을 거쳐 전송 계층(transport Layer)의 통신 망으로 전달함으로써 데이터를 송수신한다.

어플리케이션 계층

출처 : https://bnzn2426.tistory.com/52?category=770232


소켓의 종류 및 통신 흐름

  • 스트림 소켓 - TCP
    • 양방향으로 바이트 스트림을 전송한다. (연결형 소켓)
    • 오류 수정, 정송처리, 흐름제어 등 신뢰성 보장
    • 송신된 순서에 따라 중복되지않게 데이터를 수신
    • 대량 데이터 전송에 적합하다.
  • 데이터그램 소켓 - UDP
    • 비연결형소켓
    • 데이터 크기에 제한이 있다.
    • 전달이 보장되지 않는다.
    • 실시간 멀티미디어 정보를 처리하기 위해 주로 사용한다 ex) 전화

소켓의 송수신 동작 단계

소켓의 송수신 동작 단계

출처 : https://www.ibm.com/docs/en/zos/2.1.0?topic=internets-typical-client-server-program-flow-chart

  1. 소켓을 만든다 (소켓 작성 단계)
    • 서버
      • socket() 함수로 소켓을 생성한다.
      • bind() 함수로 ip와 port 번호를 설정한다.
    • 클라이언트
      • socket() 함수로 가장 먼저 소켓을 연다.
  2. 서버측의 소캣에 파이프를 연결한다. (접속 단계)
    • 서버
      • listen() 함수로 클라이언트의 접근 요청에 수신 대기열을 만들어 몇 개의 클라이언트를 대기시킬 지 결정한다.
      • accept() 함수로 클라이언트와의 연결을 기다린다.
    • 클라이언트
      • connect() 함수로 통신할 서버의 설정된 ip와 port 번호에 통신을 시도한다.
      • 통신 시도시 서버가 accept() 함수를 이용하여 클라이언트의 socket 디스크립터를 반환한다.
  3. 데이터를 송수신한다. (송수신 단계)
    • 클라이언트와 서버가 서로 send(), receive()를 하며 통신한다.
  4. 파이프를 분리하고 소켓을 말소한다. (연결 끊기 단계)
    • 서버에서 먼저 close를 호출하여 연결을 끊고 클라이언트가 이를 전달받으면 close() 함수를 호출한다.

2. 소켓의 작성 단계

  • 소켓 라이브러리의 socket이라는 프로그램 부품을 호출한다.
  • socket 내부에 제어가 넘어가서 소켓을 만드는 동작을 실행하고 끝나면 애플리케이션에 제어가 돌아온다.
  • 소켓이 생기면 디스크립터가 돌아와 애플리케이션은 이것을 받아 메모리에 기록한다.
  • 데이터 송수신 동작이 여러개일 경우 하나하나 소켓을 식별해야하는데 이 것을 디스크립터라고한다.

3. 파이프를 연결하는 접속 단계

  • 만든 소켓을 서버측 소켓에 접속하도록 프로토콜 스택에 의뢰한다.
  • 애플리케이션은 Socket 라이브러리의 connect를 호출하여 이 동작을 실행한다.
  • connect를 호출할 때 지정하는 값은 디스크립터, 서버의 IP주소, 포트 번호 이다.
  • connect가 디스크립터를 프로토콜 스택에 통지한다.
  • 프로토콜 스택이 통지받은 디스크립터를 보고 어느 소켓을 어느 서버의 소켓에 접속할지 판단하여 접속 동작을 실행한다.

4. 메시지를 주고받는 송수신 단계

  • HTTP 리퀘스트 메시지가 송신데이터이고 Socket 라이브러리의 write를 호출할 때 디스크립터와 송신 데이터를 지정한다.
  • 디스크립터로 소켓을 지정하여 연결 상대가 정해지면 목적지에 데이터를 송신한다.
  • 서버는 수신 동작을 실행하여 받은 데이터 내용을 조사하고 처리한후 응답 메시지를 반송한다.
  • 수신할 때는 Socket 라이브러리의 read를 호출하여 프로토콜 스택에 수신동작을 의뢰한다.
  • 수신한 응답메시지를 저장하기 위해 메모리 영역(수신 버퍼)을 지정한다.
  • 수신 버퍼의 메시지를 저장한 시점에 메시지를 애플리케이션에 건낸다.

5. 연결 끊기 단계에서 송수신이 종료된다.

  • HTTP 프로토콜에서는 응답 메시지의 송신이 완료되었을 때 서버에서 연결 끊기 동작을 실행하므로 웹 서버에서 Socket 라이브러리의 close를 호출하여 연결을 끊는다.
  • 클라이언트에 전달되어 클라이언트도 close를 호출하여 클라이언트 소켓이 연결 끊기 단계로 들어간다.
HTTP 통신과 SOCKET 통신
  • HTTP 통신
    • 클라이언트의 요청이 있을 때만 서버가 응답하여 해당 전보 전송 후 연결을 종료
    • 클라이언트가 요청을 보내는 경우에만 서버가 응답하는 단방향 통신이다.
    • 실시간 연결이 아닌 필요한 경우에만 서버로 요청을 보낼 때 사용한다.
  • SOCKET 통신
    • 클라이언트와 서버가 특정 포트를 통해 실시간으로 양방향 통신을 하는 방식이다.
    • 클라이언트와 서버가 계속 연결을 유지하는 양방향 통신이다.
This post is licensed under CC BY 4.0 by the author.