Nostr가 실제로 작동하는 방식: 프로토콜, 전문용어 없이
내부적으로 Nostr는 200줄의 스펙입니다. 이벤트, 서명, 릴레이, 구독. 구체적인 예제를 통한 모든 작동 부분.
Nostr에 대한 대부분의 설명은 "이것은 탈중앙화된 소셜 프로토콜입니다"에서 멈추고 흥미로운 부분은 언급하지 않습니다. 흥미로운 부분은 전체 프로토콜이 짧은 문서에 맞는다는 것입니다. 영리한 트릭도 없고, 숨겨진 복잡성도 없습니다. 단지 함께 작동하는 몇 가지 기본 요소일 뿐입니다.
이 가이드는 Nostr을 실제로 사용할 때 나타나는 순서대로 이러한 기본 요소를 설명합니다: 이벤트가 어떻게 구성되는지, 어떻게 서명되는지, 어떻게 릴레이에 도달하는지, 클라이언트가 어떻게 구독하는지, 그리고 게시물을 좋아할 때, 답글을 받을 때 또는 zap을 받을 때의 흐름이 어떻게 보이는지. 블록체인 비교도 없고, 거대한 내러티브도 없습니다. 단지 메커니즘일 뿐입니다.
요약. Nostr은 WebSocket 위의 pub/sub이며 암호화 서명이 있습니다. 클라이언트는 서명된 JSON 객체(이벤트)를 릴레이(소형 서버)에 게시하고, 다른 클라이언트는 원하는 이벤트와 일치하는 필터가 있는 릴레이를 구독합니다. 서명은 위조를 방지하고, 여러 릴레이는 단일 장애점을 방지합니다. 이것이 전체 프로토콜입니다. 나머지는 모두 다양한 종류의 콘텐츠에 대한 서식 규칙입니다.
준비되면, @nostr.blog 주소 받기
기본 요소: 이벤트
Nostr의 모든 것은 이벤트입니다. 게시물은 이벤트입니다. 반응은 이벤트입니다. 프로필 업데이트는 이벤트입니다. 직접 메시지는 이벤트입니다. Zap 영수증은 이벤트입니다.
이벤트는 정확히 다음 구조의 JSON 객체입니다:
{
"id": "abc123...",
"pubkey": "0a4f7b1a3d9a1529a3080c3ae5ee553e0af0a01d86d01677c0bb270592923f88",
"created_at": 1776329035,
"kind": 1,
"tags": [
["t", "nostr"],
["p", "3bf0c63f..."]
],
"content": "hello nostr",
"sig": "def456..."
}
6개의 필드가 의미 있는 작업을 수행합니다. id는 이벤트 자체 콘텐츠의 해시이며, 이벤트를 고유하게 식별합니다. pubkey는 작성자입니다(64자 16진법 공개 키). created_at은 Unix 타임스탬프입니다. kind는 이벤트가 나타내는 것을 설명하는 정수입니다(자세히는 아래). tags는 해시태그(t), 멘션(p는 pubkey, e는 event) 등 수십 개의 다른 것과 같은 구조화된 주석의 목록입니다. content는 일반적으로 텍스트인 자유형식 페이로드입니다.
sig는 Schnorr 서명이며, 작성자의 개인 키로 id의 해시에 대해 생성됩니다. 이것이 위조를 방지하는 필드입니다: 누구나 해시를 계산할 수 있지만, 개인 키의 보유자만 유효한 서명을 생성할 수 있습니다.
"kind"는 무엇인가
kind 필드는 클라이언트에게 이벤트를 어떻게 해석할 것인지 알려줍니다. 숫자는 전체 의미론적 유형입니다.
활발하게 사용 중인 몇 가지 kind:
| Kind | 의미 |
|---|---|
| 0 | 프로필 메타데이터(이름, 아바타, 소개) |
| 1 | 짧은 텍스트 노트(Nostr 트윗 등가물) |
| 3 | 연락처 목록(팔로우하는 사람) |
| 4 | 직접 메시지(레거시, 1059로 대체됨) |
| 5 | 삭제 요청 |
| 6 | 짧은 노트의 리포스트 |
| 7 | 반응(좋아요, 싫어요, 이모지) |
| 9734 | Zap 요청 |
| 9735 | Zap 영수증 |
| 30023 | 장문 기사 |
| 1059 | Gift-wrapped 직접 메시지(NIP-44/NIP-17) |
새로운 kind는 NIP(Nostr Implementation Possibilities)를 통해 제안되고 표준화됩니다. 누구나 제안할 수 있습니다. 광범위하게 채택된 것은 프로토콜의 사실상 일부가 되고, 채택되지 않은 것은 아무것도 깨지 않으면서 틈새 상태로 남아 있을 뿐입니다.
이벤트가 게시되는 방식
Nostr 클라이언트에서 "게시"를 탭하면 다음 순서가 실행됩니다:
- 클라이언트가 JSON을 조립합니다.
pubkey,created_at,kind,tags,content를 채웁니다. - 클라이언트가 id를 계산합니다. 이러한 필드의 정규 직렬화에 대해 SHA-256을 실행합니다. 이것이 서명이 커버하는 해시입니다.
- 클라이언트가 개인 키로 id에 서명합니다. secp256k1(Bitcoin이 사용하는 동일한 곡선)에 대한 Schnorr 서명입니다. 64바이트 서명이
sig필드가 됩니다. - 클라이언트가 각 구성된 릴레이에 WebSocket 연결을 엽니다. 또는 활성화된 기존 연결이 있으면 재사용합니다.
- 클라이언트가 메시지로 이벤트를 보냅니다. 온와이어 형식은 JSON 배열입니다:
["EVENT", {...event...}]. - 각 릴레이가 서명을 검증합니다. 서명이 청구된 pubkey에 대해 검증되지 않으면 이벤트를 거부합니다. 그렇지 않으면 수락하고 저장합니다.
- 각 릴레이가 구독자에게 이벤트를 푸시합니다. 이 이벤트와 일치하는 필터가 있는 열린 구독이 있는 모든 클라이언트가 실시간으로 이벤트를 받습니다.
전체 왕복은 릴레이 위치에 따라 50~300밀리초가 걸립니다. 어떤 릴레이가 느리거나 오프라인이면 다른 릴레이는 여전히 이벤트를 게시합니다. 이벤트가 네트워크에 존재하려면 한 개의 릴레이만 수락하면 됩니다.
클라이언트가 게시물을 가져오는 방식
읽기는 게시의 거울입니다.
클라이언트는 릴레이 목록에 WebSocket 연결을 엽니다. 각각에 대해 구독 메시지를 보냅니다:
["REQ", "sub_id_1", { "authors": ["pubkey1", "pubkey2", ...], "kinds": [1, 6], "limit": 50 }]
이것은 릴레이에 목록의 작성자로부터 최대 50개의 이벤트(kind 1(짧은 노트) 또는 kind 6(리포스트))를 요청합니다. 릴레이는:
- 일치하는 이벤트의 로컬 데이터베이스를 쿼리하고, (기본적으로 가장 오래된 것부터 최신 순서로, 제한까지)
EVENT메시지로 클라이언트에 보냅니다. EOSE(저장된 이벤트 끝) 메시지를 보내므로 클라이언트는 과거 데이터 덤프가 완료되었음을 알 수 있습니다.- 구독을 열린 상태로 유지합니다. 나중에 필터와 일치하는 새 이벤트(다른 누군가가 게시한)는 실시간으로 클라이언트에 푸시됩니다.
이렇게 피드가 라이브가 됩니다. 폴링하지 않습니다. 릴레이가 스트리밍합니다.
클라이언트는 모든 구성된 릴레이에서 이를 병렬로 수행합니다. 응답의 합집합이 타임라인입니다. id에 의한 중복 이벤트는 중복이 제거됩니다.
서명이 실제로 위조를 방지하는 방식
이것이 대부분의 설명이 무시하는 부분입니다.
클라이언트가 이벤트를 받으면, 정규 직렬화에 대해 해시를 다시 계산합니다(게시자가 한 것과 같은 방식) 그리고 Schnorr 검증을 실행합니다: pubkey, id, sig가 주어졌을 때, 서명은 암호화적으로 체크아웃되나요?
그렇다면 이벤트는 진정합니다. 이 이벤트의 작성자는 서명 시점에 그 pubkey의 보유자였습니다. 모든 클라이언트는 모든 이벤트에 대해 이 확인을 실행합니다. 잘못된 서명이 있는 위조된 이벤트를 배송하는 릴레이는 그것을 보는 모든 클라이언트에 의해 자동으로 이벤트가 삭제됩니다.
이것이 중요한 이유는 릴레이가 신뢰할 수 없다는 것을 의미하기 때문입니다. 악의적인 릴레이는 당신의 말을 당신 입에 넣을 수 없습니다. 당신의 게시물 제공을 거부하거나 다른 사람의(합법적인) 게시물을 피드에 주입할 수 있지만, 개인 키 없이 당신이 서명한 유효한 게시물을 생성할 수 없으며, 서명을 깨지 않고 기존 게시물을 수정할 수 없습니다.
이 속성의 비용은 정확히 이벤트당 하나의 Schnorr 검증이며, 이는 초당 수만 개의 이벤트에서도 모바일 클라이언트를 처리할 수 있을 만큼 충분히 빠릅니다.
릴레이가 실제로 하는 것
릴레이는 3가지 작업이 있는 단순하고 빠른 파이프입니다:
- 이벤트를 수락하고 서명을 검증합니다. 검증되지 않거나 정책 확인을 실패하는 것을 거부합니다(스팸 필터, 크기 제한, 차단된 pubkey).
- 이벤트를 저장합니다. 보통
id,pubkey,kind및 태그 값으로 인덱싱된 SQLite 또는 PostgreSQL 데이터베이스에. - 구독을 제공합니다. 들어오는
REQ필터를 데이터베이스(과거의 경우)와 라이브 이벤트(실시간의 경우)와 일치합니다.
그게 전부입니다. 릴레이는 순위 지정, 추천, 큐레이션, 수익화, 광고 표시, 알고리즘 적용 또는 플랫폼이 하는 다른 어떤 것도 하지 않습니다. 서명된 바이트를 전달합니다.
이러한 다른 작업의 부재가 릴레이가 작을 수 있는 이유입니다. 단일 월 $5 VPS는 수백 명의 활성 사용자를 제공하는 릴레이를 실행할 수 있습니다. Twitter 규모의 같은 기능은 Twitter가 다른 모든 것을 하기 때문에 수십억 달러가 듭니다.
릴레이 정책은 다릅니다. 일부는 허가 불필요이며 서명된 모든 이벤트를 제공합니다. 일부는 결제 필요("유료 릴레이" 모델), 다른 것은 특정 커뮤니티(회사 직원, Discord 서버 멤버)로 제한하고, 여전히 다른 것은 스팸 필터링에 적극적입니다. 어떤 릴레이를 사용할지 선택합니다. 선택은 어떤 게시물을 보는지와 어떤 게시물이 팔로워에게 도달하는지에 영향을 줍니다.
완전한 예제: 누군가가 당신의 게시물을 좋아합니다
함께 묶으면, Alice가 Bob이 쓴 게시물을 좋아할 때 끝에서 끝까지 무슨 일이 일어나는지 여기 있습니다.
- Bob이 게시합니다. Bob의 클라이언트는 내용 "hello world"로 kind:1 이벤트를 구성하고, 서명하고, Bob의 5개의 구성된 릴레이에 보냅니다. 각 릴레이는 수락하고 저장합니다.
- Alice가 구독합니다. Alice의 클라이언트는 Bob의 pubkey를
authors에 포함하는 필터가 있는 2개의 릴레이에 열린 구독이 있습니다. 릴레이는 Bob의 이벤트를 구독 아래로 푸시합니다. Alice의 클라이언트는 타임라인에 게시물을 표시합니다. - Alice가 좋아요를 탭합니다. Alice의 클라이언트는 내용 "+"(Nostr "좋아요" 규칙)가 있는 kind:7 이벤트를 구성하고, 반응하는 게시물(
["e", "bob_post_id"])과 작성자(["p", "bob_pubkey"])를 태그합니다. 서명하고 Alice의 5개의 구성된 릴레이에 게시합니다. - 반응이 전파됩니다.
{ "#e": ["bob_post_id"], "kinds": [7] }필터와 일치하는 활성 구독이 있는 모든 릴레이(Bob의 클라이언트가 자신의 게시물에 대한 반응을 감시하는 데 사용하는 것)는 반응을 Bob에게 푸시합니다. Bob의 클라이언트는 좋아요를 집계하고 게시물 아래 개수를 표시합니다.
일어나지 않은 것에 주목하십시오. 중앙 집중식 "좋아요 버튼" 서비스는 핑되지 않았습니다. 백엔드는 좋아요 개수를 결정하지 않았습니다. 좋아요는 단지 서명된 이벤트이며, 게시물 자체와 동일한 채널에서 발표됩니다.
Nostr이 명시적으로 하지 않는 것
의도적으로 핵심 프로토콜에서 제외된 5가지, 공유된 온와이어 형식이 아니라 클라이언트나 릴레이에 속하기 때문입니다.
- 신원 확인. Nostr은 "이 pubkey는 이 게시물에 서명했습니다"만 증명합니다. pubkey가 특정 인간에게 속하는지 여부는 NIP-05와 오프체인 컨텍스트에 의해 답변되는 별도의 질문입니다.
- 콘텐츠 조정. 프로토콜은 무엇이 표시되는지 결정하지 않습니다. 클라이언트가 필터링하고, 릴레이가 필터링하고, 사용자가 필터링합니다. 각 계층은 독립적으로.
- 검색. 전역 검색 엔드포인트가 없습니다. 일부 릴레이는 로컬 이벤트 풀에 대한 텍스트 검색을 지원합니다. 어떤 릴레이도 게시물을 찾을 수 있다는 프로토콜 보장이 없습니다.
- 알고리즘 순위 지정. 프로토콜에 "당신을 위한" 피드가 없습니다. 순위 지정은 클라이언트에서 발생합니다(있다면).
- 계정 복구. 이메일 리셋, 전화 리셋, 중앙 분쟁 시스템이 없습니다. 개인 키를 잃으면 신원을 잃습니다. 이것은 트레이드오프이지 버그가 아닙니다.
이러한 부재가 프로토콜을 작게 만드는 것입니다. 또한 중앙 집중식 플랫폼 위에 구축하는 것보다 위에 세련된 사용자 경험을 구축하기가 어렵게 만드는 것입니다. 이것이 정직한 비용입니다.
설계가 전혀 작동하는 이유
설계는 하나의 간단한 속성에 의존합니다: 서명은 검증하기가 저렴하고, 위조는 개인 키 없이 불가능하며, 릴레이는 교체하기가 무료입니다.
이 세 가지 사실이 합쳐집니다. 저렴한 검증은 모든 클라이언트가 모든 이벤트를 확인할 수 있다는 것을 의미합니다. 불가능한 위조는 릴레이를 신뢰할 필요가 없다는 것을 의미합니다. 무료 교체는 단일 릴레이가 누구에게도 권력을 가지지 않는다는 것을 의미합니다.
함께 놓으면, 플랫폼 계층이 교환 가능하고 신원 계층이 사용자가 소유하는 소셜 네트워크를 얻습니다. 이것이 "탈중앙화"가 실제로 의미하는 것입니다. 마케팅이 보통 단어를 사용하는 방식과는 반대입니다.
사용자 측에서 전체 흐름을 보고 싶다면(키 쌍, NIP-05 신원, 릴레이 목록, 지갑, 게시할 준비), nostr.blog의 가입 페이지는 이러한 단계를 한 페이지로 축약합니다. 여기에서 설명된 메커니즘이 실제로 그 흐름 아래에서 실행되는 것입니다.
자주 묻는 질문
Nostr은 블록체인인가요?
Nostr은 가짜 게시물이 나에게 귀속되는 것을 어떻게 방지하나요?
릴레이가 오프라인이 되면 어떻게 되나요?
클라이언트는 내 게시물을 어떻게 찾나요?
릴레이가 내 직접 메시지를 볼 수 있나요?
이어 읽기
Nostr란 무엇인가? 2026년을 위한 평문 안내서
Nostr은 소셜 미디어와 신원확인을 위한 단순하고 개방된 프로토콜입니다. 어떤 회사도 관리하지 않으며, 당신을 제외한 누구도 계정을 삭제할 수 없습니다. 평문으로 설명합니다.
14분 소요시작하기Nostr 사용 방법: 초보자를 위한 단계별 가이드
앱을 열고, 키 쌍을 받고, 사람들을 팔로우하고, 게시하세요. 2026년 Nostr를 시작하는 것이 어떤 모습인지, 아무도 당신에게 경고하지 않는 세부 사항들과 함께.
18분 소요정체성과 NIP-05NIP-05란 무엇인가? Nostr 주소 설명
NIP-05는 Nostr에서 사용하는 이메일 형태의 식별자입니다: alice@nostr.blog. 실제로 하는 일, 하지 않는 일, 그리고 어떻게 얻는지 알아봅시다.
15분 소요고급 · 기술Nostr DM이 정말 비공개인가? 솔직한 답변
Nostr DM은 암호화를 사용하지만 개인정보 보호 모델에는 허점이 있습니다. NIP-04, NIP-44, NIP-17 gift wrap이 무엇을 보호하는지, 그리고 언제 Signal을 대신 사용해야 하는지 알아봅니다.
16분 소요고급 · 기술2026년에 자신만의 Nostr relay를 운영하는 방법
저렴한 VPS에서 Nostr relay를 운영하는 실용적인 가이드. 어떤 소프트웨어를 사용할지, 어떻게 설정할지, 비용은 얼마인지, 왜 운영할 만한지를 다룹니다.
16분 소요