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

# LaserStream gRPC 빠른 시작

> SDK를 설치하고, 엔드포인트를 선택하여 LaserStream gRPC를 통해 첫 Solana 거래를 스트리밍하세요. 엔드포인트, 구독 요청 참조, 코드 예제 및 FAQ 포함.

## 개요

LaserStream은 관리되는 Solana gRPC 스트리밍 서비스입니다. 이는 열린 Yellowstone gRPC 프로토콜과 호환되므로 모든 Yellowstone 클라이언트가 바로 작동하며, 과거 재생, 다중 노드 장애 조치 및 완전 관리 환경과 같은 프로덕션 기능을 추가합니다.

LaserStream은 오픈 소스 gRPC 프로토콜을 사용하여 벤더 종속이 없고 기존 gRPC 구현과 최대 호환성을 보장합니다.

표준 `@triton-one/yellowstone-grpc` 클라이언트로 또는 성능 최적화된 \*\*[Helius LaserStream SDK](/docs/ko/laserstream/clients)\*\*를 사용하여 더 높은 처리량, 자동 재연결, 구독 관리, 오류 처리 등을 포함한 추가 이점을 얻을 수 있습니다.

<Card title="LaserStream SDK는 JavaScript Yellowstone 클라이언트 대비 40배 더 빠릅니다" icon="bolt" href="https://www.helius.dev/blog/laserstream-sdks">
  Rust Core와 제로 복사 NAPI 바인딩을 사용하여 JavaScript SDK 성능을 최적화한 방법을 알아보세요.
</Card>

<Warning>
  **성능 알림**: LaserStream 연결에서 지연이나 성능 문제가 발생하면 [문제 해결 섹션](#문제-해결--faq)을 참조하여 일반적인 원인과 해결책을 확인하세요.
</Warning>

<Note>
  **압축 없음**: 지연 시간을 최소화하기 위해 LaserStream은 gRPC 응답 메시지를 압축하지 않습니다. `Accept-Encoding`를 gzip 또는 zstd로 설정해도 영향을 미치지 않으며, 응답은 항상 압축되지 않은 상태로 반환됩니다.
</Note>

<Divider />

## 엔드포인트 및 지역

LaserStream은 전 세계 여러 지역에서 사용할 수 있습니다.

최적의 성능을 위해 애플리케이션과 가장 가까운 엔드포인트를 선택하세요:

### 메인넷 엔드포인트

| Region   | Location                        | Endpoint                                          |
| -------- | ------------------------------- | ------------------------------------------------- |
| **ewr**  | Newark, NJ (near New York)      | `https://laserstream-mainnet-ewr.helius-rpc.com`  |
| **pitt** | Pittsburgh, US (Central)        | `https://laserstream-mainnet-pitt.helius-rpc.com` |
| **slc**  | Salt Lake City, US (West Coast) | `https://laserstream-mainnet-slc.helius-rpc.com`  |
| **lax**  | Los Angeles, US (West Coast)    | `https://laserstream-mainnet-lax.helius-rpc.com`  |
| **lon**  | London, Europe                  | `https://laserstream-mainnet-lon.helius-rpc.com`  |
| **ams**  | Amsterdam, Europe               | `https://laserstream-mainnet-ams.helius-rpc.com`  |
| **fra**  | Frankfurt, Europe               | `https://laserstream-mainnet-fra.helius-rpc.com`  |
| **tyo**  | Tokyo, Asia                     | `https://laserstream-mainnet-tyo.helius-rpc.com`  |
| **sgp**  | Singapore, Asia                 | `https://laserstream-mainnet-sgp.helius-rpc.com`  |

### Devnet 엔드포인트

| Network    | Location                   | Endpoint                                        |
| ---------- | -------------------------- | ----------------------------------------------- |
| **Devnet** | Newark, NJ (near New York) | `https://laserstream-devnet-ewr.helius-rpc.com` |

<Note>
  **네트워크 및 지역 선택**:

  * **프로덕션 앱**의 경우 서버와 가장 가까운 메인넷 엔드포인트를 선택하세요 (예: 유럽에 배포하는 경우 Amsterdam (`ams`) 또는 Frankfurt (`fra`)를 사용하세요)
  * **테스트**: `https://laserstream-devnet-ewr.helius-rpc.com`를 사용하세요.
</Note>

### 로그 잘림

기본적으로 LaserStream은 거래 로그 메시지를 **10 KB**로 잘라내어 속도와 성능을 향상시킵니다. 전체 로그가 필요한 경우 전용 비잘림 엔드포인트를 사용할 수 있습니다 — [로그 잘림](/docs/ko/laserstream/log-truncation)을 참조하세요.

## 빠른 시작

<Tip>
  [Helius Dashboard](https://dashboard.helius.dev/laserstream)에서 LaserStream을 시작하세요. 메인넷은 비즈니스 또는 프로페셔널 플랜이 필요하고, Devnet은 개발자 플랜 이상에서 사용할 수 있습니다. 자세한 내용은 [플랜 및 가격](/docs/ko/billing/plans)을 참조하세요.
</Tip>

<Steps>
  <Step title="새 프로젝트 생성">
    ```bash theme={"system"}
    mkdir laserstream-grpc-demo
    cd laserstream-grpc-demo
    npm init -y
    ```
  </Step>

  <Step title="의존성 설치">
    우리는 `tsx`를 사용합니다, 기본 `npx tsc --init`가 TypeScript 5.x에서 `verbatimModuleSyntax`, `module: "nodenext"` 및 `types: []`를 설정한 채로 동작하여 빠른 `ts-node index.ts` 실행을 방해합니다. `tsx`는 tsconfig 없이 `.ts` 파일을 실행합니다.
  </Step>

  <Step title="API 키 획득">
    [Helius Dashboard](https://dashboard.helius.dev/)에서 키를 생성하세요.

    이 키는 LaserStream에 대한 인증 토큰으로 사용됩니다.

    <Note>
      **플랜 요구 사항**: LaserStream devnet은 모든 [플랜](/docs/ko/billing/plans)에서 사용할 수 있습니다. LaserStream mainnet은 비즈니스 또는 프로페셔널 플랜이 필요합니다.
    </Note>
  </Step>

  <Step title="구독 스크립트 생성">
    \*\*`index.ts`\*\*를 다음과 같이 만드세요:

    We use `tsx` because the default `npx tsc --init` on TypeScript 5.x sets `verbatimModuleSyntax`, `module: "nodenext"`, and `types: []`, which all break a quick `ts-node index.ts` run. `tsx` runs `.ts` files without a tsconfig.
  </Step>

  <Step title="Obtain Your API Key">
    Generate a key from the [Helius Dashboard](https://dashboard.helius.dev/).

    This key will serve as your authentication token for LaserStream.

    <Note>
      **Plan Requirements**: LaserStream devnet is available on all [plans](/docs/ko/billing/plans). LaserStream mainnet requires a Business or Professional plan.
    </Note>
  </Step>

  <Step title="Create a Subscription Script">
    Create **`index.ts`** with the following:

    ```typescript theme={"system"}
    import { subscribe, CommitmentLevel, LaserstreamConfig, SubscribeRequest } from 'helius-laserstream'

    async function main() {
      const subscriptionRequest: SubscribeRequest = {
        transactions: {
          "token-filter": { // user-defined label for this filter
            accountInclude: ['TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA'],
            accountExclude: [],
            accountRequired: [],
            vote: false,
            failed: false
          }
        },
        commitment: CommitmentLevel.CONFIRMED,
        accounts: {},
        slots: {},
        transactionsStatus: {},
        blocks: {},
        blocksMeta: {},
        entry: {},
        accountsDataSlice: [],
        // Optionally, you can replay missed data by specifying a `fromSlot` (u64 number):
        // fromSlot: currentSlot - 1000,
        // Note: replay is currently limited to the last ~216,000 slots (≈24 hours).
      };

    // Replace the values below with your actual LaserStream API key and endpoint
    const config: LaserstreamConfig = {
      apiKey: 'YOUR_API_KEY', // Replace with your key from https://dashboard.helius.dev/
      endpoint: 'https://laserstream-mainnet-ewr.helius-rpc.com', // Choose your closest region
    }

      await subscribe(config, subscriptionRequest, async (data) => {
        
        console.log(data);

      }, async (error) => {
        console.error(error);
      });
    }

    main().catch(console.error);
    ```
  </Step>

  <Step title="API 키 교체 및 지역 선택">
    `index.ts`에서 실제 API 키를 [Helius Dashboard](https://dashboard.helius.dev/)에서 제공된 것으로 업데이트하세요.

    1. 서버 위치와 가장 가까운 LaserStream 엔드포인트

    ```typescript theme={"system"}
    const config: LaserstreamConfig = {
      apiKey: 'YOUR_ACTUAL_API_KEY', // Replace with your key from Helius Dashboard
      endpoint: 'https://laserstream-mainnet-fra.helius-rpc.com', // Example: Frankfurt mainnet
      // For devnet: endpoint: 'https://laserstream-devnet-ewr.helius-rpc.com'
    }
    ```

    **네트워크 및 지역 선택 예시:**

    * **프로덕션(메인넷)**:
      * 유럽: `fra` (프랑크푸르트), `ams` (암스테르담), 또는 `lon` (런던)
      * 미국 동부: `ewr` (뉴욕)
      * 미국 서부: `slc` (솔트 레이크 시티) 또는 `lax` (로스엔젤레스)
      * 아시아: `tyo` (도쿄) 또는 `sgp` (싱가포르)
    * **개발(Devnet)**:
      * `https://laserstream-devnet-ewr.helius-rpc.com` 사용
  </Step>

  <Step title="실행 및 결과 보기">
    ```bash theme={"system"}
    npx tsx index.ts
    ```

    `confirmed` 토큰 거래에 `TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA`이 포함될 때마다 콘솔에서 데이터를 확인할 수 있습니다.
  </Step>
</Steps>

<Divider />

## 일반 워크플로우

가장 자주 보이는 워크플로우에 대한 단계별 가이드를 제공합니다. 각 가이드는 자동 재연결 및 이력 재생 기능이 내장된 [`helius-laserstream`](/docs/ko/laserstream/clients) SDK를 사용합니다.

<CardGroup cols={2}>
  <Card title="계정 구독" icon="user" href="/docs/ko/laserstream/guides/account-subscription">
    필터를 사용하여 특정 계정의 잔액, 데이터 및 소유권 변경 사항을 모니터링합니다.
  </Card>

  <Card title="거래 모니터링" icon="receipt" href="/docs/ko/laserstream/guides/transaction-monitoring">
    대상 계정을 포함하는 거래를 스트리밍하고 프로그램, 투표, 실패 상태로 필터링합니다.
  </Card>

  <Card title="슬롯 및 블록 모니터링" icon="cube" href="/docs/ko/laserstream/guides/slot-and-block-monitoring">
    네트워크 합의, 블록 생성 및 약속 수준 전환을 추적합니다.
  </Card>

  <Card title="거래 데이터 디코딩" icon="binary" href="/docs/ko/laserstream/guides/decoding-transaction-data">
    바이너리 `transactionUpdate` 페이로드를 읽을 수 있는 Solana 거래로 구문 분석합니다.
  </Card>

  <Card title="Stream Pump AMM 데이터" icon="chart-line" href="/docs/ko/laserstream/guides/stream-pump-amm-data">
    실세계 예시: 다시 연결 가능한 안전한 필터로 Pump AMM 거래를 모니터링합니다.
  </Card>
</CardGroup>

<Tip>
  메시지 처리 논리를 최적화하고 주 스레드를 장시간 차단하지 않도록 하세요.
</Tip>

<Divider />

## 구독 요청

구독 요청에 다음 일반 매개변수를 포함해야 합니다:

<Note>
  **역사 재생:** 특정 슬롯부터 데이터를 재생하려면 주요 `SubscribeRequest` 객체에 `fromSlot` 필드( `u64` 숫자)를 포함할 수 있습니다. 재생은 현재 마지막 216,000 슬롯 (≈24시간)으로 제한됩니다. [약 20분 이상 초과한 재생은 최종 데이터만 반환됩니다.](/docs/ko/laserstream/historical-replay#재생할-수-있는-최대-시간)
</Note>

<ParamField type="enum">
  처리 수준을 지정하며, **processed**, **confirmed**, **finalized** 중에서 선택할 수 있습니다.
</ParamField>

<ParamField type="array">
  계정에서 필요한 데이터 조각만 수신할 수 있도록 하는 객체 ARRAY입니다.
</ParamField>

<ParamField type="boolean">
  일부 클라우드 제공자 (예: Cloudflare)는 비활성 상태에서 일정 시간이 지난 후 유휴 스트림을 닫을 수 있습니다. 이를 방지하고 필터를 다시 보낼 필요 없이 연결을 유지하려면 이 값을 **true**로 설정하세요. 서버는 15초마다 Pong 메시지로 응답합니다.
</ParamField>

```typescript theme={"system"}
const subscriptionRequest: SubscribeRequest = {
  commitment: CommitmentLevel.CONFIRMED,
  accountsDataSlice: [],
  transactions: {},
  accounts: {},
  slots: {},
  blocks: {},
  blocksMeta: {},
  entry: {},
}
```

다음으로 계정, 블록, 슬롯 또는 거래 등 구독하려는 데이터의 필터를 지정해야 합니다.

<Accordion title="Slots">
  슬롯 업데이트에 대한 필터를 정의합니다. 사용하는 키(예: `mySlotLabel`)는 이 특정 필터 설정에 대한 **사용자 정의 레이블**로, 필요 시 여러 명명된 구성을 정의할 수 있습니다 (일반적으로 하나로 충분합니다).

  <ParamField type="boolean">
    기본적으로 모든 커밋 수준에 대해 슬롯이 전송됩니다. 이 필터를 사용하면 선택한 커밋 수준만 수신할 수 있습니다.
  </ParamField>

  <ParamField type="boolean">
    새 슬롯의 시작 뿐만 아니라 슬롯 내에서의 변경 사항에 대한 업데이트를 수신할 수 있도록 구독을 활성화합니다. 이는 더 세분화된 지연이 적은 슬롯 데이터에 유용합니다.
  </ParamField>

  ```typescript theme={"system"}
  slots: {
    // mySlotLabel is a user-defined name for this slot update filter configuration
    mySlotLabel: {
      // filterByCommitment: true => Only broadcast slot updates at the specified subscribeRequest commitment
      filterByCommitment: true
      // interslotUpdates: true allows receiving updates for changes occurring within a slot, not just new slots.
      interslotUpdates: true
    }
  },
  ```
</Accordion>

<Accordion title="계정">
  계정 데이터 업데이트에 대한 필터를 정의합니다. 사용하는 키(예: `tokenAccounts`)는 이 특정 필터 설정에 대한 **사용자 정의 레이블**입니다.

  <ParamField body="account" type="array">
    제공된 배열의 공용 키와 일치합니다.
  </ParamField>

  <ParamField body="owner" type="array">
    계정 소유자의 공개 키입니다. 제공된 배열의 공개 키와 일치합니다.
  </ParamField>

  <ParamField body="filters" type="array">
    [getProgramAccounts](https://solana.com/docs/rpc/http/getprogramaccounts)와 유사한 필터입니다. 이는 `datasize` 및/또는 `memcmp` 필터의 배열입니다. `memcmp`의 경우, 비교값은 `bytes`, `base58`, 또는 `base64` 중 하나에 직접 설정됩니다.
  </ParamField>

  <ParamField body="notifyOn" type="enum">
    수신할 업데이트를 제어합니다. 기본적으로(`lock`) 트랜잭션이 계정을 작성하지 않더라도 트랜잭션이 계정을 잠글 때마다 업데이트가 전송됩니다. 이러한 작업이 없는 업데이트를 건너뛰고 트랜잭션이 계정을 실제로 작성할 때만 알림을 받으려면 `write`로 설정하세요. 동일한 데이터의 작성도 여전히 작성으로 간주되어 전달됩니다. 건너뛴 업데이트는 이전 상태의 정확한 중복본입니다. 활동 추적 예시와 같이 계정이 트랜잭션에 의해 잠겼음을 알리는 신호로 업데이트에 의존하는 경우 비워 두세요. 이는 [Helius LaserStream SDK](/docs/ko/laserstream/clients)를 통해 사용할 수 있는 Helius 확장 기능입니다 — 표준 Yellowstone 클라이언트는 필드를 노출하지 않습니다. [notifyOn 필터링](/docs/ko/laserstream/notify-on-filtering)을 참조하세요.
  </ParamField>

  모든 필드가 비어 있으면 모든 계정이 방송됩니다. 그렇지 않으면:

  * 필드는 논리적 **AND**로 작동합니다.
  * 배열 내의 값은 논리적 **OR**로 작동합니다(단, `filters` 내에서는 논리적 **AND**로 작동합니다).

  ```typescript theme={"system"}
  accounts: {
    // tokenAccounts is a user-defined label for this account filter configuration
    tokenAccounts: {
      // Matches any of these public keys (logical OR)
      account: ["9SHQTA66Ekh7ZgMnKWsjxXk6DwXku8przs45E8bcEe38"],
      // Matches owners that are any of these public keys
      owner: ["TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"],
      // Filters - all must match (AND logic)
      filters: [
        { datasize: 165 },
        {
          memcmp: {
            offset: 0,
            base58: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"
          }
        }
      ]
    }
  },
  ```

  \~10,000개 이상의 계정을 추적하시나요? 명시적 공개 키 목록 대신(각 계정당 32바이트) 압축된 [cuckoo filter](/docs/ko/laserstream/cuckoo-filters) (\~3–4바이트 계정당)을 사용하여 단일 스트림에서 수십만 개의 계정을 구독하세요. Rust 및 JavaScript SDK에서 사용 가능합니다.
</Accordion>

<Accordion title="거래">
  거래 업데이트에 대한 필터를 정의합니다. 사용하는 키(예: `myTxSubscription`)는 이 특정 필터 설정에 대한 **사용자 정의 레이블**입니다.

  <ParamField type="boolean">
    투표 거래의 방송을 활성화하거나 비활성화합니다.
  </ParamField>

  <ParamField type="boolean">
    실패한 거래의 방송을 활성화하거나 비활성화합니다.
  </ParamField>

  <ParamField type="string">
    지정된 서명을 일치하는 거래만 방송합니다.
  </ParamField>

  <ParamField type="array">
    제공된 목록의 계정을 포함하는 거래를 필터링합니다.
  </ParamField>

  <ParamField type="array">
    제공된 목록의 계정을 포함하는 거래를 제외합니다 (`accountInclude`와 반대).
  </ParamField>

  <ParamField type="array">
    제공된 목록의 모든 계정을 포함하는 거래를 필터링합니다 (모든 계정이 사용되어야 함).
  </ParamField>

  <ParamField type="string">
    선택적 `tokenAccounts` (연관된 토큰 계정) 확장. 설정 시 `accountInclude` 지갑은 SPL 토큰 잔액을 **소유**할 때의 거래도 일치합니다 — 예: 지갑의 토큰 계정이 아닌 공개 키에 접촉하는 수신 토큰 전송. `"balanceChanged"` (잔액 델타 일치), `"all"` (참조 있음, 고용량) 또는 `"none"` (기본값, 확장 없음) 수락합니다. SDK는 문자열을 wire-level `TokenAccountExpansionControlFlag` 열거형으로 변환합니다 (`yellowstone-grpc-proto` 12.5.0+ 버전의 일부). [토큰 계정 (ATA) 필터링](/docs/ko/laserstream/token-account-filtering)에서 어떻게 작동하고 어떤 일을 하는지 확인하세요.
  </ParamField>

  모든 필드를 비워 두면 모든 거래가 방송됩니다. 그렇지 않으면:

  * 필드는 논리적 **AND**로 작동합니다.
  * 배열 내의 값은 논리적 **OR**로 처리됩니다 (`accountRequired`는 모두 일치해야 합니다).

  ```typescript theme={"system"}
  transactions: {
    // myTxSubscription is a user-defined label for this transaction filter configuration
    myTxSubscription: {
      vote: false,
      failed: false,
      signature: "",
      // Transaction must include at least one of these public keys (OR)
      accountInclude: ["86xCnPeV69n6t3DnyGvkKobf9FdN2H9oiVDdaMpo2MMY"],
      // Exclude if it matches any of these
      accountExclude: [],
      // Require all accounts in this array (AND)
      accountRequired: []
    }
  },
  ```
</Accordion>

<Accordion title="블록">
  블록 업데이트에 대한 필터를 정의합니다. 사용하는 키(예: `myBlockLabel`)는 이 특정 필터 설정에 대한 **사용자 정의 레이블**입니다.

  <ParamField type="array">
    제공된 목록의 거래 및 계정을 필터링합니다.
  </ParamField>

  <ParamField type="boolean">
    방송에 모든 거래를 포함합니다.
  </ParamField>

  <ParamField type="boolean">
    방송에 모든 계정 업데이트를 포함합니다.
  </ParamField>

  <ParamField type="boolean">
    방송에 모든 항목을 포함합니다.
  </ParamField>

  ```typescript theme={"system"}
  blocks: {
    // myBlockLabel is a user-defined label for this block filter configuration
    myBlockLabel: {
      // Only broadcast blocks referencing these accounts
      accountInclude: ["86xCnPeV69n6t3DnyGvkKobf9FdN2H9oiVDdaMpo2MMY"],
      includeTransactions: true,
      includeAccounts: false,
      includeEntries: false
    }
  },
  ```
</Accordion>

<Accordion title="블록 메타">
  이는 블록과 유사하게 작동하지만 거래, 계정 및 항목을 제외합니다. 사용하는 키(예: `blockmetadata`)는 이 구독에 대한 **사용자 정의 레이블**입니다. 현재 블록 메타데이터에 대한 필터는 사용할 수 없으며 모든 메시지가 기본적으로 방송됩니다.

  ```typescript theme={"system"}
  blocksMeta: {
    blockmetadata: {}
  },
  ```
</Accordion>

<Accordion title="엔트리">
  원장 항목을 구독하세요. 사용하는 키(예: `entrySubscribe`)는 이 구독에 대한 **사용자 정의 레이블**입니다. 현재 항목에 대한 필터는 사용할 수 없으며 모든 항목이 방송됩니다.

  ```typescript theme={"system"}
  entry: {
    entrySubscribe: {}
  },
  ```
</Accordion>

<Divider />

## 코드 예제 (LaserStream SDK)

<Tabs>
  <Tab title="슬롯 업데이트">
    ```typescript theme={"system"}
    import { subscribe, CommitmentLevel, LaserstreamConfig, SubscribeRequest } from 'helius-laserstream'

    async function main() {
        const subscriptionRequest: SubscribeRequest = {
            transactions: {},
            commitment: CommitmentLevel.CONFIRMED,
            accounts: {},
            slots: {
                slot: { filterByCommitment: true },
            },
            transactionsStatus: {},
            blocks: {},
            blocksMeta: {},
            entry: {},
            accountsDataSlice: [],
        };

        const config: LaserstreamConfig = {
            apiKey: 'YOUR_API_KEY', // Replace with your key
            endpoint: 'https://laserstream-mainnet-ewr.helius-rpc.com', // Choose your closest region
        }

        await subscribe(config, subscriptionRequest, async (data) => {
            console.log(data);
        }, async (error) => {
            console.error(error);
        });
    }

    main().catch(console.error);
    ```
  </Tab>

  <Tab title="계정 업데이트">
    ```typescript theme={"system"}
    import { subscribe, CommitmentLevel, LaserstreamConfig, SubscribeRequest } from 'helius-laserstream'

    async function main() {
        const subscriptionRequest: SubscribeRequest = {
            accounts: {
                "usdc-account": { // user-defined label for this filter
                    account: ["EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"], // USDC mint account
                    owner: [],
                    filters: []
                }
            },
            accountsDataSlice: [],
            commitment: CommitmentLevel.CONFIRMED,
            slots: {},
            transactions: {},
            transactionsStatus: {},
            blocks: {},
            blocksMeta: {},
            entry: {}
        };

        const config: LaserstreamConfig = {
            apiKey: 'YOUR_API_KEY', // Replace with your key
            endpoint: 'https://laserstream-mainnet-ewr.helius-rpc.com', // Choose your closest region
        }

        await subscribe(config, subscriptionRequest, async (data) => {
            console.log(data);
        }, async (error) => {
            console.error(error);
        });
    }

    main().catch(console.error);
    ```
  </Tab>

  <Tab title="거래 업데이트">
    ```typescript theme={"system"}
    import { subscribe, CommitmentLevel, LaserstreamConfig, SubscribeRequest } from 'helius-laserstream'

    async function main() {
        const subscriptionRequest: SubscribeRequest = {
            transactions: {
                "token-filter": { // user-defined label for this filter
                    accountInclude: ['TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA'],
                    accountExclude: [],
                    accountRequired: [],
                    vote: false,
                    failed: false
                }
            },
            commitment: CommitmentLevel.CONFIRMED,
            accounts: {},
            slots: {},
            transactionsStatus: {},
            blocks: {},
            blocksMeta: {},
            entry: {},
            accountsDataSlice: [],
        };

        const config: LaserstreamConfig = {
            apiKey: 'YOUR_API_KEY', // Replace with your key
            endpoint: 'https://laserstream-mainnet-ewr.helius-rpc.com', // Choose your closest region
        }

        await subscribe(config, subscriptionRequest, async (data) => {
            console.log(data);
        }, async (error) => {
            console.error(error);
        });
    }

    main().catch(console.error);
    ```
  </Tab>

  <Tab title="블록">
    ```typescript theme={"system"}
    import { subscribe, CommitmentLevel, LaserstreamConfig, SubscribeRequest } from 'helius-laserstream'

    async function main() {
        const subscriptionRequest: SubscribeRequest = {
            entry: {},
            accounts: {},
            accountsDataSlice: [],
            slots: {},
            blocks: {
                blocks: {
                    accountInclude: []
                }
            },
            blocksMeta: {},
            transactions: {},
            transactionsStatus: {},
            commitment: CommitmentLevel.CONFIRMED,
        };

        const config: LaserstreamConfig = {
            apiKey: 'YOUR_API_KEY', // Replace with your key
            endpoint: 'https://laserstream-mainnet-ewr.helius-rpc.com', // Choose your closest region
        }

        await subscribe(config, subscriptionRequest, async (data) => {
            console.log(data);
        }, async (error) => {
            console.error(error);
        });
    }

    main().catch(console.error);
    ```
  </Tab>

  <Tab title="블록 메타데이터">
    ```typescript theme={"system"}
    import { subscribe, CommitmentLevel, LaserstreamConfig, SubscribeRequest } from 'helius-laserstream'

    async function main() {
        const subscriptionRequest: SubscribeRequest = {
            entry: {},
            accounts: {},
            accountsDataSlice: [],
            slots: {},
            blocks: {},
            blocksMeta: {
                blockmetadata: {}
            },
            transactions: {},
            transactionsStatus: {},
            commitment: CommitmentLevel.CONFIRMED,
        };

        const config: LaserstreamConfig = {
            apiKey: 'YOUR_API_KEY', // Replace with your key
            endpoint: 'https://laserstream-mainnet-ewr.helius-rpc.com', // Choose your closest region
        }

        await subscribe(config, subscriptionRequest, async (data) => {
            console.log(data);
        }, async (error) => {
            console.error(error);
        });
    }

    main().catch(console.error);
    ```
  </Tab>

  <Tab title="엔트리">
    ```typescript theme={"system"}
    import { subscribe, CommitmentLevel, LaserstreamConfig, SubscribeRequest } from 'helius-laserstream'

    async function main() {
        const subscriptionRequest: SubscribeRequest = {
            entry: {
                entrySubscribe: {}  // Subscribe to all entries
            },
            accounts: {},
            accountsDataSlice: [],
            slots: {},
            blocks: {},
            blocksMeta: {},
            transactions: {},
            transactionsStatus: {},
            commitment: CommitmentLevel.CONFIRMED,
        };

        const config: LaserstreamConfig = {
            apiKey: 'YOUR_API_KEY', // Replace with your key
            endpoint: 'https://laserstream-mainnet-ewr.helius-rpc.com', // Choose your closest region
        }

        await subscribe(config, subscriptionRequest, async (data) => {
            console.log(data);
        }, async (error) => {
            console.error(error);
        });
    }

    main().catch(console.error);
    ```
  </Tab>
</Tabs>

<Divider />

## SDK 옵션

여러 프로그래밍 언어에 대한 공식 SDK를 제공합니다:

* **TypeScript**: [LaserStream TypeScript SDK](https://github.com/helius-labs/laserstream-sdk)
* **Rust**: [LaserStream Rust SDK](https://github.com/helius-labs/laserstream-sdk/tree/main/rust)
* **Go**: [LaserStream Go SDK](https://github.com/helius-labs/laserstream-sdk/tree/main/go)

다른 언어 또는 맞춤형 구현의 경우 [Yellowstone gRPC 프로토 파일](https://github.com/rpcpool/yellowstone-grpc/tree/v6.0.0%2Bsolana.2.2.12/yellowstone-grpc-proto/proto)을 직접 사용하여 선호하는 언어에 대한 gRPC 클라이언트를 생성할 수 있습니다.

<Divider />

## 문제 해결 / FAQ

<Accordion title="Q: LaserStream 연결에서 지연 또는 느린 성능이 발생합니다. 원인은 무엇일까요?">
  **A:** LaserStream 연결의 성능 문제는 일반적으로 다음과 같은 원인으로 발생합니다:

  * **JavaScript 클라이언트 속도 저하**: JavaScript 클라이언트는 메시지를 너무 많이 처리하거나 대역폭을 너무 많이 사용할 때 뒤떨어질 수 있습니다. 메시지 볼륨을 줄이기 위해 구독을 더 좁게 필터링하거나 [LaserStream JavaScript SDK](/docs/ko/laserstream/clients)를 사용하거나 다른 언어를 시도해보세요.

  * **제한된 로컬 대역폭**: 무거운 구독은 네트워크 대역폭이 제한된 클라이언트에 과부하를 줄 수 있습니다. 네트워크 사용량을 모니터링하고 연결을 업그레이드하거나 구독 범위를 줄이는 것을 고려하세요.

  * **지리적 거리**: 긴 네트워크 경로는 지연과 패킷 손실을 증가시킵니다. [서버와 가장 가까운 엔드포인트](#메인넷-엔드포인트)를 사용하세요. 높은 대기 시간 연결의 경우 네트워크 읽기 버퍼 크기를 늘리면 대역폭이 5배 이상 향상될 수 있습니다:

    ```bash theme={"system"}
    sudo sysctl -w net.core.rmem_max=67108864 net.ipv4.tcp_rmem="4096 87380 67108864"
    ```

    To persist across reboots, add to `/etc/sysctl.conf`:

    ```bash theme={"system"}
    net.core.rmem_max=67108864
    net.ipv4.tcp_rmem=4096 87380 67108864
    ```

    Increase the HTTP/2 stream **and connection** window sizes to 64MB to prevent flow control bottlenecks. Both are required — raising only the stream window leaves the connection-level window as the binding constraint:

    ```rust theme={"system"}
    // Rust (tonic)
    Channel::from_static("https://laserstream-mainnet-ewr.helius-rpc.com")
        .initial_stream_window_size(1024 * 1024 * 64)      // 64MB stream window
        .initial_connection_window_size(1024 * 1024 * 64)  // 64MB connection window
        .connect()
        .await?;
    ```

  * **클라이언트 측 처리 병목 현상**: 메시지 처리 논리가 최적화되어 있지 않아 주 스레드를 장기간 차단하고 있지 않은지 확인하세요.

  **클라이언트 지연 디버깅**: 클라이언트를 디버깅 할 수 있도록, 노드에서 Laserstream gRPC 서버까지 최대 대역폭을 테스트하는 도구를 구축했습니다. 사용하려면:

  ```
  cargo install helius-laserstream-bandwidth
  helius-laserstream-bandwidth --laserstream-url $LASERSTREAM_URL --api-key $API_KEY
  ```

  출력은 서버와 Laserstream 서버 간의 최대 네트워크 용량을 반환합니다. 최소한 모든 거래 데이터를 구독하려면 10MB/s가 필요하며, 모든 계정 데이터를 구독하려면 80MB/s가 필요합니다. 최적의 성능을 위해 최소 2배의 용량을 확보하는 것이 좋습니다.
</Accordion>

<Accordion title="Q: 연결 오류가 발생합니다. 무엇을 확인해야 하나요?">
  **A:** API 키와 엔드포인트가 정확한지 확인하고 네트워크가 지정된 엔드포인트로의 gRPC 출력 연결을 허용하는지 확인하세요. [Helius 상태 페이지](https://helius.statuspage.io/)에서 진행 중인 사건이 있는지 확인하세요.
</Accordion>

<Accordion title="Q: 필터가 예상대로 작동하지 않습니다. 왜 그런가요?">
  **A:** 필터 섹션에서 설명된 논리 연산자(AND/OR)를 다시 확인하세요. 공개 키가 정확한지 확인하세요. 요청에 지정된 커밋 수준을 검토하세요.
</Accordion>

<Accordion title="Q: 한 번에 여러 유형의 데이터(예: 계정 및 거래)를 구독할 수 있나요?">
  **A:** 네, 여러 키 (예: `accounts`, `transactions`) 아래에서 필터 구성을 정의할 수 있습니다.
</Accordion>

<Accordion title="Q: LaserStream에서는 소비자 그룹을 지원하나요?">
  **A:** 소비자 그룹을 구현하지 않습니다. 대신, LaserStream은 조정 레이어(따라서 그것과 관련된 대기 시간/오버헤드 없이) 없이도 팀이 원하는 동일한 결과를 제공합니다: 재개, 재생 및 다중 노드 안정성. 우리는 대부분의 워크로드에 소비자 그룹이 필요하지 않으며, 이들은 대기 시간과 운영 오버헤드를 추가한다고 믿습니다. 예를 들어, 단일 LaserStream gRPC 연결은 Solana의 거래 및 계정 데이터보다 최대 10배를 방출할 수 있으며, 대부분의 클라이언트는 작고 필터링된 조각에 구독합니다. 이 경우 소비자 그룹을 사용하는 것은 성능 여유를 태우고 또 다른 장애 지점을 소개합니다.
</Accordion>

<Accordion title="Q: 내 거래 로그 메시지가 잘립니다. 왜 그런가요?">
  **A:** LaserStream은 속도와 성능을 위해 기본적으로 거래 로그 메시지를 10 KB로 잘라냅니다. 전체 로그가 필요하면 전용 비잘림 엔드포인트에 연결하세요 — 목록은 [로그 잘림](/docs/ko/laserstream/log-truncation)을 참조하세요.
</Accordion>

<Accordion title="Q: 계정 또는 슬롯 데이터 없이 Pong 응답만 받는 이유는 무엇인가요?">
  **A:** 초기 `SubscribeRequest`에 `ping` 필드를 포함하면 LaserStream은 모든 구독 필터를 묵시적으로 무시합니다 — 한 Pong만 반환되고 계정, 거래 또는 슬롯 데이터는 반환되지 않습니다. 이를 수정하려면 초기 구독 요청에서 `ping`를 제거하고 구독이 설정된 후 별도로 스트림의 싱크를 통해 핑을 보내세요. 이렇게 하면 필터에 영향을 주지 않고도 연결을 유지할 수 있습니다.
</Accordion>
