김맥스 블로그

브라우저 주소창에 URL을 치면 일어나는 일들

패킷의 길고도 짧은 여행

최근에 컴퓨터 네트워크 공부를 다시 하면서 "브라우저 주소창에 URL을 치면 일어나는 일을 아는대로 말 하기"라는 웹 개발자 면접 단골 질문에 대해 다시 생각해보게 되었습니다. 해당 질문을 면접에서 받았을 때 어느정도 깊이로 말하는게 좋을까 생각했습니다만 한편으로는, 깊이와 상관없이 그냥 브라우저가 웹 화면을 띄우는 과정들을 그냥 다 알아보면 어떨까 싶어서 정리해 봤습니다.

몇몇 프론트엔드 기술 면접 독스에 있는 내용보다 살짝 매운맛이다-라고 생각하고 보시면 좋을 것 같습니다. 이것까지 아실 필요 없을수도 있고요 더 자세하게 정리합니다.

패킷의 길고도 짧은 여행

어떻게 클라이언트의 HTTP 요청 메시지가 서버에 전송되고, 이걸 받은 서버의 HTTP 응답 메시지가 클라이언트에 전송되는지, 그리고 브라우저가 컨텐츠를 표시하는데까지의 모든 과정을 번호순으로 정리해 보았습니다. 조금 자세하지 못하게 요약된 부분도 있기도 해서 관련 레퍼런스, 이미지와 함께 설명하도록 하겠습니다.

1. 브라우저가 주소창에 입력된 URL을 해석한다

주소창에 주소를 치면, 브라우저가 URL을 해독해서 원격지에서 조회할 웹 서버와 파일명, 포트번호(웹서버는 기본적으로 80)을 판단하고 실제 HTTP 메시지 포맷에 맞게 GET 리퀘스트 메시지를 작성할 준비를 합니다.

크롬 브라우저의 경우 브라우저 애플리케이션의 최상위 프로세스인 브라우저 프로세스의 UI 스레드가 주소창에 입력된 입력값을 평가한다고 합니다. 크롬 주소창은 검색창의 역할도 하니 주소창에 친 문자열이 URL인지 검색어인지도 검사합니다.

2. 브라우저가 HTTP GET 요청 메시지를 작성한다

URL에서 해석한 정보를 바탕으로 해당 자원을 취할 수 있고 HTTP 메시지 포맷에 맞는 상태라인, 헤더, 바디를 가지고있는 GET 리퀘스트 메시지를 작성합니다.

3. 브라우저가 DNS 요청을 OS에 의뢰하고 실행한다

이미지 출처

DNS 계층

DNS(Domain Name System)는 도메인 주소와 IP 주소를 대응시키기 위한 서버입니다. 인터넷 세상에는 막대한 수의 서버가 있기 때문에 이것을 전부 1대의 DNS 서버에 등록하는 것은 불가능합니다. 도메인을 .으로 분리하여 계층화된 도메인 정보를 DNS 서버에 정보를 분산시켜 다수의 DNS 서버에 등록합니다. 그리고 DNS 조회 요청이 오면 URL에 해당하는 부분을 따라가며 다수의 DNS 서버가 연대하여 정보가 어디에 등록되어있는지를 찾아내는 구조를 가지고 있습니다.

DNS 요청의 프로토콜은 UDP이고, DNS 서버의 IP 주소는 컴퓨터의 TCP/IP 설정 항목 중 하나라 OS가 이미 알고 있습니다. 엑세스 대상의 웹 서버가 DNS에 등록되어 있으면 IP 주소를 포함한 응답이 오고, 응답은 OS의 DNS 리졸버가 내용을 해석한 후 IP 주소를 추출하여 메모리에 저장하고 브라우저의 프로세스가 접근 할 수 있게 합니다.

브라우저는 직접 네트워크 요청을 할 수 없습니다. DNS 요청을 포함한 모든 네트워크 요청은 OS에 의뢰해서 진행합니다.

4. 브라우저가 OS의 프로토콜 스택에 메시지 송신을 의뢰하고 소켓을 작성한다

이미지 출처

TCP/IP

TCP/IP에 사용되는 프로토콜 스택의 실제 구현체는 OS단에 존재합니다.

소켓은 두 단말의 통신 동작을 제어하기 위한 제어 정보의 총체입니다. 통신 제어 정보를 기록하는 메모리 영역을 가리키는 말이기도 합니다. 뭔가 하드웨어적인 개념에 더 가까울 것이라 생각했는데 생각보다는 아니었던 것 같습니다.

클라이언트에서는 DNS조회로 IP 주소를 알아내면 지정된 포트 번호는 서버측 컴퓨터의 프로세스를 특정하기 때문에 서버측 컴퓨터의 어떤 소켓과 접속할지를 지정할 수 있습니다.

통신 종단점의 두 소켓은 파이프로 읽기 쓰기 동작을 거듭하며 데이터를 주고받게 됩니다. OS에서는 소켓이 만들어지면 메모리 영역을 확보하고, 고유한 파일 디스크립터를 통해 소켓을 식별하게 됩니다.

5. TCP 프로토콜 스택은 Three-Way Handshake를 통해 서버와의 연결을 설립한다

이미지 출처

3-way-handshake

TCP 프로토콜은 Three-Way Handshake 악수를 통해 SYN과 ACK 비트를 주고받으면서 각 단말이 통신이 가능한 상태인지 확인합니다. 과정을 간단히 설명하면 다음과 같습니다.

  1. 처음에 송신처에서 접속 요청 프로세스가 SYN 비트를 1로 만들어 연결 메시지를 전송합니다.
  2. TCP 헤더를 받은 서버는 포트 번호에 해당하는 소켓을 찾고 필요한 정보를 기록해서 접속 동작이 진행됩니다. 서버가 요청을 수락하면 수신처도 SYN 비트를 1, ACK를 1 만들어서 재전송합니다.
  3. 서버에서 돌아오는 헤더를 받은 프로세스에서는 SYN이 1이면 접속 성공으로 소켓의 서버 IP 주소나 포트 번호등과 함께 소켓에 접속 완료를 나타내는 제어 정보를 기록합니다.
  4. 마지막으로 클라이언트는 패킷을 받았다는 것을 알리기 위해 ACK 비트를 1로 만든 TCP 헤더를 반송합니다.

만약 통신 프로토콜이 https라면 https(TLS) 핸드쉐이크도 TCP 핸드쉐이크에 이어서 진행합니다.

6. TCP 프로토콜 스택에서 패킷을 만들고 TCP 헤더를 붙인다.

이미지 출처

패킷

여기서부터는 OSI 4 계층, 전송 계층의 시작점입니다.

핸드쉐이크를 통해 접속이 성립되었으면 서버로 보내야 하는 데이터(HTTP 메시지)를 TCP로 보낼 수 있는 최대치(MSS)에 맞춰 데이터를 알맞게 자르고 자른 데이터들마다 TCP 헤더를 붙여 몇번째 데이터인지 등등 제어 정보(TCP 헤더)를 덧붙입니다. 첫번째로 데이터를 조각낸 패킷을 만듭니다.

TCP 헤더의 주요한 정보들로는 송수신처의 포트 번호, 데이터 오프셋(데이터의 시작지점), ACK 번호, 6비트짜리 컨트롤 비트(URG, ACK, FIN, SYN, PSH, RST)가 있습니다.

7. IP 프로토콜 스택은 패킷을 더 잘게 나누고 원격지의 MAC 주소를 기반으로 한 MAC 헤더를 붙인다

TCP에서 만든 패킷의 기본적인 단위들을 회선과 네트워크 상황에 맞게 MTU를 기반으로 더 잘게 나누고 더 잘게 나눠진 패킷들에 IP 헤더를 붙입니다. 그런데 단말이 소통하려면 IP주소 뿐 아니라 단말이 가진 네트워크 인터페이스(LAN카드)의 고유한 MAC 주소가 필요합니다.

ARP(Address Resolution Protocol)는 IP 주소를 기반으로 MAC주소를 알아오는 역할을 합니다. ARP는 일단 먼저 같은 네트워크 내부에서 브로드캐스트로 요청을 보내서 원격지 서버가 네트워크 내부에 있으면 해당 단말의 MAC 주소를, 외부에 있으면 네트워크 라우터의 MAC 주소를 가져옵니다. 알아낸 주소를 토대로 MAC 헤더를 패킷들마다 만들어 붙입니다.

IP 헤더의 주요 정보로는 수신처 IP 주소, 4계층 프로토콜 종류, 송신처 IP 주소, 플래그(패킷이 조각으로 나뉜 것인지, 조각으로 나누는 것이 가능한지), 프래그먼트 오프셋(이 패킷의 데이터 부분이 메시지의 맨 앞부분부터 몇번째 바이트인지 나타냄) 등이 있습니다.

8. LAN 어댑터를 통해 바이너리 데이터를 전기신호로 바꾼다

송신측에서 패킷 읽을 타이밍을 잡을 때 쓰는 프리앰블 비트, 패킷의 개시 위치가 어디서부터인지를 알게 해주는 비트, 패킷 오류 검출을 위한 FCS 비트 등 데이터를 추가하여 이진 데이터를 전기신호로 바꿉니다.

그렇지만 아시다시피 LAN 어댑터가 컴퓨터에 무조건 꽂혀있어야만 인터넷을 사용할 수 있는 것은 아닙니다. Wifi나 핸드폰 데이터를 사용한 무선 통신으로도 인터넷을 이용할 수 있는데요.

  1. Wifi 공유기를 사용하는 경우 : 공유기는 IP 주소 하나를 여러 대의 컴퓨터가 공유해서 인터넷에 접속할 수 있도록 하는 기기입니다. 공유기도 LAN 어댑터가 꽂혀 있습니다. 와이파이를 사용하는 각 단말들은 무선 근거리 통신으로 공유기에 전기신호를 보내고, 공유기를 통해서 LAN 어댑터로 신호가 나갑니다.
  2. 스마트폰 데이터로 접속하는 경우 : 가장 가까운 기지국으로 전기 신호를 보내고, 기지국은 초고속 유선망과 연결되어 있습니다.

9. 원격지의 MAC 주소로 전기 신호를 송출한다.

전기 신호를 LAN 케이블을 통해 송출합니다. 데이터가 집 밖으로 나가는 순간입니다. 이때 원격지가 대역폭이 다른 외부 네트워크라면 패킷은 네트워크의 라우터로, 대역폭이 같은 내부 네트워크라면 해당 원격지로 전송됩니다.

전기 신호가 같은 네트워크 내부를 돌면서 원격지 서버를 찾아갈 때, 스위치라는 2계층 장비를 만날 수 있습니다. 스위치 하나에 여러개의 단말이 붙어있는 꼴이고, 이 스위치들을 모아 네트워크를 만들 수 있습니다. 스위치는 패킷의 맨 끝의 FCS를 대조하여 패킷 오류의 유무를 검사하기도 하고, 맥 주소 테이블을 통해 해당 스위치에 붙은 단말이 패킷의 목적지인지 검사합니다.

스위치는 연결된 단말들의 모든 MAC 주소를 알고 있어 원래 브로드캐스팅이라 이론적으로는 모든 단말에 닿아야 하는 ARP 요청 같은 것들도 스위치에서 알아서 걸러줍니다.

N계층 장비라는 말이 자주 나오는데, 위에서 패킷에 계층별로 헤더를 붙였던 동작을 설명한 것처럼 헤더와 같은 제어 정보들을 N계층까지 확인할 수 있는 장비들을 말합니다. 2계층 장비인 스위치는 MAC헤더의 정보를 확인해볼 수 있고 3계층 장비인 라우터는 MAC헤더와 더불어 IP헤더의 정보를 확인할 수 있는 식입니다. 패킷을 어디까지 까 볼수 있느냐의 차이입니다.

10. 패킷의 목적지가 외부 네트워크이면 네트워크의 라우터에 패킷이 도달한다.

이미지 출처

서브넷 구조도

라우터에 도착한 패킷은 연결된 포트를 통해 다른 네트워크에 존재하는 원격지 MAC 주소를 알아내기 위해 ARP를 원격지에 요청하고 라우팅 테이블을 뒤져서 패킷을 중개하기 위한 경로를 탐색하고 전기 신호를 송신합니다.

라우팅 테이블은 수신처의 정보(IP주소, 서브넷 마스크, 게이트웨이)와 수신처까지의 거리 등의 정보를 기록하는 표입니다. 라우터는 이 항목에 등록되어있는 IP 주소와 수신한 패킷의 수신처 IP를 비교하여 패킷을 어디로 보낼지 최적의 경로를 찾아줍니다. 이때 라우터는 회선 상황에 맞춰 패킷을 더 나누거나 하기도 합니다.

11. 엑세스 회선, 인터넷 접속용 라우터를 통과하여 인터넷의 내부로 중개된다.

라우터를 나간 패킷은 인터넷의 엑세스 회선을 통과하며 장거리 통신에 적합한 형태로 변형되고, 추가적인 제어 정보를 붙여 인터넷에 내부로 중계됩니다. 엑세스 회선의 종류에 따라 세부 동작이 다른데, FTTH 엑세스 회선을 쓸 경우 광섬유, 광통신에 알맞는 형태로 변형됩니다.

이 단계에서 전기 신호는 건물의 옥내 배선을 지나 전신주의 전화 케이블로 들어가게 됩니다. 전신주를 타고 이 전기 신호들은 통신사의 전화국으로 들어가고, 거기서 또 인터넷 접속용 라우터를 거쳐 인터넷의 내부로 중계되기 시작합니다.

12. 인터넷 내부에서의 패킷 흐름

이미지 출처

인터넷

인터넷의 실체는 한 개의 조직이 운영하는 단일 네트워크가 아니라 다수의 프로바이더(인터넷 사업자)가 네트워크를 서로 접속한 것입니다.

ADSL이나 FTTH의 엑세스 회선은 사용자가 계약한 프로바이더의 설비에 연결되어 있습니다. 통신사 인터넷에 가입하면 이런 통신사 설비에 연결된 고유한 IP주소와 회선을 얻을 수 있죠. 쉽게는 여러 통신사의 무수한 라우터들이 인터넷을 이루고 있다고 생각할 수 있습니다.

여러 프로바이더의 여러 라우팅 장비들을 거치면서 최종적으로 목적지 서버가 포함된 네트워크의 라우터를 거쳐 해당 목적지 웹 서버의 단말로 패킷이 도착합니다.

통신사들의 여러 프로바이더들을 거치면서 전기 신호는 해저 케이블을 통해 바다를 건너기도 하고, 지구를 한 바퀴 이상 돌기도 합니다(ㄷㄷ)

13. 웹 서버로 전기 신호가 도착한 이후의 동작

전기신호를 받은 웹 서버의 LAN 어댑터가 전기 신호를 이진 데이터로 바꿉니다. 네트워크 인터페이스에서 수신된 패킷의 MAC 주소를 비교하고 FCS로 패킷 훼손이 없는지 판단하여 올바른 패킷일 경우 운영체제단의 프로토콜 스택으로 올려보냅니다.

프로토콜 스택의 IP 담당 부분에서는 IP 헤더를 바탕으로 잘려서 온 패킷을 다시 리어셈블링하고 IP주소가 제대로 된게 맞는지 판단한 후 문제가 없으면 TCP 담당 부분으로 전달합니다. 이때 패킷 IP 헤더의 플래그, 오프셋 항목을 참조합니다.

TCP 담당 부분은 TCP헤더를 토대로 데이터가 잘려있는 패킷들을 다시 완성된 데이터로 만들고 해당 패킷을 잘 받았다면 클라이언트에 수신 확인 응답용 ACK 번호를 반송합니다. TCP 헤더의 시퀀스 번호를 참조합니다.

완성된 데이터를 만들었으면 제어 정보와 포트 번호를 토대로 TCP Handshake를 할 때 만들어놓은 적합한 소켓을 찾습니다.완성된 데이터를 소켓에 기록해 애플리케이션의 프로세스에 건내줍니다.

이 과정이 네트워크 계층을 올라가면서 전기 신호를 바탕으로 조각난 패킷과 헤더 정보를 바탕으로 클라이언트에서 발송한 데이터를 재조립하는 디캡슐레이션 동작입니다.

14. 서버 어플리케이션은 완성된 요청 메시지를 받고, 응답 메시지를 작성한다.

서버 애플리케이션이 http 요청 메시지를 받으면, 요청 URI를 실제 서버의 파일 시스템에서의 URI로 바꿔 해당되는 html자원을 찾아 바디에 넣은 후 리스폰스 헤더와 함께 응답 메시지를 작성합니다. 엔드포인트와 웹서버의 디렉토리는 차이가 있을 수 있기 때문에 서버에서 올바르게 찾아주는 과정이 필요합니다.

클라이언트가 요청하는 과정을 앞에서 다 설명한 것처럼, 서버도 똑같이 프로토콜 스택을 다시 내려가며 패킷 처리를 하고 인터넷과 라우터들을 거쳐 다시 응답 메시지를 클라이언트에게 반송합니다.

15. 응답 메시지를 받은 클라이언트 브라우저의 동작

클라이언트의 브라우저는 HTTP 메시지의 content-type 헤더를 보고 응답 데이터가 html임을 알아냅니다. 이를 바탕으로 브라우저가 화면 표시 동작을 실행합니다. 화면 표시는 브라우저 프로세스의 렌더러 스레드가 담당합니다.

브라우저는 HTML을 파싱하여 Critical Rendering Path를 거쳐 해석된 html을 화면에 띄우고, 파싱하다가 script나 link태그를 만나면 렌더링을 중단하고 JS, CSS등의 자원 역시 위에서 설명한 똑같은 과정을 거쳐 서버에 요청합니다.

HTML 이외의 자원들을 위와 똑같은 과정을 거쳐서 서버에서 받아 역시 또 critical rendering path를 거쳐 CSS를 적용하고 JS를 해석하여 실행시켜 완성된 웹 페이지를 브라우저 위에 띄웁니다.

16. 요청이 종료되었다면 4-Way-Handshake를 통해 접속을 끊고 소켓을 말소한다.

데이터 송수신 과정이 끝났다면 접속을 끊기 위해 4-way-handshake를 실시합니다.

  1. 요청-응답이 완료되었다면 서버측에서는 TCP 헤더의 FIN비트에 1을 설정해 연결이 끝났음을 클라이언트에게 알립니다. 2. 클라이언트는 FIN 비트를 받아 서버측이 소켓 연결을 해제하고 있음을 알고 ACK 번호를 다시 서버측에 반송합니다.
  2. 클라이언트는 이때 서버에서 보낸 데이터를 모두 수신완료했다는 사실을 어플리케이션에게 알리고 데이터 송수신 동작을 정리합니다.
  3. 클라이언트 측의 프로토콜 스택이 FIN 1 TCP 헤더를 만들어 서버에 송신한 후 서버에서 ACK가 돌아오면 서버와의 접속이 종료됩니다. 이후 소켓을 말소합니다.

HTTP 1.1부터 도입된 keep-alive 때문에 요청이 끝났더라도 바로 커넥션이 종료되지 않는게 일반적입니다. keep-alive timeout 설정이 지나고 난 후에 서버-클라이언트간 접속이 끊어지고 소켓이 만료됩니다.

맺는말

패킷의 여정을 집요하게 탐구하며 정리했습니다. 이마저도 과정 위주로 정리하느라 세부적인 기기나 개념에 대해서는 생략된 부분들이 많은 편입니다.

저도 과정 전체와 기기들에 역할을 모두 다 이해하지는 못했지만 그래도 이 정도만 알면 일단 웹 개발자로서 알아야 하는 네트워크 통신의 큰 그림 정도는 정리할 수 있지 않나.. 조심스럽게 생각해봅니다. 면접 질문도 이 내용 바탕으로 얼추 잘 대답할 수 있지 않을까도 생각해 봅니다.

공부를 하면서 전세계에 깔려있는 해저 케이블 정보를 담은 웹사이트를 접하게 되었는데 가슴이 웅장해졌습니다.

그냥 집에 앉아서 인터넷을 키기만 해도 온갖 웹앱들을 이용할 수 있는데 패킷들은 바다를 건너 수천 킬로미터를 여행합니다. 그리고 이게 몇 ms정도 밖에 안 걸립니다. 이게 가능하다고? 싶었습니다. 인간의 엄청난 기술력에 새삼 감탄하게 되더라고요. 약간의 엔지니어링뽕?을 느꼈달까요...ㅎㅎ

Reference


Written by 김맥스