내비게이션 과정에서 일어나는 일

김윤진·2022년 3월 7일
0

브라우저

목록 보기
3/4

저작권
이 글의 원문은 다음과 같은 저작권 기준을 따릅니다.
Except as otherwise noted, the content of this page is licensed under the Creative Commons Attribution 3.0 License, and code samples are licensed under the Apache 2.0 License. For details, see our Site Policies. Java is a registered trademark of Oracle and/or its affiliates.

https://developers.google.com/web/updates/2018/09/inside-browser-part1

내비게이션 과정에서 일어나는 일


브라우저의 주소 표시줄에 URL을 입력하면 브라우저가 인터넷에서 데이터를 가져와서 페이지를 표시한다

간단한 이 동작에서 사용자가 사이트를 요청하고 브라우저가 페이지 렌더링을 준비하는 과정 (이 글에서는 이 과정을 내비게이션이라고 한다) 에 초점을 맞춰 살펴보자

내비게이션을 사이트 간의 이동이라 생각하면 좋다



브라우저 프로세스에서 시작한다


브라우저 프로세스는 탭 영역 밖에 있는 모든 부분을 제어한다

브라우저 프로세스에는

  • UI 스레드
    • 역할 : 브라우저의 버튼과 입력란을 그린다
  • 네트워크 스레드
    • 역할 : 인터넷에서 데이터를 가져오기 위해 네트워크 스택을 다룬다
  • 스토리지 스레드
    • 역할 : 파일에 대한 접근을 제어한다

등이 있다

주소 표시줄에 URL을 입력하면 브라우저 프로세스의 UI 스레드가 입력을 처리한다


1단계 : 입력처리

사용자가 주소 표시줄에 타이핑을 시작하면 UI 스레드는 먼저 입력되는 내용이 검색어 (search query)인지 URL 인지 확인한다

Chorme에서 주소 표시줄은 검색창이기도 하다

UI 스레드는 입력되는 내용을 파싱해서 검색 엔진으로 이동할지 요청할 사이트로 이동할지 결정해야 한다

사용자가 입력한 문자열이 검색어 라면 문자열을 사용자가 선택한 검색 엔진의 URL과 조합해 새로운 URL 형태를 반환한다
이런 변환을 위해 Chorme은 검색 엔진의 URL 주소를 관리한다

입력된 문자열이 검색어인지 URL인지 판별하는 것은 어려운 일이기 때문에 브라우저는 이를 도와줄 서버와 통신하고나 DNS Lookup을 실행하기도 한다


2단계 : 내비게이션 시작

사용자가 Enter키를 누르면 사이트의 콘텐츠를 가져오기 위해 UI 스레드가 네트워크 호출을 시작한다

로딩 스퍼너가 탭의 모서리에 표시되고 네트워크 스레드는 요청에 대한 DNS Lookup 및 TLS 연결 설정과 같은 적절한 프로토콜을 거쳐 요청을 처리한다

이때 네트워크 스레드가 HTTP 301과 같은 서버 리디렉션 헤더를 수신할 수도 있다

그런 경우에는 네트워크 스레드UI 스레드와 통신해 서버가 리디렉션을 요청했다는 것을 알린다

그런 다음 새로운 URL 요청이 시작된다


3단계 : 응답 읽기

응답 본문인 페이로드가 들어오기 시작하면 네트워크 스레드는 필요에 따라 스트림의 처음 몇 바이트를 확인한다

페이로드가 어떤 형식의 데이터인지는 응답 헤더의 Content-Type 헤더가 알려 주지만 정보가 없거나 잘못된 정보가 있을 수 있다

그래서 이때 MIME 스니핑을 실행해 데이터의 실제 형식을 알아낸다

  • MIME 타입
    클라이언트에게 전송된 문서의 다양성을 알려주기 위한 매커니즘이다
    웹에서 파일의 확장자는 별 의미가 없다
    그러므로 각 문서와 함꼐 올바른 MIME 타입을 전송하도록 서버가 정확히 설정하는 것이 중요하다
    브라우저들은 리소스를 내려받았을 때 해야 할 기본 동작이 무엇인지를 결정하기 위해 대게 MIME타입을 사용한다
  • MIME 스니핑
    MIME 타입이 없을 때 혹은 클라이언트가 타입이 잘못 설정됐다고 판단한 어떤 다른 경우에
    브라우저들은 MIME 스니핑을 사도할 수도 있는데
    이는 리소스를 훑어보고 정확한 MIME 타입을 추측해내는 것이다
    각각의 브라우저들은 이런 과정을 다른 방식으로, 다른 환경에서 처리한다

응답이 HTML 파일이라면 데이터를 렌더러 프로세스에 전달하는 단계로 넘어간다

하지만 응답이 ZIP 형식 파일이나 다른 형식의 파일이라면 다운로드 요청이므로 다운로드 매니저에 데이터를 전달하는 단계로 넘어가야 한다

더 정확히 구분하자면 '렌더러 프로세스가 다룰 수 있는 데이터 형식일 때'와 '렌더러 프로세스가 다룰 수 없는 데이터 형식일 때'로 구분하는 것이 좋다
예를 들어 PDF 파일을 반환하는 주소로 접근했을 때 다운로드로 넘어가지 않고 브라우저에 문서를 바로 표시하는 경우를 생각할 수 있다

이 단계 또한 Safe Browsing 의 검사가 실행되는 단계이다

도메인과 응답 데이터가 악성 사이트로 알려진 사이트와 일치하는 것 같다면 네트워크 스레드는 경고 페이지를 표시하라고 알린다

이에 더해서 CORB(Cross-Origin Read Blocking) 기능이 서로 다른 사이트의 민감한 데이터가 렌더러 프로세스에서 실행되지 않게 검사한다


4단계: 렌더러 프로세스 찾기

모든 검사가 끝나고 브라우저가 요청된 사이트로 이동해야 한다고 네트워크 스레드가 확신하게 되면 네트워크 스레드는 UI 스레드에 데이터가 준비되었음을 알린다

그러면 UI 스레드는 웹 페이지의 렌더링을 수행할 렌더러 프로세스를 찾는다

네트워크 요청이 응답을 받기까지 수백 밀리초가 거릴 수 있기 때문에 이 과정을 더 빨리 진행하기 위한 최적화가 적용되어 있다

UI 스레드가 네트워크 스레드로 URL 요청을 보낼 때 UI 스레드는 이미 어느 사이트로 이동할지 알고 있다

UI 스레드는 렌더러 프로세스를 먼저 찾거나 네트워크 요청과 동시에 렌더러 프로세스를 시작한다

이런 방식에서는 모든 것이 예상대로 잘 진행된다면 네트워크 스레드가 데이터를 받을 때 이미 렌더러 프로세스는 준비 상태에 있게 된다

만약 다른 사이트로 리디렉션이 이루어져 다른 프로세스가 필요하게 된다면 미리 준비한 프로세스가 사용되지 않을 수 있다


5단계: 내비게이션 실행

이제 데이터와 렌더러 프로세스가 준비되었으므로 내비게이션을 실행하도록 브라우저 프로세스에서 렌더러 프로세스로 IPC 메서지를 전송한다

IPC (Inter Process Communication) 프로세스간 통신
대다수의 운영체제 에서는 시스템에서 함께 작동하는 다수의 애플리케이션 프로세스 간에 정보를 교환하기 위해 프로세스간의 통신 기법을 제공한다

또한 렌더러 프로세스가 HTML 데이터를 계속 수신할 수 있도록 브라우저 프로세스는 데이터 스트림으로 전달된다

렌더러 프로세스에서 내비게이션이 실행되었다는 것을 브라우저 프로세스가 확인하고 나면 내비게이션이 완료되고 문서 로딩 단계가 시작된다

이 시점에 주소 표시줄이 업데이트되고 보안 표시와 사이트 설정 UI도 새 페이지의 사이트 정보를 반영해 갱신된다

탭에 대한 세션 기록이 업데이트되어 뒤로 가기 버튼과 앞으로 가기 버튼도 방금 이동한 사이트를 반영해 작동한다

탭이나 창을 닫은 이후 탭과 세션을 복원할 수 있게 세션 기록이 디스크 드라이브에 저장된다


추가 단계: 초기 로드 완료

내비게이션이 실행되면 렌더러 프로세스는 계속 리소스를 로딩하고 페이지를 렌더링한다

렌더러 프로세스가 렌더링을 끝내면 브라우저 프로세스로 IPC 메시지를 보낸다 (이 시점은 페이지의 모든 프레임에서 onload 이벤트의 실행까지 끝낸 이후이다)

그러면 UI 스레드는 탭에서 로딩 스피너의 동작을 중지한다

끝낸다(finish)라고 표현한 것은 클라이언트 사이드의 javascript가 여전히 추가적인 리소스를 로드하거나 이후에 새로운 뷰를 렌더링할 수 있기 때문이다


다른 사이트로 내비게이션

이제 사용자가 주소 표시줄에 다른 URL을 다시 입력하면 어떻게 될까?

브라우저 프로세스는 동일한 단계를 거쳐 다른 사이트로 이동을 처리한다

하지만 그전에 현재 렌더링된 사이트에서 beforeunload 이벤트를 확인해야 한다

beforeunload 이벤트는 탭을 닫거나 이동하려고 할 때 "이 사이트를 떠나시겠습니까?"라는 경고창을 만들 수 있다

javascript 코드를 포함해 탭 안의 모든 것은 렌더러 프로세스에 의해 처리되므로 브라우저 프로세스는 새로운 내비게이션 요청이 들어오면 현재 렌더러 프로세스를 확인해야 한다

beforeunload 이벤트 핸들러는 내비게이션을 시작하기 전에 이벤트 핸들러를 실행해야하기 때문에 대기시간(latency)이 늘어난다
페이지에 입력한 데이터가 손실될 수 있는 경우에만 추가하는 것이 좋다

사용자가 링크를 클릭하거나 클라이언트 사이드 javascript에서 window.location = "https://example.com" 코드를 실행하는 것과 같이 렌더러 프로세스에서 내비게이션이 시작되면 렌더러 프로세스는 먼저 beforeunload 이벤트 핸들러를 확인한다

이후에는 브라우저 프로세스가 내비게이션을 시작했을 때의 동일한 과정을 거친다

유일한 차이점은 내비게이션 요청이 렌더러 프로세스에서 시작되어 브라우저 프로세스로 넘어간다는 점이다

현재 렌더링된 사이트와 다른 사이트로 이동하는 새로운 내비게이션이 발생하면 별도의 렌더러 프로세스가 새로운 내비게이션을 처리한다

현재 렌더링된 사이트를 처리한 렌더러 프로세스는 unload와 같은 이벤트를 처리하기 위해 유지된다

Page Lifecycle API 이벤트 후킹에 대해 알 수 있다


서비스 워커

서비스 워커가 도입되면서 내비게이션 과정에도 변화가 생겼다

서비스 워커는 애플리케이션의 코드에 네트워크 프록시를 작성할 수 잇는 수단이다

서비스 워커를 통해 웹 개발자는 무엇을 로컬 캐시에 저장할지 언제 네트워크에서 새 데이터를 가져올지 제어할 수 있다

서브스 워커가 캐시에서 페이지를 로드하도록 설정되었다면 네트워크에서 데이터를 가져오도록 요청할 필요가 없다

중요한 점은 서비스 워커가 렌더러 프로세스에서 실행되는 javascript 코드라는 점이다

그렇다면 내비게이션 요청이 들어왔을 때 브라우저 프로세스는 사이트에 서비스 워커가 있다는 것을 어떻게 알 수 있을까?

서비스 워커가 등록되면 서비스 워커의 범위는 참조 (reference)로 유지된다

서비스 워커 수명 주기

내비게이션이 발생하면 네트워크 스레드는 도메인에 등록된 서비스 워커의 범위와 비교한다

해당 URL에 등록된 서비스 워커가 있으면 UI 스레드는 서비스 워커 코드를 실행하기 위해 렌더러 프로세스를 찾는다

서비스 워커는 네트워크에 데이터를 요청하지 않고 캐시에서 데이터를 가져올 수 있다

또는 네트워크에 새 리소스를 요청할 수 있다


내비게이션 프리로드

브라우저 프로세스와 렌더러 프로세스 사이를 왕복해야 하는 상황에서 서비스 워커가 결국 네트워크에서 데이터를 요청하기로 하면 지연이 발생하게 됨을 알 수 있다

내비게이션 프리로드는 서비스 워커의 시작과 병렬로 리소스를 로딩해 내비게이션 과정의 속도를 높이는 매커니즘이다

이 요청은 헤더에 표시되어 서버가 이러한 요청에 대해 다른 콘텐츠를 보낼 수 있게 된다

예를 들어 전체 문서를 보내지 않고 업데이트된 데이터만 보낼 수 있다

0개의 댓글