logo

Link 컴포넌트는 일단 쓰는게 좋겠지?

·
7 min read

Next.js는 기본적으로 HTML의 <a> 태그를 확장한 <Link /> 컴포넌트를 제공하며, 내부 링크를 연결할 때 <a> 태그 대신 <Link /> 컴포넌트를 사용하는 것을 권장하는데요. 이는 여러 가지 성능 최적화 기능을 활용할 수 있기 때문입니다. <Link /> 컴포넌트를 사용해야 하는 가장 강력한 이유는 다음과 같습니다.

Prefetching

Next.js의 <Link /> 컴포넌트는 사용자의 현재 뷰포트에 <Link /> 컴포넌트가 표시되면, 해당 링크와 연결된 페이지의 경로와 데이터를 미리 가져옵니다. 이렇게 하면 사용자가 링크를 클릭했을 때, 페이지 로딩 속도가 크게 향상됩니다. 이렇게하면 클라이언트 측 성능을 최적화하는 데 매우 유용하겠죠! 참고로 Prefetching 기능은 프로덕션 환경에서만 활성화되므로, 개발 환경에서 테스트하려면 로컬에서 프로덕션 모드로 빌드한 후, 프로덕션 환경으로 스크립트를 실행해야 합니다.

Soft Navigation

Soft Navigation은 클라이언트 측에서의 페이지 전환을 더욱 부드럽고 빠르게 만들어줍니다. <Link /> 컴포넌트를 사용하면 페이지 전환 시 전체 페이지를 새로고침하지 않고, 클라이언트 측에서 필요한 부분만 갱신하기 때문에 네트워크 요청을 최소화하고, 브라우저의 상태나 스크롤 위치를 유지할 수 있습니다.

그 외에 Code Splitting, Caching등 최적화를 위한 다양한 기능이 내포되어 있으니 더 궁금하시다면 이 링크를 참고해보시면 좋을 것 같습니다.

Next.js는 이러한 강력한 컴포넌트를 제공하는데, 저는 이 컴포넌트를 사용하다 오히려 문제를 맞이하게 됐습니다. 😅

문제점

로그인 페이지를 둘러보던 중 개발자 도구의 네트워크 탭을 살펴보니, 제가 분명히 fetch 요청을 보낸 적이 없었는데도 세 개의 fetch 요청이 이루어졌고, 그 중 두 개는 실패한 상태였습니다. 이때 <Link /> 컴포넌트의 prefetch 기능이 작동하고 있다는 것을 알게 되었습니다.

문제의 원인은 <Link /> 컴포넌트를 내부 링크를 연결할 때 사용해야 한다는 점을 간과하고, 외부 링크로 연결되는 각 소셜 로그인 버튼을 <Link />로 감싸버린 것이었습니다 🤯. <Link /> 컴포넌트는 기본적으로 prefetch 속성이 true로 설정되어 있어, Next.js는 해당 경로의 데이터를 미리 가져오려고 시도하지만OAuth의 Redirect URI에 등록되지 않은 도메인에서 요청이 발생하면서, CORS 정책에 위배되어 fetch가 실패하고 네트워크 오류가 발생한 것입니다.

게다가, 이 동작은 버튼을 눌렀을 때만 실행되어야 했기 때문에 <Link /> 컴포넌트의 prefetch 기능은 전혀 필요하지 않았습니다.

문제 이미지

그렇다면 <Link> 컴포넌트를 사용하고 prefetch={false}로 설정하여 외부 링크를 처리하면 되지 않을까? 라는 생각이 들었지만, 여기서는 외부 링크 연결이라는 목적만을 고려할 때, 이는 불필요한 자바스크립트를 로드하여 번들 크기를 증가시키는 결과를 가져올 수 있기에 <a>태그를 사용하는게 더 적합해보였습니다.

매우 간단하게 해결 🌞

원인을 알았고 해결은 매우 쉽게 됐습니다. 다음과 같이 <Link> 컴포넌트를 <a>태그로 교체해줬고 문제는 해결됐습니다.

export default function SocialButton({
  href,
  css,
  iconSrc,
  alt,
  text,
}: ISocialLoginButtons) {
  return (
    <Button
      asChild
      className={`${css} flex h-10 items-center justify-center gap-3`}
    >
      <a href={href}>
        <span>
          <Image src={iconSrc} width={20} height={20} alt={alt} />
        </span>
        <span>{text}</span>
      </a>
    </Button>
  );
}

이로써 외부 링크에 대한 prefetch는 더이상 진행되지 않기에 네트워크 오류를 볼 수 없었습니다. 회원가입 버튼은 <Link /> 컴포넌트로 감싸줬기에 의도한대로 prefetch가 잘 진행된 모습이네요.

최종결과 이미지

요약

Next.js에서 내부 링크를 연결할 때는 <Link>, 외부 링크를 연결할 때는 <a>를 사용합시다!