본문으로 건너뛰기
이 페이지는 영문에서 기계 번역되었으므로 오역이나 어색한 표현이 있을 수 있습니다. 따라서 정확한 정보는 영어 원문을 참조하시기 바랍니다. 또한 잦은 업데이트로 인해 일부 콘텐츠는 영문이 그대로 남아있을 수 있습니다. Crowdin에서 이 페이지의 번역을 개선하는 데 동참하여 도움을 주세요. (Crowdin translation page, Contributing guide)

솔리디티 스마트 컨트랙트에서 가스 요금을 최적화하는 방법

이 가이드는 솔리디티에서 스마트 컨트랙트를 작성할 때 가스 비용을 최적화하는 방법에 대한 실용적인 단계별 안내를 제공합니다.

가스 최적화가 중요한 이유는 무엇인가요?

가스 최적화는 스마트 컨트랙트 개발의 중요한 부분입니다. 이는 네트워크 혼잡도가 높은 상황에서도 스마트 컨트랙트가 효율적이고 비용 효율적으로 유지되도록 도와줍니다. 개발자는 컨트랙트 실행의 연산 오버헤드를 줄임으로써 트랜잭션 수수료를 낮추고, 확인 시간을 단축하며, 디앱의 전반적인 확장성을 개선할 수 있습니다.

개발자에게 있어 가스 최적화는 불필요한 계산을 최소화하는 깔끔하고 안전하며 예측 가능한 코드를 작성하는 것입니다. 사용자 입장에서는 과도한 수수료를 지불하지 않고도 계약과 상호작용할 수 있도록 보장하는 것이 중요합니다.

Kaia에서 특히 중요한 이유

83개 이상의 미니 디앱이 출시되었고 계속 증가하고 있는 Kaia 블록체인은 이러한 온체인 애플리케이션의 폭발적인 성장에 힘입어 거래량에서 선도적인 EVM 호환 체인으로 부상했습니다.

각 미니 디앱은 온체인 작업을 수행하기 위해 스마트 컨트랙트에 의존합니다. 아이템 채굴, 베팅, 게임 내 자산 관리 등 모든 컨트랙트 상호작용은 가스를 소모합니다. 최적화가 이루어지지 않으면 이러한 디앱은 사용자가 상호작용하기에는 너무 비싸질 수 있으며, 특히 대규모로 사용할 경우 더욱 그렇습니다.

그렇기 때문에 가스 효율은 단순히 있으면 좋은 것이 아닙니다. 필수입니다. Kaia를 기반으로 구축하는 개발자는 기능과 보안을 유지하면서 비용을 최소화할 수 있도록 각 함수 호출을 최적화해야 합니다.

가스 최적화 기술

보관 포장

블록체인에 데이터를 저장하고 검색하는 작업은 특히 데이터가 트랜잭션과 블록에 걸쳐 지속되어야 할 때 가장 가스 비용이 많이 드는 작업 중 하나입니다. 솔리디티에서 이 데이터는 계약 스토리지에 저장되며, 이는 영구적이고 가스 비용이 발생합니다. 이러한 비용을 줄이려면 개발자는 특히 상태 변수를 선언할 때 스토리지 사용 방식을 신중하게 최적화해야 합니다.

Kaia 가상 머신(KVM)은 스토리지 슬롯이라는 단위로 계약 데이터를 저장합니다. 각 스토리지 슬롯에는 정확히 256비트(32바이트)의 데이터를 저장할 수 있습니다. 솔리디티 데이터 유형은 다양한 크기로 제공되며, 예를 들어 부울은 1바이트, 주소는 20바이트입니다.

스토리지 패킹이라는 기술을 통해 작은 변수를 하나의 32바이트 스토리지 슬롯에 맞게 촘촘하게 배열할 수 있습니다. 이렇게 하면 하나의 스토리지 슬롯에서 읽거나 쓰는 것이 여러 개의 스토리지 슬롯에 액세스하는 것보다 훨씬 저렴하기 때문에 가스 사용량을 줄이는 데 도움이 됩니다.

다음 예시를 살펴보겠습니다:

분석:

최적화되지 않은 버전(SlotUnOptimized)에서 솔리디티는 구조체를 다음과 같이 저장합니다:

  • 주소 -> 20바이트 소요 -> 슬롯 0에 저장
  • uint256 숫자확인 -> 32바이트 필요 -> 슬롯 1에 저장됩니다.
  • uint80 값(10바이트) 및 bool 실행(1바이트) -> 슬롯 2에 저장됩니다.

값**과 실행 변수는 크기가 작지만, 명시적으로 순서를 바꾸지 않는 한 정렬 패딩으로 인해 솔리디티는 자체 스토리지 슬롯에 배치합니다. 결과적으로 이 구조는 3개의 스토리지 슬롯을 사용하므로 스토리지 운영에 필요한 가스 비용이 3배가 됩니다. 그러나 '주소(20바이트) + uint80(10바이트) + bool(1바이트)`의 총 크기는 31바이트이며 단일 슬롯의 32바이트 한도 내에 해당합니다. 작은 변수가 함께 그룹화되도록 선언의 순서를 바꾸기만 하면 솔리디티는 변수를 같은 슬롯에 넣을 수 있습니다. 이것이 바로 스토리지 포장의 본질입니다.

위와 같이 최적화된 버전(SlotOptimized)에서는 모든 작은 변수가 서로 인접하여 배치되므로 컴파일러가 더 적은 슬롯에 저장할 수 있어 배포 및 런타임 가스 비용이 절감됩니다.

캐시 스토리지

스토리지 슬롯에 변수가 배치되는 방식 외에도 스토리지 액세스 및 수정과 관련된 가스 비용을 이해하는 것도 중요합니다.

Kaia 가상 머신의 각 스토리지 슬롯에는 비용이 듭니다: 초기화(첫 번째 쓰기) 20,000 가스 업데이트(후속 쓰기) 5,000 가스 이 때문에 특히 자주 호출되는 함수에서 직접 스토리지 읽기 및 쓰기 횟수를 최소화하는 것이 중요합니다. 한 가지 효과적인 패턴은 함수 내에서 여러 번 액세스해야 할 때 저장소 변수를 메모리에 캐시하는 것입니다.

다음 예시를 살펴보겠습니다:

변수를 기본값으로 초기화하지 않기

솔리디티의 모든 데이터 유형에는 미리 정의된 기본값이 있습니다. 예를 들어 address의 기본값은 address(0), bool의 기본값은 false, uint의 기본값은 0입니다. 개발자가 변수 선언 중에 bool isActive = false 또는 uint total = 0을 작성하는 등 이러한 기본값을 명시적으로 지정할 때 일반적인 비효율성이 발생합니다.

기능적으로는 올바르지만, 솔리디티가 기본적으로 이러한 값을 설정하기 때문에 배포 중에 불필요한 가스 비용이 발생합니다. 상태 변수에 값을 할당하지 않고 선언하면 컨트랙트의 바이트코드 크기를 줄이고 추가 저장소 작업을 피할 수 있습니다. 이 작은 조정은 특히 여러 변수를 다룰 때 스마트 컨트랙트를 더 효율적이고 쉽게 유지 관리할 수 있도록 도와줍니다.

다음 예시를 살펴보겠습니다:

온체인 데이터 최소화

거래에서 발생하는 가스 비용의 대부분이 컨트랙트 스토리지에 저장된 데이터에서 발생한다는 사실을 잘 알고 있습니다. 어떤 데이터를 실제로 체인에 저장해야 하는지, 아니면 오프체인에 저장해야 하는지 항상 질문하고 두 옵션의 장단점을 고려하는 것이 가장 좋습니다. 이는 완전 온체인 NFT의 경우와 오프체인 메타데이터를 사용하는 기존 NFT에 비해 얼마나 비싼지를 통해 확인할 수 있습니다. 즉, 스토리지에 더 적은 변수를 할당했기 때문에 정보를 오프체인에 저장함으로써 스마트 컨트랙트의 가스 소비를 크게 줄일 수 있습니다.

사용하지 않는 저장 공간 확보

간혹 사용하지 않는 데이터를 계약에서 해제하는 것을 잊어버리는 경우가 있는데, 이는 가스 비용을 증가시키고 네트워크 폭증을 유발하기도 합니다. 사용하지 않는 용량을 확보하는 방법은 더 이상 사용하지 않을 것이 확실해지면 값을 0으로 다시 설정하는 것만큼 간단합니다. 또한 특수 키워드 '삭제'를 솔리드로 사용하여 모든 데이터 유형을 확보할 수도 있습니다.

다음 예시를 살펴보겠습니다:

특정 함수 매개변수에 대해 메모리 대신 콜데이터에 데이터 저장

효과적인 가스 골프 기법 중 하나는 함수의 읽기 전용 배열 인수에 콜데이터를 사용하는 것입니다. 콜데이터는 외부 호출 중에 함수 인수가 저장되는 수정 불가능하고 영구적이지 않은 영역입니다. 스토리지 할당이나 복사를 포함하지 않기 때문에 메모리보다 훨씬 저렴합니다.

함수가 입력 배열이나 문자열을 수정하지 않고 읽기만 하면 되는 경우, 매개변수를 호출 데이터로 선언하면 가스 소비를 줄이는 데 도움이 됩니다. 이는 일괄 전송이나 다중 수신자 에어드랍과 같이 자주 호출되거나 대량의 입력 데이터를 처리하는 함수에 특히 유용합니다.

다음 예시를 살펴보겠습니다:

배열 대신 매핑 사용

솔리디티에서 데이터를 관리하기 위한 두 가지 기본 데이터 구조가 핵심입니다: 배열매핑입니다. 각 요소가 특정 인덱스에 할당된 항목 컬렉션을 배열하여 정렬된 목록에 적합합니다. 반면 매핑은 고유 키를 통해 값에 직접 액세스할 수 있는 키 값 저장소 역할을 합니다.

배열로 작업할 때 특정 값을 검색하려면 전체 컬렉션을 반복해야 하는 경우가 많으므로 각 계산 단계마다 가스 비용이 발생합니다. 이렇게 하면 특히 대규모 데이터 집합에서 조회 시 배열의 효율성이 떨어집니다. 유사한 항목을 순서대로 반복하거나 그룹화해야 하는 경우가 아니라면 매핑을 사용하여 데이터 목록을 관리하는 것이 가스 효율이 더 높습니다.

매핑은 일정한 시간 액세스를 제공하고 배열 탐색과 관련된 오버헤드를 피할 수 있어 많은 스마트 컨트랙트에서 가스 사용량을 최적화하는 데 선호되는 선택입니다.

다음 예시를 살펴보겠습니다:

동적 배열에 대한 고정 크기 배열

일반적으로 매핑이 배열보다 가스 효율이 높지만, 배열이 필요한 경우도 있습니다. 이러한 시나리오에서는 컴파일 시점에 요소 수를 알 수 있는 경우 고정 크기 배열을 사용하는 것이 좋습니다. 고정 크기 배열은 예측 가능한 스토리지 패턴을 제공하고 크기 조정 작업과 관련된 오버헤드를 방지합니다.

반면 동적 배열은 컨트랙트 실행 중에 크기가 커질 수 있으며, 메모리 할당 및 경계 검사에 추가 가스 비용이 발생할 수 있습니다. 가능한 경우 고정 크기 배열을 선택하면 가스 소비를 줄이고 스마트 컨트랙트의 전반적인 성능을 개선하는 데 도움이 됩니다.

이 예시를 살펴보겠습니다:

불변 및 상수 사용

솔리디티에서 가스 비용을 최적화하는 효과적인 방법은 변수를 상수 또는 불변으로 선언하는 것입니다. 이러한 특수 변수 유형은 상수의 경우 컴파일 시 또는 불변성의 경우 컨트랙트 배포 중에 한 번만 값이 할당되며, 그 이후에는 읽기 전용이 됩니다. 이러한 값은 컨트랙트의 바이트코드에 직접 포함되므로, 일반적으로 스마트 컨트랙트 실행에서 가장 비용이 많이 드는 작업 중 하나인 스토리지 액세스가 필요하지 않습니다. 따라서 코드 명확성과 효율성을 유지하면서 가스 사용량을 줄일 수 있는 강력한 도구가 됩니다.

이 예제를 살펴 보겠습니다:

최적화된 오류 처리

솔리디티에서 가스를 최적화할 때 단순하고 효율적으로 유지하는 것은 오류 처리에도 적용됩니다. 사용자 지정 오류는 문자열 메시지를 사용하는 기존의 require 문 대신 가스를 절약할 수 있는 대안을 제공합니다. 컨트랙트 바이트코드에 저장되고 메시지 길이에 따라 크기가 커지는 문자열 기반 오류와 달리 사용자 지정 오류는 훨씬 저렴합니다.

함수 선택기가 계산되는 방식과 유사하게 오류 서명의 keccak256 해시에서 파생된 컴팩트한 4바이트 선택기를 사용하여 작동합니다. 사용자 지정 오류는 require 또는 if 문 내부에서 사용하든, 디버깅 중에 명확성을 제공하면서 바이트코드 크기와 런타임 가스 비용을 줄이는 데 도움이 됩니다.

이 예제를 살펴 보겠습니다:

외부 가시성 수정자 사용

함수가 외부 소유 계정이나 다른 스마트 컨트랙트 등 컨트랙트 외부에서만 호출될 것이 확실하다면, 함수의 가시성을 외부로 선언하는 것이 가장 좋습니다. 이 지침은 솔리디티가 함수 인자와 메모리 할당을 처리하는 방식을 기반으로 합니다.

외부 함수는 외부 입력에 최적화된 읽기 전용 섹션인 호출 데이터에서 직접 매개변수를 읽습니다. 반면에 공개 기능은 내부 및 외부에서 모두 액세스할 수 있습니다. 컨트랙트 외부에서 공용 함수를 호출하면 외부 함수처럼 호출 데이터에서 인수를 읽습니다.

그러나 내부적으로 호출할 때는 인수가 메모리를 통해 전달되므로 추가 메모리 할당 및 복사로 인해 비용이 더 많이 듭니다. 특히 내부용이 아닌 기능을 외부로 표시하면 메모리 작업을 줄이고 가스 효율을 개선할 수 있습니다. 이 작은 변화로 더욱 최적화되고 비용 효율적인 스마트 컨트랙트를 만들 수 있습니다.

이 예제를 살펴 보겠습니다:

인라인 어셈블리 사용

인라인 어셈블리를 통해 개발자는 KVM 옵코드와 직접 상호 작용할 수 있습니다. 이 기술은 특정 시나리오에서 표준 솔리디티 코드에 비해 가스 효율이 더 높은 실행을 가져올 수 있습니다. 솔리디티의 안전 검사를 우회하고 가독성을 떨어뜨리지만 직접 메모리 액세스, 비트 단위 연산 또는 사용자 지정 제어 흐름과 같은 중요한 연산을 수행하는 데 특히 유용합니다. 인라인 어셈블리를 주의해서 사용하면 후드 아래에서 작업이 실행되는 방식을 정밀하게 제어할 수 있어 가스 비용을 절감하는 데 도움이 됩니다.

이 예제를 살펴 보겠습니다:

결론

가스 비용을 최적화하는 것은 솔리디티에서 효율적이고 비용 효과적인 스마트 콘트랙트를 작성하는 데 있어 매우 중요한 부분입니다. Kaia에 배포하면 이미 사용자에게 더 낮은 거래 비용을 제공하지만, 검증된 가스 최적화 기술을 적용하는 것은 개발자의 책임입니다. 이 가이드에 설명된 사례를 따르면 실행 비용을 크게 절감하고 계약 확장성을 개선하며 사용자에게 더욱 원활하고 지속 가능한 경험을 제공할 수 있습니다.

페이지를 개선해 주세요