> ## 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.

# 사전 처리된 트랜잭션

> 디코딩된 슈레드를 gRPC를 통해 `processed` 커밋 수준보다 약 8ms 빠르게 제공합니다. Helius의 Shred Delivery 제품군에 속합니다.

<Note>
  **공개 베타.** 사전 처리된 트랜잭션은 Helius의 [Shred Delivery](/docs/ko/shred-delivery) 제품군의 일부입니다. **Professional 계획 또는 그 이상** 구독자는 이용 가능하며 **1MB 당 20 크레딧**이 청구됩니다.

  평균적으로, 사전 처리된 트랜잭션은 `processed` 커밋 수준보다 **약 8ms 더 빠르게** 도착합니다. 실행 메타데이터의 비용이 발생합니다 (아래 [절충점](#어떤-데이터가-이용-가능한가요) 참조).
</Note>

사전 처리된 트랜잭션은 gRPC를 통해 Solana 트랜잭션을 받는 가장 빠른 방법입니다. Helius는 슈레드를 검증기에 도착할 때 바로 디코딩하고, 결과 트랜잭션을 전송하여 어떤 실행 후 구독보다 밀리세컨드 단위로 트랜잭션 데이터를 먼저 제공합니다 — 평균적으로 `processed` 커밋 수준보다 **약 8ms 빠릅니다**.

이 가이드는 언제 사전 처리된 트랜잭션을 사용할지, 어떤 데이터가 이용 가능한지, LaserStream SDK를 사용하여 어떻게 구독할지 설명합니다 (동일한 gRPC 연결을 통해 사전 처리된 트랜잭션도 제공합니다).

## 사전 처리된 트랜잭션의 라이프사이클 위치

Solana의 아키텍처에서, 트랜잭션은 완전히 처리되기 전에 여러 단계를 거칩니다:

1. **슈레드 수신** → 검증기가 트랜잭션 슈레드를 수신합니다 (데이터 조각). ← Helius의 \*\*[원본 슈레드 (UDP)](/docs/ko/shred-delivery/raw-shreds)\*\*가 여기에 전달됩니다.
2. **슈레드 디코딩** → 슈레드가 원본 트랜잭션으로 디코딩됩니다. ← **여기에서 사전 처리된 트랜잭션 사용 가능**
3. **트랜잭션 실행** → 트랜잭션이 런타임에 의해 실행됩니다.
4. **메타데이터 생성** → 전/후 잔액, 로그, 오류 정보가 계산됩니다.
5. **커밋** → 트랜잭션이 처리/확인/최종 상태에 도달합니다. ← **[LaserStream gRPC](/docs/ko/laserstream)** 및 \*\*[LaserStream WebSocket](/docs/ko/rpc/websocket)\*\*이 여기에서 전달됩니다.

실행 후 구독은 전체 실행 및 메타데이터 생성 후, 즉 5단계에서 데이터를 전달합니다. 사전 처리 구독은 2단계에서, 즉 슈레드 디코딩 직후, 실행 완료 전에 데이터를 전달합니다.

**절충점:** 실행 메타데이터 (잔액 변경, 로그, 오류 정보) 없이 밀리세컨드 단위로 더 빨리 트랜잭션 데이터를 받습니다.

<Warning>
  **트랜잭션 전용 스트림입니다.** 계정 및 프로그램 상태 업데이트는 런타임이 트랜잭션을 실행할 때까지 존재하지 않습니다 (4단계). 실시간 계정 또는 프로그램 업데이트 — 토큰 잔액, 본딩 곡선 상태, 프로그램 계정, 원본 트랜잭션이 아닌 데이터를 필요로 하는 경우 — 계정/프로그램 변경을 가장 빨리 받을 수 있는 \*\*[LaserStream gRPC](/docs/ko/laserstream)에서 `processed` 커밋을 사용하십시오.
</Warning>

<Tip>
  더 빠른 트랜잭션 신호가 필요하십니까? 예약된 트랜잭션을 스트리밍할 [Preconfirmations](/docs/ko/pre-confirmations/overview) 및 처리되지 않은 트랜잭션 데이터를 위한 [Raw Shreds (UDP)](/docs/ko/shred-delivery/raw-shreds)를 시도해보세요.
</Tip>

## 최선을 다한 전달 보장

사전 처리된 트랜잭션 전달은 최선을 다하며 보장되지 않습니다. 우리는 99.99% 전달률을 목표로 하지만, 다음과 같은 경우 거래가 손실될 수도 있습니다:

* 인프라 업데이트 및 재배포
* 네트워크 문제나 검증기 연결 문제
* 슈레드 디코딩 또는 처리의 예외 케이스

보장이 필요한 중요 애플리케이션은 [트랜잭션 구독](/docs/ko/laserstream/guides/decoding-transaction-data)을 사용하십시오.

## 어떤 데이터가 이용 가능한가요?

사전 처리된 트랜잭션은 완전한 트랜잭션 메시지를 포함하지만 실행 메타데이터는 포함하지 않습니다:

### 이용 가능한 데이터

* ✅ **트랜잭션 서명** - 고유 트랜잭션 식별자
* ✅ **계정 키** - 트랜잭션에 참조된 모든 계정
* ✅ **명령어** - 완전한 명령어 데이터 및 프로그램 호출
* ✅ **최근 블록해시** - 트랜잭션 만료 참조
* ✅ **서명** - 모든 트랜잭션 서명
* ✅ **투표 트랜잭션 여부** - 이것이 투표 트랜잭션인지 여부
* ✅ **슬롯 번호** - 이 트랜잭션이 포함된 슬롯

### 누락된 데이터

* ❌ **트랜잭션 메타데이터** - 토큰 잔액 변경, 전/후 잔액, 트랜잭션 상태
* ❌ **트랜잭션 오류** - 트랜잭션 실패 여부를 알 수 없습니다
* ❌ **내부 명령어** - 크로스 프로그램 호출(CPI)은 포함되지 않음
* ❌ **로그 메시지** - 실행 중 생성된 프로그램 로그
* ❌ **소비된 컴퓨팅 유닛** - 실행 메트릭은 이용 불가

사전 처리된 트랜잭션을 "제안서"를 받은 것으로 생각하십시오. 사용자가 시도한 것을 볼 수 있지만 실제로 발생한 결과는 볼 수 없습니다.

## SDK 지원 및 버전 요구사항

사전 처리된 트랜잭션 구독은 모든 LaserStream SDK에서 지원됩니다:

<CardGroup cols={3}>
  <Card title="JavaScript/TypeScript" icon="js" href="https://github.com/helius-labs/laserstream-sdk/tree/main/javascript">
    버전 **0.2.8** 이상
  </Card>

  <Card title="Rust" icon="rust" href="https://github.com/helius-labs/laserstream-sdk/tree/main/rust">
    버전 **0.1.5** 이상
  </Card>

  <Card title="Go" icon="golang" href="https://github.com/helius-labs/laserstream-sdk/tree/main/go">
    버전 **0.1.0** 이상
  </Card>
</CardGroup>

***

## 구현 예제

### JavaScript/TypeScript

JavaScript SDK는 자동 재연결 기능이 있는 전용 `subscribePreprocessed` 함수를 제공합니다:

```typescript [expandable] theme={"system"}
import {
  subscribePreprocessed,
  CommitmentLevel,
  LaserstreamConfig,
  SubscribePreprocessedRequest,
  SubscribePreprocessedUpdate
} from 'helius-laserstream';
import bs58 from 'bs58';

async function streamPreprocessedTransactions() {
  const config: LaserstreamConfig = {
    apiKey: 'YOUR_API_KEY',
    endpoint: 'https://laserstream-mainnet-ewr.helius-rpc.com',
  };

  const request: SubscribePreprocessedRequest = {
    transactions: {
      "jupiter-swaps": {
        vote: false,
        accountInclude: ['JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4']
      }
    }
  };

  const stream = await subscribePreprocessed(
    config,
    request,
    async (update: SubscribePreprocessedUpdate) => {
      if (update.transaction) {
        const tx = update.transaction;
        const signature = bs58.encode(tx.transaction.signature);

        console.log('⚡ Preprocessed transaction received:');
        console.log(`  Signature: ${signature}`);
        console.log(`  Slot: ${tx.slot}`);
        console.log(`  Is Vote: ${tx.transaction.isVote}`);
        console.log(`  Filters: ${update.filters.join(', ')}`);
        console.log('---');
      }
    },
    async (error) => {
      console.error('Stream error:', error);
    }
  );

  console.log(`✅ Preprocessed stream started (id: ${stream.id})`);

  // Graceful shutdown
  process.on('SIGINT', () => {
    console.log('\n🛑 Shutting down stream...');
    stream.cancel();
    process.exit(0);
  });
}

streamPreprocessedTransactions().catch(console.error);
```

**전체 예제:** [preprocessed-transaction-sub.ts](https://github.com/helius-labs/laserstream-sdk/blob/main/javascript/examples/preprocessed-transaction-sub.ts)

### Rust

Rust SDK는 네이티브 성능을 제공합니다:

```rust [expandable] theme={"system"}
use futures::StreamExt;
use helius_laserstream::{
    grpc::{SubscribePreprocessedRequest, SubscribePreprocessedRequestFilterTransactions},
    subscribe_preprocessed, LaserstreamConfig,
};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let config = LaserstreamConfig {
        endpoint: "https://laserstream-mainnet-ewr.helius-rpc.com".to_string(),
        api_key: "YOUR_API_KEY".to_string(),
        ..Default::default()
    };

    let mut request = SubscribePreprocessedRequest::default();
    request.transactions.insert(
        "jupiter-swaps".to_string(),
        SubscribePreprocessedRequestFilterTransactions {
            vote: Some(false),
            account_include: vec![
                "JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4".to_string()
            ],
            ..Default::default()
        },
    );

    let (stream, _handle) = subscribe_preprocessed(config, request);
    tokio::pin!(stream);

    println!("✅ Preprocessed stream started");

    while let Some(result) = stream.next().await {
        match result {
            Ok(update) => {
                if let Some(tx) = update.transaction {
                    println!("⚡ Preprocessed transaction:");
                    println!("  Slot: {}", tx.slot);
                    println!("  Is Vote: {}", tx.transaction.is_vote);
                    println!("---");
                }
            }
            Err(e) => {
                eprintln!("Stream error: {:?}", e);
                break;
            }
        }
    }

    Ok(())
}
```

**전체 예제:** [preprocessed\_transaction\_sub.rs](https://github.com/helius-labs/laserstream-sdk/blob/main/rust/examples/preprocessed_transaction_sub.rs)

### Go

Go SDK는 관용적인 Go 인터페이스를 제공합니다:

```go [expandable] theme={"system"}
package main

import (
    "log"
    "os"
    "os/signal"
    "syscall"

    laserstream "github.com/helius-labs/laserstream-sdk/go"
    pb "github.com/helius-labs/laserstream-sdk/go/proto"
)

func main() {
    log.SetFlags(0)

    clientConfig := laserstream.LaserstreamConfig{
        Endpoint: "https://laserstream-mainnet-ewr.helius-rpc.com",
        APIKey:   "YOUR_API_KEY",
    }

    voteFilter := false
    subscriptionRequest := &pb.SubscribePreprocessedRequest{
        Transactions: map[string]*pb.SubscribePreprocessedRequestFilterTransactions{
            "jupiter-swaps": {
                Vote: &voteFilter,
                AccountInclude: []string{
                    "JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4",
                },
            },
        },
    }

    client := laserstream.NewPreprocessedClient(clientConfig)

    dataCallback := func(data *pb.SubscribePreprocessedUpdate) {
        if data.Transaction != nil {
            log.Println("⚡ Preprocessed transaction:")
            log.Printf("  Slot: %d\n", data.Transaction.Slot)
            log.Printf("  Is Vote: %t\n", data.Transaction.Transaction.IsVote)
            log.Println("---")
        }
    }

    errorCallback := func(err error) {
        log.Printf("Error: %v", err)
    }

    err := client.Subscribe(subscriptionRequest, dataCallback, errorCallback)
    if err != nil {
        log.Fatalf("Failed to subscribe: %v", err)
    }

    log.Println("✅ Preprocessed stream started")
    log.Println("Press Ctrl+C to exit")

    sigChan := make(chan os.Signal, 1)
    signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)
    <-sigChan

    log.Println("\nShutting down...")
    client.Close()
}
```

**전체 예제:** [preprocessed-transaction-sub.go](https://github.com/helius-labs/laserstream-sdk/blob/main/go/examples/preprocessed-transaction-sub.go)

***

## 구독 구조 및 필터링

### 요청 구조

사전 처리된 구독 요청은 표준 구독과 유사한 구조를 따르지만, 세분화된 필터 집합을 가지고 있습니다:

```typescript theme={"system"}
interface SubscribePreprocessedRequest {
  transactions: {
    [filterName: string]: SubscribePreprocessedRequestFilterTransactions
  };
  ping?: SubscribeRequestPing;
}

interface SubscribePreprocessedRequestFilterTransactions {
  vote?: boolean;              // Include/exclude vote transactions
  signature?: string;          // Filter by specific transaction signature
  accountInclude?: string[];   // Include transactions touching these accounts
  accountExclude?: string[];   // Exclude transactions touching these accounts
  accountRequired?: string[];  // Require all these accounts to be present
}
```

### 응답 구조

업데이트는 완전한 트랜잭션 메시지와 기본 메타데이터와 함께 도착합니다:

```typescript theme={"system"}
interface SubscribePreprocessedUpdate {
  filters: string[];                             // Which filters matched
  transaction?: SubscribePreprocessedTransaction; // The transaction data
  ping?: SubscribeUpdatePing;                    // Keepalive ping
  pong?: SubscribeUpdatePong;                    // Ping response
  createdAt: Date;                               // When update was created
}

interface SubscribePreprocessedTransaction {
  transaction: SubscribePreprocessedTransactionInfo;
  slot: number;                                  // Slot containing transaction
}

interface SubscribePreprocessedTransactionInfo {
  signature: Uint8Array;                         // Transaction signature
  isVote: boolean;                               // Is this a vote transaction
  transaction: solana.storage.Transaction;       // Full transaction message
}
```

`transaction.transaction` 필드는 다음을 포함한 완전한 Solana 트랜잭션 구조를 담고 있습니다:

* **메시지** - 계정 키, 명령어, 최근 블록해시
* **서명** - 모든 트랜잭션 서명
* **주소 테이블 조회** - 버전 트랜잭션용
