[네트워크 원리] 웹 브라우저가 메시지를 만들어 서버에 보내는 과정 (1)
Network

[네트워크 원리] 웹 브라우저가 메시지를 만들어 서버에 보내는 과정 (1)

이 글은 성공과 실패를 결정하는 1%의 네트워크 원리라는 도서를 읽고 학습한 내용을 정리한 글입니다.

 

들어가며

브라우저에 접속해서 url을 입력하고 검색했을 때, 어떻게 원하는 결과가 화면에 보이는 걸까?

이번 포스팅에서는 브라우저에 URL을 입력한 순간부터 DNS 서버를 통해 IP를 조회하는 과정에 대해 알아보려고 한다.

 

요약

먼저 이 주제의 전체 포스팅에서 다룰 내용을 전반적으로 요약해보면 다음과 같다.
브라우저에 URL을 입력하면, 그 URL을 해독하는 곳부터 브라우저의 동작이 시작된다.
이는 URL을 해독하여 HTTP Request 메시지를 작성하는 과정을 의미한다. 작성된 HTTP 리퀘스트 메시지를 OS를 통해 웹 서버에 송신해야하는데, 이 때 메시지를 넘기기 위해서는 상대의 IP 주소를 OS에게 알려주어야한다. 따라서 HTTP 리퀘스트 메시지로부터 IP 주소를 알아내기 위한 작업을 DNS 서버에 의뢰한다. DNS 서버는 URL에 적힌 웹 서버의 도메인명을 활용해 IP 주소를 조사하고 응답한다. 조회된 IP 주소로 앞서 만든 HTTP 메시지를 송신하고, 그 결과를 수신하는 작업을 수행한다.

 

URL을 해독해보자.

브라우저에 URL을 입력하면, 가장 첫번째로 URL을 해독하는 작업을 수행한다. 먼저 URL에 대해 알아보자면,

URL은 http://, file://, mailto://로 시작하는 것 등 여러가지가 있다. 이 URL은 다음과 같이 구성되어있다.

http://user:password@www.cyber.co.kr:80/dir/file.html
  • http://: 프로토콜 명칭
  • user:password: 사용자명과 패스워드, 생략 가능
  • www.cyber.co.kr: 웹 서버의 도메인명
  • /dir/file.html: 파일의 경로명

 

브라우저에 URL을 입력하면, 브라우저는 먼저 이 URL을 해독한다. URL의 요소는 위에서 나타낸 것과 같이 구성되어있음을 알고, URL을 해독해보면 다음과 같다.

URL: http://www.lab.cyber.co.kr/dir/file.html

해독: http: + // + www.lab.cyber.co.kr + /dir/file.html
     (1)     (2)       (3)                   (4)

(1): 데이터 출처에 엑세스하는 방법, 프로토콜

(2): // 뒤에 이어지는 문자열이 서버의 이름임을 나타낸다.

(3): 웹 서버명

(4): 데이터 출처의 경로명

 

이렇게 URL 해독 작업을 통해 어디에 액세스해야하는 지를 알 수 있다. 이후, 브라우저는 HTTP 프로토콜을 사용해 웹 서버에 액세스하는데, 이 때 HTTP 프로토콜을 활용하기 위해서는 리퀘스트 메시지를 만들어야한다. 리퀘스트 메시지 안에는 무엇을, 어떻게 하겠다는 내용이 적혀있다. 즉, 우리는 HTTP 프로토콜과 URL 해독작업을 통해서 무엇을, 어디에, 어떻게 액세스할 것인지에 대한 정보를 전달할 수 있다.

 

'무엇을'에 해당하는 것을 URI라고 하는데, 이 URI는 페이지의 데이터를 저장한 파일의 이름을 쓴다.

'어떻게'에 해당하는 HTTP Method의 종류에 대해서는 이 글에서 다루지 않을 생각이다. 더 자세한 HTTP Method에 관한 정보를 알고 싶다면 이 글을 참고하기 바란다.

 

이렇게, URL을 해독하고 웹 서버와 파일명을 판단하면 브라우저는 이것을 바탕으로 HTTP 리퀘스트 메시지를 만든다. HTTP 메시지는 포맷이 결정되어있으므로 브라우저는 이 포맷에 맞게 리퀘스트 메시지를 만든다.

 

HTTP Request 메시지를 만들어보자.

 

이미지는 구글 서치를 통해 가져왔습니다. 출처를 알려주시면 표기하겠습니다.

HTTP Request는 위와 같은 포맷을 가진다.

맨 첫번째 줄을 Request Line이라고 부른다. Request Line에는 HTTP Method와, URI 그리고 프로토콜의 버전을 한 칸 띄어쓰기로 구분해 명시한다. GET 요청의 경우 QueryString을 포함할 수 있다. 이 쿼리 스트링은 URI 뒤 ?와 함께 나타난다. 예시를 들자면 다음과 같다.

 

GET /login?id=joanne&password=1234 HTTP/1.1

 

Request Line 다음 줄부터, 빈 행이 나올 때까지를 Request Headers라고 부른다. Request Headers에는 다양한 정보들을 명시할 수 있는데, 대표적으로 몇가지 예시를 들어보자면 현재 요청을 보내는 host가 누구인지, Accept를 통해 포함된 자원의 타입이 어떤 것들인지를 나타낼 수 있다. POST 요청의 경우에는 정보를 담을 때 쿼리스트링 대신 바디를 이용한다. 이 바디의 정보는 Request Headers의 빈 행 다음에 나타나게 되는데, 이 값이 존재하는지를 확인하기 위해서는 header의 Content-Length를 통해 알 수 있다. Content-Length는 명시된 길이 만큼의 body 내용을 갖고 있다는 것을 나타낸다.

 

HTTP Response는 위와 같은 포맷을 가진다.

맨 첫번째 줄은 Status Line이라고 하며, 프로토콜의 버전과 HTTP 상태 코드, 메시지를 담는다. HTTP 상태 코드는 여러가지가 존재하는데, 간단히 구분하자면 다음과 같고, 자세한 내용은 여기서 확인할 수 있다.

1xx: 처리의 경과 상황 등의 통지
2xx: 정상 종료
3xx: 무언가 다른 조치가 필요함 (redirect 등)
4xx: 클라이언트측의 오류
5xx: 서버측의 오류

Status Line의 다음줄부터는 Response Headers 내용을 담고 있다. 이는 HTTP Request의 Request Headers와 유사하다. 여기서의 Content-Length 또한 body의 바이트크기를 나타내는데, 리소스를 담고 있는 경우 해당 리소스를 읽어들인 바이트 사이즈와 같다.

 

HTTP 요청/응답과 관련된 포맷에 대해 자세히 알고 싶다면 이 글을 참고하면 좋다.

 

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

이제 HTTP Request를 만들었다면, 이 Request를 웹 서버로 보내 적절한 응답을 받아야한다. 브라우저는 URL을 해독하고 HTTP 메시지를 만들 순 있지만, 메시지를 네트워크로 송출하는 기능은 없기 때문에 OS에 위임하여 이 작업을 수행해야한다. OS에 송신을 의뢰할 때에는 도메인명이 아니라 IP 주소로 메시지를 받을 상대를 직접 지정해야한다. 이 IP 주소를 알아내기 위해서 앞서 URL로부터 해독했던 웹 서버의 도메인명을 이용한다. 어딘가에 이 도메인명을 전달하고, 이 도메인명에 연결되어있는 IP 주소를 받아내야한다.

 

IP 주소를 조사하는 방법은 (말로는) 간단하다. 가장 가까운 DNS 서버에 "'joanne.tistory.com'이라는 서버의 IP 주소를 가르쳐 주세요😎" 라고 질문하면 된다. 그러면, DNS 서버가 "joanne.tistory.com의 IP 주소는 1.2.3.4입니다."라는 식으로 가르쳐준다. 그럼 끝이다.

 

여기서 가장 포인트는, 브라우저는 어떻게 DNS 서버에 IP 조회 요청을 보낼 수 있을까? 라고 생각한다.

그 과정에 대해 자세히 알아보자.

 

먼저 DNS란, Domain Name System으로서 서버명과 IP주소를 대응시키기 위해 사용하는 시스템이다. 서버명과 IP주소를 대응시키는 데에 가장 많이 사용되지만, 메일 주소와 메일 서버를 대응시키는 것 등 다양한 정보를 이름에 대응해서 등록할 수 있다.

DNS 서버에 조회한다는 것은 DNS 서버에 조회 메시지를 보내고, 거기에서 반송되는 응답 메시지를 받는 것이다. 즉, DNS 서버에 대해 클라이언트로 동작해 응답 메시지를 전달받는 것이다. 이 DNS 클라이언트에 해당하는 것을 DNS 리졸버라고 부른다. 그리고 DNS의 원리를 사용해 IP 주소를 조사하는 것을 name resolution이라고 한다.

 

리졸버가 DNS 서버에 IP 주소 조회를 요청해 응답받는 과정은 다음과 같다.

1. 애플리케이션에서 리졸버를 호출하면, 제어가 리졸버로 넘어간다.

2. 리졸버에 제어가 넘어가면 DNS 서버에 문의하기 위한 메시지를 만든다. (이는 HTTP 메시지를 만드는 것과 유사하다)

3. 메시지가 만들어진 뒤 DNS서버에 해당 메시지를 송신한다. 이 송신 동작은 리졸버 스스로 하는 것이 아닌, OS의 프로토콜 스택에게 의뢰하는데 이 과정은 다음 글에서 자세히 다룰 생각이다.

4. 리졸버가 만든 메시지를 DNS 서버에 송신하면, DNS 서버는 메시지에 쓰여있는 내용을 조사해 답을 찾아 반송한다.

5. 반송된 데이터를 리졸버가 해독한 뒤, 여기서 IP 주소를 추출한다.

6. 애플리케이션에게 추출한 IP 주소를 건네줌으로서 과정이 마무리된다.

 

DNS 서버에 송신하는 조회 메시지에는 다음과 같은 정보가 포함되어있다.

(a) 이름: 서버나 메일 배송 목적지

(b) 클래스: 인터넷을 나타내는 IN

(c) 타입: 어떤 타입의 정보가 지원되는지 (A이면 IP, MX이면 메일 등)

 

이 정보를 바탕으로 a,b,c가 일치하는 레코드를 찾아 해당하는 IP를 회답한다.

 

그렇다면, 내가 요청한 도메인의 IP 주소를 갖고 있는 DNS 서버를 어떻게 찾을 수 있을까?

 

잘 설명된 이미지를 찾다 보니 opentutorials의 이미지를 참고하면 좋을 것 같아 인용하게 되었다.

opentutorials의 예시를 들자면,

(1) www.opentutorials.org의 IP 주소를 알아내기 위해서 사용자에게 가장 가까운 곳에 위치한 DNS에 www.opentutorials.org의 IP 조회를 요청한다.

(2) 가장 가까운 DNS 서버가 알고 있다면 IP 주소를 회답한다.

(3) 하지만 IP 주소를 모르면 루트 도메인 네임 서버에 조회를 요청한다.

(4) www.opentutorials는 최상위 도메인이 .org인 것을 보고, .org가 등록된 네임 서버의 IP를 전달한다.

  • 여기서 루트 도메인은 www.opentutorials.org 뒤에는 www.opentutorials.org. 과 같이 루트 도메인인 .이 숨어있다. 따라서 모든 도메인의 최상위 도메인이라고 생각할 수 있다.

(5) 루트 도메인이 .org가 등록된 네임 서버의 IP를 전달하는 것은 .org 네임서버로 가서 IP 조회를 요청해봐! 와 같은 의미로 해석할 수 있다.

(6) 그리고 다시 org를 관리하는 네임 서버에게 문의하면, opentutorials의 네임 서버 IP 주소를 알려준다. 이렇게 차차 하위 도메인으로 내려오면서 최종적으로 www.opentutorials.org의 IP 주소를 알 수 있다.

 

마치며

다시 한번 요약하자면, 우리가 브라우저에 URL을 입력하면 브라우저는 해당 URL을 해독해 HTTP Request 메시지를 만들고, 그 메시지를 바탕으로 OS에게 송신을 의뢰한다. 이 때, 송신 시에는 웹 서버의 IP 주소가 필요하므로 HTTP Request의 웹 서버 도메인명을 바탕으로 DNS 리졸버를 통해 DNS 서버에 IP 주소 조회를 요청한다. 그리고 DNS 서버로부터 IP 주소를 응답받는다.

 

이제 다음 과정은 응답받은 IP 주소를 바탕으로 실제 웹 서버에 HTTP Request를 송신하고, 결과를 응답받아야할 것이다. 그 과정에 대해서는 다음 포스팅에서 알아보자.

 

끗!