인프런 커뮤니티 질문&답변

Moa Kim님의 프로필 이미지
Moa Kim

작성한 질문수

[리뉴얼] React로 NodeBird SNS 만들기

새로 올리신 리액트쿼리 버전에서 getServerSideProps대신 getStaticProps 쓰는 이유가 궁금합니다.

해결된 질문

작성

·

297

0

안녕하세요.

자꾸 귀찮게 해드려서 죄송합니다. 리액트쿼리로 바꾸신거 조금씩 따라하면서 변형하고 있는데

/user/[id]

/post/[id]

에서 getServerSideProps대신 getStaticProps 로 바뀐걸 봤습니다.

정적은 빌드시에 데이터 불러오는거라서 데이터 변경가능성이 있는 post/[id]같은 경우는 정적을 쓰면 안될것같은 느낌인데 

무슨 장점이나 혹시 바꾸신 이유가 있을까요?

 

그리고 queryClient.prefetchQuery에 대해서도 궁금한점이 있습니다.

현재 상품을 등록하는 /item/register.tsx를 작성중이고

로그인된 유저에서 정보를 가져와야 해서 서버사이드 랜더링을 적용중에 있습니다.

 

유저정보를 가져오는 api

export function loadMyInfoAPI() {
  return axios.get('/user').then((response) => response.data);
}

back에서 라우터 부분


// 로그인 유저 정보 얻기
router.get('/', async (req, res, next) => { // GET /user 로그인 유지 위해 로그인한 유저의 정보 전송
  console.log('req.user?', req.user);
  try {
      if (req.user) { // 로그인 됐을경우
        const userDataWithoutPassword = await User.findOne({
          // 프론트로 보낼 유저 정보를 재가공
          where: { id: req.user.id },
          attributes: {
            exclude: ['password'], // 비밀번호 제외
          },
          include: [
            {
              model: User,
              as: "Customers",
              attributes: ["id", "company"],
              exclude: ['UsersRelation'],
            }
          ]
        })
        res.status(200).json(userDataWithoutPassword);
        console.log(JSON.stringify(userDataWithoutPassword));
      } else {
        res.status(200).json(null);
      }
  } catch (error) {
    console.error(error);
    next(error);
  }
});

 

프론트   /item/register.tsx에서 기본 골자는

const Register = () => {
...
  const { data: myUserInfo } = useQuery<User>('user', loadMyInfoAPI);
... 중략
 
  return (
    <AppLayout>
      <div>{JSON.stringify(myUserInfo)}</div><br />
... 중략
        <div>
          <List
            className="demo-loadmore-list"
            itemLayout="horizontal"
            dataSource={myUserInfo.Customers}
            renderItem={(item) => (
              <List.Item
                key={item.id}
                actions={[
                <>
                  <Button type="primary" shape="circle">등록</Button>
                </>
                ]}
              >
                <List.Item.Meta
                  title={
                    <>
                    {item.company}<span> | </span><span>담당자: {item.id}</span>
                  </>}
                />
              </List.Item>
            )}
          />
        </div>

이렇게 로그인된 유저 정보를 출력해주는 부분이 있습니다. myUserInfo.Customers는 me.followers와 흡사한 개념으로 맍들었고요.

 

서버사이드 랜더링은

export const getServerSideProps = async (context: GetServerSidePropsContext) => {
  const cookie = context.req ? context.req.headers.cookie : '';
  axios.defaults.headers.Cookie = '';
  if (context.req && cookie) {
    axios.defaults.headers.Cookie = cookie;
  }
  const response = await loadMyInfoAPI();
  if (!response) {
    return {
      redirect: {
        destination: '/',
        permanent: false,
      },
    };
  }
  return {
    props: {},
  };
};

단순히 로그인체크만 해서 로그인이 안됐을경우 리다이랙트만 해주는 서버사이드랜더링을 하면

back에서   console.log('req.user?', req.user);

값은 정상적으로 user객체를 출력합니다.

프론트 페이지도 정상적으로 데이터가 나오고요.

JSON.stringify(myUserInfo)로 출력한 데이터는

object
 
{9}
 
id
:
tester1
 
company
:
testers
 
name
:
test
 
phone
:
101010
 
email
:
2
 
role
:
NOVICE
 
createdAt
:
2021-12-17T04:43:25.000Z
 
updatedAt
:
2021-12-17T04:43:25.000Z
 
Customers
 
[2]
 
0
 
{2}
 
id
:
ttt3
 
UsersRelation
 
{4}
 
1
 
{2}
 
id
:
tttt
 
UsersRelation
 
{4}
 
createdAt
:
2021-12-17T08:05:07.000Z
 
updatedAt
:
2021-12-17T08:05:07.000Z
 
customerId
:
tttt
 
providerId
:
tester1

이렇게 나옵니다.

물론 데이터를 받아와서 주입해주는 부분이 없기때문에 /item/register로 주소를 쳐서 들어가면 오류가 납니다.

 

데이터를 주입시켜주기 위해 쿼리클라이언트를 사용할 경우 

export const getStaticProps = async () => {
  const queryClient = new QueryClient();
  await queryClient.prefetchQuery(['user'], () => loadMyInfoAPI());
  return {
    props: {
      dehydratedState: JSON.parse(JSON.stringify(dehydrate(queryClient))),
    },
  };
};

back에서 user는 undefined로 나오게 되고 오류가 발생합니다..

어떠한 부분때문에 같은loadMyInfoAPI 를 쓰는데도 불구하고 다른 결과가 나오는지 궁금함니다.

 

 

프론트 터미널의 오류메시지

TypeError: Cannot read property 'Customers' of undefined

    at Register (D:\3programming\excuse_moa\front_rq\.next\server\pages\item\register.js:2657:36)

    at processChild (D:\3programming\excuse_moa\front_rq\node_modules\react-dom\cjs\react-dom-server.node.development.js:3353:14) 

    at resolve (D:\3programming\excuse_moa\front_rq\node_modules\react-dom\cjs\react-dom-server.node.development.js:3270:5)       

    at ReactDOMServerRenderer.render (D:\3programming\excuse_moa\front_rq\node_modules\react-dom\cjs\react-dom-server.node.development.js:3753:22)

    at ReactDOMServerRenderer.read (D:\3programming\excuse_moa\front_rq\node_modules\react-dom\cjs\react-dom-server.node.development.js:3690:29)

    at Object.renderToString (D:\3programming\excuse_moa\front_rq\node_modules\react-dom\cjs\react-dom-server.node.development.js:4298:27)

    at renderPage (D:\3programming\excuse_moa\front_rq\node_modules\next\dist\server\render.js:596:45)

    at Object.ctx.renderPage (D:\3programming\excuse_moa\front_rq\.next\server\pages\_document.js:1161:30)

    at Function.getInitialProps (D:\3programming\excuse_moa\front_rq\.next\server\pages\_document.js:621:19)

    at Function.getInitialProps (D:\3programming\excuse_moa\front_rq\.next\server\pages\_document.js:1169:87)

error - Error: "MyDocument.getInitialProps()" should resolve to an object. But found "undefined" instead.

    at Object.loadGetInitialProps (D:\3programming\excuse_moa\front_rq\node_modules\next\dist\shared\lib\utils.js:75:15)

    at runMicrotasks (<anonymous>)

    at processTicksAndRejections (internal/process/task_queues.js:93:5)

    at async renderDocument (D:\3programming\excuse_moa\front_rq\node_modules\next\dist\server\render.js:609:30)

    at async Object.renderToHTML (D:\3programming\excuse_moa\front_rq\node_modules\next\dist\server\render.js:647:28)

    at async doRender (D:\3programming\excuse_moa\front_rq\node_modules\next\dist\server\next-server.js:1149:38)

    at async D:\3programming\excuse_moa\front_rq\node_modules\next\dist\server\next-server.js:1241:28

    at async D:\3programming\excuse_moa\front_rq\node_modules\next\dist\server\response-cache.js:64:36 {

  page: '/item/register'

}

 

back의 터미널 로그

req.user? undefined

GET /user 200 1.716 ms - 4

 

 

 

답변 1

1

제로초(조현영)님의 프로필 이미지
제로초(조현영)
지식공유자

getServerSideProps 쓰셔도 됩니다. 그냥 공식문서 따라하면서 별 생각 없이 바꿨습니다.

prefetchQuery가 문제가 아니라 axios.defaults.headers.Cookie 쪽 코드를 안 넣으셔서 그렇습니다. 이게 없으면 브라우저에서 프론트서버로 쿠키가 전달이 안 됩니다.

Moa Kim님의 프로필 이미지
Moa Kim
질문자

아~~ 쿠키넣어주니 마법처럼 잘되네요. 어젯밤부터 삽질중이었는데 답변 정말 감사드립니다 ㅠㅠ

Moa Kim님의 프로필 이미지
Moa Kim

작성한 질문수

질문하기