검색 창에 사이트 검색하면 일어나는 일
브라우저의 검색창에 '구글'을 검색하면 어떤 일이 일어날까?
첫 번째 단계
우선, '구글'을 브라우저 검색창에서 검색한다.
두 번째 단계
브라우저는 캐싱된 DNS 기록으로 IP를 체크한다.
DNS은 URL들의 이름과 IP 주소를 저장하고 있는 데이터베이스인데, 인터넷에 있는 URL은 고유의 IP 주소를 가지고 있고 이 주소를 확인하기 위해 터미널에서
nslookup www.google.com
을 검색하면 해당 IP 주소를 확인할 수 있다.
DNS의 가장 큰 목적은 URL 검색을 쉽게 하기 위한 것이며, 숫자로 검색할 수 있지만 번거롭기 때문에 문자로 쉽게 검색할 수 있도록 도와준다. 이처럼, DNS는 사람들이 웹에서 접속하기 쉽게 하는 맵핑하는 역할을 해준다.
그래서 검색을 하면 무슨 일이 일어날까?
1. 우선적으로 브라우저 캐시 확인
- 브라우저는 사용자가 접속한 후에 약간의 기간 동안 DNS 기록을 캐싱한다. 이전에 접속한 기록이 있다면 브라우저 DNS를 먼저 확인한다.
2. OS에 저장된 캐시를 확인
3. Router 캐시 확인
- 두 번째 단계까지 본인의 컴퓨터 내에 저장된 DNS 기록을 확인하는 것이며, 세번 째부터 Router와 통신해 DNS 기록을 찾는다.
- TCP/IP 통신할 때 클라이언트에서 서버로 패킷 단위로 찢어진 데이터가 노드를 통해 이동하는데 이 때 어떠한 노드로 이동해야 가장 효율적으로 이동하는지 정하는 기능을 'Routing'이라고 하며 이것을 하는 장비가 'Router'이다.
4. ISP(인터넷 서비스 제공업체) 캐시 확인
위의 단계가 나눠진 이유는 트래픽을 조절하고, 데이터 전송 시간을 줄이기 위함이다.
세 번째 단계
ISP DNS 서버가 DNS Query 전달한다.
두 번째 단계에서 4가지 방법으로 캐싱된 IP 값을 찾지 못했다면, ISP 서버가 요청한 웹 IP을 찾기 위해 DNS Query를 전달한다.
DNS Query는 여러 DNS 서버들을 탐색하여 웹 IP 주소를 찾는다. 이것을 'Recursive search'라고 부르며, DNS 서버 간 반복적으로 찾다가 찾지 못하여 에러가 발생할 때까지 검색한다.
네 번째 단계
브라우저가 서버와 TCP 연결한다.
위의 작업으로 올바른 IP를 받았다면 브라우저는 IP 주소와 일치한 서버와 연결하여 정보 전송을 요청한다. 가장 일방적으로 HTTP 요청으로 TCP/IP 요청을 한다.
'TCP/IP'는 웹 클라이언트와 서버 간 데이터 패킷이 오가기 위해 TCP Connection이 되어야 하는데, 이 때 'TCP/IP Three-way handshake'라는 프로세스를 통해 클라이언트와 서버 간 연결을 한다.
여기서, 'TCP/IP Three-way handshake'는 다음과 같은 단계를 거친다.
- 클라이언트가 서버에 SYN 패킷을 전송하여 연결 가능을 요청한다.
- 서버에 Connection을 할 수 있는 포트가 있다면 SYN/ACK 패킷을 클라이언트에 보낸다.
- SYN/ACK 패킷을 받은 클라이언트는 서버로 ACK 패킷을 보낸다.
이 과정이 완료되면 TCP 연결이 되었다는 것이다.
IP의 패킷 통신 방법은 순서와 데이터가 모두 도착하였는지 보장하지 않지만 TCP는 순서와 데이터 도착 여부를 보장하기 때문에 TCP/IP가 같이 동작한다.
다섯 번째 단계
브라우저가 웹 서버로 HTTP 통신 요청을 한다.
TCP 연결까지 완료가 되었다면, 브라우저는 GET 요청을 통해 조회할 수 있다.
GET
- 데이터를 조회할 때 사용하는 방식
- URL에 데이터를 담아 전송 (2,083, 길이 제한)
- URL이 노출되기 때문에 보안 취약
- 같은 URL 캐싱
- Body는 담지 않음
POST
- 데이터를 서버에 제출하거나 수정할 때 사용
- 데이터를 Body에 포함
- URL에 데이터가 노출되지 않아 보안 유지 (브라우저 히스토리, 서버로그에 저장되지 않음)
- 전송 길이 제한 없고 캐싱 불가
여섯 번째 단계
서버가 요청을 처리하고 Response를 생성 후 HTTP Response를 전달한다.
- 1xx, 정보만 담긴 메세지를 의미
- 2xx, Response가 성공적인 것을 의미
- 3xx, 클라이언트를 다른 URL로 리다이렉트함을 의미
- 4xx, 클라이언트 측에서 에러 발생 의미
- 5xx, 서버 측에서 에러 발생 의미
일곱 번째 단계
브라우저가 HTML Content를 보여준다.
HTML과 CSS 파일을 위 과정을 통해 전달받아 각각 트리를 만든다.
- HTML 태그를 해석하여 HTML DOM을 만든다.
- CSS가 포함되어 있다면 CSSSOM 트리 구성도 함께 진행한다.
두 트리를 결합해 렌더 트리를 구축한다.
- DOM가 CSSSOM을 결합해 렌더 트리를 만든다.
- display: none, head 태그 내부 요소는 렌더 트리에 없다.
렌더 트리 배치 (리플로우, 레이아웃)
- 렌더 트리가 생성이 되면 배치가 시작되며, 렌더 트리에서 각 노드의 위치, 크기를 계산하여 배치한다.
그리기 (리페인팅)
다음과 같은 단계로 그리기를 실행한다.
- 배경색
- 배경 이미지
- 테두리
- 자식 요소
- 아웃라인
브라우저는 변경에 대해 가능한 한 최소한의 동작으로 반응하려고 한다. 그렇기에 요소의 색깔이 변경되면 해당 요소의 리페인팅만 발생한다. 요소의 위치가 변하면 요소와 자식 그리고 형제의 리페인팅과 재배치가 발생한다. DOM 노드를 추가하면 노드의 리페인팅과 재배치가 발생한다. HTML 요소의 글꼴 크기를 변경하는 것과 같은 큰 변경은 캐시를 무효화하고 트리 전체의 배치와 리페인팅이 발생한다.
레이어 합성과 실제 화면 출력은 다음과 같다.
리플로우/리페인팅
- 리플로우와 리페인팅은 렌더링 과정에서 레이아웃 단계와 그리기 단계를 다시 거치는 과정이다.
- 렌더링 트리 구성에 사용된 모든 노드의 작은 변경에도 발생한다.
- DOM 추가, 삭제, 수정
- DOM 이동, 스타일 추가, 윈도우 크기 변경, 폰트 변경, 스크롤 등
리플로우가 발생하는 속성
- width, height, padding, margin, float, position 등과 같이 레이아웃 위치에 영향을 주는 모든 속성
- 리플로우가 발생하면, 이 후 단계는 무조건 실행된다. (리플로우 => 리페인팅 => => 컴포지트 실행)
- 리플로우, 리페인팅이 발생하는 요소가 많다면 브라우저 성능에 영향을 준다.
리페인팅이 발생하는 속성
- color, border-radius, background 등과 같이 시각적으로 보이는 속성
브라우저는 똑똑하지만, 일부는 아니다.
매 번 하나가 변경이 되면 한 번씩 리셋할 수 없다. 그래서 내부적으로 Queue를 설정해 일괄 리플로우를 실행한다. 그러나, 아래와 같은 경우는 무조건 리플로우를 한다.
- offsetTop, offsetLeft, offsetWidth, offsetHeight
- scrollTop, scrollLeft, scrollWidth, scrollHeight
- clientTop, clientLeft, clientWidth, clientHeight
- getComputedStyle(), IE의 currentStyle
위 메소드는 노드의 스타일 정보를 요구하기 때문에 브라우저는 계속 정보를 전달해야 한다. 그렇기 때문에 무조건 리플로우가 되어 브라우저가 많은 일을 하게 된다.
리플로우/리페인팅 최대학 막기
- 스타일 정보 요구를 적게하면 리플로우를 적게 할 수 있다.
- 스타일 값을 변경하는 것이 아닌 클래스 네임을 바꾸는 것이 유리하다. (따로 바꾸는 것이 아닌 한 번에 바꾸는 것)
- 클래스 네임 변경이 불가피하다면, 'cssText'를 이용해 한 번에 변경한다.
- DOM을 일괄로 한 번에 변경한다.
- 여러 번 변경이 되어야 최종 완성이 되는 DOM이 있다면, 'display: none'으로 해당 노드를 없애고 (리플로우/리페인팅 한 번) 그 노드에 최종 완성되는 노드까지 작업을 실행한 다음 (리플로우/리페인팅 발생하지 않음) display를 복원한다. (리플로우/리페인팅 한 번)
- top, left가 아닌 transform 속성을 사용한다.
- requestAnimationFrame을 사용한다. (내부적으로 transform을 사용하기에 리플로우 X)
- 스크롤은 'Intersection Observer API'를 사용한다.
OSI 7 Layer
HTTP 1.0 ~ 1.1 버전 차이
Keep-alive
- Keep-alive가 생겨서 한 번 연결하면 받고자 하는 것을 5초 간 200개 까지 한 번에 받고 연결을 끊는다.
- 하나의 연결에 여러 요청을 쓰기에 효율적이지만, 그 만큼 연결이 늘어나기 때문에 동시간대 연결이 늘어난다. 너무 많은 연결이 있으면 서버가 추가로 연결을 받을 수 없기 때문에 서버가 터지게 된다.
파이프라이닝
- 기존은 'req1 => res1 => req2 => res2' 식이지만, 'req1 => req2 => res1 => res2' 순으로 response를 기다리지 않고 요청을 보낸다.
- 그 만큼 응답 속도를 높여 페이지 렌더링 시간을 줄인다.
- HOL Blocking 문제가 발생한다.
- 'req1'의 'res1'이 너무 길어지면, 'res2', 'res3'도 늦어진다.
호스트 헤더
- 호스트 헤더가 가능하여 서브 도메인을 사용할 수 있다.
- 1.0에서는 하나의 IP에 하나의 도메인만 운영이 가능했지만, 'Host header' 추가로 서버 도메인이 가능해졌다.
인증 절차
- Client, Server 간 프록시 인증
- Proxy-authorization
- Proxy-authentication
HTTP 1.1 ~ 2 버전 차이
- 멀티플렉싱: 요청 순서 상관없이 먼저 들어온 응답 순서대로 처리
- 우선 순위에 따른 응답 처리 (CSS, Img가 여러 개 있으면 CSS를 우선 순위로 올려 먼저 응답)
- HPACK 헤더 압축
- Server Push (요청을 하지 않아도 서버에서 필요한 정보를 같이 전달)
HTTP vs HTTPS
- HTTP는 서버에서 브라우저로 값을 보낼 때, 암호화되지 않아 데이터를 쉽게 도난당할 수 있다.
- HTTPS는 서버와 브라우저 사이를 암호화 해줌으로써 보안 강화한다. (SSL 인증서)
- AMP 가속화된 모바일 페이지를 만들 때도 HTTPS를 사용해야 한다.
참조
what happens when type google, Browser에 www.google.com을 검색하면 어떤 일이 일어날까?
what happens when type google, Browser에 www.google.com을 검색하면 어떤 일이 일어날까?
kyounghwan01.github.io