---
title: "가스 최적화 트랜잭션으로 Smurfs' Society 확장하기"
description: "Smurfs' Society는 Alchemy의 가스 최적화 트랜잭션을 사용해 가스 가격 변동성이 높은 시기에도 Polygon에서 트랜잭션 채굴을 보장했습니다."
---

## Alchemy와 협업하여 온체인 트랜잭션 확장하기

**By** **The Smurfs' Society Team**

[The Smurfs' Society](https://thesmurfssociety.com/)는 스머프의 공식 web3 프로젝트입니다. 이 프로젝트는 초대 전용의 완전한 온체인 게임화 플랫폼으로, 2022년 12월에 출시되어 한 달도 안 되어 30,000개 이상의 지갑 연결과 150만 건의 온체인 전송을 기록했으며, DappRadar 기준 가장 많이 사용되는 앱 TOP 100에 들었습니다.

이 글에서는 CTO 겸 공동 창업자가 대량의 온체인 트랜잭션을 확장하는 데 따르는 기술적 과제와, 그들의 팀이 [Transact API suite](https://www.alchemy.com/transact)를 사용하는 수만 명의 플레이어에게 매끄럽고 일관된 사용자 경험을 제공하기 위해 Alchemy와 어떻게 협업하고 있는지를 다룹니다.

## **블록체인 맥락에서 '확장성'이라는 개념의 상대성**

저를 포함해 대부분의 사람들은 분당 100건의 트랜잭션을 "규모" 문제나 볼륨 문제로 여기지 않을 것입니다. 과거에 저는 TB 단위의 데이터, 낮은 지연시간, 높은 처리량을 갖춘 멀티 데이터센터 환경에서 Cassandra 클러스터를 최적화하기 위해 여러 회사와 협업한 경험이 있습니다. 그때는 블록체인 인프라를 다룰 때 이 정도로 낮은 트랜잭션 볼륨이 달성하기 어려울 수 있다는 걸 전혀 생각하지 못했습니다.

이 과제는 두 가지로 나뉩니다:

1. 트랜잭션을 물리적으로 실행할 수 있어야 합니다
1. [트랜잭션의 정확성을 보장](https://alchemy.com/blog/data-accuracy)해야 하며, 더 정확히는 그 최종 데이터 일관성과 정확도를 보장해야 합니다.

첫 번째 과제를 해결하는 것은 auto-scaling 기능을 갖춘 k8s에 배포된 다른 플랫폼 클러스터의 크기를 조정하는 것과 크게 다르지 않습니다. 한 가지 차이점은 부하를 분산시키는 방식인데, StateFulSet 안에서 HD 지갑을 사용해 각 pod가 직접 관리할 자신만의 지갑을 갖도록 했습니다. 그리고 블록체인은 트랜잭션이 (특정 순서 지갑에 대해) 순서대로 실행되도록 요구한다는 점을 기억해야 합니다.

두 번째 과제의 경우, [mempool에 들어간 트랜잭션](https://www.alchemy.com/overviews/transaction-propagation)이 채굴되지 않는 상황(gas)을 생각해 보세요.

**우리의 선택지는 다음과 같습니다:**

1. 네트워크가 잠잠해지기를 기다려서(가능하다면) 트랜잭션이 그냥 채굴되게 둡니다
1. 새로운 트랜잭션으로 덮어쓰고(nonce를 강제로) gas 설정을 높입니다
1. 단순히 다른 지갑을 사용합니다

분명히 우리의 경우, 1번도 3번도 선택할 수 없었습니다. 그래서 2번이 유일한 선택지였고, 이는 그 나름의 복잡성을 만들어냈습니다.

다음은 Alchemy와 협업하여 [Reinforced Transactions](https://www.alchemy.com/docs/reference/mev-protection)에서 [Gas Optimized Transactions](https://www.alchemy.com/docs/reference/mev-protection)로 전환해온 경험을 간략히 살펴본 것입니다.

### **정확성을 최대화하면서 하루 20,000건의 트랜잭션 채굴하기**

블록체인을 핵심 기반으로 많이 사용하는 애플리케이션이나 게임을 확장하는 것이 왜 이렇게 어려울까요?

- 단일 블록에서 채굴될 수 있는 트랜잭션 수에 의해 제한되는 걸까요?
- 네트워크 전체의 용량에 의해 제한되는 걸까요?
- 네트워크 혼잡과 특정 일중 사용 패턴에 의해 제한되는 걸까요?
- 블록체인에서 트랜잭션이 실행되는 방식에 의해 제한되는 걸까요?
- gas 가격 변동성에 의해 제한되는 걸까요?

몇 주간의 운영과 모든 컨트롤을 반복해서 개선한 끝에, 이제 게임이 최적의 조건에서 운영될 수 있는 플랫폼을 갖추게 되었습니다.

여기까지 오기 위해 극복해야 했던 모든 장애물을 설명하기 전에, 게임의 동작 방식을 소개하고, 블록체인 관점에서 자동화하는 작업들과 그 과제에 대한 개요를 드리겠습니다. 그런 다음 Alchemy와 협업하여 문제를 어떻게 해결했는지 설명하겠습니다.

## **스머프 온체인 게임은 어떻게 작동하는가?**

현재 이 게임은 일반적인 "waitlist" 개념을 뒤엎은 형태로, 플레이어는 재료를 섞어 물약을 만드는 레시피를 찾으려 시도하며, 그중 일부는 crystal(할인이 적용된 민팅 보장 접근 권한)에 대한 접근을 제공합니다.

게임에서 사용하는 모든 자산은 NFT로 표현됩니다. 이는 우리가 대체 가능하고 소모 가능하다고 간주하는 아이템(예: 재료, 물약, 파란 점토, 조각상 등)을 위한 ERC-1155 토큰이거나, 대체 불가능한 아이템(예: crystal)을 위한 ERC-721 토큰입니다.

### 스머프 게임의 상호작용

아래는 게임이 작동하기 위해 저희 플랫폼이 Polygon 네트워크와 주고받는 상호작용입니다:

1. **재료로 구성된 드롭 박스 수령** - 플레이어는 매일 3개의 재료가 든 박스를 받을 수 있습니다
1. **조각상 민팅(게임의 핵심 구성 요소)** - 모든 플레이어는 게임의 액션을 완료하려면 하나를 보유해야 합니다. 이 조각상은 플레이어가 게임에 로그인할 때 무료로 드랍됩니다. 게임이 진행되면서 조각상의 역할이 공개될 예정입니다.
1. **점토 소각** - 레시피를 시도한 플레이어가 실패하면, 파란 점토가 소각됩니다(x1)

한편 플레이어는 Polygon 네트워크에서 단일 작업을 수행합니다:

1. **레시피 조합** - 플레이어는 3개의 재료를 섞어 레시피를 만들도록 요청받습니다(이 경우 gas 수수료는 플레이어가 지불합니다).

<ImageBlock
  src="https://media.alchemy.com/1704556400-player-mixing-a-recipe.png"
  alt="플레이어가 레시피에 세 가지 재료를 섞는 The Smurfs' Society 게임 화면"
  width={654}
  height={319}
  caption="그림 1: 레시피를 만드는 플레이어"
/>

처음 두 기능의 경우, 시도한 트랜잭션이 오랫동안 채굴되지 않더라도 게임에 실질적인 영향 없이 완전히 비동기적으로 처리할 수 있습니다. 물론 경험 측면에서는 이 시간이 최대한 짧기를 바랍니다.

점토를 소각하는 것은 좀 더 까다로우며, 구현 방식의 선택은 주로 게임 자체에 의해 결정되었습니다. 플레이어가 실제로 레시피를 제안할 때, 아래 그림과 같이 3시간의 기한과 함께 섞고자 하는 모든 재료를 담은 EIP-712 구조체에 서명하는 방식으로 진행합니다.

<ImageBlock
  src="https://media.alchemy.com/1704556456-player-signs-eip-712-to-propose-a-recipe.png"
  alt="그림 2: 플레이어가 레시피를 제안하기 위해 EIP-712에 서명"
  width={354}
  height={499}
  caption="그림 2: 플레이어가 레시피를 제안하기 위해 EIP-712에 서명"
/>

이 서명은 해당 조합에 맞는 레시피가 없을 경우 소각을 승인하는 용도로 사용됩니다. 그리고 관련된 트랜잭션 수수료를 저희가 부담하기 위해, 이 burnClay 트랜잭션을 플레이어를 대신해 실행합니다.

**이 시점부터 저희는 여러 상태를 관리해야 합니다:**

1. 트랜잭션이 전송 중 - 오프체인에 저장됨 -\> 온체인으로 이동 중. 조정(reconciliation)에 사용됩니다.
1. 트랜잭션이 mempool에 있으며 채굴을 기다리는 중 - 이 전환 상태에서는 사용자가 현재 진행 중이라고 우리가 믿는 것과 실제로 처리되고 있는 것을 조정해야 하며, 시간이 얼마나 걸릴지 보장이 없습니다
1. 트랜잭션이 채굴됨 - 화면에 표시되는 파란 점토 수량이 이제 정확합니다. 이 상태는 최종 상태이며 별다른 과제를 나타내지 않습니다 - 블록체인이 신뢰의 근거(source of truth)입니다
1. 트랜잭션이 채굴되었지만 실패(aborted)로 간주됨

### 스머프 팀이 Polygon을 선택한 이유

이상적으로는 운영의 정확성과 게임 경험을 보장하기 위해 모든 상태가 1분 이내에 수렴하기를 기대합니다. 이 사용 사례를 위해 저희는 게임화 단계에서 Polygon 네트워크를 사용하기로 결정했습니다. 아래는 [Polygon을 네트워크로 선택](https://www.alchemy.com/polygon)하는 데 도움이 된 가장 중요한 기준 몇 가지입니다:

- 반응성을 위한 빠른 최종화 시간
- 운영 비용 관리를 위한 낮은 트랜잭션 수수료
- 장기적인 비전을 위한 Ethereum 상호운용성

**우리의 과제: 일관성을 최대화하면서 하루 20,000건의 트랜잭션 채굴하기**

<VideoCta
  title="Alchemy 대시보드 실제 작동 화면 보기"
  description="30분 안내 walkthrough: 대시보드의 모든 도구를 실시간으로 시연"
  ctaHref="/resources/dashboard-demo"
  thumbnail={{
    src: "https://media.alchemy.com/alchemy-dashboard-demo-thumbnail.png",
    alt: "Alchemy Dashboard Demo",
  }}
/>


## **Polygon gas 변동성의 영향을 줄이면서 높은 성공률 달성하기**

Polygon은 혼잡을 겪을 수 있으며, 이는 앞서 설명한 여러 작업에 지연을 추가함으로써 저희에게 직접적인 영향을 줄 수 있습니다. 이를 해결하기 위해 취할 수 있는 기본적인 조치들이 있습니다:

1. **샤딩(Sharding)** - 블록체인과 상호작용하는 여러 지갑을 두는 것. (DB의 connection pool과 유사하게) 운영 가능한 지갑이 있는 한, 트랜잭션은 처리될 수 있습니다.
1. **가격 상향(Over pricing)** - 트랜잭션이 제때 처리되도록 보장하기 위해, [priority fees(EIP-1559)](https://www.alchemy.com/docs/how-to-send-transactions-on-ethereum)에 대한 인센티브를 높일 수 있습니다.

초기 설정은 [**Reinforced transaction**](https://www.alchemy.com/docs/reference/mev-protection) 솔루션을 사용하고 gas 수수료 시장보다 가격을 높게 설정해 트랜잭션 최종화 시간을 최적화하는 방식이었습니다.

<ImageBlock
  src="https://media.alchemy.com/1704556545-example-of-extreme-gas-prices-on-polygon.png"
  alt="Polygon에서 발생한 극단적인 가스 비용 예시"
  width={558}
  height={199}
  caption="Polygon에서 발생한 극단적인 가스 비용 예시"
/>

<ImageBlock
  src="https://media.alchemy.com/1704556581-example-of-dramatic-gas-price-volatility-on-polygon.png"
  alt="Polygon에서 발생한 급격한 가스 비용 변동 예시"
  width={546}
  height={191}
  caption="Polygon에서 발생한 급격한 가스 비용 변동 예시"
/>

두 스크린샷은 몇 분 간격(약 5분)으로 촬영되었습니다. 매우 짧은 시간 안에 gas가 크게 변동하는 것을 볼 수 있는데, 이는 저희에게 직접적인 영향을 미칩니다. 시장 변동성에 의한 gas 가격의 급격한 상승이 발생하면, 저희 트랜잭션이 그 자리에 멈춰 지갑 중 하나를 막아버리게 됩니다!

### 변동성 있는 gas 시기에 Polygon 트랜잭션을 최적화하는 방법

저희는 다음과 같은 방식으로 변동성 있는 gas 시기 동안 트랜잭션을 최적화하는 작업을 시작했습니다:

- 애플리케이션에 복원력(resiliency)을 추가하고, 더 오랜 기간 동안 트랜잭션의 상태를 더 잘 추적함
- 징후가 나타날 때 추적하고 알림을 보냄 - 메시지가 처리되는 시간을 추적하는 방식으로 이를 수행했습니다

**미시적 관점에서 모든 것이 정상일 때는 이렇게 보입니다:**

<ImageBlock
  src="https://media.alchemy.com/1704556646-processing-time-that-varies-but-below-20-second-mark.png"
  alt="처리 시간이 변동하지만 20초 미만으로 유지되는 정상적인 프로세스"
  width={1600}
  height={432}
  caption="처리 시간이 변동하지만 20초 미만으로 유지되는 정상적인 프로세스"
/>

**그리고 거시적 관점에서, 상황이 더 흥미로워지면 이렇게 보입니다:**

<ImageBlock
  src="https://media.alchemy.com/1704556694-messages-that-are-older-than-200-seconds.png"
  alt="200초보다 오래된 메시지 예시"
  width={1600}
  height={436}
  caption="200초보다 오래된 메시지 예시"
/>

간혹 일부 메시지는 거의 200초 가까이 지체되기도 했습니다(위 예시는 저희가 겪었던 가장 힘든 날 중 하나입니다). 이 시간 격차가 너무 커지면 플레이어들이 눈치채기 시작하는데, 가장 눈에 띄는 신호는 파란 점토 카운터가 줄어들지 않는 것입니다.

가장 안 좋았던 날, Polygon 업그레이드 이후 일부 트랜잭션이 채굴되지 않아 30분간 게임을 중단해야 했습니다.

그 이후로 저희는 이 문제를 해결하기 위해 Alchemy의 새로운 서비스 중 하나를 활용하며 적극적으로 협업하고 있으며, [**Gas Optimized transactions**](https://www.alchemy.com/docs/reference/mev-protection)의 베타에 참여하기로 결정했습니다.

**Gas optimized transactions의 핵심 목표는 예측할 수 없는 이상치(outlier)를 관리하는 것입니다.**

gas를 결정하는 어떤 하드코딩된 로직으로 단일 트랜잭션에 서명하는 대신, 서로 다른 gas 가격 조건을 가진 5개 또는 10개의 트랜잭션에 서명하고, nonce 가격을 자동으로 상향 조정하는 일은 Alchemy에게 맡길 수 있다고 상상해 보세요!

저희의 경우, 다음과 같은 상향 조정(escalation) 정책을 채택하기로 결정했습니다: 1.25, 1.5, 1.75, 2, 2.25, 2.5

지금까지 이 방식으로 좋은 결과를 얻고 있습니다.

저희는 여러 최적화를 성공적으로 실행했으며, 시스템에서 실제로 작동하는 것을 확인했습니다. Alchemy 팀과의 협업을 계속 이어가기를 기대하며, 문제가 터졌던 날의 신속한 대응과 빠른 처리 속도에 대해 개인적으로 감사를 전하고 싶습니다. 결국 중요한 건 올바른 파트너를 선택하는 것이니까요!

Smurfily,

The Smurfs' Society team.
