컨텐츠로 이동

스트리밍을 사용하여 페이지 성능 향상

Astro의 SSR은 HTML 스트리밍을 사용하여 더 빠른 페이지 로딩이 가능한 경우 각 컴포넌트를 브라우저로 보냅니다. 페이지 성능을 더욱 향상시키려면 컴포넌트를 전략적으로 빌드하여 데이터 가져오기 차단을 방지함으로써 로드를 최적화할 수 있습니다.

다음 리팩토링 예시에서는 fetch 호출을 다른 컴포넌트로 이동하고 페이지 렌더링을 차단하는 컴포넌트 밖으로 이동시켜 페이지 성능을 향상시키는 방법을 보여줍니다.

다음 페이지는 프런트매터에서 일부 데이터를 가져올 때까지 기다립니다. (await 사용) Astro는 HTML을 브라우저에 보내기 전에 모든 fetch 호출이 해결될 때까지 기다립니다.

src/pages/index.astro
---
const personResponse = await fetch('https://randomuser.me/api/');
const personData = await personResponse.json();
const randomPerson = personData.results[0];
const factResponse = await fetch('https://catfact.ninja/fact');
const factData = await factResponse.json();
---
<html>
<head>
<title>A name and a fact</title>
</head>
<body>
<h2>A name</h2>
<p>{randomPerson.name.first}</p>
<h2>A fact</h2>
<p>{factData.fact}</p>
</body>
</html>

await 호출을 더 작은 컴포넌트로 이동하면 Astro의 스트리밍을 활용할 수 있습니다. 데이터 가져오기를 수행하기 위해 다음 컴포넌트를 사용하면 Astro는 제목과 같은 일부 HTML을 먼저 렌더링한 다음 데이터가 준비되면 단락을 렌더링할 수 있습니다.

src/components/RandomName.astro
---
const personResponse = await fetch('https://randomuser.me/api/');
const personData = await personResponse.json();
const randomPerson = personData.results[0];
---
<p>{randomPerson.name.first}</p>
src/components/RandomFact.astro
---
const factResponse = await fetch('https://catfact.ninja/fact');
const factData = await factResponse.json();
---
<p>{factData.fact}</p>

이러한 컴포넌트를 사용하는 아래 Astro 페이지는 페이지의 일부를 더 빨리 렌더링할 수 있습니다. <head>, <body><h2> 태그는 더 이상 데이터 가져오기로 인해 차단되지 않습니다. 그런 다음 서버는 RandomNameRandomFact에 대한 데이터를 병렬로 가져오고 결과 HTML을 브라우저로 스트리밍합니다.

src/pages/index.astro
---
import RandomName from '../components/RandomName.astro';
import RandomFact from '../components/RandomFact.astro';
---
<html>
<head>
<title>A name and a fact</title>
</head>
<body>
<h2>A name</h2>
<RandomName />
<h2>A fact</h2>
<RandomFact />
</body>
</html>

Promise를 직접 포함하기

섹션 제목: Promise를 직접 포함하기

템플릿에 Promise를 직접 포함할 수도 있습니다. 전체 컴포넌트를 차단하는 대신 Promise를 병렬로 해결하고 그 뒤에 오는 마크업만 차단합니다.

src/pages/index.astro
---
const personPromise = fetch('https://randomuser.me/api/')
.then(response => response.json())
.then(arr => arr[0].name.first);
const factPromise = fetch('https://catfact.ninja/fact')
.then(response => response.json())
.then(factData => factData.fact);
---
<html>
<head>
<title>A name and a fact</title>
</head>
<body>
<h2>A name</h2>
<p>{personPromise}</p>
<h2>A fact</h2>
<p>{factPromise}</p>
</body>
</html>

이 예시에서는 personPromisefactPromise가 로드되는 동안 A name이 렌더링됩니다. personPromise가 해결되면 A fact가 표시되고 로드가 완료되면 factPromise가 렌더링됩니다.