NIP-10은 kind 1 노트가 서로 참조하여 답글 스레드를 형성하는 방법을 지정합니다. 대화 뷰를 구축하는 데 이해가 필수적입니다.

문제

누군가 노트에 답글을 달 때 클라이언트는 알아야 합니다: 무엇에 대한 답글인가? 대화의 루트는 무엇인가? 누구에게 알려야 하는가? NIP-10은 e 태그(이벤트 참조)와 p 태그(pubkey 멘션)를 통해 이러한 질문에 답합니다.

마킹된 태그 (권장)

현대 클라이언트는 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": "좋은 지적이에요! 동의합니다.",
  "sig": "b7d3f..."
}

root 마커는 스레드를 시작한 원래 노트를 가리킵니다. reply 마커는 답변하는 특정 노트를 가리킵니다. 루트에 직접 답글하는 경우 root만 사용합니다(reply 태그 필요 없음). 이 구분은 렌더링에 중요합니다: reply는 스레드 뷰에서 들여쓰기를 결정하고, root는 모든 답글을 함께 그룹화합니다.

스레딩 규칙

  • 루트에 직접 답글: root 마커가 있는 e 태그 하나
  • 답글에 대한 답글: root 하나와 reply 하나로 두 개의 e 태그
  • root는 스레드 전체에서 일정하게 유지됩니다; reply는 응답하는 대상에 따라 변경됩니다

알림을 위한 Pubkey 태그

알림을 받아야 하는 모든 사람에 대해 p 태그를 포함합니다. 최소한 답글하는 노트의 작성자를 태그하세요. 관례적으로 부모 이벤트의 모든 p 태그도 포함합니다(대화의 모든 사람이 계속 알 수 있도록), 그리고 콘텐츠에서 @멘션하는 모든 사용자도 포함합니다.

릴레이 힌트

ep 태그의 세 번째 위치에는 해당 이벤트나 사용자의 콘텐츠를 찾을 수 있는 릴레이 URL이 포함될 수 있습니다. 이는 클라이언트가 원래 릴레이에 연결되어 있지 않아도 참조된 콘텐츠를 가져오는 데 도움이 됩니다.

더 이상 사용되지 않는 위치 기반 태그

초기 Nostr 구현은 마커가 아닌 태그 위치에서 의미를 유추했습니다: 첫 번째 e 태그가 루트, 마지막이 답글, 중간이 멘션이었습니다. 이 접근 방식은 모호성을 만들기 때문에 더 이상 사용되지 않습니다. 마커 없는 e 태그가 보이면 오래된 클라이언트에서 온 것일 가능성이 높습니다. 현대 구현은 항상 명시적 마커를 사용해야 합니다.

스레드 뷰 구축

스레드를 표시하려면 루트 이벤트를 가져온 다음 해당 루트를 참조하는 e 태그가 있는 모든 이벤트를 쿼리합니다:

["REQ", "thread", {"kinds": [1], "#e": ["<root-event-id>"]}]

created_at으로 결과를 정렬하고 reply 마커를 사용하여 트리 구조를 구축합니다. reply가 루트를 가리키는 이벤트는 최상위 답글입니다; reply가 다른 답글을 가리키는 이벤트는 중첩된 응답입니다.


주요 출처:

언급된 곳:

참고: