지난 글에서는 EVM이 스마트 컨트랙트 코드를 실행한다고 했습니다.
그럼 다음 질문은 이것입니다.
누가 이 실행 비용을 내는가?
그리고 실행을 얼마나 허용할지 어떻게 제한하는가?
이 질문에 대한 답이 Gas입니다.
처음에는 이렇게 이해하면 됩니다.
Gas
= EVM 작업에 필요한 계산량을 재는 단위
Gas는 ETH 자체가 아닙니다.
Gas는 “얼마나 많은 일을 했는가”를 재는 단위이고, 실제 수수료는 그 gas에 가격을 곱해서 ETH로 냅니다.
Gas는 수수료인가
Gas와 수수료는 같은 말이 아닙니다.
구분하면 이렇습니다.
gas
= 실행에 필요한 계산량 단위
gas fee
= 사용한 gas에 gas 가격을 곱해 계산한 실제 수수료
예를 들어 택시로 비유하면:
이동 거리
-> gas
1km당 요금
-> gas price
최종 택시비
-> gas fee
Ethereum.org는 gas fee를 어떤 작업에 사용한 gas에 gas 한 단위당 비용을 곱한 값으로 설명합니다.
왜 gas가 필요한가
EVM은 코드를 실행합니다.
코드 실행에는 계산 자원이 필요합니다.
만약 실행 비용이 없다면 문제가 생길 수 있습니다.
무한 반복 코드
너무 많은 계산을 요구하는 컨트랙트
네트워크를 계속 바쁘게 만드는 스팸 트랜잭션
그래서 이더리움은 모든 계산에 비용을 붙입니다.
계산을 많이 할수록
-> gas를 더 많이 사용
-> 더 많은 수수료가 필요
Gas는 단순히 돈을 걷기 위한 장치가 아닙니다.
네트워크가 무한 계산이나 스팸에 멈추지 않도록 실행량을 제한하는 장치이기도 합니다.
단순 ETH 전송도 gas가 필요한 이유
스마트 컨트랙트를 호출하지 않고 ETH만 보내도 gas가 필요합니다.
왜냐하면 ETH 전송도 상태를 바꾸기 때문입니다.
A balance 감소
B balance 증가
A nonce 증가
이 변화도 노드들이 검증하고 계산해야 합니다.
Ethereum.org 문서는 표준 ETH 전송에 21,000 gas가 필요하다고 설명합니다.
단순 ETH 전송
-> 21,000 gas
여기서 21,000 gas는 21,000 ETH가 아닙니다.
21,000은 계산량 단위입니다.
실제 수수료는 gas 가격에 따라 달라집니다.
수수료는 어떻게 계산하나
기본 계산식은 이렇습니다.
사용한 gas * gas 한 단위의 가격 = 수수료
EIP-1559 이후에는 gas 한 단위의 가격을 크게 두 부분으로 나눠 이해할 수 있습니다.
base fee
+ priority fee
= gas 한 단위의 가격
그래서 단순화하면:
사용한 gas * (base fee + priority fee)
= 최종 수수료
Ethereum.org의 예시는 21,000 gas를 사용하는 ETH 전송에서 base fee가 10 gwei, priority fee가 2 gwei라면:
21,000 * (10 + 2) gwei
= 252,000 gwei
= 0.000252 ETH
여기서 gwei는 ETH의 작은 단위입니다.
1 gwei
= 0.000000001 ETH
= 10^-9 ETH
처음에는 숫자보다 구조를 기억하는 것이 중요합니다.
얼마나 실행했는가: gas
한 단위당 얼마인가: gas price
최종 비용: gas * gas price
base fee와 priority fee
base fee는 프로토콜이 정하는 기본 비용입니다.
트랜잭션이 블록에 포함되려면 최소한 base fee를 충족해야 합니다.
EIP-1559 이후 base fee는 소각됩니다.
base fee
-> 프로토콜이 정함
-> 소각됨
priority fee는 블록 제안자에게 주는 팁으로 이해하면 됩니다.
트랜잭션을 더 빨리 포함시키고 싶을 때 priority fee를 더 높게 설정할 수 있습니다.
priority fee
-> 사용자가 추가하는 팁
-> 블록 제안자에게 감
처음에는 이렇게 구분하면 충분합니다.
base fee: 네트워크가 요구하는 기본 가격
priority fee: 포함 우선순위를 높이기 위한 팁
gas limit은 무엇인가
gas limit은 이 트랜잭션이 사용할 수 있는 최대 gas입니다.
사용자는 트랜잭션을 보낼 때 “이만큼까지만 실행해도 된다”는 한도를 정합니다.
gas limit
= 이 트랜잭션에 허용할 최대 실행량
예를 들어 단순 ETH 전송에 gas limit을 50,000으로 설정했다고 해보겠습니다.
실제로 필요한 gas가 21,000이라면, 21,000만 사용하고 나머지는 돌려받을 수 있습니다.
gas limit: 50,000
실제 사용: 21,000
남은 gas: 29,000
하지만 gas limit을 너무 낮게 잡으면 문제가 생깁니다.
예를 들어 단순 ETH 전송에 20,000 gas만 허용하면 필요한 21,000에 못 미칩니다.
이 경우 트랜잭션은 실행되기 전에 거절될 수 있습니다.
실행 중 gas가 부족하면
컨트랙트 호출은 단순 ETH 전송보다 더 복잡할 수 있습니다.
컨트랙트 코드가 실행되다가 gas를 모두 써버릴 수 있습니다.
이 경우 EVM은 상태 변경을 되돌립니다.
컨트랙트 실행 시작
-> storage 안의 값 변경 시도
-> 중간에 gas 부족
-> 상태 변경 되돌림
하지만 이미 실행을 시도하면서 사용한 계산량은 사라지지 않습니다.
그래서 실행이 실패해도 이미 사용한 gas에 대한 비용은 들 수 있습니다.
Ethereum.org도 트랜잭션이 실행 중 gas를 모두 사용하면 EVM이 변경 사항을 되돌리지만, 수행한 작업에 대해 제공된 gas는 소비된다고 설명합니다.
처음에는 이렇게 기억하면 됩니다.
상태 변경은 되돌릴 수 있다
이미 사용한 계산량은 비용으로 남을 수 있다
누가 무엇을 하나
Gas도 “누가 하는지”를 나눠보면 이해하기 쉽습니다.
사용자
-> 지갑 앱에서 트랜잭션 승인
지갑 앱
-> 예상 gas와 수수료 조건을 보여줌
-> 트랜잭션에 gas limit, fee 정보를 넣음
-> 사용자의 EOA 개인키로 서명
이더리움 노드
-> 트랜잭션이 수수료 조건을 만족하는지 확인
-> 블록에 포함된 트랜잭션을 실행하며 gas 사용량 계산
EVM
-> 코드 실행 단계마다 gas를 소비
-> gas가 부족하면 실행 실패 처리
사용자가 직접 gas를 하나씩 계산하는 것은 아닙니다.
대부분의 지갑 앱은 추천 수수료를 계산해 보여줍니다.
하지만 사용자가 최종 승인하기 전에 “이 트랜잭션은 대략 얼마의 수수료를 쓸 수 있다”는 정보를 확인하는 구조입니다.
정리
오늘 기준으로는 이렇게 정리합니다.
Gas는 EVM 실행에 필요한 계산량을 재는 단위다. 실제 수수료는 사용한 gas와 gas 한 단위의 가격으로 계산된다. Gas는 실행 비용을 정할 뿐 아니라, 무한 실행과 과도한 계산으로부터 네트워크를 보호하는 역할도 한다.
다음에는 Smart Contract 기초로 넘어가서, 지금까지 배운 EOA, Contract Account, EVM, Gas가 실제 컨트랙트 코드와 어떻게 연결되는지 봅니다.
참고 자료
- Ethereum.org, Gas and fees: https://ethereum.org/developers/docs/gas/
- Ethereum.org, Transactions: https://ethereum.org/developers/docs/transactions/
- Ethereum.org, Ethereum Virtual Machine: https://ethereum.org/developers/docs/evm/
- EIP-1559: https://eips.ethereum.org/EIPS/eip-1559