본문 바로가기
JavaScript/Next.js

[Next.js] CSR의 Link 태그의 원리, Link와 useRouter의 차이점

by junvely 2024. 3. 18.

[Next.js] CSR의 Link 태그의 원리, Link와 useRouter의 차이점

1. CSR의 Link 태그의 원리

❓내가 궁금했던 부분 1 : Link태그를 사용하여 페이지 이동을 설정해놓을 경우 브라우저에서 소스 코드로 확인해 보면 <a>태그로 변환되어 있다. 이는 Link태그 내부에 <a>태그가 내장되어 있기 때문인데, 그렇다면 변환된 것은 <a>태그이므로 사용자가 클릭 했을 때에 새로고침이 일어나야 하는 것이 아닌가? 어떻게 부드러운 사용성을 유지할 수 있는가? 문득 궁금했다.

Next.js의 Link 컴포넌트를 사용하면 서버에서 받은 HTML에서는 <a> 태그로 변환되어 있으므로 기본적으로는 클릭 시 새로고침이 발생합니다.그러나 사용자의 브라우저가 JavaScript를 실행할 수 있고, JavaScript가 활성화되어 있는 경우에는 다음과 같은 과정으로 부드러운 화면 전환을 경험하게 됩니다:

1. 사용자가 Link 컴포넌트를 클릭합니다.
2. 브라우저는 JavaScript를 실행하고, 클라이언트 측 라우팅 메커니즘이 활성화됩니다.
3. 클라이언트 측 라우팅은 새로운 페이지의 필요한 컴포넌트 및 데이터를 로드합니다.
4. 화면이 부드럽게 전환되면서 새로운 페이지가 렌더링됩니다. 이 과정에서는 전체 페이지를 새로 렌더링하는 것이 아니라 필요한 부분만 업데이트됩니다.
5. 사용자는 새로운 페이지로 이동한 것처럼 보이지만, 실제로는 전체 페이지의 새로고침 없이 부드럽게 화면이 전환됩니다.

이러한 과정을 통해 사용자는 페이지 전환 시에 부드러운 경험을 할 수 있습니다. 이는 클라이언트 측 라우팅을 활용하여 페이지 간 전환을 빠르고 부드럽게 만드는 원리입니다.

내가 이해하기로는, Next.js와 같은 서버 사이드 렌더링에서는 서버로부터 렌더링된 HTML 문서를 받게 된다. 서버에서 받는 HTML에서는 Link가 a태그로 변화되어 클릭시 새로고침이 일어나야 하지만, 실제로 사용자가 클릭할 때 js가 켜져있다면 새로고침을 하지 않고 페이지는 유지하면서 내부 컴포넌트를 교체해주는 식으로 화면을 부드럽게 전환되는 것처럼 보이게 하는 것 같다. 또 js가 일어나지 않는 상황에서도 페이지는 이동되어야 하기 때문에 그런 경우에는 a태그를 통해 페이지를 새로고침 하는 것으로 보인다.

 

❓내가 궁금했던 부분 2 : Next.js 13 버전 부터는 서버 컴포넌트와 클라이언트 컴포넌트를 선택적으로 사용 가능하고, 클라이언트 컴포넌트에 한해서만 hydration이 일어나 CSR을 하는 것으로 알고 있다. 클라이언트 컴포넌트로 사용하기 위해서는 "use client"를 반드시 선언해 주어야 한다고 알고있다. 하지만 Link태그 같은 경우 "use client"를 사용하지 않아도 에러가 발생하지 않는다. 클라이언트 컴포넌트로 선언도 하지 않았는데 어떻게 자동적으로 Link를 사용하면 CSR 방식으로 페이지 이동이 가능한 것일까? 

컴포넌트 모듈에 'use client' 지시어가 포함된 경우 해당 컴포넌트의 사용은 클라이언트 컴포넌트임이 보장됩니다. 하지만 컴포넌트에 'use client' 지시어가 없더라도 클라이언트에서 평가될 수 있습니다.

정적 생성을 사용하는 페이지의 경우 뷰포트의 모든 <Link /> 는 기본적으로 해당 데이터를 포함하여 미리 가져오기됩니다 (초기 또는 스크롤을 통해). 서버 렌더링 경로에 대한 해당 데이터는 < Link />를 클릭할 때만 가져옵니다


 - 공식문서 참조 : https://ko.react.dev/reference/react/use-client 
+ Link 컴포넌트는 Server Side Rendering + Client Side Routing이다. Next.js에서 제공하는 클라이언트 사이드 라우팅을 구현하는데 사용되며, 클라이언트 측 라우팅을 위한 컴포넌트이기 때문에, "use client"를 명시적으로 선언하지 않아도 클라이언트에서도 렌더링 된다. Next.js의 Link 컴포넌트가 기본적으로 클라이언트 측 라우팅을 지원하기 때문에 클라이언트 측에서만 동작하도록 설계되어 있기 때문이다.

1. Link 컴포넌트의 자동 클라이언트 측 렌더링: Next.js의 Link 컴포넌트는 자체적으로 클라이언트 측 렌더링을 수행하기 때문에 "use client"를 명시적으로 선언하지 않아도 클라이언트 측에서 렌더링됩니다. 이것은 Link 컴포넌트가 클라이언트 측 라우팅을 지원하기 위해 설계되었기 때문입니다.

2. JavaScript 번들의 서버 전달: 클라이언트 측 라우팅을 사용하는 경우에도, 서버에서 해당 페이지에 필요한 JavaScript 번들이 클라이언트로 전달됩니다. 이것은 클라이언트 측 라우팅을 위한 JavaScript 코드가 클라이언트로 전달되어야 하기 때문입니다.

3. Hydration 작업: Link 컴포넌트를 클릭하면 해당 페이지에 필요한 JavaScript 번들이 클라이언트로부터 다운로드되고 실행되며, 이를 통해 클라이언트 측 라우팅과 Hydration 작업이 수행됩니다. Hydration 작업은 클라이언트에서 미리 렌더링된 HTML과 일치하도록 페이지를 업데이트하는 과정을 의미합니다.

 

 

2. 'use Client' 동작 원리

1. React 서버 컴포넌트를 사용하는 앱의 경우, 기본적으로 앱은 서버에서 렌더링 됩니다. 'use client'는 모듈 종속성 트리에 서버-클라이언트 경계를 도입하여 효과적으로 클라이언트 모듈의 하위 트리를 만듭니다.

2. 'use client'는 React 서버 컴포넌트 앱의 모듈 종속성 트리를 분할하여 InspirationGenerator.js와 모든 종속성을 클라이언트-렌더링으로 표시합니다.

3. 렌더링하는 동안 프레임워크는 루트 컴포넌트를 서버-렌더링하고 렌더 트리를 통해 계속 진행하여 클라이언트에서 가져온 코드를 평가하지 않습니다. 그런 다음 서버에서 렌더링한 렌더 트리 부분을 클라이언트로 보냅니다. 클라이언트 코드를 다운로드한 클라이언트는 트리의 나머지 부분 렌더링을 완료합니다.

공식 문서 :  트리를 통해 잘 확인할 수 있으니 한 번 읽어보자

 

 

3. Link와 useRouter의 차이점

가장 큰 차이점은 검색엔진(SEO)인것 같다.

Link

<a>태그로 변환되기 때문에 검색엔진이 링크를 인식할 수 있으므로 SEO를 보장하면서도 사용자 경험을 개선할 수 있다. -> 검색엔진이 indexing처리를 할 때 href속성을 읽어 indexing처리를 하는데 href가 없으면 검색엔진이 추적을 할 수 없다. href props는 Link태그를 사용할 때 필수로 사용해야하기 때문에 SEO에 유리하다.

useRouter 

useRouter는 next.js에서 "함수형식"으로 routing을 해주는 Next.js가 제공하는 라이브러리이다. 크롤러가 링크를 감지하지 못해 SEO가 좋지 않을 수 있다. 페이지를 이동 할 때에 단순히 즉시 페이지를 이동하는 것이 아니라 어떤 비즈니스 로직 등을 수행한 후, 결과 처리로 페이지를 이동 하는 등 함수 형식의 기능을 수행할 때 사용한다. 외부 URL을 사용할 경우 window.location 혹은 a 태그를 사용해야 한다.

+ Next.js가 13버전이 release하면서 app routing기능을 추구하고있다. app routing을 사용한다면 useRouter는 next/router가 아닌 next/navigation에서 import하여 사용하여야 한다.

 

결론 

Next.js의 Link 컴포넌트는 자체적으로 클라이언트 측 렌더링을 수행하기 때문에 "use client"를 명시적으로 선언하지 않아도 클라이언트 측에서 렌더링된다. 이것은 Link 컴포넌트가 클라이언트 측 라우팅을 지원하기 위해 설계되었기 때문이다. 클라이언트 사이드 라우팅과 클라이언트 사이드 렌더링, 클라이언트 컴포넌트와의 관계성이 모두 같아야 한다고 생각해서 계속 고민했던 것 같다. '서버 사이드 렌더링이면서, 클라이언트 사이드 라우팅을 사용하는 Next.js는 서버 컴포넌트에서도 클라이언트 사이드 렌더링이 가능하다'가 결론이다. 굳이 클라이언트 컴포넌트가 아니어도 가능하다 = 'use client'를 사용할 필요가 없다는 것이다. 

또 React의 Link 태그와 Next.js의 Link 태그가 다른 점은 React는 클라이언트 사이드 렌더링, 클라이언트 컴포넌트 이기 때문에 서버사이드 렌더링을 하기 위해선 별도 구현이 필요하다는 점, Next.js에서는 prefetch와 같이 React의 기능을 확장하고 더 많은 기능을 제공한다는 점이다.

되도록이면 SEO를 위해 Link태그를 사용하는 것을 권장한다. 하지만 페이지를 즉시 이동하는 것이 아니라 어떤 로직을 수행 후에 이동해야 한다면 useRouter를 사용하면 될 것 같다.