브라우저 주소창에 https://www.google.com
을 입력하고 엔터를 누르면, 컴퓨터와 네트워크에서는 복잡한 처리 과정이 시작됩니다. 소프트웨어, 하드웨어, 그리고 네트워크가 어떻게 협력하여 웹페이지를 안전하게 가져오는지 단계별로 살펴보겠습니다.
1단계: DNS 조회 - 도메인을 IP 주소로 변환하기
모든 것은 사용자의 키보드에서 시작됩니다. Enter
키가 눌리는 순간, 운영체제(OS)는 키보드로부터 전기적 신호(하드웨어 인터럽트)를 받아 현재 활성화된 프로그램, 즉 웹 브라우저에게 키 입력이 발생했음을 알립니다. 브라우저는 이 입력을 해석하고, 사용자가 'https://www.google.com'으로 이동하길 원한다는 것을 인지합니다.
하지만 컴퓨터는 'https://www.google.com'이라는 문자 주소를 이해하지 못합니다. 컴퓨터 네트워크는 오직 숫자로 된 IP 주소(예: 172.217.175.68
)를 통해서만 서로를 찾아갈 수 있습니다. 마치 우리가 '철수의 집'이라는 이름 대신 '서울특별시 중구 철수대로 110'이라는 상세 주소를 알아야 찾아갈 수 있는 것과 같습니다.
이 문자 주소를 IP 주소로 변환해 주는 거대한 '인터넷 주소록' 시스템이 바로 DNS (Domain Name System)입니다. 브라우저는 이제 https://www.google.com의 IP 주소를 찾기 위한 탐색을 시작합니다.
- 브라우저 캐시 확인: 가장 먼저 브라우저는 자신의 기억을 뒤져봅니다. "혹시 내가 최근에 https://www.google.com에 방문한 적이 있나?" 만약 방문 기록이 남아있다면(캐시), IP 주소를 바로 찾아내고 이 복잡한 DNS 조회 과정을 건너뛸 수 있습니다.
- 운영체제(OS) 캐시 확인: 브라우저에 기록이 없다면, 브라우저는 운영체제에게 물어봅니다. "네게 혹시 https://www.google.com의 IP 주소 기록이 있니?" 운영체제 역시 자체적인 DNS 캐시를 가지고 있어, 여기서 발견되면 바로 반환합니다. 윈도우의 경우
hosts
파일에 수동으로 지정된 주소가 있는지도 이 단계에서 확인합니다. - 라우터(공유기) 캐시 확인: 컴퓨터에도 주소가 없다면, 이제 요청은 집이나 사무실의 라우터(공유기)로 넘어갑니다. 라우터 역시 DNS 캐시 기능이 있어, 같은 네트워크에 연결된 다른 기기가 최근에 https://www.google.com에 접속했다면 그 기록을 가지고 있을 수 있습니다.
- ISP의 DNS 서버에 문의: 여기까지 왔는데도 주소를 찾지 못했다면, 이제 요청은 처음으로 인터넷 세상으로 나아갑니다. 우리가 인터넷 서비스를 가입한 통신사(KT, SKT 등), 즉 ISP(Internet Service Provider)가 운영하는 DNS 서버에 IP 주소를 물어보게 됩니다. 대부분의 가정용 인터넷 설정은 이 ISP DNS 서버를 기본 조회 서버로 사용합니다.
ISP DNS 서버도 모른다면 어떻게 될까요? 여기서부터 DNS의 진짜 계층 구조가 동작합니다. ISP DNS 서버는 재귀적(Recursive) 쿼리를 통해 IP 주소를 찾기 위한 여정을 대신 떠나줍니다.
- 루트(Root) DNS 서버: 전 세계에 단 13개(물리적으론 더 많음)만 존재하는 인터넷의 최고 어른, 루트 서버에게 "혹시 '.com' 주소는 누가 관리하는지 아니?"라고 물어봅니다.
- TLD(Top-Level Domain) DNS 서버: 루트 서버는 '.com'을 관리하는 TLD 서버의 주소를 알려줍니다. ISP DNS 서버는 다시 이 TLD 서버에게 "혹시 'https://www.google.com' 주소는 누가 관리하니?"라고 물어봅니다.
- Authoritative DNS 서버: TLD 서버는 마침내 'https://www.google.com'의 주소 정보를 직접 관리하는 최종 책임자, 즉 구글이 직접 운영하는 Authoritative DNS 서버의 주소를 알려줍니다. ISP DNS 서버는 이 Authoritative 서버에게 "https://www.google.com의 IP 주소가 뭐야?"라고 물어보고, 드디어 최종 IP 주소(예:
172.217.175.68
)를 응답받습니다.
이렇게 얻어낸 IP 주소는 다시 라우터, OS, 브라우저 순으로 전달되어 캐시에 저장되고, 드디어 브라우저는 목적지의 주소를 알게 됩니다.
2단계: TCP 연결 설정 - 3-Way Handshake
목적지 IP 주소를 알았으니 이제 데이터를 보내야 합니다. 하지만 데이터를 무작정 던질 수는 없습니다. 중간에 데이터가 사라지거나, 순서가 뒤바뀌거나, 손상될 수 있기 때문입니다. 이를 방지하기 위해 인터넷은 TCP(Transmission Control Protocol)라는 매우 신뢰성 높은 통신 규약을 사용합니다.
TCP는 데이터를 보내기 전에 클라이언트(내 컴퓨터)와 서버(구글 서버)가 서로 통신할 준비가 되었는지 확인하는, 이른바 '3-Way Handshake'라는 3단계의 사전 통화 과정을 거칩니다.
- 클라이언트 → 서버 (SYN): 클라이언트가 먼저 서버에게 "대화를 시작하고 싶은데, 괜찮니?"라는 의미로 SYN(Synchronize)이라는 특별한 표식이 붙은 데이터 패킷을 보냅니다.
- 서버 → 클라이언트 (SYN+ACK): 서버는 SYN 패킷을 받고 "응, 좋아. 나도 준비됐어. 내 말 잘 들리니?"라는 의미로 SYN+ACK(Acknowledge) 표식이 붙은 패킷으로 응답합니다.
- 클라이언트 → 서버 (ACK): 클라이언트는 서버의 응답을 받고 "응, 잘 들려! 이제 진짜 대화를 시작하자."라는 의미로 마지막 ACK 패킷을 보냅니다.
이 세 번의 "악수"가 성공적으로 끝나면, 클라이언트와 서버 사이에는 데이터가 안전하고 순서대로 오고 갈 수 있는 안정적인 가상 연결 통로(소켓)가 열립니다. 이제 이 통로를 통해 진짜 데이터를 주고받을 준비가 되었습니다.
3단계: TLS/SSL Handshake - 암호화 연결 설정
https
의 's'는 'Secure'를 의미하며, 이는 우리가 주고받는 모든 데이터가 암호화된다는 뜻입니다. 이 암호화를 위해, TCP 연결 위에서 또 한 번의 중요한 "악수" 과정이 일어나는데, 이것이 바로 TLS/SSL Handshake입니다. 이 과정의 목표는 오직 클라이언트와 서버만이 해독할 수 있는 비밀 암호화 키, 즉 세션 키(Session Key)를 안전하게 공유하는 것입니다.
- Client Hello: 클라이언트가 먼저 서버에게 인사합니다. "안녕! 나랑 안전하게 통신하자. 내가 사용할 수 있는 암호화 기술(Cipher Suites) 목록은 이거고, 혹시 모르니 이 난수(Random Number A)도 같이 줄게."
- Server Hello: 서버가 응답합니다. "반가워. 네가 제안한 암호화 기술 중에 이걸(특정 Cipher Suite)로 하자. 그리고 이게 내 SSL 인증서야. 나도 난수(Random Number B)를 하나 줄게."
- SSL 인증서: 이 인증서는 서버의 '신분증'과 같습니다. 신뢰할 수 있는 제3자 기관(CA, Certificate Authority)이 "이 서버는 정말 www.google.com이 맞다"고 보증해 주는 문서입니다. 여기에는 서버의 공개키(Public Key)가 포함되어 있습니다.
- 인증서 검증: 클라이언트(브라우저)는 받은 SSL 인증서가 진짜인지 검증합니다.
- 이 인증서를 발급한 CA가 신뢰할 수 있는 곳인지, 브라우저나 OS에 내장된 신뢰할 수 있는 CA 목록과 대조합니다.
- 인증서가 만료되지는 않았는지 확인합니다.
- 인증서에 명시된 도메인 이름이 내가 접속하려는 'www.google.com'과 일치하는지 확인합니다.
- 이 과정에 하나라도 문제가 있다면, 브라우저는 "안전하지 않은 연결"이라는 경고창을 띄웁니다.
- 세션 키 생성 및 교환: 인증서가 진짜임이 확인되면, 가장 중요한 세션 키 생성 단계로 들어갑니다.
- 클라이언트는 암호화에 사용할 또 다른 정보인 'pre-master secret'을 생성합니다.
- 클라이언트는 이 'pre-master secret'을 아까 서버의 인증서에서 얻은 공개키로 암호화합니다. 공개키로 암호화된 정보는 오직 그에 상응하는 비밀키(Private Key)를 가진 서버만이 풀 수 있습니다. 이는 마치 누구나 잠글 수 있지만 열쇠 주인만 열 수 있는 자물쇠와 같습니다.
- 암호화된 'pre-master secret'을 서버로 전송합니다.
- 세션 키 공유 완료: 서버는 자신이 가진 비밀키로 암호화된 정보를 해독하여 'pre-master secret'을 얻습니다. 이제 클라이언트와 서버 양쪽 모두 처음에 교환했던 난수 A, 난수 B, 그리고 pre-master secret이라는 세 가지 재료를 가지게 되었습니다. 양측은 이 세 재료를 똑같은 공식에 넣어 세션 키를 만들어냅니다. 이제 클라이언트와 서버는 완벽하게 동일한 비밀 세션 키를 공유하게 된 것입니다.
- 암호화 통신 시작: 마지막으로 양측은 "이제부터 모든 대화는 방금 만든 세션 키로 암호화해서 주고받자"고 최종 확인 메시지(Finished)를 교환합니다. 이 메시지 역시 세션 키로 암호화되어 전송됩니다.
이제 클라이언트와 서버 사이에는 암호화된 안전한 통신 채널이 구축되었습니다.
4단계: HTTP 요청과 응답 처리
모든 준비가 끝났습니다. 브라우저는 이제 본래의 목적인 웹페이지를 달라는 HTTP 요청(Request) 메시지를 만들어, 방금 구축한 비밀 통로를 통해 서버로 보냅니다.
요청(Request):
HTTP 요청 메시지는 다음과 같은 구조를 가집니다.
- Start Line:
GET / HTTP/1.1
(GET 방식으로, 웹사이트의 루트(/
)에 있는 문서를, HTTP/1.1 버전으로 요청합니다.) - Headers:
Host: www.google.com
(어떤 서버에 요청하는지),User-Agent: ...
(어떤 브라우저와 OS를 쓰는지),Accept-Language: ko-KR
(한국어를 선호하는지) 등 다양한 부가 정보가 담깁니다. - Body:
GET
요청은 보통 본문이 비어있습니다. (만약 로그인 정보 등을 보낼 때는POST
방식을 사용하며, 이 Body 부분에 정보가 담깁니다.)
이 전체 HTTP 요청 메시지는 앞에서 만든 세션 키를 사용해 통째로 암호화된 후, TCP 통로를 통해 구글 서버로 전송됩니다.
서버의 처리와 응답(Response):
구글 서버는 암호화된 데이터를 받아 세션 키로 복호화하여 HTTP 요청 메시지를 확인합니다. "아, 이 사용자가 메인 페이지를 달라고 하는구나."
웹 서버 소프트웨어(예: Apache, Nginx)는 요청에 따라 적절한 파일을 찾거나, 내부 애플리케이션을 실행하여 동적인 페이지(예: 로그인된 사용자의 정보가 담긴 페이지)를 생성합니다. 그리고 그 결과를 담아 HTTP 응답(Response) 메시지를 만듭니다.
- Status Line:
HTTP/1.1 200 OK
(요청이 성공적으로 처리되었음을 알립니다. 만약 페이지가 없다면404 Not Found
가 될 것입니다.) - Headers:
Content-Type: text/html
(보내는 데이터가 HTML 문서임을 알림),Content-Length: ...
(데이터의 크기) 등의 정보가 포함됩니다. - Body: 웹페이지를 구성하는 실제 HTML 코드가 담깁니다.
이 응답 메시지 역시 세션 키로 완벽하게 암호화되어 클라이언트에게 다시 전송됩니다.
5단계: 브라우저 렌더링 - 웹페이지 화면 출력
클라이언트의 브라우저는 서버로부터 암호화된 응답을 받습니다. 그리고 자신이 가지고 있던 세션 키로 이 데이터를 복호화하여 원본 HTTP 응답 메시지를 얻습니다. 200 OK
상태 코드를 확인하고, Body에 담긴 HTML 코드를 읽기 시작합니다.
이때부터는 브라우저의 렌더링 엔진이 바빠집니다.
- HTML 파싱: HTML 코드를 한 줄 한 줄 읽어 내려가며 DOM(Document Object Model)이라는, 컴퓨터가 이해할 수 있는 나무 형태의 구조로 변환합니다.
- CSS 파싱: HTML 중간에
<link>
태그로 연결된 CSS 파일이나<style>
태그를 발견하면, 해당 CSS 코드를 파싱하여 CSSOM(CSS Object Model)이라는 스타일 구조를 만듭니다. - 렌더 트리 생성: DOM과 CSSOM을 결합하여 화면에 실제로 어떻게 보일지를 결정하는 렌더 트리(Render Tree)를 생성합니다. (예:
display: none
속성이 있는 요소는 렌더 트리에서 제외됩니다.) - 레이아웃(리플로우): 렌더 트리를 기반으로 각 요소가 화면의 어느 위치에, 어떤 크기로 배치될지 정확한 좌표와 크기를 계산합니다.
- 페인팅: 계산된 레이아웃에 따라 각 요소를 실제 화면의 픽셀로 그려내는 작업을 수행합니다.
이 과정에서 만약 HTML이 이미지(<img>
), 스크립트 파일(<script>
), 폰트 파일 등을 필요로 한다면, 브라우저는 각각의 파일에 대해 위에서 설명한 1~4단계의 과정을 거의 그대로 반복하여 서버에 추가적인 요청을 보내고 리소스를 받아옵니다. (물론, 효율성을 위해 이미 맺어진 TCP/TLS 연결을 재사용하는 등의 최적화가 이루어집니다.)
이 모든 과정이 완료되면 구글의 메인 페이지가 화면에 출력됩니다. 단순해 보이는 웹페이지 접속 과정에는 이처럼 많은 기술적 단계들이 포함되어 있으며, 이 복잡한 과정이 보통 1초 내외의 짧은 시간에 처리됩니다.
정리
- DNS 조회: 도메인명을 IP 주소로 변환
- TCP 3-Way Handshake: 클라이언트와 서버 간 연결 설정
- TLS/SSL Handshake: 암호화 통신을 위한 보안 채널 구축
- HTTP 요청/응답: 실제 데이터 송수신
- 브라우저 렌더링: HTML, CSS, JS 파싱 및 화면 출력
'IT 관련 기타 > 개발 상식' 카테고리의 다른 글
객체지향 프로그래밍 (0) | 2018.05.08 |
---|