Skip to main content
온체인 변경에 대응해야 하는 애플리케이션을 구축할 때 계정 업데이트를 위해 RPC 엔드포인트를 폴링하는 것은 비효율적이고 느립니다. 계정 구독은 계정 상태 변경에 대한 실시간 업데이트를 애플리케이션에 직접 제공하여 이를 해결합니다. 이 가이드에서는 계정 구독에 대해 알아야 할 모든 것을 다룹니다: 그것이 무엇인지, 어떻게 작동하는지, 특정 사용 사례에 최적화하는 방법입니다.

계정 모델 컨텍스트

Solana 계정과 그 구조에 익숙한 경우 이 섹션을 생략하세요.
Solana는 모든 데이터가 계정에 존재하는 계정 기반 모델을 사용합니다. 계정은 데이터와 메타데이터를 저장하는 컨테이너입니다. 각 계정에는 다음이 포함됩니다:
  • 데이터: 프로그램 상태, 토큰 잔액 또는 기타 정보가 저장된 실제 바이트
  • 소유자: 이 계정을 제어하고 데이터를 수정할 수 있는 프로그램
  • Lamports: 렌트 면제를 위한 계정의 SOL 잔액
  • 실행 가능 여부: 이 계정이 프로그램 코드를 포함하는지 여부
프로그램은 상태를 내부에 저장하지 않는 무상태입니다. 대신, 별도의 계정을 생성하고 관리하여 상태를 저장합니다. 프로그램과 상호 작용할 때 읽거나 쓸 계정을 전달합니다. 이 설계는 계정 구독을 강력하게 만듭니다: 특정 계정, 프로그램이 소유한 모든 계정 또는 특정 조건에 맞는 계정의 변경을 감시할 수 있습니다.

기본 계정 구독

토큰 계정의 변경을 구독하는 간단한 예제로 시작해 보겠습니다. 이 스크립트는 토큰 잔액이 변경될 때마다 알림을 제공합니다:
이 기본 구독을 실행하면 콘솔에 실시간 계정 업데이트가 스트리밍되는 것을 볼 수 있습니다:
무슨 일이 일어났나요? 우리의 구독이 완벽하게 작동했습니다! 우리는 Laserstream에게 토큰 계정 변경에 대해 알리라고 요청했고, 계정 BKMHWYLAX4un3HUbR7a3u9jPmzCiLNa4mSj1RiX11eWF에 대한 업데이트를 받았습니다. 이 계정에는 다음이 있습니다:
  • 2,039,280 lamports (~0.002 SOL 잔액 - 이 토큰 계정의 렌트 면제 금액입니다)
  • 소유자 프로그램 TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA (이는 SPL 토큰 프로그램입니다)
  • 거래 서명 5C9Hr5nG2j8eQz6inxPmfyjbYdmXddzUDyR1iQgEnjYQ3RNvuP4Zzc8t1enLNy7Rk8KNCtQPEQztENYWxkt9GaVD 이 계정 변경을 야기한 특정 거래를 보여줍니다
  • 슬롯 352366983 이 업데이트가 블록체인에서 발생한 시간을 나타냅니다
  • 데이터 필드는 base58로 인코딩된 165바이트의 계정 데이터를 포함합니다

데이터 크기를 사용한 계정 필터링 이해하기

데이터 필드는 실제 토큰 계정 구조를 포함하는 데 중요합니다. 이 이해를 사용하여 스마트 계정 필터링을 수행합시다.

데이터 크기 필터링을 사용하는 이유는 무엇입니까?

필터링이 필요한 이유를 이해하려면 먼저 토큰 계정의 정의를 이해해야 합니다. 지갑이 보유한 각 토큰마다 온체인에 별도의 계정이 존재합니다. 지갑이 3개의 다른 토큰(USDC, BONK, SOL)을 보유하고 있다면 실제로 1개의 지갑 계정(주요 SOL 계정)과 3개의 토큰 계정(각 토큰 유형마다 하나씩)이 있습니다. 각 토큰 계정은 정확히 165바이트이며, 보유하는 토큰(발행 주소), 소유자(지갑 주소), 토큰 양(금액)을 저장합니다. 토큰 프로그램은 Solana에서 수백만 개의 계정을 소유하고 있지만 사용자 잔액을 보유하는 “토큰 계정”이라고 생각되는 것들은 모두 아닙니다. 필터링 없이와 필터링과 함께 발생하는 상황은 다음과 같습니다: 필터링 없이 - 범람:
이것은 토큰 프로그램에 의해 소유된 모든 계정을 구독합니다. 이는 다음을 포함합니다:
  • 토큰 계정 (165바이트) - 사용자 잔액: 수백만 개의 계정
  • 발행 계정 (82바이트) - 토큰 정의: 수십만 개의 계정
  • 멀티시그 계정 (355바이트) - 공유 지갑 제어: 수만 개의 계정
  • 관련 토큰 프로그램 계정 (다양한 크기) - 수백만 개의 계정
결과: 애플리케이션은 관심 없는 수백만 개의 계정 업데이트를 지속적으로 받습니다.
스마트 필터링과 함께 - 정밀한 조작:
이는 165바이트 계정만으로 축소되어, 사용자의 토큰 잔액 계정만을 추적하는 데 필요한 정확한 것입니다. 차이점:
  • 필터링 없이: 수백만 개의 계정 업데이트 (발행 생성, 멀티시그 변경 등)
  • 데이터 크기 필터링과 함께: 오직 토큰 잔액 변경만
이는 정확한 사용자 토큰 보유를 나타내는 계정에만 집중하여 노이즈를 크게 줄입니다.

165바이트는 어디에서 왔나요?

이것은 마법이 아닙니다 - SPL 토큰 프로그램의 계정 구조에서 비롯됩니다. 소스 코드를 확인하면 Account 구조체가 정확히 165바이트로 정의되어 있는 것을 볼 수 있습니다:
이 고정된 크기를 통해 표준 토큰 계정을 정확하게 필터링하고 다음을 제외할 수 있습니다:
  • 발행 계정 (82바이트)
  • 멀티시그 계정 (355바이트)
  • 관련 토큰 계정 프로그램 계정
  • 다양한 크기의 기타 토큰 관련 계정
다른 프로그램에서 계정 크기를 계산하려면 Anchor Space Reference를 참조하세요 - Pubkey = 32바이트, u64 = 8바이트 등 서로 다른 데이터 유형이 차지하는 공간을 보여줍니다.

계정 구조 디코딩하기

왜 165바이트를 필터링했는지 이해했으니, 이제 예제 계정 안에 무엇이 있는지 디코딩해 봅시다:
165바이트는 다음과 같이 구성됩니다:
  • 바이트 0-31: 발행 주소 (이 계정이 보유한 토큰)
  • 바이트 32-63: 소유자 주소 (이 토큰 계정의 소유자)
  • 바이트 64-71: 토큰 양 (계정에 있는 토큰 수)
  • 바이트 72-164: 추가 메타데이터 (대리인, 상태, 닫기 권한 등)
이 구조화된 접근 방식은 정밀한 제어를 제공합니다: 표준 토큰 계정에 대한 업데이트만 수신하고 다른 계정 유형의 잡음은 받지 않습니다.

필터 결합하기: 데이터 크기 + memcmp로 레이저 정밀도

발행 주소가 바이트 0-31에 있다는 것을 알았으니 더 구체적으로 접근할 수 있습니다. 예를 들어 USDC 토큰 계정만 모니터링하고 싶다고 가정해 봅시다. 우리는 우리의 datasize 필터를 memcmp 필터와 결합하여 정확한 발행 주소를 타겟팅할 수 있습니다:
점진적 필터링 전략:
  1. 소유자 필터: “토큰 프로그램이 소유한 계정을 주세요” (수백만 개의 계정)
  2. 데이터 크기 필터: “하지만 165바이트 표준 토큰 계정만” (수십만)
  3. Memcmp 필터: “그리고 USDC를 보유하고 있는 계정만” (수천)
이러한 넓은 범위에서 구체적으로 나아가는 것은 효율적인 계정 모니터링의 핵심입니다. 각 필터는 결과 세트를 좁히므로, 관심 있는 정확한 업데이트만 수신합니다. 중요: 모든 필터는 AND 로직을 사용합니다 - 계정 업데이트가 트리거되려면 모든 조건이 만족되어야 합니다.

USDC 계정 업데이트 읽기: 누가, 얼마나, 어디서?

이제 필터링된 업데이트가 실제로 무엇을 포함하는지 살펴봅시다. 토큰 계정이 변경될 때 주요 질문에 답하는 USDC 전용 모니터를 만들어 봅시다:
  • 누가 이 토큰 계정을 소유하고 있나요?
  • 얼마나 많은 USDC가 이제 들어있나요?
  • 어디에서 (어떤 특정 계정) 변경되었나요?
  • 언제 이 변경이 발생했나요?
  • 어떤 거래가 이 변경을 발생시켰나요?
원시 계정 업데이트는 디코딩해야 하는 이진 데이터를 포함합니다. Solana는 주소와 서명을 위해 base58 인코딩을 사용하므로, bs58.encode() 함수를 사용하여 이진 버퍼 객체를 읽을 수 있는 문자열로 변환합니다.
이 USDC 모니터를 실행하면 다음과 같이 깔끔하고 구조화된 출력이 표시됩니다:
각 블록은 상태가 변경된 USDC 계정을 나타냅니다. 첫 번째 계정은 이제 1,500 USDC를 보유하고 있으며, 두 번째 계정은 0 USDC로 비워졌습니다. 각 거래 후 현재 잔액을 즉시 얻을 수 있으며, 어떤 특정 계정이 변경되었고 언제 발생했는지도 볼 수 있습니다. 계정 구독은 각 계정에서 발생한 최종 결과를 보여주며, 거래 세부 정보는 아닙니다. 전체 거래 맥락 (누가 누구에게 보냈는지, 수수료 등)을 이해하려면 표시된 서명을 사용하여 전체 거래를 가져와야 합니다.

완전한 필터링 참조

우리가 사용한 기본 owner, datasize, memcmp 필터 외에도 계정 구독은 결과를 더욱 좁힐 수 있는 추가 필터링 옵션을 지원합니다:

특정 계정 필터링

공개 키로 정확한 계정을 모니터링하세요:
이 접근 방식은 애플리케이션의 재무 계정 모니터링이나 특정 사용자 계정 모니터링처럼 정확히 어떤 계정이 중요한지 알고 있을 때 잘 작동합니다. 매우 큰 계정 세트의 경우, 명시적 공개 키 목록은 비용이 많이 듭니다 - 구독 요청에서 계정당 32바이트. ~10,000개 이상의 계정에서는 압축된 쿠쿠 필터 (~계정당 3–4바이트)를 사용하여 단일 스트림에서 수십만의 계정을 추적하세요. Rust 및 JavaScript SDKs에서 사용 가능합니다.

결합된 필터링 전략

여러 필터 유형을 결합하는 데에서 강력함이 나옵니다. 정신적 모델은 다음과 같습니다:
  1. owner넓은 네트를 던집니다 - “이 프로그램에서 관리하는 모든 계정을 주세요”
  2. datasize으로 구조로 필터링합니다 - “하지만 이 특정 유형의 계정만”
  3. memcmp으로 특정 데이터 타겟팅 - “그리고 이 특정 정보를 포함하는 것만”
  4. account으로 알려진 계정 모니터링 - “또는 내가 관심 있는 정확한 계정만 시청하세요”
예를 들어, 고가치 USDC 계정을 모니터링할 때:
핵심 통찰력은 각 필터가 수신하는 업데이트의 양을 줄인다는 것입니다. 필터링 없이 대부분의 계정 업데이트의 압도적인 양을 수신할 수 있습니다. 스마트 필터링으로, 경우에 맞는 업데이트만 받습니다.

큰 그림 이해하기

계정 구독을 데이터베이스 변경의 라이브 피드를 보는 것으로 생각하세요. Solana의 상태는 기본적으로 각 계정이 항목인 대규모 키-값 저장소입니다. 프로그램이 실행되면 이러한 계정을 수정합니다. 구독은 특정 항목이 실시간으로 변경되는 것을 감시할 수 있습니다. 필터링 시스템은 데이터베이스 인덱스와 같이 작동합니다 - “모든 변경”을 보는 것이 아니라 “이러한 기준을 충족하는 계정의 변경”을 보는 것입니다. 이는 관련 없는 데이터로 시스템을 혼란시키지 않고, 관련 온체인 이벤트에 즉시 반응하는 응답형 애플리케이션을 구축할 수 있게 합니다.

다른 프로그램에 이 패턴 적용하기

우리가 배운 접근 방식은 모든 Solana 프로그램에 적용할 수 있습니다. 일반적인 패턴은 다음과 같습니다:
  1. 계정 구조 조사 - 프로그램의 소스 코드나 문서를 확인하세요
  2. 소유자 필터링으로 시작 - 계정을 관리하는 프로그램을 타겟팅하세요
  3. 구조 필터를 적용 - 계정 크기, 데이터 패턴, 기타 특성을 사용해 특정 계정 유형으로 좁히세요
  4. 타겟 필터 추가 - 애플리케이션에 중요한 특정 계정, 상태 또는 데이터 값에 집중하세요.