logo
작성일

DevBlog 3. giscus로 댓글 달기

Authors
  • avatar
    Name
    seren-wib
    Twitter
Contents

글 맨 아래 댓글창을 붙인 기록. 이 블로그는 tailwind-nextjs-starter-blog 템플릿에서 시작했고, 댓글 코드는 처음부터 들어 있었음. 빠진 건 설정값뿐이었음

1. 왜 giscus

방식저장 위치문제
DisqusDisqus 서버광고와 추적 스크립트가 따라옴. 데이터가 남의 것
utterancesGitHub Issues댓글이 이슈 목록에 섞임. 답글(스레드)이 없음
giscusGitHub Discussions방문자가 GitHub 계정이 있어야 댓글을 쓸 수 있음
  • 서버도 DB도 없는 정적 블로그라 댓글을 따로 저장할 곳이 없음. GitHub Discussions를 저장소로 빌림
  • 읽는 사람이 대부분 개발자라 GitHub 로그인 조건은 문제가 안 됨
  • 글 하나 = 토론 하나. 첫 댓글이 달릴 때 giscus 앱이 토론을 만듦

2. 템플릿에 이미 있던 것

  • data/siteMetadata.js에 provider: 'giscus'와 설정 칸이 있음. 값은 전부 환경변수에서 읽음
data/siteMetadata.js
comments: {
  provider: 'giscus',
  giscusConfig: {
    repo: process.env.NEXT_PUBLIC_GISCUS_REPO,
    repositoryId: process.env.NEXT_PUBLIC_GISCUS_REPOSITORY_ID,
    category: process.env.NEXT_PUBLIC_GISCUS_CATEGORY,
    categoryId: process.env.NEXT_PUBLIC_GISCUS_CATEGORY_ID,
    mapping: 'pathname',
    // ...
  },
},
  • CSP(next.config.js)에도 script-src와 frame-src에 giscus.app이 열려 있음
  • 그런데 환경변수 네 개가 비어 있었고, 레포에 Discussions도 꺼져 있었음. 그래서 "Load Comments" 버튼을 눌러도 아무것도 안 떴음

3. GitHub 쪽 설정

Discussions 켜기

  • 레포 Settings → General → Features → Discussions 체크
  • 체크하면 기본 카테고리(Announcements, General, Q&A 등)가 바로 생김
  • 이어서 나오는 "Start discussion" 환영 글은 안 써도 됨. 댓글과 상관없음

giscus 앱 설치

  • github.com/apps/giscus에서 Install
  • Repository access는 Only select repositories로 블로그 레포 하나만 고름. All repositories로 하면 private 레포까지 앱에 열림

ID 받기

  • giscus.app에 레포 이름을 넣으면 ID를 알려 줌. gh가 있으면 GraphQL 한 번으로도 됨
gh api graphql -f query='{
  repository(owner: "seren-wib", name: "vercel-blog") {
    id
    discussionCategories(first: 10) { nodes { name id } }
  }
}'
  • id가 레포 ID(R_...), 카테고리마다 DIC_...가 카테고리 ID

카테고리는 General

  • 처음엔 giscus가 권하는 Announcements로 했음. 관리자와 앱만 새 토론을 만들 수 있어서 방문자가 엉뚱한 토론을 못 엶
  • 그런데 Announcements에 환영 공지와 글별 댓글 토론이 한데 섞임. 공지는 공지끼리 두고 싶어서 General로 옮김
  • General은 방문자도 Discussions 탭에서 새 토론을 열 수 있음. 댓글 토론 사이에 가끔 다른 글이 섞일 수 있지만 이 규모에선 감수함
  • 카테고리를 바꾸면 이미 생긴 토론도 새 카테고리로 옮겨야 함. giscus는 설정된 카테고리 안에서만 토론을 찾으므로, 안 옮기면 그 글 댓글이 안 보이고 빈 토론이 새로 생김. 토론 페이지의 Change category나 GraphQL updateDiscussion으로 옮김

4. Vercel 환경변수

이름값
NEXT_PUBLIC_GISCUS_REPOseren-wib/vercel-blog
NEXT_PUBLIC_GISCUS_REPOSITORY_IDR_...
NEXT_PUBLIC_GISCUS_CATEGORYGeneral
NEXT_PUBLIC_GISCUS_CATEGORY_IDDIC_...
  • 넷 다 비밀값이 아님. 결국 브라우저로 내려가는 값이라 plain으로 넣음
  • NEXT_PUBLIC_ 값은 빌드할 때 코드에 박힘. 환경변수만 저장하고 끝내면 사이트는 그대로임. Redeploy를 한 번 해야 반영됨

5. 버튼 없이 바로 띄우기

  • 템플릿은 "Load Comments" 버튼을 눌러야 giscus를 불러왔음. 페이지 로딩을 아끼려는 장치
  • 그런데 pliny의 giscus 컴포넌트가 이미 loading: "lazy"로 iframe을 만듦. 댓글 근처까지 스크롤해야 불러오므로 버튼이 없어도 첫 로딩은 같음
  • 그래서 버튼과 상태를 지우고 바로 렌더링
components/Comments.tsx
export default function Comments({ slug }: { slug: string }) {
  if (!siteMetadata.comments?.provider) {
    return null
  }
  return <CommentsComponent commentsConfig={siteMetadata.comments} slug={slug} />
}
  • 같이 글 아래의 "Discuss on Twitter", "View on GitHub" 링크도 지움. 댓글창이 생겼으니 쓸 일이 없음
  • 글이 길면 댓글까지 내려가기 멀지만, 오른쪽 아래 떠 있는 말풍선 버튼이 #comment로 바로 데려감

6. 매핑: pathname

  • mapping: 'pathname'은 페이지 경로로 토론을 찾음. 토론 제목이 kr/blog/devblog/devblog-03-giscus-comments/ 같은 경로가 됨
  • 이 블로그는 같은 글이 /kr/과 /en/ 두 주소에 있음. 경로가 다르니 한국어 글과 영어 글은 댓글이 따로 달림
  • 합치려면 언어 접두사를 뺀 값을 term으로 넘기는 specific 매핑을 써야 함. 지금은 언어별로 읽는 사람이 다르다고 보고 나눈 채로 둠
  • slug를 바꾸면 경로가 바뀌어 기존 댓글과 연결이 끊김. 글 주소를 바꿀 일이 있으면 Discussions에서 토론 제목도 같이 고쳐야 함

7. 정리

  • 정적 블로그 댓글은 GitHub Discussions를 빌리면 서버 없이 끝남
  • 손댈 곳은 GitHub 두 군데(Discussions, 앱 권한)와 Vercel 환경변수 네 개
  • NEXT_PUBLIC_은 빌드 타임 값이라 재배포가 필수