Next.js 는 클라이언트쪽의 navigation과 함께 서버중심의 라우팅을 사용한다. 이것은 동시 렌더링과 즉시 상태값을 로딩하는것을 지원한다. 이것은 navigation은 클라이언트쪽의 상태값을 유지하며, 값비싼 리렌더를 피하고, 중단 가능하며, 경합상태 ( 두가지의 프로세스가 한가지의 자원을 동작함)를 유발하지 않는다.
여기에 라우트들 사이에서 navigate하는 두가지의 방법이 있다.
- Link 컴포넌트
- useRouter 훅 사용
이 페이지는 Link 컴포넌트와 useRouter 사용을 어떻게 하는지 알려주고 navigation이 어떻게 동작하는지 깊게 알아본다.
Link 컴포넌트는 라우트들 사이에서 클라이언트 사이드 navigation과 prefetching을 제공하는 HTML a태그 요소의 확장 리액트 컴포넌트이다. 이것은 Next.js에서 라우트들 사이끼리 navigate하는 주요한 방법이다.
Link 컴포넌트를 사용하기 위해 next/link에서 import 해오고, 컴포넌트에게 href prop을 전달한다.
Link 컴포넌트에게 전달하기위한 선택적 props들이 있다.
동적인 segments에게 경로지정을 할때, 우리는 링크의 리스트들을 생성하기 위해서 템플릿 리터럴과 보간을 사용한다
useRouter 훅은 클라이언트 컴포넌트 안에서 라우트들을 프로그래밍적으로 바꿀수 있도록 허락한다. useRouter 훅을 사용하기 위해서, next/navigation에서 import 해오고 그리고 너의 클라이언트 컴포넌트 안에서 불러오면 된다.
useRouter훅은 push 나 refresh 같은 메서드들을 제공한다.
추천 : useRouter를 사용하는 특별한 요구가 있지 않다면 라우트들 사이에서 이동할때는 Link 컴포넌트를 사용해라.
- Link 컴포넌트나 router.push()를 불러옴으로써 라우트 변환이 초기화된다.
- 라우터가 브라우저 주소창에 있는 URL을 업데이트시킨다.
- 라우터는 클라이언트 캐시로부터 변하지않은 (예를 들어 공유된 layout들) segments들을 재사용하는 것 같은 불필요한 동작을을 피한다. 이것은 또한 부분 렌더링으로 언급된다.
- 만약에 부드러운 페이지이동의 상태(?)가 만난다면, 라우터는 서버가 아닌 캐시로부터 새로운 segment를 fetch 한다. 그게 만약 아니라면, 라우터는 서버로부터 서버컴포넌트 payload를 fetch하고 강력한 페이지이동을 동작한다 => 페이지에 대한 데이터들이 캐싱이 되어있다면 캐시로부터 데이터들을 받아오고, 그게 아니라면 서버에게 요청해서 데이터들을 받아온다는 뜻
- 만약 만들어진다면, payload가 fetch 될동안 서버로부터 loading UI를 불러온다.
- 라우터는 클라이언트쪽에서 새로운 segment를 렌더하기 위해 캐시되어있거나 새로 불러온 payload를 사용한다.
알아두면 좋은점 : 이 클라이언트 캐시는 서버사이트 HTTP 캐시와는 다르다.
새로운 라우터는 서버 컴포넌트들로부터 렌더된 결과를 저장하는 클라이언트 캐시 메모리를 가지고 있다. 이 캐시는 동시 렌더링에서 일관성을 보장하고 어느 수준에서도 무효화를 허용하는 라우트 segments들로 분리된다.
유저가 만약 app에서 페이지 이동을 할때, 라우터는 캐시에서 segments를 pre-fecth하고 전에 fetch 된 segments들의 payload를 저장한다.
이것은 특정한 경우에서, 라우터는 서버에게 새로운 요청을 하는것 대신에 캐시를 재사용할 수 있다.
이것은 불필요한 컴포넌트들을 재렌더링하고 데이터들을 re-fetching하는 것을 피함으로써 더 나은 성능을 보인다.
캐시는 router.refresh()를 사용함으로써 무효화 될수 있다. 미래에는 mutations 가 자동으로 캐시를 무효화 할것이다.
Prefetching 은 다른 페이지를 방문하기전에 뒤에서 라우트를 미리 load 해놓는 방법이다. prefetch 된 라우트들의 렌더링 결과물들은 라우터의 클라이언트쪽 캐시에 추가된다. 이것은 prefetch 된 라우트로 거의 즉시 페이지 이동을 하게 한다.
기본적으로, 라우트들은 Link 컴포넌트를 사용할때 뷰포트 안에서 보여지게 됨으로써 prefetch 된다. 이것은 스크롤링을 통하여나, 페이지가 처음으로 로드 될때 일어난다. 라우트들은 또한 useRouter훅의 메서드인 prefetch 를 사용함으로써 프로그래밍적으로 prefetch 된다.
만약에 라우트가 정적이라면, 라우트 segments들에 대한 서버컴포넌트 payloads들은 모두 prefetch 된다.
만약에 라우트가 동적이라면, 첫번째 loading.js 파일이 prefetch 될때까지 첫번째 공유된 layout 으로부터 payload 이다. (?)
이것은 동적인 라우트들을 위해 즉시 상태값들의 로딩을 허락하고, 전체 라우트들이 동적으로 prefetching 되는 비용을 감소한다.
알아두면 좋은점:
- prefetching은 production에서만 가능하다.
- prefetchinng =false 속성을 Link 컴포넌트에서 설정함으로써 prefetching을 불가능하게 할 수 있다.
페이지 이동에서, 캐시는 무효화되고 서버는 변화된 segments들을 리렌더하고 데이터들을 refetch한다.
페이지 이동에서, 변화된 segments들의 캐시는 재사용되고, 서버에 데이터를 요청 하지 않는다.
페이지 이동에서, Next.js 에서는 너가 prefetch된 페이지 이동을하는거라면 , 그리고 동적인 segments를 포함하지 않거나, 현재 라우트에서 같은 동적인 파라미터들을 갖고 있다면 soft navigation을 사용한다.
예를 들면, 동적인 [team] segment를 포함하는 라우트들을 고려해보자 /dashboard/[team]/, /dashboard[team]/ 하위 경로에서 캐시된 segments 들은 [team] 파라미터가 변화됐을때만 무효화 된다.
- /dashboard/team-red/ 에서 /dashboard/team-red/ 로 페이지 이동하는거는 soft navigation이다.
- /dashboard/team-red/ 에서 /dashboard/team-blue/ 로 페이지 이동을 하는것은 hard navigation 이다.
뒤로가기, 앞으로 가기는 soft navigation 페이지 동작이다. 이 의미는 클라이언트 캐시가 재사용되고 페이지 이동이 즉시 이루어진다.
기본적으로, Next.js 는 페이지이동에서 변화된 segment 뷰 안에서의 focus와 scroll을 설정한다. (?)
이 사용성과 접근성의 특징의 중요성은 진화된 라우팅 패턴이 이행될때 더욱 나타난다.
알아두면 좋은 점 : Next.js 는 이 동작을 이행하기 위해 각각 segment를 div 요소로 감싸는걸 사용한다. 이것은 지금 최신 Next.js Canary에서 고정되었다.