최신 브라우저의 내부 살펴보기를 읽고
2부 - 내비게이션 과정에서 일어나는 일
-
원문 : https://developers.google.com/web/updates/2018/09/inside-browser-part2 (by. Mariko Kosaka)
-
시리즈 두 번째 글에서는 내비게이션 과정에서 Chrome이 하는 일을 다룹니다
-
내비게이션 = 사용자가 사이트를 요청하고 브라우저가 페이지 렌더링을 준비하는 과정
-
내비게이션에서 Chrome의 여러 프로세스와 스레드가 어떤 일을 담당하는지 살펴보자
-
그리고 내비게이션 과정의 속도를 높이기 위한 기술인 서비스 워커와 내비게이션 프리로드를 알아보자
브라우저 프로세스에서 시작한다
- 1부에서 브라우저 프로세스가 탭 영역 밖에 있는 모든 부분을 제어한다고 설명했다
- 브라우저 프로세스에는 UI 스레드, 네트워크 스레드, 스토리지 스레드 등이 있다
- UI 스레드는 브라우저의 버튼과 입력란을 그린다
- 네트워크 스레드는 인터넷에서 데이터를 가져오기 위해 네트워크 스택을 다룬다
- 스토리지 스레드는 파일에 대한 접근을 제어한다
- 주소 표시줄에 URL을 입력하면 브라우저 프로세스의 UI 스레드가 입력을 처리한다
간단한 내비게이션
1단계 : 입력 처리
-
사용자가 주소 표시줄에 타이핑을 시작
-
UI 스레드는 먼저 입력되는 내용이 검색어(search query)인지 URL인지 확인
-
Chrome에서 주소 표시줄은 검색창이기도 함
-
UI 스레드는 입력되는 내용을 파싱해서 검색 엔진으로 이동할지 요청한 사이트로 이동할지 결정
-
검색어 = 검색 엔진의 URL과 조합해 새로운 URL 형태로 반환
-
URL = 이를 도와줄 서버와 통신하거나 DNS Lookup을 실행하여 URL인지 판별
2단계 : 내비게이션 시작
-
사용자가 Enter 키를 누름
-
사이트의 콘텐츠를 가져오기 위해 UI 스레드가 네트워크 호출 시작
-
로딩 스피너가 탭의 모서리에 표시
-
네트워크 스레드는 요청에 대한 DNS Lookup 및 TLS 연결 설정과 같은 적절한 프로토콜을 거쳐 요청을 처리
-
이때 네트워크 스레드가 HTTP 301과 같은 서버 리디렉션 헤더를 수신할 수 도 있음
-
그런 경우에는 네트워크 스레드가 UI 스레드와 통신해 서버가 리디렉션을 요청했다는 것을 알림
-
그런 다음 새로운 URL 요청이 시작
3단계 : 응답 읽기
-
응답 본문인 페이로드가 들어오기 시작
-
네트워크 스레드는 필요에따라 스트림의 처음 몇 바이트를 확인
-
페이로드가 어떤 형식의 데이터인지는 응답 헤더의 Content-Type 헤더가 알려줌
-
하지만 정보가 없거나 잘못된 정보가 있을 수 있음
-
그래서 이때 MIME 스니핑을 실행해 데이터의 실제 형식을 알아냄
-
https://source.chromium.org/chromium/chromium/src/+/master:net/base/mime_sniffer.cc;l=5
-
응답이 렌더러 프로세스가 다룰수 있는 데이터 형식인가?
-
렌더러 프로세스에 전달
-
렌더러 프로세스가 다룰수 없다면?
-
브라우저에 문서를 바로 표시하는 경우 예) PDF 형식, JSON 형식 등..
-
ZIP 파일등을 다운로드 하는 경우 => 다운로드 매니저
-
이 단계는 또한 Safe Browsing의 검사가 실행되는 단계
-
도메인과 응답 데이터가 악성 사이트로 알려진 사이트와 일치하는 것 같다면
-
네트워크 스레드는 경고 페이지를 표시하라고 알림
-
이에 더해서 CORB(Cross-Origin Read Blocking) 기능이 서로 다른 사이트(cross-site)의 민감한 데이터가 렌더러 프로세스에서 실행되지 않게 검사
4단계 : 렌더러 프로세스 찾기
-
모든 검사가 끝나고 브라우저가 요청된 사이트로 이동해야 한다고 네트워크 스레드가 확신하게 되면
-
네트워크 스레드는 UI 스레드에 데이터가 준비되었음을 알림
-
그러면 UI 스레드는 웹 페이지의 렌더링을 수행할 렌더러 프로세스를 찾음
-
네트워크 요청이 응답을 받기까지 수백 밀리초가 걸릴 수 있기 때문에 이 과정을 더 빨리 진행하기 위한 최적화가 적용되어 있음
-
2단계에서 UI 스레드가 네트워크 스레드로 URL 요청을 보낼 때 UI 스레드는 이미 어느 사이트로 이동할지 알고 있음
-
UI 스레드는 렌더러 프로세스를 먼저 찾거나 네트워크 요청과 동시에 렌더러 프로세스를 시작
-
이런 방식에서 모든 것이 예상대로 잘 진행된다면 네트워크 스레드가 데이터를 받을 때 이미 렌더러 프로세스는 준비 상태에 있게 됨
-
만약 다른 사이트로 리디렉션이 이루어져
-
다른 프로세스가 필요하게 되면 미리 준비한 프로세스가 사용되지 않을 수 도 있음
5단계 : 네비게이션 실행
-
이제 데이터와 렌더러 프로세스가 준비되었음
-
네비게이션을 실행하도록 브라우저 프로세스에서 렌더러 프로세스로 IPC 메시지를 전송
-
또한 렌더러 프로세스가 HTML 데이터를 계속 수신할 수 있도록 브라우저 프로세스는 데이터 스트림을 전달
-
렌더러 프로세스에서 네비게이션이 실행되었다는 것을 브라우저 프로세스가 확인하고 나면 내비게이션이 완료되고 문서 로딩 단계가 시작
-
이 시점에서 주소 표시줄이 업데이트, 보안 표시, 사이트 설정 UI도 새 페이지 사이트 정보를 반영해 갱신
-
탭에 대한 세션 기록이 업데이트되어 뒤로 가기 버튼과 앞으로 가기 버튼도 방금 이동한 사이트를 반영해 작동
-
탭이나 창을 닫은 이후 탭과 세션을 복원할 수 있게 세션 기록이 디스크 드라이브에 저장
추가 단계 : 초기 로드 완료
- 내비게이션이 실행되면 렌더러 프로세스는 계속 리소스를 로딩하고 페이지를 렌더링
- 렌더링 프로세스가 렌더링을 '끝내면' 브라우저 프로세스로 IPC 메시지를 보냄
- 이 시점을 페이지의 모든 프레임에서 onload 이벤트의 실행까지 끝낸 이후
- 그러면 UI 스레드는 탭에서 로딩 스피너의 작동을 중지
다른 사이트로 내비게이션
-
사용자가 주소 표시줄에 다른 URL을 다시 입력하면 어떻게 될까?
-
브라우저 프로세스는 동일한 단계를 거쳐 다른 사이트로 이동을 처리
-
하지만 그전에 현재 렌더링된 사이트에서 beforeunload 이벤트를 확인해야함
-
beforeunload 이벤트는 탭을 닫거나 이동하려고 할 때, "이 사이트를 떠나시겠습니까"라는 경고창을 만들 수 있음
-
Javascript 코드를 포함해 탭 안의 모든 것은 렌더러 프로세스에 의해 처리
-
브라우저 프로세스는 새로운 내비게이션 요청이 들어오면 현재 렌더러 프로세스를 확인
-
window.location - "https://naver.com" 코드를 실행하는 것과 같이 렌더러 프로세스에서 내비게이션이 시작될 수 있음
-
렌더러 프로세스는 먼저 beforeunload 이벤트 핸들러를 확인
-
이후에는 브라우저 프로세스가 내비게이션을 시작했을 때와 동일한 과정을 거침
-
현재 렌더링된 사이트와 다른 사이트로 이동하는 새로운 내비게이션이 발생하면 별도의 렌더러 프로세스가 새로운 내비게이션을 처리
-
현재 렌덜이된 사이트를 처리한 렌더러 프로세스는 unload와 같은 이벤트를 처리하기 위해 유지
-
더 자세한 내용은 Page Lifecycle API에서 'Overview of Page Lifecycle states and events"를 참고하자
-
https://developers.google.com/web/updates/2018/07/page-lifecycle-api
서비스 워커
-
서비스 워커가 도입되며 내비게이션 과정에도 변화가 생김
-
서비스 워커는 애플리케이션의 코드에 네트워크 프락시를 작성할 수 있는 수단
-
서비스 워커를 통해 웹 개발자는 무엇을 로컬 캐시에 저장할지, 언제 네트워크에서 새 데이터를 가져올지 제어할 수 있음
-
서비스 워커가 캐시에서 페이지를 로드하도록 설정되었다면 네트워크에서 데이터를 가져오도록 요청할 필요가 없음
-
중요한 점은 서비스 워커는 렌더러 프로세스에서 실행되는 Javascript 코드임
-
그렇다면 내비게이션 요청이 들어왔을 때 브라우저 프로세스는 사이트에 서비스 워커가 있다는 것을 어덯게 알 수 있을까?
-
서비스 워커가 등록되면 서비스 워커의 범위는 참조(reference)로 유지 됨
-
내비게이션이 발생하면 네트워크 스레드는 도메인을 등록된 서비스 워커의 범위와 비교
-
해당 URL에 등록된 서비스 워커가 있으면 UI 스레드는 서비스 워커 코드를 실행하기 위해 렌더러 프로세스를 찾음
내비게이션 프리로드
- 서비스 워커가 결국 네트워크에서 데이터를 요청하기로 하면 지연이 발생하게 됨
- 내비게이션 프리로드는 서비스 워커의 시작과 병렬로 리소스를 로딩해 내비게이션 과정의 속도를 높이는 매커니즘
- 이 요청은 헤더에 표시되어 서버가 이러한 요청에 대해 다른 콘텐츠를 보낼수 있게 함
- 예를 들어 전체 문서를 보내지 않고 업데이트된 데이터만 보낼수 있음