> ## Documentation Index
> Fetch the complete documentation index at: https://www.helius.dev/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# preprocessedSubscribe 사용 방법

> 사전 처리된 Solana 트랜잭션을 WebSocket을 통해 스트리밍하는 preprocessedSubscribe 메서드를 사용하세요. 계정으로 필터링하고 처리 전 약정을 위해 바이너리 페이로드를 디코딩하세요.

<Note>
  **공개 베타.** `preprocessedSubscribe`는 **모든 유료 요금제**에서 이용 가능하며, **메시지당 0.1 크레디트**(전송된 트랜잭션당 한 메시지)로 측정됩니다.
</Note>

## `preprocessedSubscribe`란 무엇인가요?

`preprocessedSubscribe`는 사전 처리된 트랜잭션을 스트리밍하는 Helius WebSocket 메서드로, **`processed` 약정 수준에 도달하기 전에 전달되는** 사전 실행 Solana 트랜잭션을 제공합니다. Helius는 여러 사전 실행 소스를 집계하여 - 주로 검증자에 도착할 때 직접 디코딩된 세로드, 예약된 트랜잭션([사전확인](/docs/ko/pre-confirmations/overview)) 신호로 보충됨 - 이를 중복 제거된 단일 스트림으로 집약된 바이너리 메시지로 전송합니다.

사전확인 신호에서 소싱된 트랜잭션은 전용 [Preconfirmations](/docs/ko/pre-confirmations/overview) 제품에서보다 늦게 이 피드에 도착하며, 이 제품이 가장 빠른 접근을 제공합니다.

이전의 사전 처리된 LaserStream 제품의 후속입니다. [gRPC를 통해 사전 처리된 트랜잭션](/docs/ko/preprocessed-transactions/grpc)을 현재 사용하는 경우 이 방법으로 전환하세요. 이는 일반 WebSocket 연결을 통해 더 낮은 지연 시간으로 동일한 유형의 데이터를 제공합니다. gRPC 전송은 약식화될 것입니다.

| 스트림                                                                              | 상대적 타이밍                                | 커버리지                  | 데이터                |
| -------------------------------------------------------------------------------- | -------------------------------------- | --------------------- | ------------------ |
| [Preconfirmations](/docs/ko/pre-confirmations/overview)                               | 가장 빠름                                  | 참여하는 검증자에 의해 예약된 트랜잭션 | 트랜잭션 및 사전확인 상태     |
| `preprocessedSubscribe`                                                          | 보통 Preconfirmations 이후, `processed` 이전 | 폭넓은 Solana 트랜잭션 커버리지  | 실행 전 서명된 트랜잭션      |
| [`transactionSubscribe`](/docs/ko/rpc/websocket/transaction-subscribe) at `processed` | 실행 후                                   | 처리된 트랜잭션              | 실행 메타데이터가 포함된 트랜잭션 |

<Warning>
  `preprocessedSubscribe`는 **최상의 노력을 기울인, 사전 실행 신호**이며 약정 수준이 아닙니다. 스트리밍된 트랜잭션은 실패할 수 있으며, 버려지거나 다른 포크에 착지할 수 있습니다. 이를 최종적으로 처리하기 전에 처리되거나 확인된 스트림에 대조하세요.
</Warning>

## 엔드포인트

`preprocessedSubscribe`는 Helius Gatekeeper 엔드포인트인 `wss://beta.helius-rpc.com`에서 제공됩니다. API 키를 쿼리 매개변수로 인증하세요:

```
wss://beta.helius-rpc.com/?api-key=<API_KEY>
```

각 API 키는 **10개의 동시 연결/구독**으로 제한됩니다.

## 구독

`preprocessedSubscribe` 메서드를 사용하여 JSON-RPC 요청을 전송하세요. `params`는 계정 필터를 포함하며 필수적입니다 — `accountInclude`와 `accountRequired`는 그 사이에 최소한 하나의 계정을 지정해야 합니다 (참고: [Filtering](#필터링)):

```json theme={"system"}
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "preprocessedSubscribe",
  "params": {
    "accountInclude": ["JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4"],
    "accountExclude": [],
    "accountRequired": []
  }
}
```

서버는 구독 ID를 포함한 JSON 텍스트 프레임으로 구독을 확인합니다:

```json theme={"system"}
{
  "jsonrpc": "2.0",
  "result": 1,
  "id": 1
}
```

이 확인 후, 트랜잭션 업데이트는 **바이너리** WebSocket 프레임으로 도착합니다 — [알림 페이로드](#알림-페이로드)를 참조하세요.

## 필터링

모든 구독은 `params`의 계정 필터에 의해 범위가 지정됩니다. 필터링은 서버 측에서 이루어지며, 이를 통해 원하시는 트랜잭션만을 수신합니다:

```json theme={"system"}
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "preprocessedSubscribe",
  "params": {
    "accountInclude": ["JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4"],
    "accountExclude": ["Vote111111111111111111111111111111111111111"],
    "accountRequired": []
  }
}
```

| 필터                | 매칭 동작                                |
| ----------------- | ------------------------------------ |
| `accountInclude`  | 트랜잭션이 열거된 계정 중 **하나라도** 참조할 때 매칭합니다. |
| `accountExclude`  | 트랜잭션이 열거된 계정 중 **하나라도** 참조하면 드롭합니다.  |
| `accountRequired` | 트랜잭션이 열거된 모든 계정을 참조할 때만 매칭합니다.       |

필터 규칙:

* 세 가지 필터는 AND 로직으로 결합됩니다.
* `accountInclude`와 `accountRequired`는 그 사이에 **최소한 하나의 계정**을 지정해야 합니다 — 비필터링 전체 스트림은 없습니다.
* 계정은 base58로 인코딩된 공개 키입니다. 각 목록은 최대 **5,000**개의 주소를 허용합니다.

### 주소 조회 테이블 (ALT) 해석

계정 필터는 트랜잭션의 정적인 계정 키를 넘어 매칭됩니다 — Helius는 서버 측에서 [주소 조회 테이블](/docs/ko/glossary#address-lookup-table-alt)을 해석하므로 `accountInclude`, `accountExclude`, `accountRequired`도 ALT를 통해 로드되는 계정을 매칭합니다. 계정의 공개 키만 전달하면 되며, ALT 매핑을 유지하거나 테이블을 직접 해석할 필요는 없습니다.

## 알림 페이로드

알림은 **바이너리** WebSocket 프레임으로 전달됩니다 (JSON 아님). 각 프레임은 압축된 바이트 레이아웃의 단일 트랜잭션을 포함합니다:

| 바이트  | 필드            | 타입                              | 설명                         |
| ---- | ------------- | ------------------------------- | -------------------------- |
| 0    | `version`     | `u8`                            | 페이로드 스키마 버전. 현재는 `1`.      |
| 1–8  | `slot`        | `u64` (little-endian)           | 트랜잭션이 관찰된 슬롯.              |
| 9–72 | `signature`   | 64 바이트                          | 트랜잭션의 첫 번째 서명, 바이너리 형식.    |
| 73+  | `transaction` | `bincode(VersionedTransaction)` | 서명된 트랜잭션, bincode-직렬화된 형태. |

고정된 73바이트 접두사를 순서대로 읽은 다음, [`bincode`](https://docs.rs/bincode)-를 통해 남은 바이트를 `VersionedTransaction`로 역직렬화하여 명령어, 계정 및 주소 테이블 조회 정보를 읽으세요. 서명은 접두사에 포함되어 있어 디코딩 없이 전체 트랜잭션 본문을 식별하고 중복 제거할 수 있습니다.

항상 `version` 바이트를 먼저 읽고 확인하세요. Helius가 페이로드 형식을 업데이트해야 하는 경우 버전이 증가합니다 — 이를 통해 스키마 변경이 있어도 디코더가 계속해서 작동하도록 브랜치를 나누세요.

## 예제

```javascript theme={"system"}
const WebSocket = require('ws');
const bs58module = require('bs58');
const bs58 = bs58module.default ?? bs58module;

const ws = new WebSocket('wss://beta.helius-rpc.com/?api-key=<API_KEY>');

ws.on('open', () => {
  ws.send(JSON.stringify({
    jsonrpc: '2.0',
    id: 1,
    method: 'preprocessedSubscribe',
    // Only Jupiter v6 transactions — accountInclude/accountRequired must
    // specify at least one account between them.
    params: {
      accountInclude: ['JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4'],
      accountExclude: [],
      accountRequired: []
    }
  }));

  // Keep the connection alive
  setInterval(() => ws.ping(), 30_000);
});

ws.on('message', (data, isBinary) => {
  // The subscribe acknowledgement arrives as a JSON text frame
  if (!isBinary) {
    const msg = JSON.parse(data.toString());
    if (msg.id === 1) console.log('Subscribed, ID:', msg.result);
    return;
  }

  // Notifications arrive as binary frames:
  // version (u8) | slot (u64 LE) | signature ([u8; 64]) | bincode(VersionedTransaction)
  const buf = Buffer.from(data);
  const version = buf.readUInt8(0); // currently 1 — branch on this if it changes
  if (version !== 1) return; // unknown schema version; update your decoder
  const slot = buf.readBigUInt64LE(1);
  const signature = bs58.encode(buf.subarray(9, 73));
  const txBytes = buf.subarray(73); // bincode-serialized VersionedTransaction

  console.log('Preprocessed transaction:', { slot, signature, bytes: txBytes.length });
  // Deserialize txBytes (bincode) into a VersionedTransaction with your Solana tooling
});

ws.on('error', console.error);
ws.on('close', () => process.exit(1));
```

## 어떤 데이터가 제공되나요?

각 알림은 서명된 트랜잭션, 첫 번째 서명 및 슬롯을 포함합니다. 배달은 실행 전에 이루어지므로, 스트림에는 다음이 포함되지 않습니다:

* 실행 상태 또는 오류
* 사전/사후 잔액 또는 토큰 잔액 변경
* 로그 메시지 또는 내부 명령어
* 소비된 컴퓨트 유닛

이를 "제안"을 수신하는 것으로 생각할 수 있지만, "결과"가 아닙니다 — 발신자가 시도한 것을 보지만 실제로 일어난 일을 보지 못합니다. 계정 및 프로그램 상태 업데이트도 이 단계에서는 존재하지 않습니다. 실시간 계정 상태가 필요한 경우, `processed` 약정에서 [LaserStream gRPC](/docs/ko/laserstream)를 사용하세요.

## 역압력

스트림은 느린 소비자에게 무기한 버퍼링되지 않습니다. 클라이언트가 너무 느리게 읽고 서버 측에서 **4,000개 이상의 메시지**가 백업되면, Helius는 연결을 닫습니다 — 깨끗한 WebSocket 종료 프레임을 수신합니다. 수신 루프에서 트랜잭션 디코딩 및 전략 로직과 같은 무거운 작업을 진행하지 말고 프레임을 도착보다 빠르게 소모하며, 연결 종료 후 다시 연결하고 다시 구독하세요.

## 전송 보장

전송은 최선의 노력을 기울인 것으로 보장되지 않으며, 과거 재생은 없습니다. 클라이언트는 다음을 수행해야 합니다:

1. 연결이 닫힌 후 다시 연결하고 다시 구독하세요.
2. 트랜잭션 서명으로 중복 제거하세요.
3. 슬롯을 관찰로 처리하고, 최종성으로 처리하지 마세요.
4. 실행 결과가 중요할 때는 처리되거나 확인된 스트림에 대조하세요.

## 가격

`preprocessedSubscribe`는 **모든 유료 요금제**에서 이용 가능하며, 제공된 트랜잭션당 하나의 메시지가 **메시지당 0.1 크레디트**로 측정되며, 이는 요금제에서 청구됩니다. 자세한 사항은 [크레디트](/docs/ko/billing/credits)를 참조하세요.

## 관련

<CardGroup cols={2}>
  <Card title="사전 처리된 트랜잭션 (gRPC)" icon="binary" href="/docs/ko/preprocessed-transactions/grpc">
    동일한 사전 실행 데이터를 gRPC에서 제공합니다. 이 방법으로 대체될 예정입니다.
  </Card>

  <Card title="Preconfirmations" icon="bolt" href="/docs/ko/pre-confirmations/overview">
    세로드가 되기 전 스트리밍된 예약 트랜잭션 - 가장 이른 트랜잭션 신호.
  </Card>

  <Card title="Raw Shreds (UDP)" icon="network-wired" href="/docs/ko/shred-delivery/raw-shreds">
    UDP를 통해 제공되는 미처리 세로드 패킷입니다. 디세로드 작업을 구현하세요.
  </Card>

  <Card title="transactionSubscribe" icon="tower-broadcast" href="/docs/ko/rpc/websocket/transaction-subscribe">
    풍부한 필터링과 실행 메타데이터가 있는 실행 후 트랜잭션.
  </Card>
</CardGroup>
