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

# Solana 우선 수수료 추정: Account Keys 방법

> Helius Priority Fee API를 사용하여 account keys로 Solana 우선 수수료를 추정합니다. 사전 거래 분석 및 배치 작업을 위한 빠른 수수료 추정.

<Info>
  **고급 방법**: 사전 거래 분석, 배치 작업 및 계정 패턴 연구와 같은 특수한 사용 사례를 위해 account keys로 우선 수수료를 얻습니다.
</Info>

## 개요

account keys 방법은 전체 거래를 구성하기 전의 수수료를 빠르게 추정하거나 계산할 때 거래 직렬화에 대한 더 간단한 대안을 제공합니다.

<CardGroup cols={2}>
  <Card title="고급 사용 사례" icon="key">
    * 사전 거래 분석
    * 계정 배치 작업
    * 시장 조사 및 패턴
    * 특수 아키텍처
  </Card>

  <Card title="트레이드 오프" icon="scale-unbalanced-flip">
    * 직렬화된 거래보다 정확성이 낮음
    * 지시사항에 대한 구체적인 분석 불가능
    * 계정 수준 패턴에 최적화
  </Card>
</CardGroup>

<Warning>
  **권장 사항**: 대부분의 애플리케이션에는 [직렬화된 거래 방법](/docs/ko/priority-fee/estimating-fees-using-serialized-transaction)을 대신 사용하세요. 이 account keys 방법은 계정 수준의 분석이나 사전 거래 계획이 필요한 특수한 사용 사례를 위한 것입니다.
</Warning>

## Account Keys 사용 시기

<Tabs>
  <Tab title="이상적인 사용 사례">
    <CardGroup cols={2}>
      <Card title="사전 거래 계획" icon="calendar">
        전체 거래를 구성하기 전의 수수료 추정
      </Card>

      <Card title="간편 통합" icon="puzzle-piece">
        아키텍처가 거래 직렬화를 어렵게 만드는 경우
      </Card>

      <Card title="빠른 시장 분석" icon="chart-line">
        거래를 구성하지 않고 특정 계정의 수수료 패턴 분석
      </Card>

      <Card title="다중 계정 분석" icon="users">
        여러 계정에 걸친 수수료 패턴 독립적 이해
      </Card>
    </CardGroup>
  </Tab>

  <Tab title="특수한 시나리오">
    **연구 및 분석**: 다른 계정 및 프로그램에 걸친 수수료 패턴 연구 시

    **배치 작업**: 여러 계정에 걸친 수수료 패턴 분석 시

    **사전 계획**: 복잡한 거래 워크플로우를 구축하기 전의 비용 추정 시

    **맞춤 아키텍처**: 시스템 제약으로 인해 거래 직렬화를 할 수 없을 때
  </Tab>
</Tabs>

## 빠른 시작

<Steps>
  <Step title="계정 식별">
    거래에 포함될 계정을 결정하세요
  </Step>

  <Step title="API 호출">
    계정 키와 원하는 우선 순위 수준으로 요청하세요
  </Step>

  <Step title="수수료 적용">
    추정치를 사용하여 거래에 우선 순위 수수료를 설정합니다
  </Step>
</Steps>

### 기본 예제

<CodeGroup>
  ```javascript JavaScript theme={"system"}
  import { ComputeBudgetProgram } from "@solana/web3.js";

  // 1. Identify accounts involved in your transaction
  const accountKeys = [
    "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", // Token program
    "YOUR_WALLET_ADDRESS",                          // Your wallet
    "RECIPIENT_ADDRESS"                             // Recipient
  ];

  // 2. Get priority fee estimate
  const priorityFee = await getPriorityFeeEstimate(connection, accountKeys, "Medium");

  // 3. Add to your transaction
  const priorityFeeIx = ComputeBudgetProgram.setComputeUnitPrice({
    microLamports: priorityFee
  });
  transaction.add(priorityFeeIx);
  ```

  ```python Python theme={"system"}
  import requests

  # Get priority fee estimate
  def get_priority_fee_estimate(account_keys, priority_level="Medium"):
      response = requests.post(
          "https://mainnet.helius-rpc.com/?api-key=YOUR_API_KEY",
          json={
              "jsonrpc": "2.0",
              "id": "1",
              "method": "getPriorityFeeEstimate",
              "params": [{
                  "accountKeys": account_keys,
                  "options": {
                      "priorityLevel": priority_level,
                      "recommended": True
                  }
              }]
          }
      )
      return response.json()["result"]["priorityFeeEstimate"]

  # Usage
  accounts = ["ACCOUNT_1", "ACCOUNT_2", "ACCOUNT_3"]
  fee = get_priority_fee_estimate(accounts, "High")
  print(f"Priority fee: {fee} micro-lamports")
  ```
</CodeGroup>

## 구현 가이드

### 핵심 기능

우선 수수료 추정을 위한 재사용 가능한 함수입니다:

```javascript theme={"system"}
async function getPriorityFeeEstimate(connection, accountKeys, priorityLevel = "Medium") {
  const response = await fetch(connection.rpcEndpoint, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
      jsonrpc: "2.0",
      id: "1",
      method: "getPriorityFeeEstimate",
      params: [{
        accountKeys: accountKeys,
        options: { 
          priorityLevel: priorityLevel,
          recommended: true 
        }
      }]
    })
  });
  
  const result = await response.json();
  
  if (result.error) {
    throw new Error(`Fee estimation failed: ${JSON.stringify(result.error)}`);
  }
  
  return result.result.priorityFeeEstimate;
}
```

### 여러 우선 순위 수준의 완전한 예제

<Accordion title="전체 구현을 보려면 확장">
  ```javascript theme={"system"}
  const { 
    Connection, 
    PublicKey, 
    Transaction, 
    ComputeBudgetProgram 
  } = require("@solana/web3.js");

  // Initialize connection
  const connection = new Connection("https://mainnet.helius-rpc.com/?api-key=YOUR_API_KEY");

  async function analyzeAccountPriorityFees() {
    // Define accounts involved in your transaction
    const accountKeys = [
      "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", // Token program
      "YOUR_WALLET_ADDRESS",                          // Your wallet
      "TOKEN_ACCOUNT_ADDRESS",                        // Token account
      "RECIPIENT_ADDRESS"                             // Recipient
    ];
    
    try {
      // Get estimates for different priority levels
      const [lowFee, mediumFee, highFee, veryHighFee] = await Promise.all([
        getPriorityFeeEstimate(connection, accountKeys, "Low"),
        getPriorityFeeEstimate(connection, accountKeys, "Medium"), 
        getPriorityFeeEstimate(connection, accountKeys, "High"),
        getPriorityFeeEstimate(connection, accountKeys, "VeryHigh")
      ]);
      
      console.log("Priority Fee Estimates:");
      console.log(`Low:      ${lowFee} micro-lamports`);
      console.log(`Medium:   ${mediumFee} micro-lamports`);
      console.log(`High:     ${highFee} micro-lamports`);
      console.log(`VeryHigh: ${veryHighFee} micro-lamports`);
      
      // Get all levels at once for comparison
      const allLevels = await getAllPriorityLevels(connection, accountKeys);
      console.log("\nAll priority levels:", allLevels);
      
      return {
        low: lowFee,
        medium: mediumFee,
        high: highFee,
        veryHigh: veryHighFee,
        allLevels
      };
    } catch (error) {
      console.error("Error getting priority fees:", error);
      throw error;
    }
  }

  // Helper function to get all priority levels
  async function getAllPriorityLevels(connection, accountKeys) {
    const response = await fetch(connection.rpcEndpoint, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({
        jsonrpc: "2.0",
        id: "1",
        method: "getPriorityFeeEstimate",
        params: [{
          accountKeys: accountKeys,
          options: { 
            includeAllPriorityFeeLevels: true
          }
        }]
      })
    });
    
    const result = await response.json();
    
    if (result.error) {
      throw new Error(`Fee estimation failed: ${JSON.stringify(result.error)}`);
    }
    
    return result.result.priorityFeeLevels;
  }

  // Run the analysis
  analyzeAccountPriorityFees();
  ```
</Accordion>

## 계정 유형 및 전략

<Tabs>
  <Tab title="프로그램 계정">
    대량 프로그램 계정은 경쟁으로 인해 일반적으로 높은 우선 수수료를 나타냅니다.

    ```javascript theme={"system"}
    // Popular program accounts
    const programAccounts = [
      "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", // Token program
      "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL", // Associated token program
      "M2mx93ekt1fmXSVkTrUL9xVFHkmME8HTUi5Cyc5aF7K"  // Metaplex program
    ];

    const programFees = await getPriorityFeeEstimate(connection, programAccounts, "Medium");
    console.log(`Program account fees: ${programFees} micro-lamports`);
    ```

    <Note>
      **예상 행동**: 높은 거래량과 경쟁으로 인한 높은 수수료.
    </Note>
  </Tab>

  <Tab title="사용자 지갑">
    활동적인 사용자 지갑은 활동에 따라 다른 수수료 패턴을 가질 수 있습니다.

    ```javascript theme={"system"}
    // Active user wallets
    const userWallets = [
      "USER_WALLET_1", // Active trader
      "USER_WALLET_2"  // Regular user
    ];

    const walletFees = await getPriorityFeeEstimate(connection, userWallets, "Medium");
    console.log(`User wallet fees: ${walletFees} micro-lamports`);
    ```

    <Tip>
      **전문가 팁**: 보다 정확한 추정을 위해 송신자 및 수신자 지갑을 모두 포함하세요.
    </Tip>
  </Tab>

  <Tab title="토큰 계정">
    특정 토큰 계정은 토큰의 인기에 따라 다양한 패턴을 보일 수 있습니다.

    ```javascript theme={"system"}
    // Popular token accounts
    const tokenAccounts = [
      "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", // USDC mint
      "So11111111111111111111111111111111111111112",  // SOL mint
      "YOUR_TOKEN_ACCOUNT"                            // Your specific token account
    ];

    const tokenFees = await getPriorityFeeEstimate(connection, tokenAccounts, "Medium");
    ```
  </Tab>
</Tabs>

## 고급 구성 옵션

<AccordionGroup>
  <Accordion title="빈 슬롯 평가">
    `evaluateEmptySlotAsZero` 옵션은 계정 기반 추정에 특히 유용합니다:

    ```javascript theme={"system"}
    async function compareEmptySlotHandling(accountKeys) {
      const withEmptyAsZero = await fetch(connection.rpcEndpoint, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          jsonrpc: "2.0",
          id: "1",
          method: "getPriorityFeeEstimate",
          params: [{
            accountKeys: accountKeys,
            options: { 
              priorityLevel: "Medium",
              evaluateEmptySlotAsZero: true // Default: true
            }
          }]
        })
      });

      const withoutEmptyAsZero = await fetch(connection.rpcEndpoint, {
        method: "POST", 
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          jsonrpc: "2.0",
          id: "1",
          method: "getPriorityFeeEstimate", 
          params: [{
            accountKeys: accountKeys,
            options: {
              priorityLevel: "Medium",
              evaluateEmptySlotAsZero: false
            }
          }]
        })
      });
      
      const result1 = await withEmptyAsZero.json();
      const result2 = await withoutEmptyAsZero.json();
      
      console.log(`With empty as zero: ${result1.result.priorityFeeEstimate}`);
      console.log(`Without empty as zero: ${result2.result.priorityFeeEstimate}`);
    }
    ```

    <Note>
      `true` (기본값)일 때, 거래가 없는 슬롯은 제외되지 않고 0수수료로 처리됩니다. 이는 활동이 적은 계정에 대해서도 보다 균형 잡힌 추정을 제공합니다.
    </Note>
  </Accordion>

  <Accordion title="세부 정보 포함">
    각 계정의 수수료 패턴에 대한 세부 정보를 요청하세요:

    ```javascript theme={"system"}
    async function getDetailedFeeEstimate(connection, accountKeys) {
      const response = await fetch(connection.rpcEndpoint, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          jsonrpc: "2.0",
          id: "1",
          method: "getPriorityFeeEstimate",
          params: [{
            accountKeys: accountKeys,
            options: { 
              includeDetails: true,
              priorityLevel: "Medium"
            }
          }]
        })
      });
      
      const result = await response.json();
      console.log("Detailed fee analysis:", result.result);
      return result.result;
    }
    ```

    이는 각 계정에 대해 수수료가 어떻게 계산되었는지에 대한 추가 정보를 제공합니다.
  </Accordion>

  <Accordion title="사용자 정의 조회 기준 기간">
    수수료 추정을 위해 분석할 슬롯 수를 조정하세요:

    ```javascript theme={"system"}
    async function getCustomLookbackEstimate(accountKeys, lookbackSlots = 50) {
      const response = await fetch(connection.rpcEndpoint, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          jsonrpc: "2.0",
          id: "1",
          method: "getPriorityFeeEstimate",
          params: [{
            accountKeys: accountKeys,
            options: { 
              priorityLevel: "Medium",
              lookbackSlots: lookbackSlots  // 1-150, default is 150
            }
          }]
        })
      });
      
      const result = await response.json();
      return result.result.priorityFeeEstimate;
    }

    // Compare different lookback periods
    const shortTerm = await getCustomLookbackEstimate(accountKeys, 50);   // Recent trends
    const longTerm = await getCustomLookbackEstimate(accountKeys, 150);   // Historical average

    console.log(`Short-term estimate: ${shortTerm} micro-lamports`);
    console.log(`Long-term estimate: ${longTerm} micro-lamports`);
    ```

    <Tip>
      **작은 조회 기준**: 최근의 변동성 있는 데이터

      **큰 조회 기준**: 보다 안정적이고 역사적 맥락
    </Tip>
  </Accordion>
</AccordionGroup>

## 계정 선택을 위한 모범 사례

<CardGroup cols={1}>
  <Card title="쓰기 가능한 계정 포함" icon="pen-to-square">
    **우선 순위**: 수정될 계정에 집중

    ```javascript theme={"system"}
    const writableAccounts = [
      "YOUR_WALLET",        // Paying fees
      "TOKEN_ACCOUNT",      // Being modified  
      "RECIPIENT_ACCOUNT"   // Receiving tokens
    ];
    ```
  </Card>

  <Card title="키 프로그램 추가" icon="gear">
    **문맥**: 관련 프로그램 계정을 포함

    ```javascript theme={"system"}
    const programAccounts = [
      "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", // Token program
      "CUSTOM_PROGRAM_ID"                           // Your program
    ];
    ```
  </Card>
</CardGroup>

## 오류 처리 및 대체 방법

<CodeGroup>
  ```javascript Robust Implementation theme={"system"}
  class AccountBasedFeeEstimator {
    constructor(connection) {
      this.connection = connection;
      this.fallbackFee = 10000; // 10k micro-lamports fallback
    }

    async getEstimate(accountKeys, priorityLevel = "Medium") {
      try {
        // Primary attempt
        const estimate = await this.getPrimaryEstimate(accountKeys, priorityLevel);
        return estimate;
      } catch (error) {
        console.warn("Primary estimate failed:", error.message);
        
        // Fallback to different configuration
        try {
          return await this.getFallbackEstimate(accountKeys, priorityLevel);
        } catch (fallbackError) {
          console.warn("Fallback estimate failed:", fallbackError.message);
          return this.fallbackFee;
        }
      }
    }

    async getPrimaryEstimate(accountKeys, priorityLevel) {
      const response = await fetch(this.connection.rpcEndpoint, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          jsonrpc: "2.0",
          id: "1",
          method: "getPriorityFeeEstimate",
          params: [{
            accountKeys: accountKeys,
            options: { 
              priorityLevel: priorityLevel,
              recommended: true 
            }
          }]
        })
      });

      const result = await response.json();
      if (result.error) {
        throw new Error(result.error.message);
      }
      
      return result.result.priorityFeeEstimate;
    }

    async getFallbackEstimate(accountKeys, priorityLevel) {
      // Try with fewer accounts or different settings
      const coreAccounts = accountKeys.slice(0, 3); // Take first 3 accounts
      
      const response = await fetch(this.connection.rpcEndpoint, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          jsonrpc: "2.0",
          id: "1",
          method: "getPriorityFeeEstimate",
          params: [{
            accountKeys: coreAccounts,
            options: { 
              priorityLevel: "Medium", // Use medium as fallback
              evaluateEmptySlotAsZero: true
            }
          }]
        })
      });

      const result = await response.json();
      if (result.error) {
        throw new Error(result.error.message);
      }
      
      return result.result.priorityFeeEstimate;
    }
  }

  // Usage
  const estimator = new AccountBasedFeeEstimator(connection);
  const fee = await estimator.getEstimate(accountKeys, "High");
  ```

  ```javascript Simple Error Handling theme={"system"}
  async function safeGetPriorityFee(accountKeys, priorityLevel = "Medium") {
    try {
      return await getPriorityFeeEstimate(connection, accountKeys, priorityLevel);
    } catch (error) {
      console.warn(`Priority fee estimation failed: ${error.message}`);
      
      // Return reasonable fallback based on priority level
      const fallbacks = {
        "Low": 1000,
        "Medium": 5000,
        "High": 15000,
        "VeryHigh": 50000
      };
      
      return fallbacks[priorityLevel] || 5000;
    }
  }
  ```
</CodeGroup>

## 한계 및 고려 사항

<Warning>
  **계정 기반 방법의 한계:**

  1. **읽기 전용 계정에 대해 덜 정확함** - 알고리즘은 쓰기 가능한 계정에 중점을 둡니다
  2. **지시사항별 분석 없음** - 특정 작업을 고려할 수 없음
  3. **계정 활동 의존성** - 비활성 계정에 대해 덜 정확함
  4. **거래 크기 고려 없음** - 거래 복잡성을 고려하지 않음
</Warning>

<Note>
  **직렬화된 거래로의 업그레이드 시기:**

  * 가장 높은 정확성을 요구하는 생산 애플리케이션
  * 여러 지시사항이 포함된 복잡한 거래
  * 지시사항별 수수료 패턴이 중요한 경우
  * 성능이 중요한 애플리케이션
</Note>

## 관련 리소스

<CardGroup cols={2}>
  <Card title="직렬화된 거래" icon="file-code" href="/docs/ko/priority-fee/estimating-fees-using-serialized-transaction">
    전체 거래 직렬화를 사용한 보다 정확한 방법
  </Card>

  <Card title="API 참조" icon="book" href="/docs/ko/api-reference/priority-fee/getpriorityfeeestimate">
    전체 API 문서 및 매개변수
  </Card>
</CardGroup>
