이전 글에서 Astro 기반 블로그 구축 방법을 다뤘습니다. 이번 글에서는 정적 사이트에서 사용자와의 상호작용을 가능하게 하는 댓글 시스템 구현에 대해 다루겠습니다. 🚀
🤔 왜 Giscus인가?
정적 사이트의 한계
Astro로 구축한 정적 블로그는 성능과 보안 측면에서 뛰어나지만, 사용자와의 상호작용 부족이라는 한계가 있습니다. 특히 댓글 기능이 없으면 독자들의 피드백을 받기 어렵고, 블로그의 활성도가 떨어질 수 있습니다.
댓글 시스템 옵션 비교
솔루션 | 데이터 저장소 | 설정 복잡도 | 비용 | 커스터마이징 | 관리 편의성 |
---|---|---|---|---|---|
Giscus | GitHub Discussions | 🟢 쉬움 | 🟢 무료 | 🟢 높음 | 🟢 높음 |
Disqus | 자체 서버 | 🟡 보통 | 🟡 유료 | 🟡 보통 | 🟡 보통 |
Commento | 자체 서버 | 🔴 어려움 | 🟡 유료 | 🟢 높음 | 🔴 낮음 |
Utterances | GitHub Issues | 🟢 쉬움 | 🟢 무료 | 🟡 보통 | 🟡 보통 |
Giscus를 선택한 핵심 이유
- GitHub Discussions 기반: 개발자 친화적인 환경에서 댓글 관리
- 완전 무료: 별도 서버나 데이터베이스 비용 없음
- 자동 동기화: GitHub에서 댓글 작성 시 실시간 반영
- 테마 지원: 라이트/다크 모드 지원
- 다국어 지원: 한국어 UI 제공
- 오픈소스: 커뮤니티 기반으로 지속적인 개선
🏗️ 아키텍처 설계
전체 시스템 구조
+---------------+ +----------------+ +---------------------+
| 사용자 | ---> | Astro 블로그 | ---> | GitHub Discussions |
| 댓글 작성/조회 | | (Giscus) | | 댓글 저장/관리 |
+---------------+ +----------------+ +---------------------+
|
v
+----------------------+
| 빌드 시 자동 |
| Discussion 생성 |
+----------------------+
핵심 설계 원칙
- 별도 Public Repository 사용: Giscus는 private repository를 지원하지 않으므로, 댓글 저장을 위해 별도의 public repository 사용
- Discussion 자동 생성: 개별 포스트에 매칭되는 Discussion이 없을 경우 Giscus가 404 에러를 발생시키므로, 빌드 시 자동으로 Discussion을 생성하여 에러 방지
- 테마 자동 동기화: 사이트 테마 변경 시 댓글 테마도 자동 변경
🚀 Giscus 설정 및 구현
1단계: GitHub Repository 준비
별도 Repository 생성
댓글 저장을 위해 별도의 public repository를 생성합니다. (예: username/blog-comments
)
필수 조건:
- ✅ Repository가 public이어야 함
- ✅ Discussions 기능 활성화
- ✅ Giscus 앱 설치
Giscus 앱 설치
- Giscus 앱 페이지에서 “Install” 클릭
blog-comments
repository 선택하여 설치- 필요한 권한 부여 (Discussions 읽기/쓰기)
2단계: Giscus 설정
giscus.app에서 다음 설정을 구성합니다:
기본 설정:
<script
src="https://giscus.app/client.js"
data-repo="[ENTER REPO HERE]"
data-repo-id="[ENTER REPO ID HERE]"
data-category="[ENTER CATEGORY NAME HERE]"
data-category-id="[ENTER CATEGORY ID HERE]"
data-mapping="pathname"
data-strict="0"
data-reactions-enabled="1"
data-emit-metadata="0"
data-input-position="bottom"
data-theme="preferred_color_scheme"
data-lang="ko"
crossorigin="anonymous"
async
></script>
3단계: Astro 컴포넌트 구현
Comments 컴포넌트 생성
---
---
<!-- Giscus 댓글 컨테이너 -->
<div class="giscus-comments mt-10"></div>
<script is:inline>
(() => {
/**
* Giscus 스크립트 속성 설정 및 생성
*/
function configureGiscusScript(script) {
const attributeMap = {
"data-repo": "username/blog-comments", // GitHub 저장소 (예: username/blog-comments)
"data-repo-id": "R_kgDOGxxxxxxxx", // 저장소 ID (GitHub에서 확인)
"data-category": "Announcements", // Discussion 카테고리
"data-category-id": "DIC_kwDOGxxxxxxxx", // 카테고리 ID (GitHub에서 확인)
"data-mapping": "pathname", // URL 매핑 방식
"data-strict": "0", // 엄격 모드 (0: 비활성화)
"data-reactions-enabled": "1", // 반응 기능 (1: 활성화)
"data-emit-metadata": "0", // 메타데이터 전송 (0: 비활성화)
"data-input-position": "bottom", // 입력창 위치
"data-theme": getCurrentTheme(), // 블로그에 적용된 테마
"data-loading": "lazy", // 로딩 방식
"data-lang": "ko", // 언어 설정
crossorigin: "anonymous", // CORS 설정
};
// 속성 일괄 설정
Object.entries(attributeMap).forEach(([key, value]) => {
script.setAttribute(key, value);
});
script.src = "https://giscus.app/client.js";
}
/**
* Giscus 댓글 시스템 로드
*/
function loadGiscus() {
const container = document.querySelector(".giscus-comments");
if (!container) return;
container.innerHTML = "";
const script = document.createElement("script");
configureGiscusScript(script);
container.appendChild(script);
}
// 초기화 실행
loadGiscus();
})();
</script>
4단계: 레이아웃에 통합
---
// src/layouts/PostDetails.astro
// ... 기존 imports ...
import Comments from "@/components/Comments.astro";
---
<!-- ... 기존 콘텐츠 ... -->
<div class="mt-8">
<ShareLinks />
</div>
<Comments />
<hr class="mt-6 border-dashed" />
<!-- ... 나머지 레이아웃 ... -->
🎨 테마 자동 동기화 구현
테마 동기화의 필요성
정적 블로그에서 Giscus 댓글 시스템을 사용할 때, OS의 디스플레이 모드 변경이나 블로그의 테마 변경 시 댓글 컴포넌트의 테마도 자동으로 동기화되어야 합니다.
테마 감지 메커니즘
Comments.astro
컴포넌트에서 구현된 테마 감지 시스템은 다음과 같은 방식으로 작동합니다:
/**
* 현재 테마 가져오기
* @returns {string} 'dark' 또는 'light'
*/
function getCurrentTheme() {
return document.documentElement.getAttribute("data-theme") === "dark"
? "dark"
: "light";
}
/**
* Giscus iframe에 테마 변경 메시지 전송
* @param {string} theme - 적용할 테마
*/
function updateGiscusTheme(theme) {
const iframe = document.querySelector(".giscus-frame");
if (!iframe?.contentWindow) return;
iframe.contentWindow.postMessage(
{
giscus: {
setConfig: {
theme: theme === "dark" ? "dark" : "light",
},
},
},
"https://giscus.app"
);
}
/**
* 테마 변경 감지를 위한 Observer 설정
*/
function setupThemeObserver() {
// 중복 방지
if (window.__giscusThemeObserver) return;
window.__giscusThemeObserver = new MutationObserver(mutations => {
mutations.forEach(mutation => {
if (mutation.attributeName === "data-theme") {
const newTheme = getCurrentTheme();
updateGiscusTheme(newTheme);
}
});
});
window.__giscusThemeObserver.observe(document.documentElement, {
attributes: true,
attributeFilter: ["data-theme"],
});
}
핵심 동작 원리
- DOM 속성 감지:
document.documentElement
의data-theme
속성 변화를MutationObserver
로 감시 - 실시간 테마 동기화: 사이트 테마 변경 시 즉시 Giscus iframe에
postMessage
로 테마 정보 전달 - 자동 테마 적용: Giscus가 전달받은 테마 정보를 바탕으로 댓글 UI 테마 자동 변경
- 중복 방지:
__giscusThemeObserver
키를 사용하여 Observer 중복 생성 방지
이를 통해 사용자는 어떤 방식으로 테마를 변경하더라도 댓글 시스템이 일관된 테마로 표시되는 경험을 얻을 수 있습니다.
🎯 결론
Giscus를 통한 댓글 시스템 구현으로 정적 블로그의 한계를 극복하고, 사용자와의 상호작용을 가능하게 만들었습니다.
다음 단계
이제 기본적인 댓글 시스템이 완성되었으니, 다음 글에서는 GitHub Discussions 자동 생성 시스템을 통해 댓글 시스템의 완성도를 높여보겠습니다.
📚 참고 자료
Giscus 댓글 시스템 구현을 통해 느낀 점: 정적 사이트에서도 동적인 사용자 상호작용을 구현할 수 있다는 것을 확인했습니다. 특히 GitHub Discussions를 활용한 방식은 개발자 친화적이면서도 안정적이어서 매우 만족스럽습니다.