프리로드, 프리페치, 프리커넥트: 리소스 힌트로 사이트 성능 끌어올리기 (번역)

hejuby·2024년 7월 23일
0

원본 글: Preload, Preconnect, Prefetch: Improve Your Site's Performance with Resource Hints

요약: 리소스 힌트(Resource hint)는 브라우저가 웹페이지를 더 빠르게 로딩할 수 있게 해주는 HTML 태그입니다. 리소스 힌트를 사용하면 페이지 로딩 속도를 단축시키거나 더 나은 사용자 경험을 제공할 수 있습니다. 프리로드(Preload)는 중요한 리소스들을 페치하고 캐싱합니다. 프리커넥트(Preconnect)는 외부 사이트로의 연결을 미리 설정합니다. 그리고 프리페치(Prefetch)는 중요할 것 같은 리소스들을 미리 로드합니다.

모던 웹 브라우저들은 리소스들의 우선순위를 정하고 중요한 리소스를 먼저 페칭하거나 사용자가 방문할 것 같은 페이지를 추측하는 등의 다양한 테크닉들을 사용하여 웹사이트의 전체적인 성능을 끌어올립니다.

하지만, 아무리 브라우저의 성능이 좋아졌더라도, 사이트의 성능에 대한 결정을 브라우저에만 의존하는 건 좋지 않은 선택일 수 있습니다.

어떤 리소스가 가장 중요하고 사용자가 실제로 어떻게 사이트를 사용하는 지는 웹사이트의 주인인 당신이 가장 잘 알고 있습니다. 그리고 웹사이트의 전체적인 성능, 체감 속도, 그리고 사용자 경험을 끌어올리기 위해서 브라우저가 페이지를 더 빨리 로드하게 하고 싶을 겁니다.

여기서 우리는 리소스 힌트를 사용할 수 있습니다.

다음 내용들에선 리소스 힌트에 대해서 알아보고 어떻게 가장 잘 활용할 수 있는 지 살펴 보겠습니다.

브라우저의 동작 방식 (간단히)

리소스 힌트에 대한 이해를 하기 위해 브라우저가 어떻게 동작하는 지 간단히 알아봅시다.

선언문: 다음 내용은 브라우저의 실제 동작 방식을 매우 간단하게 표현한 것입니다. 만약 더 자세한 내용을 알고 싶으면 이 글을 살펴 보세요. - Populating the page: how browsers work

우리는 브라우저가 페이지를 로딩할 때 전체 동작 과정을 세 단계로 나눌 수 있습니다.

  • 연결 설정
  • 코드 다운로드, 파싱, 렌더링
  • 페이지 상호작용하게 만들기

첫번째 단계에서, 브라우저는 리소스를 다운로드하기 위해 서버와의 연결을 수립합니다. 이 과정에서 도메인의 IP 주소를 조회하고, 서버와의 연결을 설정하고, 보안을 위해 연결을 암호화합니다.

위 과정이 완료되면, 브라우저는 정보를 다운로드 받고 파싱하여, 도큐먼트 객체 모델(DOM)CSS 객체 모델(CSSOM)을 생성하고, 콘텐츠를 렌더링하게 됩니다.

마지막 단계는 페이지를 상호작용하게 만드는 것입니다. 앞서 말한 모든 과정은 모두 메인 스레드에서 일어나는 일입니다. 브라우저의 메인 스레드에서 파싱, 렌더링, 페인팅이 끝나면 그 뒤엔 지연된 자바스크립트 파일을 통해 스크롤, 터치 등의 상호 작용을 가능하게 합니다.

간단하게 표현했지만, 페이지가 로딩될 때마다 브라우저 내부에선 이런 과정이 매번 일어나게 됩니다.

이제 리소스 힌트를 어떻게 이 단계들에 적용할 수 있을 지 알아봅니다.

리소스 힌트(Resource Hint): 프리페치, 프리커넥트, 프리로드

이름이 말해주는 것처럼, 리소스 힌트는 브라우저에게 특정 리소스나 웹페이지를 어떻게 다뤄야 할 지 알려주는 힌트 또는 지침입니다. 다른 말로 하면, 이 지침들을 이용해서 페치하거나 렌더할 출처와 리소스들의 우선 순위를 정하는 데에 도움을 줄 수 있습니다.

모든 리소스 힌트는 HTML 문서 head 태그 안에 있는 link 요소의 rel 속성에서 사용할 수 있습니다.

이 코드 스니펫들을 웹사이트에 적용하면 특정 파일들을 일반적인 방법으로 페이지를 로딩할 때 찾아내는 것보다 브라우저가 더 빨리 로딩할 수 있게 합니다.

이제 리소스 힌트의 개요와 장점, 그리고 사용법에 대해 알아보겠습니다.

프리페치(Prefetch)

link rel=prefetch는 나중에 사용될 수도 있는 리소스를 페치하고 브라우저의 캐시에 저장하게 하는 낮은 우선 순위의 리소스 힌트입니다.

prefetch는 매우 낮는 우선 순위를 가지기 때문에, 높은 중요성을 가진 파일에 사용하는 건 올바르지 않습니다.

prefetch를 사용하는 좋은 방법은 후속 페이지의 로딩 시간을 개선시키기 위해서입니다. 예를 들어, prefetch 디렉티브를 사용자 인증에 적용할 수 있습니다. 이 방법을 사용하면, 사용자가 개인정보를 입력하는 시간을 활용하여 다음에 보게 될 페이지에 필요한 리소스들을 미리 로드할 수 있습니다.

사이트 방문자의 행동을 예상하고 리소스를 프리페칭함으로써, 콘텐츠가 포함된 첫 페인트상호작용 시작 시간같은 지표들을 향상시킬 수 있습니다. 넷플릭스가 상호작용 시작 시간을 30% 줄였던 것처럼 말이죠.

지금까지 말한 모든 건 링크 프리페칭이라고도 할 수 있는 프리페칭에 대한 이야기입니다. 하지만 다른 두가지의 프리페칭 또한 중요하므로 살펴보고 갑니다.

1. DNS 프리페칭

브라우저는 호스트(서버)에 연결하기 전에 호스트 이름(URL)을 IP 주소로 변환하는 DNS 룩업이라는 과정을 거칩니다.

이 과정은 몇 밀리초밖에 걸리지 않습니다. 하지만 만약 대부분의 웹사이트에서 하는 것처럼 서드 파티 도메인에서 파일들을 로딩하려면, 브라우저는 DNS 룩업을 각각의 도메인마다 실행해야 합니다. 몇몇 사이트(예: 뉴스 웹사이트)는 매우 많은 외부 리소스를 사용하는데, 이는 페이지당 몇십개의 DNS 룩업이 있을 수도 있다는 것을 의미합니다.

이런 케이스에서 dns-prefetch 힌트를 사용하면 로딩 과정에서 리소스가 필요하다는 걸 알고 난 뒤 수행하는 게 아니라, 지금 바로 이러한 작업이 필요하다는 걸 브라우저에게 알려줍니다. 결과적으로는 이 몇 밀리초들을 아낄 수 있습니다.

Web Almanac 2021에서 소개되었듯이, 좋은 실례는 최적화된 결과를 위해 dns-prefetchpreconnect 힌트와 함께 사용하는 것입니다. 그 이유는 preconnect에 대해 이야기하는 섹션에서 알아보겠습니다.

2. 프리렌더링(Prerendering)

프리렌더링은 사용자가 방문할 지도 모르는 리소스를 미리 최적화한다는 점에서 프리페칭과 매우 비슷합니다. 차이점은, 특정 리소스 대신에 프리렌더는 전체 페이지를 실제로 렌더링한다는 점입니다.

프리커넥트(Preconnect)

dns-prefetch처럼, preconnect 디렉티브는 서버에 첫번째 요청을 보내기 전에 브라우저가 초기 연결을 설립하는 데에 도움을 줍니다.

그렇지만 preconnect는 한발짝 더 나아가 있습니다. preconnect를 사용한 DNS 룩업에서는 TLS 협상TCP 핸드셰이크를 포함합니다. 이것은 결과적으로, 왕복 시간(Time To Interactive)을 없애고 시간을 더 많이 아낄 수 있게 합니다.

하지만 여기서 궁금증이 하나 생깁니다.

dns-prefetch가 하는 것, 그리고 그 이상을 preconnect가 할 수 있다면 애초에 dns-prefetch를 사용할 이유가 없지 않나요?

대부분의 케이스에서 preconnectdns-prefetch를 대신해 선택될 수 있지만, 문제는 preconnect가 몇몇 브라우저에서 지원하지 않는다는 점입니다.

(역자 주: 2024년 현재 preconnect는 IE와 Opera Mobile을 제외한 대부분의 브라우저에서 지원하고 있습니다.)

다행인 점은 둘을 같이 사용하면 최적의 결과를 낼 수 있습니다. preconnect에 대한 폴백으로 다음과 같이 dns-prefetch를 사용할 수 있습니다.

구글에 따르면 다음과 같습니다.

중요한 서드 파티 원본에 대한 조기 연결을 설정하면 로드 시간을 100~500ms 단축할 수 있습니다. 이 수치는 사소해 보일 수 있지만 사용자가 웹페이지 성능을 인식하는 방식에 차이를 만듭니다.

2019년에는 크롬이 중요한 출처들을 프리커넥트함으로써 왕복 시간을 1초 가까이 줄일 수도 있었습니다.

프리로드(Preload)

preload 디렉티브가 어떻게 동작하는 지 설명하기 전에 한가지를 분명히 하고자 합니다.

preload가 주로 '리소스 힌트'로 언급되긴 하지만 사실 그렇지 않습니다. 프리로드는 선언적 페칭이고, 힌트보단 명령어에 가까워 브라우저가 무조건 실행하게 됩니다.

다시 말하면, 페이지에서 매우 중요한 리소스를 preload는 브라우저가 발견하기 전에 강제로 다운로드하게 할 수 있습니다.

preload 디렉티브는 중요 렌더링 경로에 포함되지만 브라우저가 쉽게 발견하지 못하는 리소스에 제일 잘 동작합니다. 예를 들어, 폰트, CSS, 중요한 자바스크립트 파일 등이 있습니다.

dns-prefetch 그리고 preconnect와의 또다른 차이점은, 앞의 두가지가 relhref 속성만 필요하다면 preload는 좀 더 복잡하다는 것입니다. 프리로드하고 싶은 리소스의 컨텐츠 타입을 명시한 as 속성을 추가해야 합니다.

구글 엔지니어링 매니저인 Addy Osmani에 따르면, 프리로딩할 때 as 속성을 명시해주는 건 필수적입니다.

만약 무엇을 프리로드할 지 명시할 때 유효한 as를 사용하지 않는다면, 예를 들어 스크립트의 경우, 결과적으로 두번 페치하게 될 것입니다.

아래는 표시할 수 있는 모든 as 속성의 값 목록입니다.

as 속성을 포함시키는 것은 브라우저가 타입에 따라 프리페치된 리소스의 우선 순위를 정하는 데에 도움을 주고 캐시에 그 리소스가 이미 있는 지 판단할 수 있게 해줍니다.

어떻게 리소스 타입에 따라 우선 순위가 결정되는 지 알아보려면 Chrome Resource Priorities and Scheduling을 참고하세요.

폰트 같은 몇몇 리소스들에는 crossorigin 속성 또한 포함해 주어야 합니다.

crossorigin 속성은 HTTP CORS 리퀘스트의 모드를 설정합니다. CORS(교차 출처 리소스 공유, Cross-Origin Resource Sharing)은 브라우저가 리소스를 로딩하기 위해 허용해야 하는 출처들을 서버가 자기 자신 이외에도 표시하도록 허락해주는 메커니즘입니다. 여기서 더 자세하게 언급하지는 않겠지만, CORS에 대해 알아보고 싶다면 이 문서를 참고하세요.

as 속성과 비슷하게, crossorigin 없이 폰트를 프리로딩 하는 건 더블 페칭이 될 겁니다. 여기에 Addy Osmani의 글에서 발췌한 이 주제에 관한 또다른 내용입니다.

프리로드를 사용해 폰트를 페칭할 때 crossorigin 속성을 추가하지 않으면, 두번 다운로드 될 겁니다. 리퀘스트가 익명 모드 CORS를 사용하기 때문입니다. 페이지와 같은 출처에서 폰트가 로딩된다고 해도 마찬가지입니다. 또한 다른 익명 페칭에도 적용될 수 있습니다(예: 기본 XHR).

더 많은 리소스 힌트, 더 많은 문제들

여기까지 읽고 난 다음, 가능한 한 많은 리소스 힌트를 사용하면 무조건 브라우저가 페이지를 더 빠르게 로딩하게 될 거라고 생각할 수도 있습니다.

하지만 그건 정답이 아닙니다.

아래는 리소스 힌트를 적용할 때 고려해야 할 몇가지 방해물입니다.

1. 프리페치는 데이터 사용량을 늘릴 수도 있습니다.

prefetch가 낮은 다운로드 우선 순위를 가지고 있다고 해도, 그것이 아무 문제점이 없다는 뜻은 아닙니다. prefetch는 사이트의 데이터 사용량을 늘릴 수 있는데, 그건 당신(늘어난 서버 트래픽)과 사용자(불필요한 리소스 사용) 모두에게 영향을 줄 수 있습니다. 또한, 결과적으로 사용하지 않을 데이터를 로딩할 수도 있습니다. 그러므로 여러번 심사숙고하고 사용하세요.

2. 프리렌더는 대역폭 낭비를 유발할 수도 있습니다.

prerender를 이용한 도박은 전체 페이지들을 미리 다운로드 하기 때문에, prefetch보다 더 큰 판돈을 걸어야 합니다. 이는 prerender를 리소스적으로 무거운 힌트로 만들고, 대역폭 낭비를 유발하게 합니다. 특히 모바일 디바이스에서 말이죠. 그리고 최악의 부분은 유저가 페이지를 요청하지 않는 경우 힌트의 효과가 아무것도 발휘되지 않는다는 점입니다.

3. 프리커넥트는 추가적인 CPU 사용으로 이어질 수도 있습니다.

preconnect가 낮은 우선 순위를 가지고 있다고 해도, 여전히 사이트의 성능에 안좋은 영향을 끼칠 수 있습니다. 만약 설정된 연결이 빨리 사용되지 않는다면(크롬의 경우 10초 이내), preconnect 디렉티브는 CPU 사용량만 늘린 뒤 브라우저에 의해 자동으로 종료될 것입니다. 추가적으로 암호화 인증의 크기는 3KB 내외인데, 이는 다른 중요한 리소스들과 대역폭 경쟁을 할만한 정도의 크기입니다. 그러므로 preconnect를 아껴서 사용하세요.

4. 프리로드는 브라우저의 분석기에서 설정한 우선 순위를 덮어 씌울 수도 있습니다.

preload는 브라우저가 즉시 리소스를 다운로드하게 만드는 강력한 지시문입니다. 하지만, 모던 브라우저는 리소스 우선 순위 최적화가 꽤 잘 되어있어 preload를 지나치게 사용하는 건 부정적인 결과가 나올 수도 있습니다. 예를 들어, 비동기 리소스 URL에 preload를 사용한다고 생각해 봅시다. 그러면 브라우저는 리소스를 더 빨리 페치하고 더 빨리 파싱해서, 페이지 로딩 시 초기 메인 스레드를 방해해 비동기의 장점을 모두 없애버릴 것입니다.

다시보기

지금까지 많은 내용에 대해 이야기했는데, 그 중에서 가장 중요한 부분들을 다시 살펴봅시다.

  • dns-prefetchpreconnect는 도메인 이름의 우선 순위를 정하는 데에 사용됩니다(예: https://example.com).
  • prefetchpreload는 리소스 로딩의 우선 순위를 정하는 데에 사용됩니다. prefetch가 뒤따라 오는 페이지의 로딩 시간을 개선하는 데에 쓰이는 반면, preload는 현재 페이지의 중요한 리소스에 가장 잘 작동합니다.
  • prerender는 전체 페이지를 참조합니다(예: blog.html).
  • prefetch, prerender, 그리고 preconnect는 리소스 힌트들이고, 브라우저가 봤을 때 잘 맞을 것 같은 곳에 사용됩니다. preload 디렉티브는 브라우저가 실행해야만 하는 명령어입니다.
  • preload를 사용할 때 더블 페칭을 피하기 위해 ascrossorigin 속성을 포함하는 걸 잊지 마세요.
  • 리소스 힌트가 낮은 우선 순위를 가지고 있다고 해도, 여전히 사이트의 성능에 영향을 끼칠 수 있습니다. 꼭 필요할 때만 알맞게 사용하세요.
  • preload는 브라우저 분석기의 우선 순위를 덮어 씌울 수 있는 매우 강력한 디렉티브입니다. 모던 브라우저는 리소스 우선 순위 최적화가 매우 잘 되어 있다는 걸 명심하시고, preload '힌트'는 아껴서 사용하세요.

새롭게 알게 된 리소스 힌트에 대한 지식을 사용해서 컨텐츠와 에셋 로딩 속도를 늘리고 사이트의 전체적인 성능을 끌어올려 보세요. 그리고 새로운 업데이트를 할 때마다 실제 환경(현장 데이터에 집중하세요)에서 웹사이트를 테스트 해보는 걸 잊지 마세요.

Niko Kaleev, 2024

0개의 댓글