NIP-10: 텍스트 노트 스레딩
NIP-10은 kind 1 노트가 서로를 참조하여 답글 스레드를 형성하는 방법을 명세한다. 대화 뷰를 구축하는 데 필수적이다.
작동 방식
누군가 노트에 답글을 달 때, 클라이언트는 다음을 알아야 한다: 이것은 무엇에 대한 답글인가? 대화의 루트는 무엇인가? 누구에게 알림을 보내야 하는가? NIP-10은 e 태그(이벤트 참조)와 p 태그(공개 키 멘션)를 통해 이 질문에 답한다.
마커 태그 (권장)
최신 클라이언트는 e 태그에 명시적 마커를 사용한다:
{
"id": "f9c2e...",
"pubkey": "a3b9c...",
"created_at": 1734912345,
"kind": 1,
"tags": [
["e", "abc123...", "wss://relay.example.com", "root"],
["e", "def456...", "wss://relay.example.com", "reply"],
["p", "91cf9..."],
["p", "14aeb..."]
],
"content": "Great point! I agree.",
"sig": "b7d3f..."
}
root 마커는 스레드를 시작한 원본 노트를 가리킨다. reply 마커는 답변하는 특정 노트를 가리킨다. 루트에 직접 답글을 달 때는 root만 사용한다(reply 태그 불필요). 이 구분은 렌더링에 중요하다: reply가 스레드 뷰에서 들여쓰기를 결정하고, root가 모든 답글을 그룹화한다.
스레딩 규칙
- 루트에 직접 답글:
root마커가 있는e태그 하나 - 답글에 대한 답글:
e태그 두 개, 하나는root, 하나는reply root는 스레드 전체에서 일정하게 유지되고,reply는 응답 대상에 따라 변경된다
알림과 멘션
알림을 받아야 할 모든 사람의 p 태그를 포함한다. 최소한 답글 대상 노트의 작성자를 태그한다. 관례적으로 부모 이벤트의 모든 p 태그도 포함하여 대화에 참여하는 모든 사람이 계속 업데이트를 받을 수 있도록 하며, 콘텐츠에서 @멘션하는 사용자도 추가한다.
릴레이 힌트
e와 p 태그의 세 번째 위치에 해당 이벤트 또는 사용자의 콘텐츠를 찾을 수 있는 릴레이 URL을 포함할 수 있다. 이는 클라이언트가 원래 릴레이에 연결되어 있지 않더라도 참조된 콘텐츠를 가져오는 데 도움이 된다.
상호운용성 참고사항
초기 Nostr 구현에서는 마커 대신 태그 위치에서 의미를 추론했다: 첫 번째 e 태그가 루트, 마지막이 답글, 중간이 멘션이었다. 이 방식은 모호성을 만들기 때문에 더 이상 권장되지 않는다. 마커 없는 e 태그가 보이면 이전 클라이언트에서 작성된 것일 가능성이 높다. 최신 구현은 항상 명시적 마커를 사용해야 한다.
클라이언트가 이전 스레드를 올바르게 렌더링하려면 두 형식을 모두 파싱할 수 있어야 한다. 실제로 NIP-10 상호운용성은 부분적으로 마이그레이션 문제다: 생산자는 마커 태그를 내보내야 하지만, 소비자는 이전의 위치 기반 형식도 허용해야 한다.
스레드 뷰 구축
스레드를 표시하려면 루트 이벤트를 가져온 다음, 해당 루트를 참조하는 e 태그가 있는 모든 이벤트를 쿼리한다:
["REQ", "thread", {"kinds": [1], "#e": ["<root-event-id>"]}]
결과를 created_at 기준으로 정렬하고 reply 마커를 사용하여 트리 구조를 구축한다. reply가 루트를 가리키는 이벤트는 최상위 답글이고, reply가 다른 답글을 가리키는 이벤트는 중첩된 응답이다.
주요 출처:
언급된 뉴스레터:
같이 보기: