라임과 청록 원형 패턴의 댓글 구조 글 커버

댓글: utterances와 GitHub Actions 알림 파이프라인

댓글은 공개 저장소의 utterances로, 알림과 모더레이션은 GitHub Actions로. 올리브영 기술블로그의 댓글 알림 시스템을 개인 블로그용으로 옮긴 기록.

kese· 1분 읽기
목차

요구 사항

댓글 시스템에 원한 건 세 가지다. 서버를 두지 않을 것, 댓글 데이터가 내 GitHub에 남을 것, 새 댓글이 달리면 알림이 올 것. Disqus는 광고와 추적이 싫고, 직접 DB를 운영하기엔 정적 블로그의 취지와 어긋난다. 남은 선택지는 GitHub Issue를 댓글 저장소로 쓰는 utterances였다.

구조

방문자가 utterances 위젯으로 댓글을 쓰면 공개 kese-comments 이슈에 저장되고, GitHub Actions가 비공개 kesekr에 알림 이슈를 만드는 흐름도
댓글의 경로. 읽기는 공개 저장소에서, 알림과 분석은 비공개 저장소에서 일어난다.

흐름은 두 저장소를 오간다.

  1. 방문자가 포스트 하단의 utterances 위젯으로 댓글을 쓴다. GitHub 계정 로그인이 필요하다.
  2. utterances가 공개 저장소 kese/kese-comments에 포스트별 Issue를 만들고, 댓글을 이슈 댓글로 저장한다.
  3. issue_comment.created 이벤트가 kese-comments의 GitHub Actions 워크플로우를 깨운다.
  4. 워크플로우가 이슈 제목(/blog/<slug>/)에서 slug를 뽑고, 비공개 kese/kesekr에서 포스트와 content/authors.yaml의 작성자 매핑을 읽는다.
  5. Gemini 키가 설정되어 있으면 댓글 분류·독성 레벨(0-5)·추천 답변을 생성하고, Level 4 이상은 댓글을 즉시 삭제한다.
  6. 결과는 비공개 kesekr에 알림 Issue로 쌓인다. 같은 포스트의 알림 Issue가 열려 있으면 새로 만들지 않고 댓글로 합친다.

올리브영에서 가져온 것

이 자동화는 oy-techblog/tech-blog-comment를 이식한 것이다. 원본은 조직 블로그용이라 작성자를 member.yaml에서 찾고 별도 조직 저장소에 알림을 둔다. 개인 블로그로 옮기며 작성자 매핑은 content/authors.yaml로 줄였고, 알림 대상은 비공개 블로그 저장소 자체로 향하게 했다. 원본의 workflow가 step-level bot 체크로는 실제 잡을 건너뛰지 못하는 문제가 있어 job-level 조건으로 고쳤다.

공개 범위도 이 과정에서 자연스럽게 갈렸다. 댓글 원문은 공개 kese-comments에, 알림·AI 분석·월별 메트릭은 비공개 kesekr에 남는다.

왜 비공개가 아니라 공개 저장소인가

utterances는 로그인하지 않은 방문자도 댓글을 읽을 수 있어야 해서 저장소가 반드시 공개다. 처음엔 비공개 저장소와 승인 큐를 Netlify Functions로 만들었다. 그런데 댓글 데이터는 어차피 공개 글 아래에 달리는 공개 텍스트고, 승인이 필요한 건 표시가 아니라 대응이었다. 그래서 기본을 utterances로 바꿨다.

다만 승인 큐 설계가 완전히 버린 건 아니다. 함수 백엔드는 GATSBY_COMMENTS_PROVIDER=functions로 그대로 살아 있어서, 나중에 '댓글이 달려도 바로 공개하지 않는' 운영이 필요해지면 되돌릴 수 있다. 트레이드오프를 둘 다 보유한 채 기본값만 바꾼 셈이다.

#github#utterances#github-actions#댓글

kese · 개발자

만들고, 부수고, 기록하는 사람. 이 블로그는 그 과정의 원장이다.

소개 보기

관련 글

댓글

GitHub 계정으로 로그인해 댓글을 남길 수 있습니다. 댓글은 kese-comments 저장소 이슈로 공개 저장됩니다.