배울 내용
- Next.js의 Pre-Rendering
- SSG와 SSR
- 데이터가 있는 SSG, 데이터가 없는 SSG
- getStaticProps를 활용하여 외부 블로그 데이터를 인덱스 페이지로 가져오는 방법
기본적으로 Next는 모든 페이지를 Pre-Rendering함
즉, Next는 클라이언트 측의 JS에서 모든 작업을 수행하는 것이 아닌 미리 각 페이지에 대한 HTML을 생성
이렇게 하기 때문에 기업들의 SEO를 가져올 수 있음
이렇게 생성되는 HTML들은 최소한의 JS만 연동되기 때문에
페이지가 그려질 때 JS는 완벽한 인터랙션을 가짐 (이것을 hydration라고 함)
React와는 다르게, 브라우저에서 JS를 비활성화 하더라도 JS없이 렌더링이 되는 걸 볼 수 있음
- SSG (스태틱 사이트 제네레이션) : 빌드시 HTML를 생성하는 렌더링 방법으로 미리 렌더링된 HTML이 각 요청에서 재사용
- SSR (서버 사이드 렌더링) : 각 요청에 HTML을 생성하는 사전 렌더링 방법
중요한 것은 하이브리드적으로 어떤 페이지에서는 SSG를, 어떤 페이지에서는 SSR을 사용할 수 있다는 것
우리의 페이지가 CDN에 의해 한 번만 만들어질 때는 SSG를 사용하는 것을 추천 받는데 그 이유는 이렇게 해야 서버에서 모든 요청마다 페이지를 렌더하는 것보다 훨씬 빠르기 때문
사용자의 요청에 앞서, 이 페이지를 미리 렌더링 할 수 있습니까? 라고 스스로에게 묻고 그 대답이 예인 경우 SSG를 선택해야함
하지만, SSG는 사용자 요청보다 먼저 페이지를 렌더링 할 수 없는 경우에는 좋지 않음 (요청이 잦은 페이지)
페이지에서 자주 업데이트가 되는 데이터에서는 SSR을 사용할 수 있음 속도는 더 느리지만 미리 렌더링된 페이지는 항상 최신 상태이기 때문
혹은 Pre-Rendering없이 클라이언트의 JS를 사용하여 자주 업데이트 되는 데이터를 채울 수 있음
SSG는 데이터 유무에 관계없이 수행할 수 있음
여태 실습한 페이지는 외부 데이터를 가져올 필요가 없었기에 이런 페이지는 앱이 프로덕션용으로 빌드될 때 자동으로 생성
하지만 일부 페이지는 외부 데이터를 가져오지 않고는 HTML을 그릴 수 없기 때문에 파일 시스템에 엑세스 하거나 외부 API를 가져오거나 빌드시 데이터베이스 쿼리를 해야만 함
Next는 이 경우 (SSG with data)를 즉시 지원
구성 요소를 내보낼 때 async함수도 함께 내보내어
루트폴더에 posts를 만든 후 여러 .md 파일을 생성
마크다운에 존재하는 메타데이터를 분석할 수 있는 gray-matter를 npm으로 설치
파일시스템을 읽기 위한 유틸리티 함수를 만들 것임
lib 라는 최상위 디렉토리 생성 후
안에 lib라는 파일을 만든 후에 posts.js 의 코드를 복사
import fs from 'fs';
import path from 'path';
import matter from 'gray-matter';
const postsDirectory = path.join(process.cwd(), 'posts');
export function getSortedPostsData() {
// Get file names under /posts
const fileNames = fs.readdirSync(postsDirectory);
const allPostsData = fileNames.map((fileName) => {
// Remove ".md" from file name to get id
const id = fileName.replace(/\.md$/, '');
// Read markdown file as string
const fullPath = path.join(postsDirectory, fileName);
const fileContents = fs.readFileSync(fullPath, 'utf8');
// Use gray-matter to parse the post metadata section
const matterResult = matter(fileContents);
// Combine the data with the id
return {
id,
...matterResult.data,
};
});
// Sort posts by date
return allPostsData.sort((a, b) => {
if (a.date < b.date) {
return 1;
} else {
return -1;
}
});
}
Next에서 lib 폴더에는 pages, styles 폴더와 같이 할당될 이름이 없으므로 보통 lib 그 자체나 utils라는 파일명을 사용
이제 마크다운 파일들을 읽고 index.js에다가 넣어줄 것임
두 가지 Pre-Redering에서 각 페이지마다 렌더링 방법을 선택할 수 있기 때문에 hybrid로 구성 가능
아까 작성했던 코드를 마무리 해주고
Props를 정상적으로 넣어줌 (index.js)
그러면 우리가 md 파일에 넣었던 정보들을 확인할 수 있음
또한 우리는 Fetch와 데이터베이스의 Query도 사용 가능
서버에나 활용되는 이러한 것들이 가능한 이유는 getStaticProps는 SSR기반이기 때문에 가능, 이런 것들은 CSR에서는 절대 불가함
심지어 브라우저의 JS 번들을 활용하지 않기에 우리가 데이터베이스에 바로 코드를 적을 수 있다는 것
getStaticProps는 페이지에서만 내보내질 수 있음 왜냐하면 페이지가 렌더링 되기 전에 React에 필요한 모든 데이터가 있어야 하기 때문
앞서 누누이 말한대로, SSG는 빌드시 한번만 발생하므로 자주 업데이트 되거나 요청마다 변경되는 데이터에는 적합하지 않아서 이럴 땐 SSR을 사용해야함
SSR을 활용한다면
getStaticProps대신 getServerSideProps를 사용하면 됨
getServerSideProps는 요청시마다 호출되기 때문에 해당 매개변수 (context)에서는 요청별 매개변수가 포함됨
하지만 getServerSideProps 요청시마다 데이터를 가져와야하는 페이지를 미리 렌더링 하는 경우에만 사용 해야만함
서버가 모든 요청에 대해 결과를 계산해야하고 추가 구성없인 CDN에서 결과를 캐시할 수 없기에 느림
데이터를 미리 렌더링할 필요가 없을 땐 그냥 CSR을 활용
이런 접근 방식은 사용자 대시보드 페이지에 적합, 대시보드는 비공개의 사용자별 페이지이므로 요청이 많고 SEO와 관련이 없고 페이지를 미리 로드할 필요가 없기 때문
Next에서는 SWR을 제공하여 데이터를 쉽게 가져옴
caching, revalidation, focus tracking, refetching on interval등을 제공