렌더링 방식을 결정하는 Next.js의 데이터 호출 메서드 - getServerSideProps, getStaticProps 사용기, params, query props 사용하기

GY·2022년 2월 17일
0

Next.js

목록 보기
1/7
post-thumbnail

❓ 어디서 어떻게 사용하면 될까?

의외로 당황했던 부분은, 이 메서드를 쓰는 방법은 알겠는데 그래서 어디에서 선언해주어야 하는 것인지, 이 메서드에서 호출한 데이터를 어디에서 어떻게 props로 전달받아 사용하는 것인지 모르겠다는 것이었다. 다른 코드들을 구글링해서 찾아봐도 이 부분에 대해서는 알기 어려웠다. 아마 다른 사람들에게는 너무나 당연한 부분인데, 나 혼자 몰랐나 보다.

그래서! 내가 정리해야겠다!
나 같은 사람이 또 있다면 참고할 수 있도록!

컴포넌트 선언문 밖에다가 적어주면 된다. 당연한 말이지만 컴포넌트 export문 위,아래 상관 없이 컴포넌트 밖에 적어주면 된다.

  return (
 // 생략
  );
}

export const getStaticProps: GetStaticProps = async () => {
// 생략
};

export default Contacts;

// 여기에도 작성해도 된다.

그리고 이 데이터를 사용할 컴포넌트에서 props를 그대로 사용하면 되는데, 구조분해 할당을 원한다면 다음과 같이 일반적으로 props를 전달받을 때와 동일하게 작성해주면 된다.

function Contacts({ qaTypes, qas }) {

그럼, 어떻게 사용했는지 알아보자.

이번 프로젝트에서 맡은 페이지는 고객센터 페이지와 상품 목록 페이지 2개였다.

  • 고객센터 페이지는 정적 렌더링을,
  • 상품 목록 페이지는 서버 사이드 렌더링을 사용하기로 결정했다.

페이지 별 렌더링 방식을 결정한 내용과, 전체 프로젝트에 대한 내용은 아래 회고 포스팅에 담았다.
👉 포스팅 보러가기


1️⃣ 고객센터 페이지 - 정적 렌더링: getStaticProps

getStaticProps는 빌드 시점에 api를 호출하고 데이터를 응답 받아서 HTML 을 완성하는 정적생성을 위한 메서드이다.
GetStaticProps 타입을 지정해준다음 원하는 데이터를 호출하고, 응답값을 return 문 내에서 props에 지정해준다.

export const getStaticProps: GetStaticProps = async () => {
  const qaType = {
    buy: 1,
    sell: 2,
  };
  const qaTypesRes = await axios.get(FAQ_TYPE);
  const buyQaRes = await axios.get(FAQ_CONTENT(qaType.buy));
  const sellQaRes = await axios.get(FAQ_CONTENT(qaType.sell));

  return {
    props: {
      qaTypes: qaTypesRes.data.qaTypes,
      qas: {
        1: buyQaRes.data.qas,
        2: sellQaRes.data.qas,
      },
    },
  };
};

export default Contacts;

2️⃣ 목록페이지 - SSR: getServerSideProps

사실 메서드 이름만 다를 뿐 사용법은 똑같다.

context 파라미터

getServerSideProps는 context라는 인자를 받는다.

export async function getServerSideProps(context) {
  return {
    props: {
    //
    }
  }
}

context 안에는 다음과 같은 파라미터들이 포함되어 있다.

  • params: 페이지가 다이나믹 라우팅되었을 경우 파라미터를 담는다.
  • query: URL의 쿼리스트링을 담는다
  • req: HTTP Request 객체
  • res: HTTP Response 객체
  • preview: 페이지가 프리뷰 모드인지 아닌지 여부
  • previewData: setPreviewData 메서드에 의해 셋팅되는 값

getServerSideProps 메서드는 페이지가 호출될 때마다 요청된다.따라서 request 파라미터도 포함되어 있다.

이번 프로젝트에서는 params와 query만 사용해보았다.
나머지 파라미터에 대해서는 아직 잘 모르겠지만, 기회가 될 때 사용해보며 공부해봐야겠다.

### ❗️ params, query로 router.query 대체하기

>프로젝트 진행에서 문제가 되는 부분이 있었다.
홈 페이지 > 브랜드 페이지 > 목록 페이지 순으로 이동하면서 보여주어야 했다.

1. 홈 페이지에서 카테고리1, 즉 카페나 편의점을 선택하면
브랜드 페이지에서 해당 카테고리1에 해당하는 브랜드들을 보여준다. 
- 예:카페클릭 -> 스타벅스, 투썸 플레이스 등 카페 브랜드 표시
2. 이 브랜드를 클릭하면 해당 브랜드의 기프티콘 상품을 보여준다. 
- 예: 스타벅스 클릭 -> 스타벅스 기프티콘 목록 표시
![](https://velog.velcdn.com/images%2Fgygy%2Fpost%2Ff4e5f7bb-d396-49c4-aaf2-8fc245b1924d%2Fezgif.com-gif-maker%20(18).gif)

데이터 모델은 conCategory1과 conCategory2 두개의 뎁스로 이루어져있었다.

목록 페이지에서 상품목록들을 보여주려면 이 2개의 id가 필요했다.
카페 -> 스타벅스의 상품들을 모여주려면
conCategory1인 카페의 id 67, conCategory2인 스타벅스의 id 63이 필요했다.

{
"conCategory1": {
"id": 67,
"name": "카페",
"discountRate": 50,
"imageUrl": "imgsrc.jpg",
"conCategory2s": [
{
"id": 63,
"name": "스타벅스",
"conCategory1Id": 67,
"imageUrl": "imgsrc.jpg",
"conItems": [
{
"id": 137,
"name": "카페아메리카노 T",
"originalPrice": 4500,
"minSellingPrice": 3830,
"count": 15719,
"imageUrl": "imgsrc.jpg"
},
{
"id": 3308,
"name": "무료음료쿠폰 Tall (추가결제시 사이즈업가능)",
"originalPrice": 6300,
"minSellingPrice": 4850,
"count": 2609,
"imageUrl": "imgsrc.jpg"
}
]


브랜드 페이지에서 해당 conCategory1의 id와 클릭한 conCategory2의 id는 쿼리스트링으로 Link 태그를 통해 넘겨주었고, 이것을 Next.js에서 제공하는 useRouter()메서드를 사용해 router.query를 받아오려고 했다.

> 문제는!

query 값이 받아와지지 않아 데이터 호출을 할 수 없었던 것이다.

router.query의 값은 페이지가 2번 렌더링되면서 undefined였다가 이후에 맞는 값이 할당된다.
그런데 그전에 데이터를 받아와 화면을 그려야 하고,, 이 id값을 파라미터로 사용해야 했기 때문에 데이터 호출에서 에러가 발생했다.

> 이 문제, 어떻게 해결했을까?

바로 getServerSideProps의 params,와 query라는 props를 사용하는 것!

- params: 현재 url의 파라미터를 받아올 수 있다.
- query: 현재 url의 쿼리파라미터를 받아올 수 있다.

```tsx
export const getServerSideProps: GetServerSideProps = async ({
  params,
  query,
}) => {
  const res = await axios.get(
    `https://api2.ncnc.app/con-category1s/${params.id}/nested`,
  );
  return {
    props: {
      query: query.conCate2,
      data: res.data,
    },
  };
};

예를 들어,
url/brands/67?conCate2=63
이렇게 conCategory1과 conCategory2의 id값을 쿼리스트링으로 넣었다고 하자.
그러면 params에는 {id: 67}
query에는 {conCate2: 63}
의 데이터가 담긴다.

(참고로 이 목록페이지는 brands/[id].tsx로 동적 라우팅을 했기 때문에 params에 id라는 key로 값이 담긴다.)

그러면 해당하는 params로 conCategory1의 id값을 넣어 데이터를 호출해 사용할 수 있다.
query로 전달되는 conCategory2는 이 conCategory1에 해당하는 데이터 중 특정 브랜드의 상품만 필터링하기 위해 필요했기 때문에, 페이지내에서 사용할 수 있도록 함께 props로 전달해주었다.



Reference

profile
Why?에서 시작해 How를 찾는 과정을 좋아합니다. 그 고민과 성장의 과정을 꾸준히 기록하고자 합니다.

0개의 댓글