-
[Next.js] next/link - <Link> 태그Front-End(Web)/React - 프레임워크(React, Next) 2022. 10. 3. 14:20반응형
🤔 서론
본래는, 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
반응형'Front-End(Web) > React - 프레임워크(React, Next)' 카테고리의 다른 글
[React] Concurrecy(동시성) - #2. Error Boundary (0) 2022.10.27 [React] Concurrency(동시성) - #1. Suspense와 React.lazy (0) 2022.10.24 [React] 자식 컴포넌트 제어 - forwardRef, useImperativeHandle (0) 2022.09.15 [Next.js] Dark Mode 구현하기 (0) 2022.09.12 [Next.js] Next.js 12 변경사항 (0) 2022.09.01