Next 프로젝트를 처음 생성하고, 초기 세팅되어있던 페이지들을 하나씩 뜯어보면서 구조를 파악하는 중이다. 그러다가
pages/users/[id].tsx에서 다음과 같은 함수를 발견했고, 아마 데이터를 가져오는데 있어서 build time에 가져오도록 하는 그런 함수인듯 싶어서 찾아봤다.
들어가기 전
CSR : 첫 렌더시에는 페이지 로드만 수행, 다시 렌더링할 때 데이터를 불러온다. 그래서 데이터가 검색엔진에 걸리지 않는다. 대신에 데이터를 한번에 가져오기 때문에 페이지 이동시에는 속도가 빠르다.
SSR : 첫 렌더시에 데이터도 같이 가져온다. 렌더를 한번만 수행하기 때문에 초기 로딩 속도가 빠르고, 검색 엔진에 데이터가 걸린다. 그러나 페이지를 이동할때마다 매번 데이터를 불러오기 때문에 페이지 이동 시 속도가 느리다.
NextJS는 SSR 기반이지만, 페이지가 로드된 이후에는 React에서 CSR을 이용하는 방식을 사용한다.
1. pages폴더 안에 폴더를 생성하면, 안에 있는 페이지들은 서버측에서 먼저 로드해준다.
2. 페이지가 로드된 이후에 동적인 데이터를 가져오는 과정은 CSR방식을 사용한다. 그렇게 때문에 데이터는 페이지가 로드된 이후에 다시 렌더되면서 불러온다. 검색엔진에 걸리지 않는다.
=> 페이지가 로드될 때 데이터도 가져오도록 하려면(SSR 방식을 사용하려면) NextJS의 데이터 패칭 함수들을 사용해서 처음 렌더시에 데이터를 불러올 수 있도록 해줘야한다.
페이지 로드 순서
1. Next 서버에서 GET요청이 들어오면 URL에 맞는 Page를 찾는다.
2. _app.tsx에 getInitialProps 함수가 있다면 실행한다. (공통적인 데이터를 불러올 때 사용하기 좋음 => 리덕스??)
3. 각 Page Component에 있는 getInitialProps 를 실행한다.
4. _document.tsx의 getInitialProps 를 실행한다.
5. props는 _app.tsx -> page Component 순서로 렌더링한다.
6. 마지막에 _document.tsx를 통해 html 형태로 출력한다.
Data PreRendering
Next 9.3버전 이전에는 getInitialProps 함수로만 데이터 패치를 했다. 9.3버전 이후로는 이제 getStaticProps, getStaticPath, getServerSideProps 로 세분화되었다.
Next는 데이터 요구 사항이 없는 경우 페이지가 정적인지 자동으로 확인하고, getInitialProps, getServerSideProps 를 사용하지 않는다면 페이지는 정적 HTML로 사전에 렌더링해서 자동으로 페이지를 최적화한다. (자동 정적 최적화)
_app.tsx에서 getInitialProps를 사용해서 모든 페이지에서 사용하는 데이터를 지정할 수 있으나, 자동 정적 최적화가 일어나지 않기 때문에 모든 페이지가 SSR을 통해 제공된다.
=> getInitialProps를 사용하면 getStaticProps나 getServerSideProps를 지원하지 않는다.
기본적으로 4개의 메소드는 리턴한 값을 해당 컴포넌트의 props로 전달한다.
1. getInitialProps
- context를 기본 props로 받는다.
- context 내부에는 ctx객체와 Component가 존재한다.
- Component는 해당 컴포넌트(함수가 존재하는 컴포넌트), ctx는 객체로 현재 pathname, query등을 포함하고 있다.
- asPath : 전체 path로 /user?mode=user 로 접속하면 /user?mode=user
- pathname : 현재 path /user?mode=user 로 접속하면 /user
- query : query를 객체 형태로 제공 {mode : user}
- req
- res
- err
=> 굉장히 제한적이기 때문에 Next에서는 getInitailProps함수보다는 그 외의 함수들을 사용하는 것을 권장한다.
2. getStaticProps
빌드시 고정되는 값으로 빌드 이후에는 수정 불가
기본적으로 context 객체를 인자로 받는다.
context 객체 구성
- params : 동적 라우트 페이지면, 라우트의 파라미터 정보(Link에서 params를 전달 받는 경우를 말하는 것 같다.) - req
- res
- query
- preview
- previewData
반환값
- props (optional) : 컴포넌트로 리턴할 값
- revalidate (optional) : 페이지가 재생성되는 시간(sec), 기본값은 false
- notFound (optional) : boolean값
데이터를 빌드시에 가져와서 static하게 제공하기 때문에 빠른 속도로 페이지가 렌더된다.
주로 매 요청마다 fetch할 필요가 없는 데이터를 가진 페이지를 렌더링할 때 사용한다.
기본 프로젝트에 있던 함수를 분석해보면 다음과 같다.
export const getStaticProps: GetStaticProps = async ({ params }) => {
//구조분해할당을 사용해서 params를 바로 가져옴
try {
const id = params?.id;
const item = sampleUserData.find((data) => data.id === Number(id));
return { props: { item } }; //컴포넌트에 props로 item을 반환
} catch (err: any) {
return { props: { errors: err.message } };
}
};
3. getStaticPaths
페이지가 동적 라우팅을 사용하며, getStaticProps를 사용하면, 빌드시에 정적으로 렌더링할 경로를 설정해야한다. 정의하지 않는 하위 경로는 접근해도 화면이 드지 않는다. 라우팅되는 경우의 수 모두 작성해야한다.
export const getStaticPaths: GetStaticPaths = async () => {
// Get the paths we want to pre-render based on users
const paths = sampleUserData.map((user) => ({
params: { id: user.id.toString() },
}));
// We'll pre-render only these paths at build time.
// { fallback: false } means other routes should 404.
return { paths, fallback: false };
};
위의 코드를 분석해보자면 저 함수가 작성된 컴포넌트의 위치는 /user/[id].tsx이다.
그래서 id에 올 수 있는 모든 변수들을 가져오는 것이다. 해당 컴포넌트에서는 이미 작성해둔 정적 데이터(sampleUserData)를 사용하기 때문에 해당 데이터에서 모든 id를 가져온다.
주의해야할 점은 값은 무조건 String 타입을 가져야한다.
반환 값
- paths : 경로들
- fallback : paths이외의 경로가 들어올 때는 설정한다. false로 설정하면 404가 뜬다.
4. getServerSideProps
빌드와 상관없이, 매 페이지 요청마다 데이터를 가져온다.
기본적으로 context 객체를 인자로 받는다.
반환값
- props (optional) : 컴포넌트로 리턴할 값
- redirect (optional) : 값 내부와 외부 리소스 redirect을 허용한다.
- notFound (optional) : boolean값
=> 간단하게 찾아봤지만 아직 어렵다,, 더 공부할 예정
참고
'개발 공부 > Next JS' 카테고리의 다른 글
[노마드코더] NextJS 시작하기 #4 (0) | 2022.04.09 |
---|---|
[노마드코더] NextJS 시작하기 #3 (0) | 2022.04.08 |
[노마드코더] NextJS 시작하기 #2 (0) | 2022.04.07 |
[노마드코더] NextJS 시작하기 #1 (0) | 2022.03.22 |
[WEB] Next.js + Typesctipt + StyledComponents 프로젝트 생성하기 (0) | 2022.03.15 |