브라우저는 어떻게 동작하는가
들어가기전에
-
유명한 브라우저 동작 방식 글이 있다.
-
원본 글을 보니 2011년에 쓴 글이라 콘텐츠의 상당 부분은 정확하지 않는다고 적혀있음
-
브라우저 동작 방식은 나름 low 하다고 생각해서 자료 볼 때 작성 된 날짜를 고려해야겠다는 생각을 못 했는데 반성.
-
공식 문서가 읽기 불편해도 중요하게 이야기 하는 이유가 있다. 신뢰성 ↑↑
우리는 왜 브라우저 동작 방식을 알아야할까?
- 사용자는 로드가 빠르고 상호작용이 원활한 콘텐츠로 이루어진 웹 경험을 원합니다.
- 웹 브라우저 동작 방식을 이해하면
실제 성능
및체감되는 성능
을 향상시키는 방법을 이해하는데 도움이 됩니다.
웹 성능에 있어서 두 가지 주요한 문제는 지연시간
과 브라우저가 대부분 싱글 스레드
로 동작한다는 점
→ 빠른 로딩을 하는데 있어서 지연시간은 이겨내야할 중요한 문제
→ 메인 쓰레드가 요청된 모든 작업을 수행하면서 유저와 상호 작용에 반응을 보장하기 위해서는 렌더링 시간이 중요
❓
MDN 문서에 브라우저가 싱글 스레드라고 적혀있는게 의문
수업 시간에서 브라우저는 탭마다 각각 프로세스라고 했고,
이벤트 루프도 별도의 스레드에서 실행 되는걸로 알고 있는데, 왜 싱글 스레드라고 했을까?
MDN에서는 메인 스레드를 기준으로 말했기 때문이다.
크롬(Blink 엔진), Firefox (Gecko엔진), Safari(WebKit엔진) 모두 메인 스레드는 싱글이다.
메인스레드는 자바스크립트 실행과 DOM 조작을 담당한다.
( 자바스크립트는 기본 설계 원칙이 싱글 스레드로 동작 )
1. 탐색 ( Navigation )
- 웹 페이지를 로딩하는 첫 단계
- 우리가 주소창에 URL 입력, 링크 클릭, 폼 제출하는 등의 요청 보낼 때마다 발생
- 웹 최적화의 목표 중 하나는 탐색이 완료될 때까지의 시간을 최소화 하는 것 !
1-1. DNS 조회
- 브라우저가 DNS 조회 요청
- 호스트 네임 → ip 주소로 응답
- ip는 일정 기간 동안 캐시 된다고 합니다.
- 모바일은 DNS 가기 전에 셀타워를 거친다 !
셀타워는 이동통신사가 설치한 네트워크 인프라의 일부임
셀타워를 거치기 때문에 모바일은 탐색 완료 되는 시간이 더 오래 걸릴 수 있다.
1-2. TCP 핸드셰이크
- IP를 알고난 후에는, 브라우저는 서버와 연결을 합니다.
- 뭐를 통해? TCP 3-way handshake를 통해
- TCP 3-way handshake
- 수업 시간에 배웠던 내용
- SYN(SYNchronize) 클→서: 내 시작번호는 ~ 야
- SYN-ACK(SYNchronize-ACKnowledgement) : 서→클: 내 시작 번호는~, 너 다음 번호는 ~기대할게
- ACK(ACKnowledge) : 클→서 : 알겠어, 너 다음 번호는 ~ 기대할게
- 기대하는 시퀀스 번호가 아니면 연결이 취소
- TCP 3-way handshake
1-3. TLS 협상 ( TLS Negotiation )
- HTTPS를 이용한 연결을 위해서는 또 다른 핸드셰이크가 필요함
- 암호화에 쓰일 함호를 결정하고, 서버를 확인하고, 실제 데이터 전송 전에 안전한 연결이 이루어지도록 한다.
- TCP 핸드셰이크로 끝난게 아니라 실제 요청 전에 클-서 3번 더 왕복해야함
DNS : 2번
TCP-3way-handshake : 3번
TLS Negotiation : 3번
총 8번의 왕복이 있고 난 후에, 브라우저는 요청을 할 수 있다.
2. 응답 ( Response )
- 웹서버로 한 번 연결이 성립되고 나면, 브라우저는 유저 대신 초기
HTTP GET request
보내서 HTML 파일 요청함 - 서버는 관련 응답 헤더와 함께 HTML 내용을 응답함
- 브라우저가 초기 요청에 대한 응답에 대한 TTFB ( Time to First Byte ) 시간을 측정도 한다고 함
그 외, 네트워크 트래픽을 관리하는 매커니즘
혼잡 제어
- 데이터가 안정적으로 전송 되기 위해 전송 속도 조절도 하고 모니터링도 하는 것을 말합니다.
### TCP 슬로우 스타트
- 처음 스타트를 느리게 하다가 빨라지면 증가 시키는 것을 말합니다.
```jsx
처음: 1개 패킷
↓
성공하면: 2개 패킷
↓
성공하면: 4개 패킷
↓
성공하면: 8개 패킷
(지수적 증가)
```
3. 구문 분석 ( Parsing )
- 브라우저가 첫 번째 데이터 청크 (데이터를 작은 조각으로 나눈 것)을 받으면 구문 분석을 시작합니다.
- 구문 분석은 브라우저가 네트워크를 통해 받은 데이터를 DOM, SSCOM으로 바꾸는 단계를 말합니다.
3-1. DOM 트리 구축
- HTML을 처리하여 DOM 트리를 만듬
- DOM 노드의 개수가 많아질수록, DOM 트리를 만드는데 오랜 시간이 걸립니다.
- CSS, 이미지와 같은 논 블로킹 자원을 발견하면 해당 자원을 요청하고 분석을 계속합니다.
- `async` 나 `defer` 같은 설정이 되지 않은 `script` 태그는 렌더링을 막고 HTML 분석을 중지시킵니다.
- 프리로드 스캐너가 이 작업을 가속화하지만, 과도한 스크립트는 여전히 주요한 병목 구간이 될 수 있습니다.
```jsx
1. HTML 바이트 → 문자 변환
↓
2. 토큰화 (Tokenization)
↓
3. 노드 생성
↓
4. DOM 트리 구축
```
프리로드 스캐너
- HTML을 파싱하면서 미리 필요한 리소스를 찾아 다운로드를 시작하는 역할을 합니다.
- 메인 스레드랑 별도의 스레드에서 동작
- 메인 파싱 작업을 방해하지 않고 병렬로 처리할 수 있다.
일반 로드:
HTML 파싱 → 리소스 발견 → 리소스 요청 → 다운로드
프리로드:
HTML 파싱 ─→ 계속 진행
↓
리소스 미리 발견
↓
리소스 요청 시작
3-2 CSSOM 구축
- CSS를 처리하고 CSSOM 트리를 만드는 것
- DOM 과 비슷하게 트리 구조
1. CSS 바이트 → 문자 변환
↓
2. 토큰화 (Tokenization)
↓
3. 노드 생성
↓
4. CSSOM 트리 구축
3-3. Javascript 컴파일
- CSS 분석되고 CSSOM 생성되는 동안, 프리 스캐너 덕에 JS 파일 같은 다른 자원도 다운로드 됨
1. 코드 다운로드
↓
2. 파싱 (구문 분석)
↓
3. AST 생성 ( 추상 구문 트리 : 코드의 구조를 컴퓨터가 이해하기 쉽게 만든 데이터 구조라고 생각하면 됨)
↓
4. 바이트코드 생성
↓
5. 실행
3-4. 전체적으로 맥락 이해하기
- HTML 파싱 시작
- CSS/JS 파일 미리 발견(프리로드 스캐너)
- CSS 병렬 다운로드
- 비동기 JS 병렬 다운로드
- 각자 준비되는 대로 처리
4. 렌더 ( Render )
- 화면의 일부분을 CPU 대신 GPU 가 그리면서 메인 스레드의 부담이 줄고 성능이 향상 된다고 합니다.
- 렌더 단계에서는
스타일
→레이아웃
→페인트
순서로 진행 - 이를 렌더링 파이프라인 이라고 합니다.
4-1. 스타일
- CSSOM과 DOM 트리는 구문 분석되는 과정에서 생성되고 렌더 트리로 합성 됩니다.
- 점진적 렌더링 과정
사용자가 더 빨리 콘텐츠를 볼 수 있는 장점이 있습니다.
```jsx
DOM 파싱 시작 ─────────────────────────▶
│
├─── 일부 DOM 생성 ──┐
│ │
CSSOM 파싱 시작 렌더 트리 부분 생성
│ │
├─── 일부 CSSOM ────┘
│
▼
계속 진행...
```
- 렌더 트리는 보이는 요소의 레이아웃을 계산 ( 루트부터 → 보이는 노드를 순회 )
```jsx
display: none // 렌더트리에 포함되지 않는다.
visibility: hidden // 자리를 차지하기 때문에 렌더 트리에 포함
```
- 각각 보이는 노드는 그 노드에 적용된 CSSOM 규칙이 있는데, CSS 캐스케이드 방식에 따라 각 노드의 계산된 스타일이 무엇일지 결정합니다.
<aside>
❓
**CSS 캐스케이드**
하나의 요소에 여러 스타일 규칙이 있을 때, 어떤 스타일이 최종적으로 적용될지 결정하는 규칙
</aside>
4-2. 레이아웃
- 렌더 트리를 기반으로 각 노드의 도형 값을 계산하기 위해 레이아웃을 실행하는 것
- 즉, 모든 노드의 너비, 높이, 위치를 결정하는 프로세스입니다.
4-3. 페인트
- 각 노드를 화면에 페인팅 하는 것
- 브라우저는 레이아웃 단계에서 계산된 각 박스를 실제 화면의 픽셀로 변환합니다.
4-2 그 외 레이어와 합성
- 레이어와 합성은 성능 최적화를 위한 단계
```jsx
// 레이어란 ? 여러 층으로 나누어 처리, 레이어는 독립적으로 처리 가능하고 GPU를 활용해 효율적으로 처리 가능
웹 페이지
├── 레이어 1 (메인 콘텐츠)
├── 레이어 2 (fixed 헤더)
└── 레이어 3 (애니메이션 요소)
// 합성이란 ? 레이어를 순서대로 쌓아서 최종 화면에 생성
레이어 3 (최상단)
↓
레이어 2 (중간)
↓
레이어 1 (배경)
= 최종 화면
```
5. 상호작용 - TTI
- DNS 조회부터 페이지가 상호작용할 준비가 될 때까지 측정하는 단위
- 좋은 사용자 경험을 위해 사용자 입력에 TTI가 50ms 안에 반응해야한다고 한다. (그래야 부드럽게 느껴진다함)
시작 ────────────────────────► TTI 달성
│
├── DNS 조회
├── 페이지 로드
├── 첫 콘텐츠 표시
└── JavaScript 실행 완료
Leave a comment