
언어 🇰🇷 한국어
Val Town 설치
설문
Val Town 앱에 실시간 댓글 추가
Val Town 은 Deno에서 TypeScript를 실행하므로 val은 실제 서버입니다. 이는 FastComments에 적합합니다: 위젯은 페이지에 삽입되는 script 태그이며, Secure SSO나 웹훅 검증처럼 비밀이 필요한 모든 작업을 동일한 val에서 서버 측으로 실행할 수 있습니다.
이 가이드는 HTTP val에 댓글 위젯을 추가하고, 인덱스 페이지에 댓글 수를 표시하며, 사용자가 이미 가지고 있는 Val Town 계정으로 로그인하고, 댓글 웹훅을 받는 방법을 다룹니다.
시도하는 데 계정이 필요하지 않습니다. 예제는 tenantId: "demo" 를 사용하며, 공유 샌드박스이며, 2단계에서 자신의 것으로 전환하는 방법을 설명합니다.
1단계: 위젯 추가 
위젯은 script 태그와 컨테이너 요소로 구성되어 있으므로, val이 이미 렌더링하는 무엇이든 손쉽게 삽입할 수 있습니다. 이 예제는 Val Town의 HTTP 템플릿에서 사용하는 Hono JSX를 사용합니다.
Run 
배포 전에 urlId를 정하세요
urlId는 댓글이 어느 스레드에 속하는지 결정합니다. 설정하지 않으면 현재 페이지 URL을 정리한 버전이 기본값으로 사용되는데, 이것이 바로 Val Town에서 변경되는 부분입니다: 서브도메인을 등록하기 전까지 val은 긴 *.web.val.run 호스트명을 가지며, 브랜치마다 별도의 URL이 생기고, 페이지 이름을 바꾸면 경로가 달라집니다. 이러한 변화마다 조용히 별개의 빈 스레드가 만들어지고, 그 결과 "내 댓글이 사라졌다"는 증상으로 나타납니다.
위 예제처럼 게시글 슬러그나 데이터베이스 id처럼 여러분이 관리하는 안정적인 값으로 설정하세요. url도 함께 전달하면 알림 이메일과 관리 도구가 실제 페이지로 연결될 수 있습니다.
JavaScript 없이 댓글 유지하기
FastComments는 전체 스레드를 서버 측에서 렌더링하므로, val에서 <noscript> 블록에 넣을 수 있습니다:
Run 
파라미터는 URL 인코딩하세요. 서버 측 버전은 익명 및 로그인 댓글 작성, SSO, 중첩 답글을 지원합니다.
2단계: 자체 계정 사용 
tenantId: "demo"는 공유 공개 샌드박스입니다. 가입 없이 바로 사용할 수 있어 예제에서 이 값을 사용하지만, FastComments를 사용해 보는 모든 사람이 같은 스레드에 글을 쓰고 누구나 해당 내용을 관리할 수 있습니다. 중요한 것을 게시하기 전에 반드시 변경하세요.
테넌트 ID는 API secret 페이지에서 확인할 수 있습니다.
테넌트 ID는 공개 정보이며 브라우저 코드에 포함됩니다. API secret은 그렇지 않으며, 이 페이지의 어떤 내용도 API secret을 필요로 하지 않습니다.
환경 변수에서 읽기
Val Town의 val은 무료 티어에서 공개되므로 소스 코드가 전 세계에 노출됩니다. 민감한 정보는 환경 변수에 보관하고 Deno.env.get으로 읽으세요:
Run 
Val Town에서는 두 번째 이유로 인해 이것이 평소보다 더 중요합니다: val을 리믹스하면 환경 변수의 키는 복사되지만 값은 복사되지 않습니다. 환경 변수에 보관된 secret은 다른 사람의 계정으로 val과 함께 전달되지 않습니다. 파일에 작성된 secret은 전달됩니다.
"demo"로 폴백하면 자신의 테넌트를 설정하기 전에 val을 리믹스하는 사람도 val을 계속 사용할 수 있습니다.
EU 계정
계정, 데이터, 키는 하나의 리전에 존재합니다. 계정이 eu.fastcomments.com에서 생성되었다면 모든 위젯 설정에 region: "eu"가 필요하고, 스크립트는 cdn-eu.fastcomments.com에서 로드됩니다. 그렇지 않다면 둘 다 그대로 두세요.
인덱스 페이지의 댓글 수 
인덱스 페이지에서는 행마다 하나의 comment-count 위젯을 렌더링하지 마세요. 이는 게시물당 하나의 요청이 발생합니다. 전체 페이지에 대해 단일 요청으로 처리되는 bulk count를 사용하세요.
각 행에 해당 스레드가 사용하는 urlId를 표시하고, bulk 위젯을 한 번만 로드하세요:
Run 
스크립트는 페이지 내 모든 .fast-comments-count 요소를 찾아 해당 카운트를 채워 넣습니다.
data-fast-comments-url-id는 게시물의 댓글 위젯이 사용하는 urlId와 일치해야 합니다. 위젯이 슬러그를 사용한다면, 마커도 슬러그를 사용합니다. 일치하지 않을 경우 댓글이 있는 스레드에서도 0이 표시됩니다.
스크립트는 window.FastCommentsBulkCountConfig를 폴링하므로, 스크립트 태그 앞이나 뒤에 설정을 넣는 것이 중요하지 않습니다.
std/oauth를 사용한 보안 SSO 
이미 방문자가 누구인지 val이 알고 있다면, Secure SSO는 해당 신원을 위젯에 전달하여 두 번째 로그인을 보지 않도록 합니다. 만들 엔드포인트도 없고 런타임에 호출할 것도 없습니다: 서버 측에서 세 개의 값을 계산하여 위젯 설정에 전달하면 됩니다.
Val Town은 std/oauth를 통해 설정 없이 바로 사용할 수 있는 로그인을 제공하므로, 방문자는 이미 가지고 있는 Val Town 계정으로 로그인할 수 있습니다. 이를 여러분의 앱에서 사용하는 것으로 바꿔도 FastComments 쪽은 변경되지 않습니다.
서버에서 페이로드 빌드하기
API 시크릿은 페이로드에 서명하며 브라우저 코드에 절대 노출되어서는 안 됩니다. npm에서 SDK를 설치하세요. Val Town의 Deno 런타임에서 그대로 작동합니다:
Run 
getPayload()는 { userDataJSONBase64, verificationHash, timestamp }를 반환합니다. 이 세 값만 브라우저에 전달됩니다. 시크릿은 이들에 서명한 후 폐기되므로, 페이지의 어떤 것도 다른 사용자를 위조할 수 없습니다.
위젯에 전달하기
Run 
oauthMiddleware는 GET /auth/login, GET /auth/callback, POST /auth/logout을 자동으로 추가해 줍니다. 로그아웃은 POST인 반면, 위젯은 logoutURL을 GET으로 이동하므로, logoutURL이 POST를 전송하는 여러분만의 작은 라우트를 가리키도록 하세요.
방문자가 로그아웃 상태일 때는 loginURL만 포함된 sso를 전달하세요. 그러면 위젯은 익명 댓글 상자 대신 로그인 프롬프트를 표시합니다.
자주 발생하는 문제
timestamp는 에포크 밀리초 단위여야 하고, 미래 시점이어서는 안 되며, 이틀 이상 오래되어서도 안 됩니다. 해시를 계산하는 동일한 요청에서 서버에서 생성하세요. 브라우저에서 생성하는 것이 전형적인 실패 사례입니다: 값이 해시된 값과 달라져 모든 댓글이 거부됩니다.
신원 제공자(identity provider)에서 isAdmin이나 isModerator를 절대 설정하지 마세요. Val Town 계정으로 로그인하는 것은 누가 여러분의 사이트를 중재해야 하는지에 대한 아무런 정보도 제공하지 않습니다.
전체 필드 목록, 그룹 기반 스레드, 배지에 대해서는 SSO 가이드를 참조하세요.
웹훅 수신 
A val은 자연스러운 웹훅 수신기입니다: 안정적인 URL을 가지고 있으며, 서명을 검증할 수 있고, SQLite와 블롭 스토리지를 내장하고 있습니다.
FastComments는 ${timestamp}.${body}에 계정의 API 비밀키로 서명하고 두 개의 헤더를 전송합니다:
Run 
이 메서드는 이벤트를 전달합니다: 생성되거나 업데이트된 댓글의 경우 PUT, 삭제된 경우 DELETE.
Run 
문제를 일으키는 두 가지
원시 바이트를 검증하세요. JSON을 파싱하고 다시 직렬화하면 키 순서와 공백이 바뀌어 해시가 달라지며, 그 결과 원인 없이 모든 전달이 실패합니다. 이것이 웹훅 수신기가 "그냥 작동하지 않는다"는 일반적인 이유입니다.
상수 시간으로 비교하세요. 서명에 대한 단순 === 연산은 일치한 바이트 수를 누출하게 되며, 이는 바이트를 하나씩 위조하는 데 충분합니다.
이벤트 처리
빠르게 응답하세요. FastComments는 2xx가 아닌 응답에 대해 재시도하며, 계속 실패하는 엔드포인트는 결국 자동으로 비활성화됩니다. 따라서 응답을 반환한 후에 실제 작업을 수행하고, 인라인으로 처리하지 마세요.
해당 작업을 댓글 ID에 대해 멱등하도록 만드세요. 재시도 시 새로운 타임스탬프로 다시 서명되며, 편집 및 삭제 시 동일한 댓글 ID가 다시 도착하므로 중복 제거를 위한 안정적인 기준이 없습니다.
예시 Vals 
이 가이드의 각 부분을 다루는 리믹스 가능한 공개 val 네 개입니다.
Blog with comments (라이브)는 모든 게시물 아래에 댓글 스레드가 있고 인덱스에는 대량 댓글 수가 표시되는 Markdown 블로그입니다. 리믹스하는 즉시 작동하며, 환경 변수 하나만 설정하면 본인 계정으로 연결됩니다.
SSO demo (라이브)는 방문자를 Val Town 계정으로 로그인시키고 해당 신원을 위젯에 전달하여 두 번째 로그인이 필요 없게 합니다.
Webhook receiver (라이브)는 모든 전송에서 HMAC 서명을 검증하고 이벤트를 SQLite에 저장합니다. 테스트 페이로드에 서명하여 자기 자신에게 전송하는 버튼이 있어, 실제 웹훅을 설정하기 전에 검증이 성공하는 것을 확인할 수 있습니다.
Agent skills (라이브)는 위젯, SSO, REST API, 모더레이션, Disqus 마이그레이션을 다루는 FastComments 에이전트 스킬 라이브러리입니다. 리믹스하면 Val Town의 에이전트인 Townie가 skills/ 디렉터리에서 스킬을 자동으로 가져오므로, 문서를 채팅에 붙여넣지 않아도 에이전트가 댓글 설정 방법을 알게 됩니다.
동일한 스킬은 npx skills add fastcomments/skills로 어디서든 설치할 수 있습니다.
도메인 오류 
demo 테넌트를 끄면 위젯이 인증 오류로 로드되지 않을 수 있습니다. 이는 FastComments가 해당 도메인에서 귀하의 계정을 사용할 수 있도록 허용해야 함을 인식하지 못하기 때문입니다.
Val Town은 여기서 다시 살펴볼 가치가 있습니다. 왜냐하면 val은 하나 이상의 호스트명으로 접근할 수 있기 때문입니다:
- 모든 HTTP val은 긴 기본 엔드포인트
<org>--<id>.web.val.run를 가집니다. - 맞춤 서브도메인을 클레임하면
<name>.val.run이 추가됩니다. - 맞춤 도메인(custom domain)을 사용하면 세 번째가 추가됩니다.
- 브랜치는 자체 URL을 갖게 됩니다.
위젯을 제공하는 실제 호스트명을 모두 추가하세요. 설정 후에 서브도메인을 클레임하면 해당 서브도메인도 추가해야 합니다. 그렇지 않으면 위젯이 이전 URL에서는 작동하지만 새로운 URL에서는 실패합니다.
Val Town 앱에 설문 추가 
FastComments가 Val Town 앱에 설치되면, 댓글 안에서 실시간 설문조사를 실행할 수 있습니다. 위젯 사용자 정의 설정에서 Enable Polls 를 켜면 설문조사 버튼이 댓글 도구 모음에 나타납니다. 설문조사는 2~10개의 옵션을 가질 수 있으며, 결과는 페이지에 있는 모든 사람에게 실시간으로 업데이트되고, 설문조사를 누가 만들 수 있는지와 투표에 로그인 필요 여부를 선택할 수 있습니다. Val Town에 추가로 설치할 것이 없습니다.
Live Polls 데모 체험하기 또는 설문조사 문서를 읽고 설정하세요.