블로그에 붙이려고 직접 만든 댓글 서비스, orbithall
글이라는 행성 곁에 궤도 하나
2026/09/21블로그에 붙이려고 직접 만든 댓글 서비스, orbithall
이 블로그의 글 아래에 있는 댓글창은 상용 서비스가 아니다. 2025년 가을쯤에 직접 만든 댓글 서비스 orbithall이다. Go로 API 서버를 만들고, 어느 페이지에나 붙일 수 있는 위젯과 사이트를 관리하는 어드민까지 만들어 이 블로그에 연결했다.
꽤 공들여 만든 만큼 과정을 시리즈로 정리해 보려 한다. 편마다 기능 하나를 골라 어떻게 동작하는지, 왜 그렇게 결정했는지를 적고, 마지막에는 그 단계에서 코딩 에이전트인 Claude Code와 어떻게 작업했는지를 덧붙인다. 이 글은 그 첫 편으로, orbithall이 어떤 서비스이고 왜 만들었는지를 다룬다.
왜 직접 만들었나
오래전에 Disqus를 써 본 적이 있다. 글과 완전히 독립된 댓글 서비스가 스크립트 몇 줄로 어느 페이지에나 붙는다는 개념이 처음엔 꽤 신기했다. 그때의 기억 덕분에 이런 서비스가 대략 어떤 구조로 만들어질지는 머릿속에 그려져 있었다.
직접 만들기로 한 데는 몇 가지 이유가 있었다. 우선 머릿속에만 있던 독립형 댓글 서비스의 구조를 직접 구현해 보고 싶었다. Disqus를 쓸 때 댓글창이 뜨기까지 느리다고 느꼈던 기억도 남아 있었고, 요금제나 댓글 데이터가 특정 서비스에 묶이는 것도 부담스러웠다.
공부 목적도 있었다. 백엔드 언어로는 써 본 적이 거의 없는 Go를 골랐는데, Go의 생산성이 궁금했다. 타입이 엄격한 컴파일 언어, 그리고 쓰는 방식이 어느 정도 정해진 언어와 프레임워크라면 에이전트와 함께 코딩할 때 더 빠르고 안정적이지 않을까 싶었다. 실제로 어땠는지는 시리즈를 진행하며 이야기해 보겠다.
문턱 없는 댓글
댓글은 쉽게 남길 수 있어야 한다고 생각한다. 글을 읽어 주는 것만으로도 고마운데, 의견을 남겨 저자에게 말을 걸어 주는 건 훨씬 고마운 일이다. 그 과정에 로그인 같은 턱이 없었으면 했다.
그래서 orbithall의 댓글은 이름과 비밀번호만으로 남긴다. 계정도 로그인도 없다. 비밀번호는 나중에 본인이 쓴 댓글을 고치거나 지울 때 쓴다.
문턱을 낮춘 대가도 분명하다. 익명이면 스팸이나 부적절한 글이 들어오기 쉽다. 지금은 HTML 태그를 모두 걷어내고, 같은 IP에서 짧은 시간에 댓글을 몰아 쓰지 못하게 막고, 작성자 본인만 30분 안에 비밀번호로 수정·삭제할 수 있게 했다. 다만 신고 기능이나 관리자가 댓글을 지우는 기능은 아직 없다. 이 숙제는 마지막 회고 편에서 다시 이야기하겠다.
어떻게 생겼나

orbithall은 네 부분으로 이루어져 있다.
| 구성 | 하는 일 | 기술 | 올라가 있는 곳 |
|---|---|---|---|
| API 서버 | 댓글 조회·작성·수정·삭제, 사이트 관리 | Go, Chi | Render |
| DB | 사이트, 글, 댓글 저장 | PostgreSQL | Neon |
| 위젯 | 페이지 안에서 댓글창을 그림 | Preact, Bun | jsDelivr |
| 어드민 | 사이트 등록, 통계, 댓글 확인 | Next.js | Vercel |
블로그에 붙이는 방법은 간단하다. 위젯의 CSS와 스크립트를 불러오고, 댓글을 띄울 자리에 글의 식별자(slug)를 담은 div를 두면 된다.
<div data-orb-container data-widget-type="comments" data-post-slug="orbithall-introduce"></div>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/june20516/orbithall@widget/v1.1.1/static/embed.css" />
<script src="https://cdn.jsdelivr.net/gh/june20516/orbithall@widget/v1.1.1/static/embed.js"></script>
<script>
OrbitHall.init({ apiKey: '<사이트 API 키>' });
</script>
위젯은 페이지에서 이 div를 찾아 댓글창을 그리고, 사이트 API 키를 붙여 API 서버에서 해당 글의 댓글을 가져온다. 글은 따로 등록할 필요 없이, 첫 댓글이 달릴 때 slug를 기준으로 자동으로 만들어진다. 이 블로그에서는 실제로 이렇게 보인다.

블로그 하나만 쓸 서비스였지만, 구조는 여러 사이트를 받을 수 있게 만들었다. 구글 계정으로 어드민에 로그인해 사이트를 등록하면 그 사이트 전용 API 키가 나온다. 머릿속에 그렸던 독립형 댓글 서비스의 구조를 제대로 연습해 보고 싶었고, 혹시 주변에서 필요하다는 사람이 있으면 내줄 수 있겠다는 생각도 있었다. 상용화까지는 생각하지 않았다. 서비스로 내놓으려면 기본 기능에 더해 이 서비스만의 특색이 있어야 하는데, 지금의 orbithall은 기본에 충실한 댓글 서비스다.
이름에 담은 것
이 블로그는 우주 콘셉트다. 글 하나를 행성이나 항성이라고 생각하면, 그 주변에는 궤도가 생긴다. 댓글은 그 궤도에 올라탄 위성 같은 말들이다. 그런 자리를 마련해 주는 서비스라서 궤도(orbital)에 빗대고, 발음이 비슷하게 orbit을 가져왔다. 뒤에 붙은 hall은 사람들이 모여 이야기하는 공간이라는 느낌을 담았다.
만든 과정
| 시기 | 한 일 |
|---|---|
| 2025년 10월 초~중순 | 백엔드 뼈대와 댓글 API |
| 2025년 10월 말 | 첫 배포, 위젯, 블로그 연결 |
| 2025년 11월 초 | 어드민 |
| 2025년 11월~2026년 8월 | 작업 중단, 그사이 무료로 쓰던 DB가 비활성 프로젝트로 정리됨 |
| 2026년 9월 | DB 이전, 어드민 댓글 조회, 보안 보강 |
한동안 손을 놓고 있다가, 블로그 글을 다시 쓰고 다듬으면서 orbithall도 함께 정상화했다. 쓰던 무료 DB가 오래 쓰지 않은 프로젝트를 지워 버려서, 개인 프로젝트에 좀 더 우호적인 곳을 찾아 옮겼다. 원래도 쌓인 데이터가 거의 없어서 새로 시작하는 데 큰 부담은 없었다.
시리즈는 이 흐름을 따라간다.
- 소개 (이 글)
- 백엔드 뼈대: Go로 처음 만든 API 서버와 테스트
- 댓글 API: 데이터 모델, 인증, 스팸 방어
- 위젯: 어느 페이지에나 붙는 댓글창과 배포
- 어드민: 구글 로그인과 사이트 관리
- 운영과 이전: 무료 인프라로 버티기
- 회고: 못 만든 것, 그리고 에이전트와 일한 방식
에이전트와 작업하며
orbithall은 처음부터 에이전트와 함께 만들었다. 시작하기 전에 "완벽하진 않지만 실제 비즈니스에서 굴러가는 수준"의 바이브 코딩 사례를 가까이서 겪어 볼 기회가 있었는데, 그때 문서를 먼저 쓰고 그 문서를 기준으로 구현하는 방식을 경험했다. orbithall도 그 방식으로 시작했다. 그래서 첫 커밋에는 코드보다 문서 틀이 먼저 들어갔다. 작업 문서와 명세서 템플릿, 결정 기록(ADR)을 모아 둘 자리, 그리고 "이 작업 문서를 읽고 명세대로 구현해 줘"처럼 에이전트에게 일을 맡기는 방식까지 적어 두었다.
역할은 이렇게 나눴다. 문서 초안도 에이전트가 쓰고, 문서와 코드를 리뷰하는 일은 거의 직접 했다. 공부가 목적이기도 해서 코드를 읽다가 모르는 부분은 계속 물었다. 원래 알던 백엔드 지식에서 출발해 꼬리에 꼬리를 무는 질문으로 파고들다 보면, 문제가 될 만한 부분이 미리 보이곤 했다.
다만 이 방식에도 빈틈이 있었다. 하나는 먼저 써 둔 문서가 어느새 코드와 어긋난 것이다. 문서를 기준으로 구현을 시작해도, 구현하면서 바뀐 결정은 문서로 돌아가지 않았다. 예를 들어 레이트리밋 문서에는 댓글 수정과 삭제도 작성과 같은 제한을 받는다고 확정해 두었는데, 실제 코드는 작성에만 제한을 건다. 문서를 먼저 쓰는 방식은 에이전트에게 방향을 잡아 주기엔 좋았지만, 그 문서를 코드에 맞춰 계속 고치는 일은 나도 에이전트도 챙기지 않았다.
다른 하나는 테스트였다. 테스트 코드가 실제 코드보다 많을 만큼 신경을 썼는데도, 댓글 작성자의 IP를 가리는 함수는 제대로 검증하지 못했다. 테스트는 가려진 IP가 비어 있지 않은지만 확인했고, 넣어 본 주소도 전부 IPv4였다. 그사이 2001:db8::1처럼 줄여 쓴 IPv6 주소는 가려지지 않은 채 원본 그대로 공개 API로 나가고 있었다. 이 버그는 11개월 뒤 다시 작업을 시작하고서야 리뷰 과정에서 발견했다. 테스트가 많다는 것이 곧 안심할 근거는 아니었던 셈이다.
정리하면, 문서와 테스트는 있다는 것만으로 코드를 지켜 주지 않았다. 이런 일들은 해당 편에서 자세히 풀어 보려 한다. 나중에는 superpowers 같은 잘 짜인 워크플로 플러그인의 도움을 많이 받게 되는데, 그 전후로 무엇이 달라졌는지는 회고 편에서 비교해 보겠다.
저장소
- API 서버와 위젯: june20516/orbithall
- 어드민: june20516/orbithall-admin