Gatsby 블로그에 Github 댓글 적용하기. 하루만에 Utterances에서 Giscus로. (다크 테마 적용)

작성 : 2023-10-10수정 : 2023-10-10

목차 펼치기

머리말

다른 기술블로그들을 구경하다보면 Github와 연동해 댓글을 작성할 수 있는 공통의 폼이 보인다. 그동안 별 생각이 없다가 내 블로그에도 적용하면 괜찮겠다 라는 생각이 들었다.

최종적으로는 Giscus를 사용했고, 다크 테마까지 적용했다.


 적용된 Giscus 다크 테마 UI

적용된 Giscus 다크 테마 UI



Utterances 적용

처음 Github를 통해 댓글을 다는 라이브러리를 찾을 때, Utterances 글이 많이 보였다. Github의 Issue를 활용하여 댓글 기능을 구현하는 방식이었다.

별 의문 없이 작업을 진행하고 배포까지 진행했다.


작업은 심플하며 공식 문서에서도 잘 설명되어 있다.


설치

  1. Public Github 리포지토리를 준비한다.

    1. 댓글이 Issue로 생성될 리포지토리다.

    2. 댓글 기능을 적용하려는 프로젝트의 리포지토리가 아니어도 된다.

  2. utterances app

    을 설치한다.

  3. 공식 문서

    에서 사용할 스크립트 코드를 만든다.

    1. 리포지토리 경로, 매핑 기준, 테마를 선택하면 자동으로 스크립트 코드가 생성된다.

      1. 매핑 기준은 Issue title contains page pathname를 선택했다. pathname을 통한 관리가 제일 무난할 듯하다.

  4. 댓글을 사용하려는 위치에 해당 스크립트를 삽입한다.


Utterances.tsx

컴포넌트를 생성한 후, 적당한 위치에 추가했다.


코드

javascript
1import * as React from 'react';
2import { useRef, useEffect } from 'react';
3
4const Utterances = () => {
5  const utterancesRef = useRef<HTMLDivElement>(null);
6
7  useEffect(() => {
8    const script = document.createElement('script');
9    script.src = 'https://utteranc.es/client.js';
10    script.setAttribute('repo', 'dearlsh94/WeeZip');
11    script.setAttribute('issue-term', 'pathname');
12    script.setAttribute('theme', 'github-light');
13    script.setAttribute('cross-origin', 'anonymous');
14    script.async = true;
15
16    if (utteranceRef.current) {
17      utteranceRef.current.appendChild(script);
18    }
19  }, []);
20
21  return (
22    <div id="utterances-box">
23      <div ref={utterancesRef} />
24    </div>
25  );
26};
27
28export default Utterances;

Utterances.tsx 컴포넌트 코드



 https://www.instagram.com/treefeely/

다크 테마는 나중에 작업하기로 하고 편하게 배포를 진행했는데, 이때만 해도 몰랐다. 바로 다음 날 마이그레이션하게 될 줄은…



Giscus

배포를 완료한 이튿날, Giscus 라이브러리를 알게 되었다. Utterances를 기반으로 개발된 라이브러리인데, Github Discussions 기능을 활용해 답글까지 지원이 된다. 다국어도 지원하고, Theme도 더 많고, 최근까지도 커밋이 이루어지고 있어 더욱 좋아보였다.


그렇게 Utterances에 다크 테마 적용을 하려던 작업을, Giscus로 마이그레이션 및 다크 테마 적용하기로 변경되었다.


Utterances는 중복 이슈가 생성되는 버그에 대한 이야기도 있고, 설치하고 사용하는 경험에 있어서도 Giscus가 더 깔끔하다고 느껴졌다.


Utterances를 기반으로 만들어진 라이브러리여서인지, 적용하는 방식은 유사하다.


설치

  1. Public Github 리포지토리를 준비한다.

    1. 댓글이 작성될 Discussions 를 위한 리포지토리다.

    2. 댓글 기능을 적용하려는 프로젝트의 리포지토리가 아니어도 된다.

  2. [Repository] - [Settings] - [Features] - [Discussions] 기능을 사용하기로 체크한다.

  3. [Repository] - [Discussions] 에 신규 카테고리를 생성한다.

    1. 댓글이 작성될 신규 카테고리로, ‘Comments’로 명명했다.

    2. Announcement 등급으로 생성한다.

  4. Giscus app

    을 설치한다.

  5. 공식 문서

    에서 사용할 스크립트 코드를 만든다.

    1. 친절하게도 한국어도 지원한다.

    2. 리포지토리 경로, 매핑 기준, 테마를 선택하면 자동으로 스크립트 코드가 생성된다.

      1. 매핑 기준은 Issue title contains page pathname를 선택했다. pathname을 통한 관리가 제일 무난할 듯하다.

    3. 리포지토리 이름을 작성하면 정상적으로 설치가 가능한 지 유효성 검사도 진행해준다.

  6. 댓글을 사용하려는 위치에 해당 스크립트를 삽입한다.



 Giscus로 작성된 포스트 댓글

Giscus로 작성된 포스트 댓글


실제 댓글을 작성하면 위와 같이 보여지게 된다. 매핑 기준으로 pathname을 선택했기 때문에 게시글의 주소로 생성되었다.


직접 테스트 해보니 생성된 Discussion을 종료해도 댓글 UI에서는 확인할 수 있었다.



다크 테마 적용하기

이번에는 작업하는 김에 다크테마까지 같이 작업하기로 했다. 문서를 뒤적거리다 보니 Giscus iframe에

postMessage

를 전송해 설정을 제어할 수 있다는 가이드가 있었고, 이를 사용한 블로그의 글도 있었다.



최초 렌더링 시에는 로컬 스토리지에 저장된 테마 값을 확인해서 스크립트를 불러오고, 이후에는 해당 기능을 이용해 블로그의 테마가 변경되는 것에 맞게

postMessage

를 전송하도록 했다.



코드

data-repo-id

data-category-id

는 혹시 몰라서 제거 했다. 해당 코드는 공식문서에서 생성해준 값을 동일하게 사용하면 된다.


javascript
1import { CONFIG_THEME_KEY } from '@src/constants';
2import { useLocalStorage } from '@src/hooks/useLocalStorage';
3import * as React from 'react';
4import { useRef, useEffect } from 'react';
5
6const Giscus = () => {
7  const { getConfig } = useLocalStorage();
8  const giscusRef = useRef<HTMLDivElement>(null);
9
10  useEffect(() => {
11    const configTheme = getConfig(CONFIG_THEME_KEY);
12
13    const script = document.createElement('script');
14    script.src = 'https://giscus.app/client.js';
15    script.setAttribute('data-repo', 'dearlsh94/WeeZip');
16    script.setAttribute('data-repo-id', '');
17    script.setAttribute('data-category', 'Comments');
18    script.setAttribute('data-category-id', '');
19    script.setAttribute('data-mapping', 'pathname');
20    script.setAttribute('data-strict', '0');
21    script.setAttribute('data-reactions-enabled', '1');
22    script.setAttribute('data-emit-metadata', '0');
23    script.setAttribute('data-input-position', 'bottom');
24    script.setAttribute('data-theme', configTheme && configTheme === 'dark' ? 'dark' : 'light');
25    script.setAttribute('data-lang', 'ko');
26    script.setAttribute('cross-origin', 'anonymous');
27    script.async = true;
28
29    if (giscusRef.current) {
30      giscusRef.current.appendChild(script);
31    }
32  }, []);
33
34  return (
35    <div id="giscus-box">
36      <div ref={giscusRef} />
37    </div>
38  );
39};
40
41export default Giscus;

Giscus.tsx


theme

값의 변경에 따라

postMessage

를 보내준다. 나는

'dark'

'light'

값을 사용했다.

javascript
1...
2React.useEffect(() => {
3  // Giscus 모듈 처리
4  const iframe = document.querySelector<HTMLIFrameElement>('iframe.giscus-frame');
5  iframe?.contentWindow?.postMessage(
6    {
7      giscus: {
8        setConfig: {
9          theme: theme,
10        },
11      },
12    },
13    'https://giscus.app'
14  );
15}, [theme]);
16...

ThemeController

Wanna get in touch?

All Icons byiconiFy