본문으로 바로가기

Link

https://nextjs.org/docs/api-reference/next/link

 

Link는 내부는 어떠한 태그도 가능합니다만 관습적으로 a 태그를 사용합니다.

import Link from "next/link";

<Link href="....">
  <a>이동</a>
</Link>

 

특징 1)

Link가 좋은 점은 프로덕션 모드에서 뷰포트에 Link 컴포넌트가 보일 때마다 prefetch를 한다는 것입니다. 그 결과 Link를 눌렀을 때 로딩없이 즉시 이동할 수 있도록 합니다. 사용자 입장에서는 엄청 빠른 것으로 보이죠!

 

Furthermore, in a production build of Next.js, whenever Link components appear in the browser’s viewport, Next.js automatically prefetches the code for the linked page in the background. 

 

특징 2)

외부 링크에는 <a> 태그를 사용합시다.

If you need to link to an external page outside the Next.js app, just use an <a> tag without Link.

 

특징 3)

Link 자체에는 classname이나 style이 먹지 않습니다. Link 내부 태그에 먹여줍시다.

<Link href="/">
  <a className="foo" target="_blank" rel="noopener noreferrer">
    Hello World
  </a>
</Link>

 

 

 


 

(outdated) 다이나믹 라우팅으로 인해 아래 방식을 굳이 사용할 이유가 없어졌습니다.

 

darrengwon.tistory.com/745

 

만약 특정 정보를 받아와야해서 프론트 서버로 링크를 연결한다면 정상적으로 작동은 하지만 이동시 새로고침이 되어버린다. SPA 라는 웹 특성상 새로고침은 가급적 막아야 한다.

/server.js
server.get('/user/:id', (req, res) => app.render(req, res, '/user', {id: req,params.id})});

// 프론트 서버로 Link를 연결 => 이동은 정상적이나 새로고침 됨
<Link href={`/user/${User.id}`}><a>링크</a></Link>

아래와 같이 href를 pathname과 query로 이루어진 객체로 전달하게 되면 새로고침이 되지 않습니다.

이 방시은 url이 /user/?xxx 꼴로 쿼리스트링이 붙게 됩니다.

<Link href={{pathname: "/user", query: {id: User.id}}} ><a>링크</a></Link>

쿼리스트링이 붙지 않은 채 깔끔한 url을 만들고 싶다면 Link의 as 속성을 이용하면 됩니다.

<Link href={{pathname: "/user", query: {id: User.id}}} as={`/user/${User.id}`}><a>링크</a></Link>

 


 

 

prefetch를 이용해 일반 SPA가 작동하는 것 처럼 다른 페이지를 초반 로드할 때 미리 가져올 수 있습니다.

(사실 사용할 일이 별로 없습니다)

 

물론 프로덕션 레벨에서는 뷰포트 내에 Link 컴포넌트가 넘어왔을 때 자동 로드하지만 prefetch는 보이기도 전에 로드한다는 점이 다릅니다.

 

문제는, 이 방식을 이용할 경우 코드스플리팅이 의미가 없어진다는 것입니다.

따라서 Link에 prefetch를 적용할만한 경로는 사용자가 자주 접근할만한 곳에만 둬야 합니다.

 

<Link href="/profile" prefetch>
  <a>
    프로필
  </a>
</Link>

 

 

 

router

https://nextjs.org/docs/api-reference/next/router

history.push 등의 기능을 담고 있음

import { useRouter } from 'next/router'

function ActiveLink({ children, href }) {
  const router = useRouter()

  const handleClick = (e) => {
    e.preventDefault()
    router.push(href)
  }

  return (
    <a href={href} onClick={handleClick} >
      {children}
    </a>
  )
}

export default ActiveLink

 

다음과 같이 쿼리를 살어보낼 수도 있음.

router.push({
  pathname: `/board/${Post.section}/write`,
  query: { id: Post._id },
});

 

쿼리를 클라이언트단에서 받고 싶다면 router에서 빼다 쓰면되고

import { useRouter } from 'next/router';

const PostDetailPage: NextPage<{}> = () => {
  const router = useRouter();

  return (
    <div>
      <Link href="/">
      	<a>홈으로</a>
      </Link>
      <br />
      // router.query를 통해 query 값을 클라이언트 단에서 사용 가능
      Post ID: {router.query.id}
    </div>
  );
};

export default PostDetailPage;

 

SSR 단에서 쓰고 싶다면 context에서 빼다 쓰면 됩니다.

export async function getServerSideProps(context) {
  const { id } = context.query;

  return { props: {} };
}

 

 

Head

https://nextjs.org/docs/api-reference/next/head

html head 부분 코드 변경 가능

즉, meta와 title, link 부분을 작성할 수 있다는 것입니다.

기존에 사용하던 react-helmet과 같은 기능을 합니다. 찾아보니 SO에서는 So no, you don't need to use react-helmet if you are using Next.js. Just use next/head. 라는 군요!

import Head from "next/head";

<Head>
  <title>무언가의 제목</title>
  <link ...>
</Head>

 

 

이게 참 좋은 점이, 각 페이지마다 다른 og:title, image를 지정할 수 있다는 것입니다. 페이지 수가 많은 커뮤니티형 웹에서 사용하면 좋을 것 같습니다.

 

<Head>
  <meta property="og:title" content="My new title" key="title" />
</Head>

 

 

dynamic

말 그대로 다이나믹 import를 할 수 있게 해준다.

https://nextjs.org/docs/advanced-features/dynamic-import

 

Next.js supports ES2020 dynamic import() for JavaScript. With it you can import JavaScript modules (inc. React Components) dynamically and work with them. They also work with SSR.

 

You can think of dynamic imports as another way to split your code into manageable chunks.

 

React에서 했던 것처럼 다이나믹 import를 통해 page 폴더 외부에서 다른 컴포넌트를 대상으로 코드 스플리팅을 구현할 수 있게 되었다.  

import dynamic from 'next/dynamic'

const DynamicComponent = dynamic(() => import('../components/hello'))

function Home() {
  return (
    <div>
      <Header />
      <DynamicComponent />
      <p>HOME PAGE is here!</p>
    </div>
  )
}

export default Home

 

그러나 위와 같은 단순한 다이나믹 import 외에도 여러 기능이 있는데 import 로더와 SSR 제외 기능이 있다.

아래와 같이 ssr, loading에 대한 정보를 주면 된다.

import dynamic from "next/dynamic";

const QuillNoSSRWRapper = dynamic(import("quill"), {
  ssr: false,
  loading: () => <span>loading...</span>,
});

 

 

 

error

https://darrengwon.tistory.com/752

 

 

관련 내용을 다른 포스트에서 정리했습니다.

음.. 주의점은, errorCode를 핸들링하는 로직을 컴포넌트 내 최상위에 두어야 한다는 것입니다.

import Error from 'next/error'

export async function getServerSideProps() {
  const res = await fetch('https://api.github.com/repos/vercel/next.js')
  const errorCode = res.ok ? false : res.statusCode
  const json = await res.json()

  return {
    props: { errorCode, stars: json.stargazers_count },
  }
}

export default function Page({ errorCode, stars }) {
  if (errorCode) {
    return <Error statusCode={errorCode} />
  }

  return <div>Next stars: {stars}</div>
}

 

 

Image

이미지 최적화에 사용됩니다. 별도의 포스트에 정리하였습니다.

import Image from 'next/image'

function Home() {
  return (
    <>
      <h1>My Homepage</h1>
      <Image
        src="/me.png"
        alt="Picture of the author"
        width={500}
        height={500}
      />
      <p>Welcome to my homepage!</p>
    </>
  )
}

export default Home

 

 

amp

https://nextjs.org/docs/api-reference/next/amp

아직 사용해 본 경험이 없습니다..


darren, dev blog
블로그 이미지 DarrenKwonDev 님의 블로그
VISITOR 오늘 / 전체