타입스크립트의 공변성과 반공변성
타입스크립트의 타입 할당관계 규칙인 공변성과 반공변성에 대해서 알아봅시다.
안녕하세요! 오늘은 Giscus
를 사용하여 블로그 댓글 시스템을 제공하는 방법에 대해서 알아보겠습니다.
최근에 블로그를 보면 아시겠지만 얼마부터 제 블로그에도 Giscus
를 사용하여 댓글 시스템을 제공하고 있는데요, 제가 실제로 구축해보면서 알게된 정보들을 공유드리려고 합니다. 😀
Giscus
는 깃허브의 Discussions(토론)
기능을 사용하여 손쉽고, 무료로 웹 사이트 내에 설정이 가능한 댓글 시스템입니다.
이와 유사한 시스템은 GitHub Utterances
가 있는데요, Utterances도 깃허브 계정만 있다면 누구나 댓글을 작성할 수 있는 유명한 댓글 시스템입니다.
그렇다면, 이 두 시스템의 차이점은 어떤것이 있을까요? 아래 표를 통해서 비교해보겠습니다.
대표 기능 | Utterances | Giscus |
---|---|---|
오픈 소스 | O | O |
무료 여부 | O | O |
답글 달기 | 닉네임을 언급하여 댓글로 작성 | O |
블로그 글 이모지 반응 | X | O |
댓글 이모지 반응 | O | O |
저장 위치 | Issues | Discussions |
마지막 업데이트 | 2022년 2월 | 최근 |
기본적인 기능들은 유사하나 답글 제공 및 블로그 글에 대한 기능도 제공한다는 점에서 되게 마음에 들었고, 블로그에 Giscus 시스템을 사용해야겠다고 생각했습니다.
추가적으로, 댓글이라는 기능은 Issues (이슈)
보다는 Discussions (토론)
에서 관리되는것이 좋다고 생각드네요.
그리고 최근에 저도 발견했던 Utterances의 보안 문제가 하나 있었는데요, 마지막 업데이트일을 봤을때 해결되지 않을 이슈여서 Utterances를 놔주기로 했습니다.
보안문제 관련 링크 https://github.com/utterance/utterances/issues/649
Giscus
는 앞서 말씀드렸다시피 Discussions
기능으로 관리가 되는 시스템입니다. 그리고 Discussions
에서 댓글로 저장하려는 토론의 카테고리를 설정해줘야 합니다.
가장 먼저 Giscus를 등록할 Repository의 Discussions
를 활성화 해주어야 합니다. 기본적으로 체크가 해제된 상태일텐데요, 이를 체크해주도록 합니다.
그리고 새로고침을 하고나면, Repository 탭에 Discussions
라는 탭이 새로 생긴걸 보실 수 있습니다. Discussions
탭을 누르고, 카테고리 메뉴로 들어갑니다.
Discussions
의 카테고리 메뉴로 들어오시면 기본적으로 생성된 카테고리들이 쭉 보이는데요, 새로운 카테고리를 생성하기 위해 New Category 버튼을 눌러줍니다.
위 사진처럼 카테고리를 생성하는 페이지가 나오는데요. 카테고리 이름과 설명은 자유롭게 하되, Discussion Format
은 Announcement로 설정하는것을 추천드립니다.
Announcement는 누구나 토론에 대해 댓글을 작성할 수 있지만, 토론을 생성하는것은 오직 Repository Owner
만 가능한 권한 시스템입니다.
이렇게 카테고리 설정을 모두 끝냈다면, Giscus 앱 설치 페이지로 가셔서 원하는 Repository에 설치를 해주시면 됩니다. 설치하는것은 되게 쉬워서 추가적인 설명은 생략하겠습니다.
이제 본격적으로 Giscus
를 설치 및 설정을 해보도록 하겠습니다. 먼저 공식 사이트에 들어갑니다.
맨 처음에는 소개글과 작동원리 등이 적혀져있는데요, 스크롤을 조금 내리면 저장소
설정란이 보입니다.
저장소 입력 형식은 사용자 이름/레포지토리 이름
으로 작성해주시면 됩니다. 저의 경우엔 yiyb0603/yiyb-blog
로 작성을 해주었습니다.
다시 아래로 스크롤을 내리면 페이지 - Discussions 연결
설정이 있는데요. 이 설정은 어떤 값으로 Discussions 토론을 생성할것인지를 고르는 설정입니다.
저는 페이지 title 포함을 설정하였습니다만, 주로 사용하는 설정에 대해서 간단하게 설명드리자면
Discussions 연결 설정을 끝내고나면 Discussion 카테고리
선택 박스가 있는데요. 이는 아까 만들었던 카테고리를 선택하시면 됩니다.
마지막으로 편의 기능 및 테마를 설정하는란이 나오는데요. 이부분은 취향껏 선택하시면 됩니다.
저는 기본 기능을 사용하였고, 테마는 라이트 모드일때는 GitHub Light
, 다크모드일때는 RStudio Cobalt
테마를 사용했습니다.
모든 과정을 끝내고 밑으로 스크롤 하시면 위처럼 script
코드가 자동으로 생성 되었는데요. 이 코드를 웹 페이지에 등록하면 Giscus 설치는 끝이 납니다.
저는 Next.js에서 연동했기 때문에, Next.js 코드를 작성해보겠습니다. (React.js에서도 거의 동일합니다.)
일단은 댓글을 렌더링 할 컴포넌트 파일을 아래처럼 작성해줍니다. useGiscus
라는 커스텀 훅은 다음 단계에서 작성하니, 오류가 뜨더라도 괜찮습니다.
import { useRef } from 'react';
import useGiscus from '@/hooks/giscus/useGiscus';
const PostComment = (): JSX.Element => {
const commentRef = useRef<HTMLDivElement>(null);
useGiscus(commentRef);
return (
<div
ref={commentRef}
margin='6rem 0 0 0'
></div>
);
};
export default PostComment;
그 다음으로 useGiscus
라는 이름의 커스텀 훅을 아래처럼 작성해줍시다.
import { RefObject, useRef, useEffect } from 'react';
// Giscus 설정 페이지에서 만들어준 Script 태그의 속성들을 object로 만들었습니다.
const giscusSetup = {
id: 'giscus-comment',
src: 'https://giscus.app/client.js',
'data-repo': 'yiyb0603/yiyb-blog',
'data-repo-id': 'R_kgDOJB64hA',
'data-category': 'Blog Comment',
'data-category-id': 'DIC_kwDOJB64hM4CaASM',
'data-mapping': 'title',
'data-strict': '0',
'data-reactions-enabled': '1',
'data-emit-metadata': '0',
'data-theme': 'light',
'data-input-position': 'bottom',
'data-lang': 'ko',
crossorigin: 'anonymous',
async: 'true',
};
const useGiscus = <T extends HTMLElement>(giscusRef: RefObject<T>): void => {
const initializedRef = useRef<boolean>(false);
useEffect(() => {
if (giscusRef.current === null || initializedRef.current) {
return;
}
const giscusScript = document.createElement('script');
for (const [key, value] of Object.entries(giscusSetup)) {
giscusScript.setAttribute(key, value);
}
giscusRef.current.append(giscusScript);
initializedRef.current = true;
}, [giscusRef]);
};
export default useGiscus;
참고로 next/script
의 Script 태그를 사용하면 타입 오류가 발생하기 때문에, setAttribute
메소드를 사용하여 타입 오류없이 태그를 설정할 수 있도록 적용했습니다.
다수의 setAttribute
메소드를 사용하면 가독성이 떨어질 수 있으므로 객체를 순회하여 설정하는 코드를 작성해주었습니다.
대다수의 분들은 위 과정에서 끝! 이지만 제 블로그는 자체적인 테마 변경 기능을 지원하고 있습니다. 그래서 블로그 테마가 라이트모드일때와 다크모드일때 각각 Giscus의 테마를 변경하고 싶어서 찾아보았습니다.
그리고 마침내! 방법을 찾을 수 있었습니다. Giscus를 개발자 도구로 보시면 iframe
태그를 사용해서 보여주고 있음을 알 수 있는데요. postMessage
메소드를 사용하여 iframe
윈도우와 통신할 수 있도록 Giscus에서 제공합니다. 😀
테마 뿐만 아니라 이것저것 통신할 수 있도록 제공하는 것 같습니다.
그렇게 라이트 모드일때는 GitHub Light
다크 모드일때는 RStudio Cobalt
테마를 사용하도록 구현할 수 있었고, useGiscus
커스텀 훅의 코드는 최종적으로 아래처럼 작성할 수 있었습니다.
import { RefObject, useRef, useEffect } from 'react';
import { SystemTheme } from '@/enums/theme';
import useTheme from '../theme/useTheme';
const giscusSetup = {
id: 'giscus-comment',
src: 'https://giscus.app/client.js',
'data-repo': 'yiyb0603/yiyb-blog',
'data-repo-id': 'R_kgDOJB64hA',
'data-category': 'Blog Comment',
'data-category-id': 'DIC_kwDOJB64hM4CaASM',
'data-mapping': 'title',
'data-strict': '0',
'data-reactions-enabled': '1',
'data-emit-metadata': '0',
'data-theme': 'light',
'data-input-position': 'bottom',
'data-lang': 'ko',
crossorigin: 'anonymous',
async: 'true',
};
const useGiscus = <T extends HTMLElement>(giscusRef: RefObject<T>): void => {
const { theme } = useTheme();
const initializedRef = useRef<boolean>(false);
useEffect(() => {
if (
giscusRef.current === null ||
initializedRef.current ||
theme === SystemTheme.DEFAULT
) {
return;
}
const giscusScript = document.createElement('script');
for (const [key, value] of Object.entries(giscusSetup)) {
giscusScript.setAttribute(key, value);
}
if (theme === SystemTheme.LIGHT) {
giscusScript.setAttribute('data-theme', 'light');
} else {
giscusScript.setAttribute('data-theme', 'cobalt');
}
giscusRef.current.append(giscusScript);
initializedRef.current = true;
}, [giscusRef, theme]);
useEffect(() => {
if (theme === SystemTheme.DEFAULT) {
return;
}
const giscusIframe =
document.querySelector<HTMLIFrameElement>('.giscus-frame');
if (giscusIframe === null) {
return;
}
giscusIframe.contentWindow?.postMessage(
{
giscus: {
setConfig: {
theme: theme === SystemTheme.LIGHT ? 'light' : 'cobalt',
// 라이트 모드일때는 GitHub Light, 다크 모드일때는 RStudio Cobalt 테마 사용
},
},
},
'https://giscus.app',
);
}, [theme]);
};
export default useGiscus;
이번 섹션은 기존에 Utterances를 사용하다가 Giscus로 마이그레이션 하는분들을 위한 섹션인데요. Issues
에 등록되어 있는 댓글을 Discussions
로 옮기는 방법에 대해서 알려드리겠습니다.
먼저 옮기고자 하는 Issue로 들어간다음 오른쪽 하단의 Convert to discussion
을 누르고, 처음에 생성한 Discussions 카테고리를 선택하면 끝입니다.
만약 블로그 댓글이 많지 않으신분은 몇번 딸깍만 하면 끝이납니다만, 댓글들이 수많은 글에 작성되어있는 분이라면 자동화 스크립트
로 하는것이 나을 것 같네요. 저는 댓글이 별로 없어서 그냥 1분만에 옮길 수 있었습니다.
오늘은 Giscus
댓글 시스템을 설정하여 웹에 게시하는 방법을 알아보았는데요. 기존에 Utterances만 사용하던 저에게는 정말 좋은 시스템이라고 생각드네요.👍 많은 분들이 Giscus
시스템을 설정하는데 제 글이 도움이 된다면 좋겠습니다.
이상으로 글을 마치도록 하겠습니다. 읽어주셔서 감사합니다!
타입스크립트의 타입 할당관계 규칙인 공변성과 반공변성에 대해서 알아봅시다.
GitHub Actions의 재사용 가능한 워크플로우를 사용하여 로직을 재사용 해보겠습니다.