[Next] NextJS 페이지간 query 데이터 이동방법 (Link, next/router)

김정민·2022년 6월 13일
15
post-custom-banner

Next에서 페이지를 전환하면서 간단하게 데이터를 전송하는 방법을 알아보려고 합니다.
대표적으로 두가지 방법이 존재합니다 Link 태그를 이용하는 방법과 router객체를 이용하는 방법입니다.

Link 태그를 이용

Next 에서 클라이언트 사이드에서 경로간의 이동은 Link컴포넌트를 통해 이루어질 수 있다.

Link 는 다음과 같은 props를 허용

  • href - 이동할 경로 혹은 URL. 유일한 필수 prop. (필수이기 때문에 href를 안 적으면 에러난다)
  • as - 브라우저 URL 표시 줄에 표시 될 경로에 대한 선택적 데코레이터. Next.js 9.5.3 이전에는 동적 경로에 사용되었으므로 이전 문서 에서 작동 방식을 확인하길 바란다.
  • passHref - href property를 Link 자식에게 강제로 전달하게 한다. 기본값은 false.
  • prefetch - 백그라운드에서 페이지를 미리 가져온다. 기본값은 true. 뷰 포트에 있는 모든 항목(초기에 혹은 스크롤을 통해)이 미리 로드 된다. prefetch={false}를 통해 프리페치를 비활성화할 수 있다. 정적 생성을 사용하는 페이지는 더 빠른 페이지 전환을 위해 데이터가 포함된 JSON파일을 미리 로드한다.
  • replace - history 스택(방문 기록)에 새 url을 추가하는 대신 현재 상태를 변경한다. 기본값은 false
  • scroll - 페이지 전환 후 페이지 상단으로 스크롤할지 여부. 기본값은 true.
  • shallow - getStaticProps, getServerSideProps, getInitialProps을 다시 실행하지 않고 현재 경로를 업데이트. 기본값은 false.

정말 다양한 props들이 있는데 이번에는 데이터를 가지고 이동하는 방법을 알아보는 것이니 href, as 를 중심으로 알아보자

import Link from 'next/link'

function Posts({ posts }) {
  return (
    <li key={post.id}>
        <Link href={`/blog/${post.id}`}>
          <a>{post.title}</a>
        </Link>
    </li>
      ))}
  )
}

export default Posts

해당 코드는 데이터를 별도로 가지고 보내지않는 일반적인 Link 사용법이다,

import Link from 'next/link'

function Home() {
  return (
    <ul>
      <li>
        <Link
          href={{
            pathname: '/about',
            query: { name: 'test' },
          }}
        >
          <a>About us</a>
        </Link>
      </li>
      <li>
        <Link
          href={{
            pathname: '/blog/[slug]',
            query: { slug: 'my-post' },
          }}
        >
          <a>Blog Post</a>
        </Link>
      </li>
    </ul>
  )
}

export default Home

위에 query에 담아서 이동을 할 수 있다.

위의 예는 다음 링크를 가진다:

  • 미리 정의된 경로: /about?name=test
  • 동적 경로: /blog/my-post

하지만 이렇게되면 사용자 url에 query에 데이터가 전부 노출된다.
그리고 또한 보내고 싶은 data가 Object형태일 경우 string으로 변환을 해주어야한다. 이를 JSON.stringify를 사용해서 변환할 수 있는데 그러면 URL의 길이가 어마해진다.

그러므로 해결을 위해 as props를 추가해서 방지해주자

import Link from 'next/link'

//생략
        <Link
          href={{
            pathname: '/about/question/[name]',
            query: { post: JSON.stringify(post) },
          }}
          as={`/about/question/${post.name}`}
        >
          <a>About us</a>
        </Link>

  //생략


export default Home
  • href : 실제 URL 주소
  • as : masking되어 브라우저의 URL 바에 보여질 주소

as는 간단하게 Route Masking 으로 표현할 수 있다.

router 이용 (useRouter hook)

이번에는 경로 정보를 담고 있는 라우터 객체를 한번 살펴보도록 하겠습니다.

라우터 객체는 next/router 모듈에서 useRouter 훅을 불러와 사용할 수 있습니다.

import { useRouter } from 'next/router';

export default function Home() {
  const router = useRouter();
  console.log(router);
  // ...
}

router 를 콘솔로 찍어보면 아래와 같은 객체가 나타난다.

  • asPath - string - basePath 또는 locale 없이 브라우저에 표시되는 경로 (쿼리포함)
  • basePath - string - 활성 basePath (활성화 된 경우)
  • defaultLocale - string - 현재 기본 locale (활성화 된 경우)
  • isFallback - boolean - 현재 페이지가 fallback 모드인지 여부
  • isPreview - boolean - 앱이 현재 미리보기 모드인지 여부
  • isReady - boolean - 라우터 필드가 클라이언트 측에서 업데이트되고 사용할 준비가 되었는지 여부. useEffect 메소드 내에서만 사용해야하며 서버에서 조건부로 렌더링 하는 데에 사용해야한다.
  • locale - string - 활성 로케일 (활성화 된 경우)
  • locales - string[] - 지원되는 모든 로케일 (활성화 된 경우)
  • pathname - string - 현재 경로. 이는 /pages 의 페이지 경로이며(파일명) 구성된 basePath 또는 locale 은 포함되지 않는다.
  • query - object - 객체로 구문 분석 된 쿼리 문자열. 페이지에 데이터 가져오기 요구사항이 없는 경우 사전 렌더링 중에 빈 객체가 된다. 기본값은 {}
    ⇒ 동적 라우팅 사용시 쿼리값이 객체로 들어감.

router에 메서드도 어마하게 많지만 데이터 전송하는 방법만을 다루겠습니다.

router.push

💡 클라이언트 사이드 라우팅을 처리한다. next/link 로 충분하지 않은 경우에 유용하다.

router.push(url, as, options)
  • url - 이동할 경로
  • as - 브라우저에 표시될 URL에 대한 선택적 데코레이터.
  • options - 다음 구성 옵션이 있는 선택적 객체
    - scroll - 기본 값은 true. 선택 boolean. 이동 후 페이지를 상단으로 스크롤 제어.
    - shallow - 기본 값은 false. getStaticProps, getServerSideProps 또는 getInitialProps 를 다시 실행하지 않고 현재 페이지의 경로를 업데이트.
    - locale - 선택적 문자열. 새 페이지의 로케일을 나타낸다.

기본적인 push

import { useRouter } from 'next/router';

export default function Page() {
  const router = useRouter();
  return (
    <button type="button" onClick={() => router.push('/about')}>
      Click me
    </button>
  )

query로 data 넘기기 (with URL Object)

💡 next/link 에서 사용한 것처럼 URL 객체를 사용할 수 있다.

import { useRouter } from 'next/router'

export default function ReadMore({ post }) {
  const router = useRouter()

  return (
    <button
      type="button"
      onClick={() => {
        router.push({
          pathname: '/post/[pid]',
          query: { pid: post.id },
          },
		  "/order"
        )
      }}
    >
      Click here to read more
    </button>
  )
}

두번째 인자로 마스킹까지 해주었다.

개인적으로 Link는 클릭 시 별도의 동작이 필요없고 넘겨주기만 하면될 때 저렇게 Link사용하며,
클릭 시 부가적인 함수나 동작이 실행되고 페이지넘겨줘야할 때 router.push를 사용한다

같이보면 좋은 포스팅

Link 공식문서
https://kimsangyeon-github-io.vercel.app/blog/2021-07-28-nextjs-router

post-custom-banner

1개의 댓글

comment-user-thumbnail
2022년 10월 25일

자세한 글 감사합니다~ 도움이 되었습니다.
[slug] 컴포넌트에서 query 꺼내쓰는 방법도 알고 싶어요

답글 달기