요즘 프로젝트를 Next.js로 진행하고 있어서 새롭게 Next.js를 공부하는 중입니다. 전에는 React나 Vue로 CSR(Client Side Rendering)만을 했었는데 Next.js로 SSR(Server Side Rendering)을 하자니 헷갈리는 부분들이 많았습니다. 특히 Next.js는 SSR 뿐만 아니라 CSR도 지원하기 때문에 각 부분이 SSR로 동작하는지 CSR로 동작하는지 구분이 모호해서 개발을 할 때 많이 해맸습니다. 그래서 이 부분에 대해 확실히 정리하고자 내용을 정리하며 공부했고 지금부터 쓸 내용은 나름대로 제가 정리한 내용을 글로 쓴 것입니다.
CSR과 SSR에서 화면에 렌더링 될 데이터를 어떻게 받아올 것이냐에 초점을 맞추는 것이 둘을 구분하는데 도움이 되겠다는 생각을 했습니다. 그래서 이번 글에서는 Next.js에서 데이터를 받아오는 4가지 방식에 대해서 다루면서 Next.js의 SSR과 CSR에 대해 더 구체적으로 이해하는 시간을 가져보도록 하겠습니다.
Next.js에서 Data를 Fetching하는 방식은 아래의 4가지 방식이 있습니다.
1. CSR(Client Side Rendering)
2. SSR(Server Side Rendering)
3. SSG(Static Site Generation)
4. ISR(Incremental Static Regeneration)
지금부터 하나씩 차례대로 살펴보도록 하겠습니다.
CSR
React를 다루어보신 분들은 알 내용이겠지만 Next.js에서의 CSR은 결국 React의 useEffect를 사용해서 data를 fetch해오는 방식입니다. 코드는 아래와 같습니다.
import { useEffect, useState } from 'react'
import styles from '../styles/Home.module.css'
import axios from 'axios';
export default function Home() {
const [dateTime, setDateTime] = useState(null);
useEffect(async () => {
try {
const response = await axios.get('https://worldtimeapi.org/api/ip');
setDateTime(response.data.datetime);
}
catch (e) {
console.error(e);
}
},[]);
return (
<div className={styles.container}>
{dateTime || "불러오는 중 ..."}
</div>
)
}
이 웹을 동작시켜보면 처음에는 브라우저에 "불러오는 중..."이 뜨다가 api 호출로 response를 받은 후에는 현재 시간이 나타납니다.
CSR 방식은 client side(여기서는 브라우저)에서 페이지가 요청될 때마다 받아온 js 파일로 api 호출을 합니다. 데이터를 받는 과정은 클라이언트가 js 파일을 받은 후 진행되기 때문에 처음에는 데이터가 없는 상태로 "불러오는 중..."이 먼저 뜨게 되는겁니다. 그렇기 때문에 정리하자면 CSR은 화면이 먼저 표시된 다음에 데이터를 받아온다고 생각하시면 되겠습니다.
SSR
SSR 방식은 Next.js에서 제공하는 getServerSideProps라는 async 함수를 사용합니다. 코드는 아래와 같습니다.
import styles from '../styles/Home.module.css'
import axios from 'axios';
export default function Home(props) {
const { dateTime } = props;
return (
<div className={styles.container}>
{dateTime || "불러오는 중 ..."}
</div>
)
}
export async function getServerSideProps() {
const response = await axios.get("https://worldtimeapi.org/api/ip");
return {
props: {
dateTime: response.data.datetime
}
}
}
코드를 실행해보시면 아까와는 다르게 페이지가 로딩 시간을 거친 후 현재시간이 표시되는 것을 알 수 있습니다. "불러오는 중..."이라는 텍스트는 화면에 뜨지 않습니다. 이것은 SSR에서는 브라우저에서 데이터를 받아오는 것이 아니라 서버에서 데이터를 미리 받아서 그 값을 이용해 구성한 html 파일을 브라우저에게 전달해주기 때문입니다. 브라우저는 데이터를 받아올 필요없이 그저 서버에서 보내준 html파일을 렌더링하면 됩니다. 서버에서 데이터를 받아오는 과정은 페이지가 로드되기 전 진행됩니다.
getServerSideProps는 서버에서 실행되는 함수입니다. 그렇기 때문에 저 함수안에 console.log("hello")를 넣어주면 브라우저가 아닌 서버의 콘솔창에 "hello"가 뜨는 것을 확인할 수 있습니다.
SSG
SSG 방식은 Next.js에서 제공하는 getStaticProps라는 async function을 사용합니다. 코드는 아래와 같습니다.
import styles from '../styles/Home.module.css'
import axios from 'axios';
export default function Home(props) {
const { dateTime } = props;
return (
<div className={styles.container}>
{dateTime || "불러오는 중 ..."}
</div>
)
}
export async function getStaticProps() {
const response = await axios.get("https://worldtimeapi.org/api/ip");
return {
props: {
dateTime: response.data.datetime
}
}
}
실행해보면 SSR과 비슷하지만 페이지를 리로드해도 시간이 바뀌지 않는 것을 확인할 수 있습니다.
(Next.js app에서 코드를 실행할 때 yarn dev 명령어를 이용해 실행하고 있다면 페이지를 리로드하면 시간이 바뀝니다. 이는 yarn dev(next dev)로 실행할 경우 getStaticProps()가 매번 실행되도록 되어있기 때문입니다. dev로 실행하지 않기 위해서는 yarn build로 프로젝트를 빌드하신 후 yarn start로 실행하셔야 합니다.)
코드만 보면 그냥 함수 이름만 getServerSideProps()에서 getStaticProps()로 바뀐것을 볼 수 있습니다. 그럼 왜 이런식으로 동작상에 차이가 있는 것일까요? 그것은 getServerSideProps()는 매 페이지 요청마다 서버에서 실행되지만 getStaticProps()는 빌드할 때 한번만 실행되는 함수이기 때문입니다. 그러므로 화면에 표시된 시간을 빌드가 될 때 api 호출을 해서 받아온 데이터(시간)입니다. getStaticProps()는 빌드시 한번만 실행되기 때문에 성능상으로 이점이 있지만 지금과 같은 경우는 getServerSideProps()를 쓰는것이 더 적절해 보입니다.
ISR
ISR은 완전히 새로운 방식은 아니고 getStaticProps()로 빌드시 데이터를 받아오되 일정 시간이 지난 후의 페이지 요청에 대해서는 함수가 다시 실행됩니다. 그 시간을 설정해주는 방법은 아래 코드를 보시면 알 수 있습니다.
import styles from '../styles/Home.module.css'
import axios from 'axios';
export default function Home(props) {
const { dateTime } = props;
return (
<div className={styles.container}>
{dateTime || "불러오는 중 ..."}
</div>
)
}
export async function getStaticProps() {
const response = await axios.get("https://worldtimeapi.org/api/ip");
return {
props: {
dateTime: response.data.datetime
},
revalidate: 5
}
}
yarn build를 다시 하시고 yarn start를 하셔서 페이지에 접속을 한 후 리로드를 계속 해보면 시간이 바뀌지 않지만 어느 시점에 갑자기 바뀝니다. 이것은 우리가 빌드가 된 후 5초 뒤의 요청에 대해서는 빌드를 새로해 getStaticProps()를 다시 실행하도록 revalidate라는 것을 이용해 설정해줬기 때문입니다. 여기서 헷갈리지 말아야 할 점은 매 5초마다 함수가 실행되는 것이 아니라 5초 뒤의 요청이 들어온 시점에 함수가 실행되는 것입니다. 그렇기 때문에 6초뒤에 페이지를 리로드하면 5초 뒤의 시간이 아닌 정확히 6초 뒤의 시간이 표시됩니다. 간단하게 정리하면 마지막 요청을 보내고 일정시간이 지나기 전에는 SSG로 동작하다가 일정시간이 지난 후에는 SSR로 동작을 한다고 생각하시면 되겠습니다.
마무리
지금까지 Next.js에서 데이터를 받아오는 4가지 방법인 CSR, SSR, SSG, ISR에 대해서 살펴보았습니다. 저는 이 4가지 방식을 공부하며 이해한 후로는 Next.js로 개발하는 것이 한결 편해졌고 이슈가 생겼을 때 쉽게 대처할 수 있게 되었습니다. 초보자분이 Next.js로 코드를 짜다가 자주 실수하는 부분이 Client Side에서 돌아가는 함수가 아닌 getStaticProps나 getServerSideProps에서 client의 로직을 짜는 것입니다. 하지만 이 글을 읽고 조금 더 Next.js에서 클라이언트에서 돌아가는 부분은 무엇이고 서버에서 돌아가는 부분은 무엇인지, 그리고 각 로직은 언제 실행이 되는것인지 이해가 되셨길 바라고 Next.js로 좀 더 수월하게 개발하셨으면 좋겠습니다.
그럼 저는 이만.
'개발 공부 > WEB' 카테고리의 다른 글
[React] <></>에 key props 추가하는 방법 (0) | 2022.03.30 |
---|---|
[React] 배열 렌더링 시 key props를 사용하는 이유 (0) | 2022.03.27 |
[React] setState가 바로 적용되지 않는 이유 (1) | 2022.02.12 |
[주니어 개발자의 퇴근 후 글쓰기] Spring Framework (0) | 2021.12.07 |
글자수 세기 웹페이지 만들기 (2) | 2020.08.27 |