노현진's Blog

Next.js Giscus 사용 방법

Next.js 프로젝트에서 Giscus 사용 방법에 대해 정리한 페이지입니다.

Posted
Preview Image
By HyunJinNo

Tags

TypeScript, Next.js, Giscus

1. 개요

Next.js 프로젝트에서 Giscus 사용 방법에 대해 정리한 페이지입니다.

2. Giscus 사용하기

2.1. Step 1 - Discussions 기능 활성화하기

먼저 Discussions 기능을 활성화해야 합니다. 다음과 같이 Giscus에 연결할 Public 저장소에서 Settings > General로 이동한 후 Discussions 항목을 체크하여 Discussions 기능을 활성화합니다.

Settings 탭

General

Discussions 활성화

Discussions 기능

2.2. Step 2 - Giscus 앱 설치하기

GitHub Apps - giscus에 접속하여 Giscus 앱을 설치한 후, 해당 저장소에 권한을 부여합니다.

Giscus 앱 설치

Giscus 앱 설치

권한 부여하기

권한 부여 완료

2.3. Step 3 - Giscus 설정값 설정하기

giscus에 접속하여 저장소, 테마 등을 설정합니다.

2.3.1. 저장소 설정

위에서 설정한 저장소 이름을 입력하면 됩니다. 아래와 같이 "통과했습니다! 이 저장소는 모든 조건을 만족합니다."가 표시되면 성공한 것입니다.

저장소 설정

2.3.2. 페이지 ↔️ Discussions 연결

페이지와 Discussion을 연결할 방법을 선택합니다. 저는 pathname 방식을 선택하였습니다.

페이지 ↔️ Discussions 연결

2.3.3. Discussion 카테고리

새 Discussion이 만들어질 카테고리를 설정합니다. 저는 Giscus에서 권장하는 Announcements 카테고리를 선택하였습니다.

Discussion 카테고리

2.3.4. 기능

추가 기능을 선택합니다. 저의 경우 초기 로딩 속도를 고려하여 지연 로딩 기능을 추가하였습니다.

기능

2.3.5. 테마

마지막으로 원하는 Giscus 테마를 선택합니다.

테마

2.3.6. giscus 사용

Giscus 설정 이후에 다음과 같은 script 태그가 표시됩니다. 추후 해당 정보를 사용하기 위해 복사해 둡니다.

html
1<script
2  src="https://giscus.app/client.js"
3  data-repo="HyunJinNo/mdx-blog"
4  data-repo-id="R_kgDOQ9dfZA"
5  data-category="Announcements"
6  data-category-id="DIC_kwDOQ9dfZM4C285K"
7  data-mapping="pathname"
8  data-strict="0"
9  data-reactions-enabled="1"
10  data-emit-metadata="0"
11  data-input-position="bottom"
12  data-theme="preferred_color_scheme"
13  data-lang="ko"
14  data-loading="lazy"
15  crossorigin="anonymous"
16  async
17></script>

2.4. @giscus/react 패키지 설치하기

Giscus를 React 프레임워크인 Next.js 프로젝트에서 사용할 예정이므로 단순히 script 태그를 사용하는 것보단, wrapper를 사용하는 것이 좋습니다. 다음 명령어를 입력하여 @giscus/react 패키지를 설치합니다.

bash
1npm i @giscus/react

2.5. Comment 컴포넌트 만들기

다음과 같이 Comment 컴포넌트를 생성합니다. Giscus는 클라이언트 사이드에서 동작하므로 해당 컴포넌트를 클라이언트 컴포넌트로 선언해야 합니다. repo, repoId 등의 값들은, script 태그에 있는 prop들을 옮기면 됩니다.

Info.

div 태그를 사용할 필요는 없습니다. 저의 경우 블로그 게시글과의 간격 유지를 위해 사용하였습니다.

typescript
1/* @/features/comment/ui/Comment.tsx */
2
3"use client";
4
5import Giscus from "@giscus/react";
6
7export const Comment = () => {
8  return (
9    <div className="mt-20">
10      <Giscus
11        id="comments"
12        repo="HyunJinNo/mdx-blog"
13        repoId="R_kgDOQ9dfZA"
14        category="Announcements"
15        categoryId="DIC_kwDOQ9dfZM4C285K"
16        mapping="pathname"
17        strict="0"
18        reactionsEnabled="1"
19        emitMetadata="0"
20        inputPosition="bottom"
21        theme="preferred_color_scheme"
22        lang="ko"
23        loading="lazy"
24      />
25    </div>
26  );
27};

2.6. Giscus 사용 예시

다음과 같이 블로그 게시글 하단에 댓글 기능을 추가하였습니다.

typescript
1import { PostMetadata } from "@/entities/post";
2import { Comment } from "@/features/comment";
3import { convertDateFormat } from "@/shared/lib/utils";
4import Image from "next/image";
5
6export async function generateMetadata({
7  params,
8}: {
9  params: Promise<{ post: string }>;
10}) {
11  const { post } = await params;
12  const mod = await import(`@/content/${post}.mdx`);
13  const metadata: PostMetadata = mod.metadata;
14
15  return {
16    title: metadata.title,
17    description: metadata.description,
18  };
19}
20
21export default async function MdxLayout({
22  params,
23  children,
24}: {
25  params: Promise<{ post: string }>;
26  children: React.ReactNode;
27}) {
28  const { post } = await params;
29  const mod = await import(`@/content/${post}.mdx`);
30  const metadata: PostMetadata = mod.metadata;
31
32  // Create any shared layout or styles here
33  return (
34    <main className="flex w-full flex-col">
35      <header className="mb-8 flex flex-col">
36        <h1 className="mb-2 text-3xl font-semibold text-black">
37          {metadata.title}
38        </h1>
39        <p className="mb-6 text-lg">{metadata.description}</p>
40        <div className="text-custom-gray flex flex-col gap-4 text-sm">
41          <span>
42            Posted{" "}
43            <time className="font-medium">
44              {convertDateFormat(metadata.date)}
45            </time>
46          </span>
47          <div className="relative aspect-video">
48            <Image
49              className="rounded-xl border border-gray-100 bg-gray-100 object-cover"
50              src={metadata.imagePath}
51              alt="Preview Image"
52              fill={true}
53            />
54          </div>
55          <div className="flex flex-row items-center justify-between">
56            <span>By HyunJinNo</span>
57            <span>10 min read</span>
58          </div>
59        </div>
60      </header>
61      {children}
62      <Comment />
63    </main>
64  );
65}

Giscus 사용 예시

Giscus 사용 예시

3. 참고 자료

© HyunJinNo. Some rights reserved.