1인 개발 꿀팁 💡기능 구현💬 댓글 기능Giscus

Giscus를 이용한 댓글 기능 구현

  • Giscus는 GitHub 저장소의 Discussions를 이용한 댓글 기능을 제공하는 무료 서비스입니다. (Powered by Vercel)
  • 1in.dev에서 사용하는 댓글 기능입니다.
  • 사용자들이 Github 계정을 가지고 있는 개발자 대상 서비스에서 사용하기 좋습니다.

  • <script> 형태로 사용할 수 있고, React/Vue/Svelte 등의 컴포넌트로도 사용할 수 있습니다.
  • 자세한 설정이나 사용 방법은 https://giscus.app/ko 에서 확인할 수 있습니다.

1. 기본 설정

  1. GitHub 저장소를 공개로 설정
  2. 해당 저장소의 Discussions 기능 활성화 (Settings > Features > Discussions ✅ 체크)
  3. GitHub에서 giscus 앱 설치 (원하는 저장소에만 설치하거나 모든 저장소에 설치)
  4. giscus.app 웹사이트에서 Giscus를 연결할 저장소 링크를 추가하여 코드를 얻습니다. (repo, repoId, category, categoryId 등)
  5. Giscus <script> 코드 또는 컴포넌트를 원하는 웹페이지에 추가

2. React/Vue/Svelte 컴포넌트 설정

자세한 사용 방법은 https://github.com/giscus/giscus-component 에서 확인

Giscus 패키지 설치

npm install @giscus/react
# or
npm i @giscus/vue     # for Vue
npm i @giscus/svelte  # for Svelte
npm i @giscus/solid   # for Solid

컴포넌트 생성

// components/comment/giscus.jsx
 
import Giscus from "@giscus/react";
 
export default function CommentSection() {
  return (
    <Giscus
      repo="your-github-username/your-repo-name"
      repoId="your-repo-id"
      category="Announcements" // GitHub Discussions 카테고리 이름
      categoryId="your-category-id"
      mapping="pathname" // 페이지와 디스커션을 매핑하는 방법
      reactionsEnabled="1"
      emitMetadata="0"
      inputPosition="top" // 댓글 입력창 위치
      theme="light" // 테마 (light, dark, preferred_color_scheme 등)
      lang="ko" // 언어 설정
      loading="lazy"
    />
  );
}

컴포넌트 사용

import Giscus from "@/components/comment/giscus";
 
// 페이지 내용
 
<br />
<Giscus />

3. Dark/Light Mode에 따라 테마 변경하는 컴포넌트 예시

import Giscus from "@giscus/react";
import { useTheme } from "next-themes";
import { useEffect, useState } from "react";
 
// 사용 가능한 테마 목록을 상수로 정의
export const GISCUS_THEMES = {
  light: [
    "light",
    "light_high_contrast",
    "light_protanopia_deuteranopia",
    "light_tritanopia",
    "noborder_light",
    "gruvbox_light",
    "catppuccin_latte",
  ],
  dark: [
    "dark",
    "dark_high_contrast",
    "dark_protanopia_deuteranopia",
    "dark_tritanopia",
    "dark_dimmed",
    "transparent_dark",
    "noborder_dark",
    "noborder_gray",
    "rstudio_cobalt",
    "purple_dark",
    "gruvbox_dark",
    "catppuccin_frappe",
    "catppuccin_macchiato",
    "catppuccin_mocha",
    "fro",
  ],
  auto: ["preferred_color_scheme"],
  custom: ["custom"],
};
 
export default function GiscusComponent() {
  const { theme } = useTheme();
  const [mounted, setMounted] = useState(false);
 
  // 컴포넌트가 마운트된 후에만 렌더링
  useEffect(() => {
    setMounted(true);
  }, []);
 
  // 테마에 따른 giscus 테마 선택
  const getGiscusTheme = () => {
    if (theme === "dark") return "dark_high_contrast";
    if (theme === "light") return "light_high_contrast";
    return "preferred_color_scheme";
  };
 
  // 마운트되기 전에는 아무것도 렌더링하지 않음
  if (!mounted) return null;
 
  return (
    <Giscus
      key={theme} // theme이 변경될 때마다 컴포넌트를 다시 마운트
      id="comments"
      repo="Integerous/giscus-test"
      repoId="R_kgDOOMnFRQ"
      category="Announcements"
      categoryId="DIC_kwDOOMnFRc4CoVUk"
      mapping="pathname"
      term="1in.dev"
      reactionsEnabled="1"
      emitMetadata="0"
      inputPosition="top"
      // theme="preferred_color_scheme"
      theme={getGiscusTheme()}
      lang="ko"
      loading="lazy"
    />
  );
}