우리는 종종 브라우저에 naver.com, google.com 등을 입력하여 해당 포털 사이트로 이동한다.
평소에는 아무런 생각없이 이용했던 이런 작은 부분이 어떠한 단계를 걸쳐서 완성되는지 알아보려고 한다.
1. 브라우저의 주소 입력창에 google.com을 입력한다.
2. 브라우저는 google.com의 해당 IP주소를 찾기 위해 DNS 레코드의 캐시를 확인한다.
DNS(Domain Name System)은 웹사이트의 이름(URL)과 URL의 IP주소를 관리하는 데이터베이스이다. 모든 URL은 고유한 IP주소가 할당되어 있다. IP주소는 액세스를 요청하는 웹사이트의 서버를 호스팅 하는 컴퓨터라고 생각하면 쉽다.
DNS의 주요 목적은 사람들이 쉽게 사이트 주소를 찾을 수 있도록 도와주는 것이다. 왜냐하면 DNS가 없다면 내가 원하는 사이트에 접속하려면 해당 사이트의 IP 주소가 적혀있는 두꺼운 종이책 또는 서류에서 해당 IP를 찾아서 직접 입력해야 하기 때문이다.
DNS가 IP를 찾는 단계는 4단계로 이루어진다. (즉, 브라우저는 4번의 캐시 확인을 한다.)
- 1. DNS 쿼리는 우선 브라우저 캐시를 확인한다. 브라우저는 내가 이전에 방문한 웹사이트의 DNS 기록을 저장하고 있기 때문에 이를 활용 할 수 있다.
- 2. 브라우저는 OS의 캐시를 확인한다. 브라우저 캐시에 검색하는 DNS 레코드가 없다면, 브라우저가 내 컴퓨터 OS에 시스템 호출 (gethostname) 을 통해 DNS기록을 가져온다.
- 3. OS의 캐시에도 없으면 라우터 캐시를 확인한다. 브라우저는 라우터에서 DNS기록을 저장한 캐시를 확인한다.
- 4. 마지막으로, ISP 캐시를 확인한다. 만약 위의 모든 단계에서 DNS기록을 참지 못한다면 ISP에서 DNS기록을 찾는다. ISP는 (Internet Service Provider)는 DNS 서버를 가지고 있는데, 해당 서버에서 DNS기록 캐시를 검색할 수 있다.
* 캐시는 네트워크 트래픽을 규제하고 데이터 전송시간을 개선하는데 필수적이기 때문에 많이 유지되고 있다.
* DNS는 복잡하고 매우 빨라야하기 때문에 DNS데이터는 웹브라우저 사이의 서로 다른 계층과 인터넷의 다양한 위치에 임시로 저장된다. 즉, 캐시에 저장하게 되며 이러한 캐시는 브라우저 캐시, 운영체제 캐시, 라우터 캐시 ISP의 캐시 등이 있다.
3. 요청한 URL이 캐시에 없다면, ISP의 DNS서버가 DNS 쿼리로 해당 URL에 해당하는 서버의 IP주소를 찾는다.
만약, 웹브라우저가 캐시 계층에서 IP주소를 찾을 수 없는 경우 회사의 네트워크 또는 ISP의 DNS가 재귀적 DNS조회를 실행한다. 재귀적 DNS조회는 인터넷에 존재하는 여러 DNS 서버에 요청하여, 원하는 IP를 찾을 때까지 DNS 서버에 요청한다.
우리가 접하는 많은 웹사이트 URL은 주로 루트(Root) 도메인 -> 최상위 도메인 -> 2단계 도메인 -> 3단계 도메인 단계로 검색된다. 각 단계별로 DNS 조회 때 사용되는 해당하는 서버의 이름이 존재한다.
4. 웹 브라우저가 서버와의 TCP연결 시작
브라우저가 올바른 IP주소를 수신하면 해당 IP주소와 일치하는 서버와 연결을 시도한다. 주로 TCP 연결을 설정하고 HTTP를 통해 통신을 시작한다. 만약 여기서 HTTPS를 사용하는 경우 데이터의 암호화를 위해 TLS ( Transport Layer Security) 핸드 셰이크라는 추가 과정을 수행한다.
* TLS핸드쉐이크는 데이터 보안 통신에서 매우 중요한 주제임으로 나중에 따로 포스팅할 예정이다.
다시 본론으로 돌아와, 클라이언트와 서버 간의 데이터 패킷을 전송하기 위해 HTTP요청을 보내고 이 과정에서 TCP(전송 제어 프로토콜)을 사용한다. 즉 TCP 연결이 먼저 되어야 데이터 패킷 전송이 가능하기 때문에 TCP/IP 3-WAY Handshake연결 과정이 선행되어야한다. 이러한 3-WAY Handshake는 SYN(Synchronize: 연결 요청)과 ACK(Acknowledgement: 확인 / 승인) 메시지를 클라이언트와 서버가 교환하여 서로 연결되었음을 확인하는 단계를 거쳐서 진행된다.
- 3-WAY Handshake
1. 클라이언트는 DNS에 해당하는 서버의 IP를 찾은 후 해당 IP로 SYN패킷을 보내 연결이 가능한지 요청한다.
2. 서버에 새 연결을 수락할 수 있는 열린 포트가 있는 경우, SYN/ACK 패킷을 사용하여 SYN 패킷에 ACK(승인)으로 응답한다. SYN/ACK 패킷이 서버에서 클라이언트로 전송된다.
3. 서버로 부터 SYN/ACK 패킷을 전송받은 클라이언트는 패킷을 수신하고 ACK패킷을 서버에 다시 전송한다.
*STATUS
- closed: 닫힌 상태
- listen: 포트가 열린 상태 (연결 가능한 포트가 on)
- syn_rcv: syn요청을 받고 상대방의 응답(ack)을 기다리는 중
- established: 포트 연결 상태
* "netstat" 명령어를 통한 네트워크 (TCP/UDP) 상태를 확인하기
* netstat [-a] [-e] [-n] [-s] [-r] [-p proto] [interval]
-a : 컴퓨터에서 수신되어 활성화되어 있는 모든 TCP 및 UDP 포트를 표시
-r : 라우팅 테이블 확인 및 Connection 되어 있는 포트번호 확인
-n : 현재 다른 PC와 연결(Established) 되어 있는 포트번호 확인
-e : 랜카드에서 송수신한 패킷의 용량 및 종류 확인 (-s와 같이 사용한다.)
-s : IP, ICMP, TCP, UDP 프로토콜의 상태
* Activie Connections Display State
- LISTEN : 서버의 데몬이 떠서 접속 요청을 기다리는 상태
- SYS-SENT : 로컬의 클라이언트 애플리케이션이 원격 호스트에 연결을 요청한 상태
- SYN_RECEIVED : 서버가 원격 클라이언트로부터 접속 요구를 받아 클라이언트에게 응답했지만 아직 클라이언트에게 확인 메시지를 받지 않은 상태
- ESTABLISHED : 3 Way-Handshaking이 완료된 후 서로 연결된 상태
- FIN-WAIT1, CLOSE_WAIT, FIN-WAIT2 : 서버에서 연결을 종료하기 위해 클라이언트에게 종결을 요청하고 회신을 받아 종료하는 과정의 상태.
- CLOSING : 확인 메시지가 전송 도중 분실된 상태
- TIME-WAIT : 연결은 종료되었지만 분실되었을지 모를 느린 세그먼트를 위해 당분간 소켓을 열어놓은 상태
- CLOSED : 완전히 종료된 상태
5. 웹 브라우저가 HTTP 요청을 서버로 전송
웹 브라우저가 서버와 연결되면 HTTP 프로토콜을 통해 통신한다. 즉, 웹브라우저는 서버와 연결된 후 해당 페이지의 콘텐츠 요청을 하기 위해 서버에 HTTP 요청을 전송한다. HTTP 요청에는 요청 라인과 헤더가 있으며 요청 라인에는 HTTP 메서드가 포함된다.
예를 들면 GET /URL/123 HTTP/1.1 요청 라인에 대한 내용은 /URL/123에서 리소스를 가져오고 HTTP/1.1 통신을 원한다는 뜻이다. HTTP 메서드는 요청의 의미를 표현해준다. POST, PUT 또는 PATCH 메서드는 새 데이터를 생성하거나 기존 데이터를 업데이트하기 위한 목적이며, DELETE 메서드는 지정된 경로에서 리소스를 삭제하는 것을 의미한다.
다음으로 요청 헤더에서는 라우팅에 도움이 되는 추가 정보를 서버에 전달하고, 어떤 유형의 클라이언트가 요청을 수행하는지 나타낸다.
마지막으로 요청의 본문이다. 요청(request)에서의 본문은 보통 GET 요청에 대한 내용을 요청하기 때문에 비어있는 편이다. 하지만 POST, PUT 또는 PATCH와 같은 기존의 리소스를 조작하는 요청의 경우 기존의 리소스에 업데이트할 클라이언트 쪽에서 보내는 데이터가 포함된다. 요청 본문은 여러 형식일 수 있으나 서버는 요청 헤더의 Content-Type을 기반으로 형식을 이해한다.
요청 라인과 헤더가 있는 URL에 대한 전체 요청의 예시
GET /blog/1620 HTTP/1.1
Host: channy.creation.net
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
sec-ch-ua: " Not A;Brand";v="99", "Chromium";v="90", "Google Chrome";v="90"
sec-ch-ua-mobile: ?0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0(Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36(KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Referer: <https://channy.creation.net/>
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
dnt: 1
sec-gpc: 1
*HTTP 메서드 : GET / POST / PUT / PATCH / DELETE
6. 웹 서버가 요청(Request)을 처리하고 응답(Response)을 다시 전송
웹 서버는 요청을 받고 요청 라인, 헤더 및 본문의 정보를 기반으로 요청 처리 방법을 결정한다. 응답에는 다음과 같은 정보들이 포함된다.
- 클라이언트에게 요청 상태를 알려주는 상태 라인
- 브라우저에 응답 처리 방법을 알려주는 응답 헤더
- 해당 경로에서 요청된 리소스(HTML, CSS, Javascript, 이미지 파일과 같은 콘텐츠 또는 데이터)
상태 라인에는 HTTP버전과 요청 상태의 숫자 및 텍스트 표현이 모두 포함된다. 응답에 대한 내용의 예시는 다음과 같다.
HTTP/1.1 200 OK
Date: Tue, 25 May 2021 19:40:59 GMT
Server: Apache
X-Frame-Options: SAMEORIGIN
X-Powered-By: Express
Cache-Control: max-age=0, no-cache
Content-Type: text/html; charset=utf-8
Vary: Accept-Encoding
X-Mod-Pagespeed: 1.13.35.2-0
Content-Encoding: br
Keep-Alive: timeout=1, max=100
Connection: Keep-Alive
Transfer-Encoding: chunked
<!DOCTYPE html>
<html lang="ko">
<head>
나머지 HTML 항목
웹 브라우저는 HTTP 상태 코드를 판별하여 성공/실패 또는 다양한 에러를 나타낸다. 위에서의 상태 코드는 200으로 브라우저는 성공으로 판단하고 응답을 랜더링 한다.
전송받은 리소스는 텍스트 또는 텍스트가 아닌 정적 파일과 같은 데이터일 수 있다. 대부분의 웹 서버는 동적 리소를 생성하여 코드, 탬플릿 등을 통해 HTML을 구축하고 동적 데이터와 결합하여 응답으로 텍스트를 다시 전송하여 웹 브라우저가 이를 렌더링 하게 한다.
7. 웹 브라우저가 응답받은 콘텐츠 렌더링
웹 브라우저가 서버로부터 응답을 받으면 응답 헤더를 검사하여 리소스 렌더링에 관한 정보를 확인한다. 위의 응답 코드를 보면 CONTENT-TYPE 헤더는 브라우저에 응답 본문에서 HTML 리소스를 수신했음을 알려주고 있다. 즉 브라우저는 HTML로 페이지를 표현하면 된다.
즉, HTML 골격을 렌더링하고 이후 HTML 태그를 확인하여 정적 데이터, CSS, JS 파일 등과 같은 요소에 대한 GET 요청을 보낸다. 이러한 모든 데이터가 종합적으로 표현되어 최종적으로 사용자에게 보이게 되는 것이다.
8. 마무리
웹 브라우저에 URL을 입력했을 때, 일어나는 일들을 간단하게 알아보았다. 위의 과정을 간단하게 정리해보자면
1. 웹 브라우저에 URL을 입력하고 ENTER을 누른다.
2. 웹 브라우저가 도메인의 IP주소를 조회한다. ( 4단계 거쳐서 캐시를 찾고 이후 DNS를 검색한다.)
3. 웹 브라우저가 찾은 IP 주소를 기반으로 서버와 TCP 연결을 시작한다.
4. 웹 브라우저가 HTTP 요청을 서버로 전송한다. (혹은 HTTPS)
5. 웹 서버가 요청을 처리하고 응답을 다시 웹 브라우저로 전송된다. (요청과 응답이 어떻게 구성되어있는지 확인)
6. 웹 브라우저가 전송받은 콘텐츠를 렌더링 한다.
댓글