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

# 요금

> MagicBlock의 요금 모델은 탈중앙화 클라우드 인프라를 기반으로 합니다. 목표는 개발자에게 **예측 가능한 컴퓨팅 비용** 을 제공하면서도, 우선 접근이나 전용 리소스가 필요한 기업에는 **유연성** 을 제공하는 것입니다.

export const VRFCostSimulator = () => {
  const [vrfpm, setVrf] = useState(5);
  const [isER, setIsER] = useState(false);
  const alternativeVrfFeePerTx = 0.002;
  const magicblockVrfFeePerTx = 0.0005;
  const magicblockVrfFeePerTxDiscounted = 0.0;
  const solPriceUSD = 200;
  const days = Array.from({
    length: 30
  }, (_, i) => i + 1);
  const width = 600;
  const height = 300;
  const padding = 50;
  const minutesPerDay = 24 * 60;
  const alternativeVrfCosts = days.map((_, i) => (i + 1) * vrfpm * minutesPerDay * alternativeVrfFeePerTx * solPriceUSD);
  const magicblockVrfCosts = days.map((_, i) => {
    const feePerTx = isER ? magicblockVrfFeePerTxDiscounted : magicblockVrfFeePerTx;
    return (i + 1) * vrfpm * minutesPerDay * feePerTx * solPriceUSD;
  });
  const totalAlternativeVrfCost = vrfpm * minutesPerDay * days.length;
  const maxCost = Math.max(...alternativeVrfCosts, ...magicblockVrfCosts);
  const xStep = (width - padding * 2) / (days.length - 1);
  const yScale = val => height - padding - val / maxCost * (height - padding * 2);
  const linePath = data => data.map((val, i) => `${i === 0 ? "M" : "L"}${padding + i * xStep},${yScale(val)}`).join(" ");
  const lastIndex = days.length - 1;
  return <div style={{
    maxWidth: width
  }}>

            {}
      <div style={{
    marginBottom: "1rem",
    display: "flex",
    alignItems: "center",
    gap: "0.5rem"
  }}>
        <span style={{
    fontSize: "14px"
  }}>Solana</span>
        <label style={{
    position: "relative",
    display: "inline-block",
    width: "36px",
    height: "20px",
    marginBottom: 0,
    verticalAlign: "middle"
  }}>
          <input type="checkbox" checked={isER} onChange={() => setIsER(!isER)} style={{
    opacity: 0,
    width: 0,
    height: 0
  }} />
          {}
          <span style={{
    position: "absolute",
    cursor: "pointer",
    top: 0,
    left: 0,
    right: 0,
    bottom: 0,
    backgroundColor: isER ? "#2545f6" : "#2545f6",
    transition: ".4s",
    borderRadius: "24px"
  }} />

          {}
          <span style={{
    position: "absolute",
    height: "18px",
    width: "18px",
    left: isER ? "calc(100% - 19px)" : "1px",
    top: 1,
    bottom: "3px",
    backgroundColor: "white",
    transition: ".4s",
    borderRadius: "50%"
  }} />
        </label>
        <span style={{
    fontSize: "14px"
  }}>With ER</span>
      </div>

      {}
      <div style={{
    display: "flex",
    flexDirection: "column",
    gap: "1rem",
    marginTop: "1rem",
    marginBottom: "1rem"
  }}>
        {}
        <label style={{
    fontSize: "14px"
  }}>
          VRF request(s) per minute: {vrfpm.toLocaleString()}
          <input type="range" min="1" max="100" step="1" value={vrfpm} onChange={e => setVrf(Number(e.target.value))} style={{
    width: "100%"
  }} />
        </label>
      </div>

      {}
      <div style={{
    marginTop: "1rem",
    lineHeight: 1.5,
    fontSize: "14px"
  }}>
        <p>
          <strong>{(totalAlternativeVrfCost / 1_000_000).toLocaleString(undefined, {
    minimumFractionDigits: 0,
    maximumFractionDigits: 2
  })}M randomness provisions</strong> over 30 days.
            </p>

          <p style={{
    marginTop: "0.5rem"
  }}>
            {" "}You save{" "}
            <span style={{
    fontWeight: "bold",
    color: "#aa00ff"
  }}>
              ${(alternativeVrfCosts[lastIndex] - magicblockVrfCosts[lastIndex]).toLocaleString(undefined, {
    minimumFractionDigits: 0,
    maximumFractionDigits: 2
  })}{', or '}{(alternativeVrfCosts[lastIndex] / magicblockVrfCosts[lastIndex]).toLocaleString(undefined, {
    minimumFractionDigits: 0,
    maximumFractionDigits: 2
  })}x cheaper
            </span>
            .
          </p>

      </div>

      {}
      <div style={{
    width: "100%",
    maxWidth: "600px",
    margin: "0 auto",
    paddingLeft: "40px",
    paddingRight: "10px"
  }}>
        <svg width={width} height={height} viewBox={`0 0 ${width} ${height}`} width="100%" height="auto" preserveAspectRatio="xMidYMid meet" style={{
    overflow: "visible"
  }}>
          {Array.from({
    length: 5
  }, (_, i) => {
    const y = padding + i * ((height - 2 * padding) / 4);
    const price = ((4 - i) / 4 * maxCost).toFixed(0);
    return <g key={i}>
                <line x1={padding} y1={y} x2={width - padding} y2={y} stroke="#eee" />
                <text x={padding - 5} y={y + 4} textAnchor="end" fontSize="12" fill="#555" fontWeight="bold">
                  ${Number(price).toLocaleString()}
                </text>
              </g>;
  })}

          {days.map((day, i) => {
    if ((i + 1) % 10 === 0) {
      const x = padding + i * xStep;
      return <g key={i}>
                  <line x1={x} y1={padding} x2={x} y2={height - padding} stroke="#eee" />
                  <text x={x} y={height - padding + 15} textAnchor="middle" fontSize="12" fill="#555" fontWeight="bold">
                    {day}
                  </text>
                  <circle cx={x} cy={yScale(alternativeVrfCosts[i])} r={3} fill="#59e09d" />
                  <text x={x} y={yScale(alternativeVrfCosts[i]) - 8} fontSize="14" fill="#59e09d" textAnchor="middle" fontWeight="bold">
                    ${alternativeVrfCosts[i].toLocaleString()}
                  </text>
                  <circle cx={x} cy={yScale(magicblockVrfCosts[i])} r={3} fill="#aa00ff" />
                  <text x={x} y={yScale(magicblockVrfCosts[i]) - 8} fontSize="14" fill="#aa00ff" textAnchor="middle" fontWeight="bold">
                    ${magicblockVrfCosts[i].toLocaleString()}
                  </text>
                </g>;
    }
    return null;
  })}

          <line x1={padding} y1={padding} x2={padding} y2={height - padding} stroke="#aaa" />
          <line x1={padding} y1={height - padding} x2={width - padding} y2={height - padding} stroke="#aaa" />

          {}
          <text x={width / 2} y={height - padding + 40} fontSize="12" fill="#555" textAnchor="middle">
            Day
          </text>
          <path d={linePath(alternativeVrfCosts)} stroke="#59e09d" strokeWidth="2" fill="none" />
          <path d={linePath(magicblockVrfCosts)} stroke="#aa00ff" strokeWidth="2" fill="none" />
        </svg>
      </div>

      {}
      <div style={{
    display: "flex",
    justifyContent: "space-between",
    alignItems: "center",
    flexWrap: "wrap",
    gap: "0.5rem",
    marginBottom: "1rem"
  }}>
        {}
        <div style={{
    display: "flex",
    gap: "0rem 1rem",
    flexWrap: "wrap"
  }}>
          <div style={{
    display: "flex",
    alignItems: "center",
    gap: "0.5rem"
  }}>
            <div style={{
    width: 12,
    height: 12,
    backgroundColor: "#59e09d"
  }} />
            <span style={{
    fontSize: "14px"
  }}>
              Other VRFs
            </span>
          </div>
          <div style={{
    display: "flex",
    alignItems: "center",
    gap: "0.5rem"
  }}>
            <div style={{
    width: 12,
    height: 12,
    backgroundColor: "#aa00ff"
  }} />
            <span style={{
    fontSize: "14px"
  }}>MagicBlock VRF</span>
          </div>
        </div>

        {}
        <div style={{
    display: "flex",
    alignItems: "center"
  }}>
          <span style={{
    fontSize: "14px"
  }}>Price: {solPriceUSD} USD/SOL</span>
        </div>
      </div>

    </div>;
};

export const ERCostSimulator = () => {
  const [tps, setTps] = useState(10000);
  const [cpm, setCpm] = useState(30);
  const [dpm, setDpm] = useState(1);
  const [isDedicated, setIsDedicated] = useState(false);
  const solanaFeePerTx = 0.000005;
  const erFeePerCommit = 0.0001;
  const erFeePerSession = 0.0003;
  const dedicatedBaseFee = 0.00000005;
  const solPriceUSD = 200;
  const days = Array.from({
    length: 30
  }, (_, i) => i + 1);
  const width = 600;
  const height = 300;
  const padding = 50;
  const secondsPerDay = 24 * 60 * 60;
  const commitFeesPerDay = cpm / 60 * secondsPerDay * erFeePerCommit * solPriceUSD;
  const sessionFeesPerDay = dpm / 60 * secondsPerDay * erFeePerSession * solPriceUSD;
  const solanaCosts = days.map((_, i) => (i + 1) * tps * secondsPerDay * solanaFeePerTx * solPriceUSD);
  const erCosts = days.map((_, i) => {
    const base = (i + 1) * (commitFeesPerDay + sessionFeesPerDay);
    const extra = isDedicated ? (i + 1) * tps * secondsPerDay * dedicatedBaseFee * solPriceUSD : 0;
    return base + extra;
  });
  const totalSolanaTx = tps * secondsPerDay * days.length;
  const maxCost = Math.max(...solanaCosts, ...erCosts);
  const xStep = (width - padding * 2) / (days.length - 1);
  const yScale = val => height - padding - val / maxCost * (height - padding * 2);
  const linePath = data => data.map((val, i) => `${i === 0 ? "M" : "L"}${padding + i * xStep},${yScale(val)}`).join(" ");
  const lastIndex = days.length - 1;
  const handleTpsChange = newTps => {
    setTps(newTps);
    const maxCpm = newTps * 20;
    if (cpm > maxCpm) {
      setCpm(maxCpm);
    }
    const maxDpm = newTps * 20;
    if (dpm > maxDpm) {
      setDpm(maxDpm);
    }
  };
  const handleCpmChange = newCpm => {
    const requiredTps = Math.ceil(newCpm / 2);
    if (requiredTps > tps) setTps(requiredTps);
    setCpm(newCpm);
  };
  const handleDpmChange = newDpm => {
    const requiredTps = Math.ceil(newDpm / 2);
    if (requiredTps > tps) setTps(requiredTps);
    setDpm(newDpm);
  };
  return <div style={{
    maxWidth: width
  }}>

      {}
      <div style={{
    marginBottom: "1rem",
    display: "flex",
    alignItems: "center",
    gap: "0.5rem"
  }}>
        <span style={{
    fontSize: "14px"
  }}>Public Node</span>
        <label style={{
    position: "relative",
    display: "inline-block",
    width: "36px",
    height: "20px",
    marginBottom: 0,
    verticalAlign: "middle"
  }}>
          <input type="checkbox" checked={isDedicated} onChange={() => setIsDedicated(!isDedicated)} style={{
    opacity: 0,
    width: 0,
    height: 0
  }} />
          {}
          <span style={{
    position: "absolute",
    cursor: "pointer",
    top: 0,
    left: 0,
    right: 0,
    bottom: 0,
    backgroundColor: isDedicated ? "#2545f6" : "#2545f6",
    transition: ".4s",
    borderRadius: "24px"
  }} />

          {}
          <span style={{
    position: "absolute",
    height: "18px",
    width: "18px",
    left: isDedicated ? "calc(100% - 19px)" : "1px",
    top: 1,
    bottom: "3px",
    backgroundColor: "white",
    transition: ".4s",
    borderRadius: "50%"
  }} />
        </label>
        <span style={{
    fontSize: "14px"
  }}>Dedicated Node</span>
      </div>

      {}
      <div style={{
    display: "flex",
    flexDirection: "column",
    gap: "1rem",
    marginTop: "1rem",
    marginBottom: "1rem"
  }}>
        {}
        <label style={{
    fontSize: "14px"
  }}>
          Transaction(s) per second: {tps.toLocaleString()}
          <input type="range" min="1" max="50000" step="1" value={tps} onChange={e => handleTpsChange(Number(e.target.value))} style={{
    width: "100%"
  }} />
        </label>

        {}
        <div style={{
    display: "flex",
    gap: "1rem"
  }}>
          <label style={{
    flex: 1,
    fontSize: "14px"
  }}>
            Commit(s) per minute: {cpm}
            <input type="range" min="1" max="100" step="1" value={cpm} onChange={e => handleCpmChange(Number(e.target.value))} style={{
    width: "100%"
  }} />
          </label>
          <label style={{
    flex: 1,
    fontSize: "14px"
  }}>
            Delegation Session(s) per minute: {dpm}
            <input type="range" min="1" max="100" step="1" value={dpm} onChange={e => handleDpmChange(Number(e.target.value))} style={{
    width: "100%"
  }} />
          </label>
        </div>
      </div>

      {}
      <div style={{
    marginTop: "1rem",
    lineHeight: 1.5,
    fontSize: "14px"
  }}>
        <p>
          <strong>{(totalSolanaTx / 1_000_000).toLocaleString(undefined, {
    minimumFractionDigits: 0,
    maximumFractionDigits: 2
  })}M transactions</strong> over 30 days.
            </p>

        {erCosts[lastIndex] < solanaCosts[lastIndex] ? <p style={{
    marginTop: "0.5rem"
  }}>
            {" "}You save{" "}
            <span style={{
    fontWeight: "bold",
    color: "#aa00ff"
  }}>
              ${(solanaCosts[lastIndex] - erCosts[lastIndex]).toLocaleString(undefined, {
    minimumFractionDigits: 0,
    maximumFractionDigits: 2
  })}{', or '}{(solanaCosts[lastIndex] / erCosts[lastIndex]).toLocaleString(undefined, {
    minimumFractionDigits: 0,
    maximumFractionDigits: 2
  })}x cheaper
            </span>
            .
          </p> : <p style={{
    marginTop: "0.5rem"
  }}>
            {" "}Try <strong>lowering commits and delegations</strong> to get a cost advantage.
          </p>}
      </div>

      {}
      <div style={{
    width: "100%",
    maxWidth: "600px",
    margin: "0 auto",
    paddingLeft: "40px",
    paddingRight: "10px"
  }}>
        <svg width={width} height={height} viewBox={`0 0 ${width} ${height}`} width="100%" height="auto" preserveAspectRatio="xMidYMid meet" style={{
    overflow: "visible"
  }}>
          {Array.from({
    length: 5
  }, (_, i) => {
    const y = padding + i * ((height - 2 * padding) / 4);
    const price = ((4 - i) / 4 * maxCost).toFixed(0);
    return <g key={i}>
                <line x1={padding} y1={y} x2={width - padding} y2={y} stroke="#eee" />
                <text x={padding - 5} y={y + 4} textAnchor="end" fontSize="12" fill="#555" fontWeight="bold">
                  ${Number(price).toLocaleString()}
                </text>
              </g>;
  })}

          {days.map((day, i) => {
    if ((i + 1) % 10 === 0) {
      const x = padding + i * xStep;
      return <g key={i}>
                  <line x1={x} y1={padding} x2={x} y2={height - padding} stroke="#eee" />
                  <text x={x} y={height - padding + 15} textAnchor="middle" fontSize="12" fill="#555" fontWeight="bold">
                    {day}
                  </text>
                  <circle cx={x} cy={yScale(solanaCosts[i])} r={3} fill="#59e09d" />
                  <text x={x} y={yScale(solanaCosts[i]) - 8} fontSize="14" fill="#59e09d" textAnchor="middle" fontWeight="bold">
                    ${solanaCosts[i].toLocaleString()}
                  </text>
                  <circle cx={x} cy={yScale(erCosts[i])} r={3} fill="#aa00ff" />
                  <text x={x} y={yScale(erCosts[i]) - 8} fontSize="14" fill="#aa00ff" textAnchor="middle" fontWeight="bold">
                    ${erCosts[i].toLocaleString()}
                  </text>
                </g>;
    }
    return null;
  })}

          <line x1={padding} y1={padding} x2={padding} y2={height - padding} stroke="#aaa" />
          <line x1={padding} y1={height - padding} x2={width - padding} y2={height - padding} stroke="#aaa" />

          {}
          <text x={width / 2} y={height - padding + 40} fontSize="12" fill="#555" textAnchor="middle">
            Day
          </text>
          <path d={linePath(solanaCosts)} stroke="#59e09d" strokeWidth="2" fill="none" />
          <path d={linePath(erCosts)} stroke="#aa00ff" strokeWidth="2" fill="none" />
        </svg>
      </div>

      {}
      <div style={{
    display: "flex",
    justifyContent: "space-between",
    alignItems: "center",
    flexWrap: "wrap",
    gap: "0.5rem",
    marginBottom: "1rem"
  }}>
        {}
        <div style={{
    display: "flex",
    gap: "0rem 1rem",
    flexWrap: "wrap"
  }}>
          <div style={{
    display: "flex",
    alignItems: "center",
    gap: "0.5rem"
  }}>
            <div style={{
    width: 12,
    height: 12,
    backgroundColor: "#59e09d"
  }} />
            <span style={{
    fontSize: "14px"
  }}>Solana Only</span>
          </div>
          <div style={{
    display: "flex",
    alignItems: "center",
    gap: "0.5rem"
  }}>
            <div style={{
    width: 12,
    height: 12,
    backgroundColor: "#aa00ff"
  }} />
            <span style={{
    fontSize: "14px"
  }}>MagicBlock (ER Sessions + Commits)</span>
          </div>
        </div>

        {}
        <div style={{
    display: "flex",
    alignItems: "center"
  }}>
          <span style={{
    fontSize: "14px"
  }}>Price: {solPriceUSD} USD/SOL</span>
        </div>
      </div>

    </div>;
};

***

## 제품 요금

<div id="ephemeral-rollup" />

<Tabs>
  <Tab title="Ephemeral Rollup">
    **Public nodes** 는 무료 트랜잭션과 낮은 진입 장벽으로 MagicBlock 구축을 쉽게 시작할 수 있게 해줍니다. 수수료는 세션을 닫거나 데이터를 Solana로 커밋할 때만 부과됩니다.

    <table style={{ width: "100%", tableLayout: "fixed" }}>
      <thead>
        <tr>
          <th>수수료 유형</th>
          <th>금액 (SOL)</th>
          <th>설명</th>
        </tr>
      </thead>

      <tbody>
        <tr>
          <td>기본 수수료</td>
          <td>0</td>
          <td>거래당 (Tx)</td>
        </tr>

        <tr>
          <td>세션 수수료</td>
          <td>0.0003</td>
          <td>ER 세션당 (undelegation 시)</td>
        </tr>

        <tr>
          <td>커밋 수수료</td>
          <td>0.0001</td>
          <td>Solana 커밋당</td>
        </tr>
      </tbody>
    </table>

    **Dedicated nodes** 는 기업과 대규모 팀에 적합합니다. 전용 인프라를 통해 높은 신뢰성, 예측 가능한 비용, 그리고 MEV 보호를 제공합니다.

    [ER 더 알아보기 →](/ko/pages/ephemeral-rollups-ers/how-to-guide/quickstart)

    ### ER 비용 시뮬레이터: 30일

    <ERCostSimulator />
  </Tab>

  <Tab title="Private Ephemeral Rollup">
    Private Ephemeral Rollup은 스마트 컨트랙트가 정의한 커스텀 프라이빗 연산을 지원합니다.

    커스텀 PER 로직에는 표준 ER 요금이 적용됩니다. [Ephemeral Rollup 요금 보기 →](#ephemeral-rollup)
  </Tab>

  <Tab title="VRF">
    VRF 서비스는 **온체인에서 증명 가능한 공정한 랜덤성** 을 제공합니다. 수수료에는 증명 생성과 온체인 게시 비용이 포함됩니다.

    > ⚠️ 참고: 이 비용에는 랜덤성을 요청하는 트랜잭션 자체는 포함되지 않습니다. ER에서는 무료이며, Solana에서는 priority fee 설정에 따라 달라질 수 있습니다.

    <table style={{ width: "100%", tableLayout: "fixed" }}>
      <thead>
        <tr>
          <th>VRF 유형</th>
          <th>금액 (SOL)</th>
          <th>설명</th>
        </tr>
      </thead>

      <tbody>
        <tr>
          <td>ER (\<50 ms)</td>
          <td>무료</td>
          <td>랜덤성 요청당</td>
        </tr>

        <tr>
          <td>Solana (\<500 ms)</td>
          <td>0.0008</td>
          <td>랜덤성 요청당</td>
        </tr>

        <tr>
          <td>Solana (1/2 seconds)</td>
          <td>0.0005</td>
          <td>랜덤성 요청당</td>
        </tr>
      </tbody>
    </table>

    ### VRF 비용 시뮬레이터: 30일

    <VRFCostSimulator />

    [Solana VRF 더 알아보기 →](/ko/pages/verifiable-randomness-functions-vrfs/introduction/solana-vrf)
  </Tab>

  <Tab title="Private Payments API">
    Private Payment API를 사용하면 Solana Mainnet 및/또는 Private ER에서 프라이빗 스테이블코인 전송을 간단하게 처리할 수 있습니다.

    <table style={{ width: "100%", tableLayout: "fixed" }}>
      <thead>
        <tr>
          <th>결제 유형</th>
          <th>고정 수수료 (SOL)</th>
          <th>변동 수수료</th>
        </tr>
      </thead>

      <tbody>
        <tr>
          <td>Solana Mainnet</td>
          <td>0.002</td>
          <td>0.1%</td>
        </tr>
      </tbody>
    </table>

    <CardGroup cols={1}>
      <Card title="API 레퍼런스" icon="book" href="/ko/pages/private-ephemeral-rollups-pers/api-reference/per/introduction" iconType="duotone">
        Private Payments API 엔드포인트 살펴보기
      </Card>
    </CardGroup>
  </Tab>
</Tabs>

***

## 고객 지원

**직접 노드를 운영** 하기 위한 지원이 필요하면 아래로 문의해 주세요.

📧 [development@magicblock.xyz](mailto:development@magicblock.xyz)

<CardGroup cols={2}>
  <Card title="에페메럴 롤업(ER)" icon="bolt" href="/ko/pages/ephemeral-rollups-ers/how-to-guide/quickstart" iconType="duotone">
    Solana에서 실시간 무수수료 트랜잭션을 안전하게 실행하세요.
  </Card>

  <Card title="프라이빗 에페메럴 롤업(PER)" icon="shield-check" href="/ko/pages/private-ephemeral-rollups-pers/how-to-guide/quickstart" iconType="duotone">
    규정 준수를 유지하면서 민감한 데이터 보호 — Ephemeral Rollups 위에 구축되었습니다.
  </Card>

  <Card title="프라이빗 결제 API" icon="bag-shopping-plus" href="/ko/pages/private-ephemeral-rollups-pers/api-reference/per/introduction" iconType="duotone">
    몇 초 만에 앱에 온체인 비공개 송금을 통합하세요 — 기본적으로 규정 준수.
  </Card>

  <Card title="Solana VRF" icon="dice" href="/ko/pages/verifiable-randomness-functions-vrfs/introduction/solana-vrf" iconType="duotone">
    게임, 추첨, 실시간 앱에 증명 가능하게 공정한 온체인 랜덤니스를 추가하세요.
  </Card>

  <Card title="가격 오라클" icon="waveform" href="/ko/pages/tools/oracle/introduction" iconType="duotone">
    트레이딩과 DeFi를 위한 저지연 온체인 가격 피드에 접근하세요.
  </Card>
</CardGroup>
