[1. 웹 브라우저에 URL을 입력]
[1-1. URL]
URL(Uniform Resource Locater)은 인터넷에서 웹 페이지, 이미지, 비디오 등 리소스의 위치를 가리키는 문자열이다.
다음과 같은 표현 방식을 사용한다.
scheme://<user>:<password>@<host>:<port>/<url-path>
- scheme: 자원에 접근할 방법을 정의해 둔 프로토콜 이름을 입력받는다.
- user, password: 사용자의 정보를 전달해 서버에서 사용자를 인증하는 데 사용하며, 현재는 거의 쓰이지 않는다.
- host: 서버의 도메인 이름 또는 IP 주소를 받는다.
- 도메인 이름을 입력받으면 DNS 조회를 통해 도메인 사이트를 호스팅하는 서버의 IP 주소로 변환하는 작업이 이루어진다.
- port: 서버가 대기하고 있는 논리적 주소이다.
- 웹 서버는 일반적으로 80(http) 혹은 443(https)에서 요청을 대기하며, scheme에서 프로토콜을 지정하면 포트를 생략할 수 있다.
- url-path: 웹 리소스의 위치를 지정하는 데 사용되는 URL. 서버에서 특정 리소스나 파일의 위치를 지정한다.
- 계층 구조를 가지고 있다.
- 쿼리 스트링을 통해 추가적인 매개변수를 전달할 수 있다. (/product?id=123)
- 프래그먼트를 통해 특정 섹션을 나타내기도 한다. (/product#add-cart-icon)
[1-2. http]
http는 Hypertext Transfer Protocol의 약자로, WWW(또는 W3) 상에서 정보를 주고받을 수 있는 애플리케이션 계층 프로토콜이다.
클라이언트와 서버 사이에서 발생하는 요청/응답을 규격화한다.
각 요청을 요약하면 다음과 같다.
[1-3. https]
http는 다음과 같은 3가지의 취약점을 가지고 있다.
- 암호화되지 않은 데이터를 전송하기 때문에, 제 3자가 정보를 가로챌 수 있다.
- 데이터의 무결성을 보장하지 않기 때문에 전송 과정에 데이터 위/변조가 일어나도 검증할 수 없다.
- 서버의 신원을 인증하지 않는다. 즉 피싱을 위한 위조 사이트인지, 진짜 사이트인지 확인하지 않는다.
이와 같은 일을 해결하기 위해 http 프로토콜에 SSL 프로토콜을 추가해 보안을 강화한 것이 https 프로토콜이다.
https는 위 취약점들을 다음과 같이 보완한다.
- SSL/TLS를 사용해 데이터를 암호화한다.
- SSL/TLS를 통해 데이터의 무결성을 검증한다.
- 디지털 인증서를 사용해 서버의 신원을 확인한다.
https는 클라이언트가 서버에 접속을 시도하면, SSL/TLS 핸드셰이크를 시작한다.
위 과정을 통해 서버와 클라이언트는 암호화 알고리즘과 세션 키를 협상하여 사용하고, 이를 통해 보안을 보장받을 수 있다.
[2. 웹 브라우저가 도메인 이름의 IP 주소 조회]
사용자가 위와 같은 양식의 URL을 주소창에 입력하고 엔터를 누르면, 브라우저는 도메인을 사용해 접근하려는 서버의 IP 주소를 조회한다.
이는 DNS 조회를 통해 이루어진다.
먼저 브라우저는 DNS 캐시를 사용하여 이 도메인 이름으로 식별되는 IP 주소를 이미 인식하고 있는지 컴퓨터에 묻고, 그렇다면 이름이 IP 주소로 변환되어 브라우저는 웹 서버와 내용을 주고 받는다.
브라우저 캐시 -> OS 캐시 -> 라우터 캐시 -> ISP 캐시 순으로 확인한다.
만약 컴퓨터가 도메인 이름 뒤에 어떤 IP가 있는지 모르는 경우 DNS 서버에 계속 요청한다.
DNS 서버(네임 서버)의 작업은 정확히 어떤 IP 주소가 등록된 각 도메인 이름과 일치하는지 컴퓨터에 알려주는 것이다.
컴퓨터가 요청된 IP 주소를 알게 되면 브라우저는 웹 서버와 콘텐츠를 주고 받을 수 있다.
네임 서버는 계층 구조로 이루어져 있으며, 오른쪽에서 왼쪽으로 가장 상위의 네임 서버부터 하위의 네임 서버로 재귀적으로 주소를 요청하게 된다.
[3. 웹 브라우저가 서버와의 TCP 연결 시작]
브라우저가 올바른 IP 주소를 확인하면, 그 IP 주소의 서버와 TCP 연결을 설정한다.
이 과정은 TCP 3-way handshake로 다음과 같이 이루어진다.
- 클라이언트는 서버로 SYN 패킷을 전송한다.
- 클라이언트의 시퀀스 번호, 클라이언트의 포트 번호, 서버의 포트 번호를 포함한다.
- 서버는 클라이언트의 SYN 패킷을 수신한 후 SYN-ACK 패킷을 클라이언트로 응답한다.
- 서버의 시퀀스 번호와 클라이언트의 시퀀스 번호에 대한 응답 번호(클라이언트 시퀀스 번호 + 1)를 포함한다.
- 클라이언트는 서버의 SYN-ACK 패킷을 수신한 후, ACK 패킷을 서버로 전송한다.
- 서버의 시퀀스 번호에 대한 응답 번호(서버 시퀀스 번호 + 1)를 포함한다.
이 과정에서 시퀀스 번호를 사용해 데이터의 순서와 무결성을 보장하고, 서버와 클라이언트가 서로의 통신 상태를 확인하며, 전송 경로를 설정하게 된다.
만약 https를 사용하는 경우, 위 TCP 설정에 이어 TLS 핸드셰이크 과정이 필요하다.
과정은 다음과 같다.
- ClientHello: 클라이언트가 지원하는 암호화 옵션을 서버에 전송한다.
- ServerHello: 서버가 선택한 암호화 옵션을 클라이언트에 전송한다.
- 서버 인증서: 서버가 자신의 인증서를 클라이언트에 전송한다.
- 서버 키 교환: 필요한 경우 서버가 키 교환 정보를 전송한다.
- 서버 완료: 서버가 초기 메시지 전송을 완료한다.
- 클라이언트 인증서: 필요한 경우 클라이언트가 자신의 인증서를 서버에 전송한다.
- 클라이언트 키 교환: 클라이언트가 세션 키 생성을 위한 정보를 서버에 전송한다.
- 인증서 확인: 필요한 경우 클라이언트가 인증서를 통해 서명된 메시지를 전송한다.
- 변경 암호 명령: 클라이언트가 암호화된 통신을 시작할 준비가 되었음을 알린다.
- 완료: 클라이언트와 서버가 핸드셰이크가 완료되었음을 확인한다.
위 모든 과정을 요약하면 다음과 같다.
[4. 웹 브라우저가 HTTP 요청을 서버로 전송]
클라이언트와 서버가 TCP(+ TLS) 핸드셰이크 과정까지 완료하면, 클라이언트는 서버에 http 요청을 전송한다.
요청에는 요청 라인, 헤더, 본문 등이 포함된다.
요청 라인은 요청 메서드, 요청 리소스 경로, 통신할 HTTPS 버전 등을 포함한다.
GET /blog/1620 HTTP/1.1 -> "blog/1620"에서 리소스를 가져온다. HTTP/1.1과 통신하려고 함.
요청 헤더는 요청을 라우팅하는 데 도움이 되는 추가 정보를 서버에 전달한다.
서버에 요청을 보내는 방식, 클라이언트의 특성 등을 서버에 알리는 데 사용된다.
Host: channy.creation.net
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
요청 본문은 POST, PUT 등의 요청에서 주로 사용되며, 클라이언트가 서버로 전송할 데이터를 포함한다.
[5. 웹 서버가 요청을 처리하고 응답을 다시 전송]
[6. 웹 브라우저가 콘텐츠 렌더링]