본문 바로가기
Develop

Nextjs에서 tag cloud 사용하기

by hongreat 2024. 9. 21.

 

 

 

 

 

Tag Cloud는 tag들을 마치 구름처럼 뭉게뭉게(?) 표현해주는 라이브러리 입니다.

기존에 Tag 페이지가 나쁘진 않았지만, 뭔가 태그가 많아질수록 위아래로 길어지는 느낌이 마음에 들지 않아서 변경하게 되었습니다.

Nextjs에서 tag-cloud 라이브러리를 적용한 과정을 기록합니다.

 

환경은 다음과 같습니다.

 

macOS 15.0(어제업글완.)

nextjs 14.2.3

node v18.20.4

npm 10.7.0

 

Nextjs tag cloud

 

 

(이미지의 윗 부분이 tag-cloud 를 적용한 부분, 아래 쪽이 기존에 태그 부분 입니다.)

 

 

 

 

 

목차

     

     

     

     

     

    라이브러리 설치

     

    먼저, react-tag-cloud 라이브러리를 설치합니다.

    npm install react-tag-cloud

     

    이후, 에 무슨 에러가 뜨는 듯하면서 npm audit 하라하는 메시지가 뜹니다.

     

    큰 의미가 없었으며, npm run dev로 서버를 재실행 하니 적용되었습니다.

     

     

    페이지 구성

     

    tag가 보여지는 페이지에서 metadata를 생성하고 있었습니다.

    이는 서버 컴포넌트로서 이곳에서 tag-cloud 를 바로 생성하려고하니 에러가 발생했습니다.

     

    서버 컴포넌트와 클라이언트 컴포넌트

     

    Next.js는 서버 컴포넌트와 클라이언트 컴포넌트를 엄격하게 구분합니다.

    tag-cloud 를 적용하기 위해 클라이언트 컴포넌트를 사용해야 하며, 이를 서버 컴포넌트와 함께 사용할 수 없습니다.

     

    이로 인해 'use client'를 사용하라는 에러 메시지가 발생했습니다.

     

    간단히 설명하자면, 메타 태그에 대한 로직은 서버에서 처리되며, 태그 클라우드는 클라이언트 사이드(브라우저)에서 생성됩니다.

     

    코드는 아래와 같습니다.

     

    적용된 페이지는 아래 메인블로그 페이지 입니다.

     

    스타일에 대해서는 언제든..변경될 수 있습니다.

     

    tag/page.tsx

    import { genPageMetadata } from 'app/seo';
    import TagCloudClient from './TagCloudClient';
    import OriginTagList from './OriginTagList';
    export const metadata = genPageMetadata({
      title: 'Tags',
      description: 'Things I blog about',
    });
    export default function Page() {
      return (
        <>
          {/* 클라이언트 컴포넌트 */}
          <TagCloudClient />
          <div className="flex flex-col items-start justify-start divide-y divide-gray-200 dark:divide-gray-700 md:mt-24 md:flex-row md:items-center md:justify-center md:space-x-6 md:divide-y-0">
            <div className="space-x-2 pb-8 pt-6 md:space-y-5">
              <h1 className="text-3xl font-extrabold leading-9 tracking-tight text-gray-900 dark:text-gray-100 sm:text-4xl sm:leading-10 md:border-r-2 md:px-6 md:text-6xl md:leading-14">
                Tags
              </h1>
            </div>
            <div className="flex max-w-lg flex-wrap">
              <OriginTagList />
            </div>
          </div>
        </>
      );
    }

     

     

     

     

     

    tag/TagCloudClient.tsx

     

    tag cloud 객체를 라이브러리에서 가져오고 화면에 렌더링 할 TagCloudClient 컴포넌트를 정의합니다.

     

    tagData의 상황에 맞게 커스텀 해야합니다. 저는 directory 에서 정적으로 관리하는 tag 를 JSON 파일로 관리합니다.

    tagData는 그 파일에서 가져온 각 태그의 이름을 키로 하고 등장 횟수를 값으로 가지는 객체입니다.

    스키마 예시로 {"어떤태그":태그개수} => {"django":18}  (Record<string, number... )이렇게 되어있습니다.

     

     

    sort 로 tag 개수 순서대로 정렬하고 map 을 돌려서, sortedTags 배열의 각 태그를 value와 count 속성을 가지는 객체로 변환합니다. 

     

     

     

    'use client';
    import { TagCloud } from 'react-tagcloud';
    import tagData from 'app/tag-data.json';
    import { slug } from 'github-slugger';
    export default function TagCloudClient() {
      const tagCounts = tagData as Record<string, number>;
      const tagKeys = Object.keys(tagCounts);
      const sortedTags = tagKeys.sort((a, b) => tagCounts[b] - tagCounts[a]);
      const tagCloudData = sortedTags.map((tag) => ({
        value: tag,
        count: tagCounts[tag],
      }));
      return (
        <div className="w-full pt-8">
          <TagCloud
            minSize={12}
            maxSize={35}
            tags={tagCloudData}
            className="tag-cloud"
            colorOptions={{ hue: 'blue' }}
            onClick={(tag) => (window.location.href = `/tags/${slug(tag.value)}`)}
          />
        </div>
      );
    }

     

     

    적용된 부분은 아래 링크에서 확인 할 수 있습니다. 

    궁금한 점은 댓글 부탁드립니다.

     

     

    레퍼런스 링크