Ghost 블로그에 댓글 및 채팅 기능 추가 가이드
Ghost 블로그에 댓글과 채팅 기능을 붙이는 방식을 비교합니다. 외부 임베드와 직접 만든 문의 위젯의 장단점, Code Injection, 보안과 스팸 방지를 정리했습니다.
Ghost 블로그에 댓글과 채팅 기능을 붙이는 방법은 크게 외부 서비스를 임베드하는 방식과 직접 백엔드를 만들어 연결하는 방식으로 나뉩니다. 실습은 Disqus와 Tawk.to 같은 외부 서비스 삽입을 소개했지만, 운영 관점에서는 개인정보, 외부 스크립트 성능, 디자인 일관성, 데이터 보관 위치까지 같이 고려해야 합니다.
구성 방식 비교
| 방식 | 장점 | 주의점 |
|---|---|---|
| Disqus 같은 외부 댓글 | 설정이 빠르고 관리 화면이 제공됩니다. | 외부 스크립트, 광고/트래킹, 디자인 이질감이 생길 수 있습니다. |
| Tawk.to 같은 외부 채팅 | 실시간 상담 기능을 빠르게 붙일 수 있습니다. | 사이트 로딩, 개인정보, 브랜드 문구, 외부 장애 영향을 받습니다. |
| 직접 만든 문의 위젯 | 디자인과 데이터 흐름을 완전히 제어할 수 있습니다. | 서버 API, 저장소, 알림 연동, 스팸 방지, 운영 모니터링이 필요합니다. |
Ghost Code Injection 위치
Ghost Admin에서 외부 스크립트를 넣을 때는 보통 다음 위치를 사용합니다.
- Ghost Admin에 로그인합니다.
Settings또는Code injection메뉴로 이동합니다.- 전체 사이트에 필요한 스크립트는 Site Footer에 넣는 편이 일반적입니다.
- 댓글처럼 특정 post template에만 필요한 기능은 theme 수정이나 post footer injection을 검토합니다.
외부 스크립트는 렌더링을 막지 않도록 footer 쪽에 넣고, 로딩 실패 시 본문 읽기가 깨지지 않게 구성하는 것이 좋습니다.
Disqus 댓글 방식
Disqus를 사용한다면 서비스에서 사이트를 등록하고 Ghost용 Universal Code를 받아 삽입합니다. 다만 댓글 위젯은 포스트별 canonical URL과 slug를 기준으로 댓글을 연결하므로, 도메인 변경이나 slug 변경 전에는 댓글 매핑 영향을 확인해야 합니다.
<div id="disqus_thread"></div>
<script>
var disqus_config = function () {
this.page.url = window.location.href;
this.page.identifier = window.location.pathname;
};
(function() {
var d = document, s = d.createElement('script');
s.src = 'https://YOUR_SHORTNAME.disqus.com/embed.js';
s.setAttribute('data-timestamp', +new Date());
(d.head || d.body).appendChild(s);
})();
</script>직접 만든 문의 채팅 방식
직접 만든 채팅 위젯은 보통 브라우저 위젯, 서버 API, 알림 채널로 나눕니다.
- 브라우저 위젯: 이름, 이메일, 메시지 입력, 대화 내역 표시
- 서버 API: 메시지 저장, 스팸 제한, 알림 전송
- 운영 알림: Slack, Email, Matrix, Discord 등 운영자가 보는 채널
// 브라우저 위젯에서 메시지를 보내는 최소 예시
async function sendInquiry(payload) {
const res = await fetch('/chat/messages', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
name: payload.name,
email: payload.email,
message: payload.message
})
});
if (!res.ok) {
throw new Error('message send failed');
}
return res.json();
}서버 API에서 필요한 기능
POST /chat/messages
- visitor_id
- name
- email
- message
- created_at
GET /chat/messages?visitor_id=...
- visitor message
- operator reply
- created_at
- delivery status새로고침 후에도 대화를 이어가려면 visitor id, 이름, 이메일을 브라우저 localStorage나 서버 세션으로 연결해야 합니다. 단, 이메일 같은 개인정보는 최소한만 저장하고 보관 기간을 정해야 합니다.
보안과 스팸 방지
- HTML을 그대로 저장하거나 다시 렌더링하지 말고 escape 처리합니다.
- IP/visitor 기준 rate limit을 둡니다.
- 외부 알림 webhook이나 토큰은 브라우저에 노출하지 않습니다.
- 첨부파일 기능은 별도 검증 전까지 넣지 않습니다.
- 운영자 답글 기능을 만들면 권한 인증과 audit log를 남깁니다.
적용 후 확인
curl -I https://example.com/
curl -s https://example.com/ | grep -E 'chat|comment|disqus' || true
# 브라우저에서 확인할 것
# 1. 위젯이 본문을 가리지 않는지
# 2. 모바일에서 입력창이 화면 밖으로 나가지 않는지
# 3. 새로고침 후 대화가 유지되는지
# 4. 외부 스크립트 실패 시 페이지가 정상 표시되는지