[Next.js] next/link - <Link> 태그
🤔 서론
본래는, Next 스터디를 진행하면서 <Link>에 Styled-Components를 적용하며 겪었던 이슈를 정리하려는 포스팅이었다.
그런데, Next를 처음 공부할 때에도 next/link를 정리한 적이 없어 이번 기회에 한 번 전체적으로 제대로 공부해보고자 한다!
🤍 next/link 및 <Link> 태그
Next.js에서 페이지 간의 링크전환에 <Link> 태그를 주로 사용한다.
페이지 리렌더링 없이 이동시켜주는 SPA 동작을 담당하며, <a> 태그로 전환되어 SEO에 적합하거나 다음 페이지를 prefetch 하는 등의 장점이 있다.
그렇기에 네비게이션 바에서 많이 볼 수 있으며, 아래와 같이 사용될 수 있다.
(pages 폴더 내 index.tsx, about/index.tsx, blog/[slug].tsx 세 가지 페이지에 대한 라우팅을 제공하는 예시)
import Link from 'next/link'
function Navbar() {
return (
<ul>
<li>
<Link href="/">
<a>Home</a>
</Link>
</li>
<li>
<Link href="/about">
<a>About Us</a>
</Link>
</li>
<li>
<Link href="/blog/hello-world">
<a>Blog Post</a>
</Link>
</li>
</ul>
)
}
위처럼, <Link> 태그를 사용하고 href로 이동할 path를 지정하면 <a> 태그와 유사하게 동작한다. <Link> Props는 아래가 있다.
- href : 이동할 경로 혹은 URL (필수값이므로 누락 시 에러 발생)
- as : 브라우저 URL 표시줄에 노출될 경로에 대한 선택적 데코레이터 (Next.js 9.5.3 전에는 동적경로로 사용됨)
- passHref : href 프로퍼티를 <Link> 자식에게 강제로 전달. 기본값은 false.
- prefetch : 뷰포트에서 경로에 해당하는 페이지들을 백그라운드에서 미리 가져온다. 기본값은 true.
- replace : history 스택(방문기록) 마지막 기록을 현재 페이지로 대체한다. 기본값은 false.
- scroll : 페이지 전환 후 상단으로 스크롤할지 여부. 기본값은 true.
- shallow : SSR을 다시 실행하지 않고 현재 경로를 업데이트. 기본값은 false.
- locale : 링크에 locale을 추가해준다. (Next 10부터 추가)
<Link> 태그는 웹에서 렌더링 될 때는 <a> 태그로 전환된다.
- Dynamic Routes(동적 경로)로 이동
import Link from 'next/link'
function Posts({ posts }) {
return (
<ul>
{posts.map((post) => (
<li key={post.id}>
<Link href={`/blog/${encodeURIComponent(post.slug)}`}>
<a>{post.title}</a>
</Link>
</li>
))}
</ul>
)
}
export default Posts
Next.js 9.5.3 이후 동적경로에 연결할 때 특별히 해야할 일이 없다. (경로를 캐치하는 등)
하지만, 보간(interpolation)이나 URL 객체로 링크를 생성하는 것은 권장하는 편이라고 한다.
- 자식이 <a> 태그로 감싸진 커스텀 컴포넌트인 경우
어떻게 보면 이 포스팅을 정리하게 된 시발점이라고 할 수 있겠다.
Styled-Compoents로 스타일하는 경우 React-Router 에서는 <Link> 태그를 styled(Link)로 커스텀이 가능했으나, Next.js는 이를 지원하지 않았다.
그렇기에, 내부에 <a> 태그 기반의 Styled-Components를 넣고 여기에 passHref로 링크를 전달해주는 게 일반적이다.
import Link from 'next/link'
import styled from 'styled-components'
const RedLink = styled.a`
color: red;
`
function NavLink({ href, name }) {
// Must add passHref to Link
return (
<Link href={href} passHref>
<RedLink>{name}</RedLink>
</Link>
)
}
export default NavLink
passHref를 전달하지 않으면 Shift or Ctrl + 클릭이 되지 않아 UX에 좋지 않으며, <a> 태그에 href가 없어 SEO 손상이 될 수 있다.
* 참고 : emotion의 JSX Pragma(@jsx jsx)를 사용한다면, <a> 태그를 직접 사용하더라도 passHref가 필요
- 자식이 함수형 컴포넌트인 경우
import Link from 'next/link'
const MyButton = React.forwardRef(({ onClick, href }, ref) => {
return (
<a href={href} onClick={onClick} ref={ref}>
Click Me
</a>
)
})
function Home() {
return (
<Link href="/about" passHref>
<MyButton />
</Link>
)
}
export default Home
<Link> 내부에 함수형 컴포넌트가 적용된 경우, passHref와 더불어 forwardRef() 로 자식 컴포넌트를 감싸야한다.
* forwardRef() 참고 링크 : https://abangpa1ace.tistory.com/270
- URL 객체 사용
<Link> 또한 URL 객체를 받을 수 있다. pathname, query 등 객체를 통해 URL 문자열이 생성될 수 있다.
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
예제는 각각 /about?name=test, /blog/my-post 경로로 파싱된다. Node.js URL 모듈정의의 모든 속성을 사용 가능하다.
정말 간단하게 정리가 끝났다. 내용 자체는 많지 않지만 관습적으로 많이 쓰는 <Link>의 숨은 장점들을 많이 발견하였다.
as, replace 등으로 url 커스텀이 가능할 뿐 아니라, locale이 Next.js 10에 추가되어 다국어 대응에도 유용함을 느꼈다.
<Link> 내에 Styled-Components나 함수 컴포넌트를 적용하는 경우도 종종 있으니 passHref, forwardRef 등을 감안해서 작업하도록 해야겠다!
🧷 출처
- [next/link 개념] Next.js 공식문서 : https://nextjs.org/docs/api-reference/next/link
- [next/link 개념] Next.js 공식문서(번역) : https://crong-dev.tistory.com/50
- [next/link 참고] f-dever-error-log 님의 블로그 : https://f-dever-error-log.tistory.com/56