이전 글에서 Astro 기반 블로그 구축 방법을 다뤘습니다. 이번 글에서는 정적 사이트에 댓글 시스템을 붙이는 방법을 다룹니다. 🚀
🤔 왜 Giscus ↗인가?
정적 사이트의 한계
Astro로 만든 정적 블로그는 빠르고 공격 표면이 작습니다. 대신 서버가 없어서 독자와 주고받는 기능을 직접 넣기 어렵습니다. 댓글 기능이 없으면 독자의 피드백을 받을 곳이 없습니다.
댓글 시스템 옵션 비교
| 솔루션 | 데이터 저장소 | 설정 복잡도 | 비용 | 커스터마이징 | 관리 편의성 |
|---|---|---|---|---|---|
| Giscus | GitHub Discussions | 🟢 쉬움 | 🟢 무료 | 🟢 높음 | 🟢 높음 |
| Disqus | 자체 서버 | 🟡 보통 | 🟡 유료 | 🟡 보통 | 🟡 보통 |
| Commento | 자체 서버 | 🔴 어려움 | 🟡 유료 | 🟢 높음 | 🔴 낮음 |
| Utterances | GitHub Issues | 🟢 쉬움 | 🟢 무료 | 🟡 보통 | 🟡 보통 |
Giscus를 선택한 이유
- GitHub Discussions 기반: 개발자 친화적인 환경에서 댓글 관리
- 완전 무료: 별도 서버나 데이터베이스 비용 없음
- 자동 동기화: GitHub에서 댓글 작성 시 실시간 반영
- 테마 지원: 라이트/다크 모드 지원
- 다국어 지원: 한국어 UI 제공
- 오픈소스: 커뮤니티 기반으로 지속적인 개선
🏗️ 아키텍처 설계
전체 시스템 구조
flowchart TD
A[사용자<br/>댓글 작성 / 조회] --> B[Astro 블로그<br/>Giscus 위젯]
B --> C[GitHub Discussions<br/>댓글 저장 / 관리]
D[Astro Build] -->|빌드 시 자동 생성| C
설계 원칙
- 별도 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-commentsrepository 선택하여 설치- 필요한 권한 부여 (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 댓글은 iframe으로 뜨기 때문에 블로그 테마를 따라가지 않습니다. 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"],
});
}
동작 순서
flowchart TD
A[data-theme 변경] -->|MutationObserver| B[getCurrentTheme]
B --> C[postMessage]
C --> D[Giscus iframe<br/>테마 자동 적용]
- DOM 속성 감지:
document.documentElement의data-theme속성 변화를MutationObserver로 감시 - 실시간 테마 동기화: 사이트 테마 변경 시 즉시 Giscus iframe에
postMessage로 테마 정보 전달 - 자동 테마 적용: Giscus가 전달받은 테마 정보를 바탕으로 댓글 UI 테마 자동 변경
- 중복 방지:
__giscusThemeObserver키를 사용하여 Observer 중복 생성 방지
사용자가 어떤 방식으로 테마를 바꿔도 댓글 영역이 사이트와 같은 테마로 표시됩니다.
🎯 결론
Giscus로 서버 없이 정적 블로그에 댓글 기능을 붙였습니다.
다음 단계
다음 글에서는 빌드 때 Discussion을 미리 만드는 GitHub Discussions 자동 생성 시스템을 다룹니다.
📚 참고 자료
Giscus 댓글 시스템을 구현하며 느낀 점: 정적 사이트에서도 댓글 같은 동적 기능을 붙일 수 있었습니다. 댓글 데이터가 GitHub Discussions에 쌓이니 GitHub에서 바로 관리할 수 있어 편했습니다.