이전 포스팅에서 SSR에 대해 알아보았는데요. 이번에는 NextJS 의 다른 렌더링에 대해 알아보도록 하겠습니다.
NextJS의 경우 기본적으로 모든 페이지는 pre-render 하게 배치하는 특징을 가지고 있습니다.
🙋 프리랜더링이 뭐였죠?
🤖 프리랜더링은 사전에 HTML 파일들을 만든다는 의미입니다. 맞춤제작이 아닌 기성품 같은 느낌이죠.
NextJs가 프리랜더링을 기본적으로 채택하는 이유는 기존에 만들어 놓았기 때문에 (기성품 처럼..) 많은 클라이언트의 요청에도 신속하게 대응할 수 있고 이는 곳 퍼포먼스의 향상으로 이어지게 됩니다.
그리고 NextJS를 사용하는 큰 이유라고 볼 수 있는 SEO의 향상이 있죠. 프리 랜더링의 경우 HTML 파일이기 때문인 이유이죠.
🙋 생성된 프리 랜더링은 어떻게 동작하나요?
🤖 기본에 만들어진 HTML 파일에 최소한의 JS를 첨부한 형식으로 브라우저에 로드가 될때 나머지 완전한 JS 가 적용이 되는 형식입니다.
🙋 이해가 잘 안되네요 ㅠㅠㅠ 그래서 프리 랜더 한거랑 안한거 차이가 뭔가요?
만약에 JS 파일을 서버로 부터 받아오지 못했다는 가정하에 프리랜더링한 페이지와 안한 페이지는 아래와 같이 나타날 수 있습니다.👇
먼저 JS가 로드 되기전에는 아무것도 나오지 않고 서버로부터 JS 파일을 받고 적용한 순간 원하던 웹 페이지가 도출될 것입니다.
그러나 프리랜더링이 적용이 되어있다면, 로드한 순간에 이미 기본적으로 만들어진 HTML 파일이 아래 👇 와 같이 보이고 , 이후 JS 파일이 로드 된 후부터 Link 같은 컴포넌트들이 작동하기 시작하는 것이지요.
이러한 과정을 Hydration(수분공급 💧) 이라고 합니다.
Hydration 은 정적인 무언가에 마치 생기를 불어넣는듯한 그런 작업들을 진행하는 것을 의미합니다.
이전 포스팅에서도 다뤘다시피 사전랜더에는 두 가지 종류가 있습니다.
이 둘의 차이점은 언제 렌더링 하느냐!입니다.
정적 생성은 빌드 시에 HTML파일을 생성하는 사전랜더링 방식입니다. 그리고 이렇게 생성된 HTML 파일을 요청하는 유저들에게 제공하게 됩니다. 같은 파일을 여럿이서 보는 것이죠.
🙋 언제 쓰나요?
페이지를 만들어두고 CDN을 통해
재사용하기 때문에 대부분의 케이스에서 정적생성이 빠르고 좋습니다.
반대로 SSR 은 사용자의 요청에 맞게 그때그때 만들어 렌더링을 진행하게 됩니다.
🙋 이건 언제 쓰나요?
정적생성의 경우 기존에 만들어 놓은 기성품이기 때문에 최신 유행을 반영하기 쉽지 않은것 같이 항상 최신 상태를 유지해야하는 경우에 SSR을 사용하게 됩니다.
기존에 만들어놨던 페이지를 정적생성으로 재탄생 시킬 예정이다.
index.js
2. 컴포넌트에서 리스트를 따로 받을 수 있었고.
export default function Home({list}) {
3. 아래와 같이 리스트를 가져오는 코드는 쓸모 X
// const API_URL = process.env.NEXT_PUBLIC_API_URL
// const [list,setList] = useState([]);
// const [isLoading, setIsLoading] = useState(true);
// useEffect(() => {
// axios.get(API_URL)
// .then((res) =>{
// setList(res.data)
// console.log(res.data)
// setIsLoading(false);
// })
// }, [])
return (
<div>
<Head>
<title>HOME | JUSER</title>
</Head>
{/* {
isLoading && (<div style= {{padding : "300px 0"}}>
<Loader inline="centered" active>
Loading
</Loader>
</div>)
}
{
!isLoading &&( */}
<>
<Header as ="h3" style={{paddingTop : 40}}>Best Item</Header>
<Divider />
<ItemList list = {list.slice(0,9)}/>
<Header as ="h3" style={{paddingTop : 40}}>New Item</Header>
<Divider />
<ItemList list = {list.slice(9)}/>
</>
)
{/* } */}
</div>
)
}
// 1. 정적생성에서 list 데이터를 만들었기 때문에
export async function getStaticProps() {
// 빌드시에 딱 한번만 호출되고 바로 static file로 빌드됨. = 이후 수정 불가.
const apiUrl = process.env.API_URL;
const res = await axios.get(apiUrl);
const data= res.data
return {
props: {
list : data,
name : process.env.name
}
}
}
위의 getStaticProps
의 경우는 내가 이미 만들어둔 컴포넌트를 스테틱 파일로 만들어 두는 것으로 속도를 향상시켰습니다.
🙋 그럼 다이나믹 페이지는 불가능한가욧!?
🤖 10가능.
물론 가능합니다. 이때 사용하는 기능이 getStaticPath
입니다. 다이나믹 페이지는 [].js 페이지로 해당 아이디에 따라 새롭게 생성하는 페이지를 의미합니다. 그렇기 때문에 어떤 id 가 올지 모르기 때문에 기존의 getStaticProps
로 페이지를 생성할 수 없습니다. 그런데 만약 갯수가 한정적이고, 미리 들어올 id를 알 수 있으면 가능합니다.
먼저 위의 3개의 id 만 static 파일을 생성한다고 했을때,
# [id].js - getStaticProps 적용.
const Post = ({item , name}) => {
return <>{ item && (<>
<Head>
<title>{item.name}</title>
<meta name = "description" content ={item.description}></meta>
</Head>
{name} 환경입니다.
<Item item ={item}/></>)}</>
}
export default Post;
export async function getStaticProps(context) {
// context : 여러가지 정보, params, 요청,
const id = context.params.id;
const apiUrl = `http://makeup-api.herokuapp.com/api/v1/products/${id}.json`
const res = await axios.get(apiUrl);
const data = res.data
return {
props: {
item: data,
name: process.env.name
}
}
}
여기에서 👇
# [id].js - getStaticPaths 적용.
const Post = ({ item, name }) => {
return <>{item && (<>
<Head>
<title>{item.name}</title>
<meta name="description" content={item.description}></meta>
</Head>
{name} 환경입니다.
<Item item={item} /></>)}</>
}
export default Post;
export async function getStaticPaths() {
return {
paths: [
{ params: { id: '740' } },
{ params: { id: '730' } },
{ params: { id: '729' } }
],
fallback: false, // fallback : 없는 페이지에 대한 대응을 할지 안할지 설정.
};
}
저렇게 적용을 하면 해당 id 740,730,729 의 상품 페이지는 미리 만들어두지만, fallback
속성이 false 이기 때문에 이 3가지 상품 이외에는 상품 페이지를 만들어 두지 않게 된다.
(3가지 상품페이지만 만들어진 상태.)
이 3가지 제품 말고는 404에러가 발생하게 된다.
그렇다면 저 부분을 true 로 바꾸면???
처음엔 3가지 상품에 대한 파일 밖에 없었지만 , 스크롤을 내릴 수록 해당 상품들의 페이지가 나오게 됩니다.
그리고 속도 역시 어마무시하게 향상이 됩니다. js를 꺼도 정상적으로 나오고 체감이 될정도로 빠릅니다!
🙋 이게 어떻게 가능한겨...??
🤖 Link의 prefetch 덕분임 ㅋ
우리가 썼던 Next Link의 경우엔 prefetch라는 속성이 있는데 디폴트가 true 이고 이 속성의 기능이
첫 화면이나 스크롤을 내렸을 때, 그 viewport 안에 있는 페이지는 모두 프리로드가 됩니다.