스마트 컨트랙트 호출 시에 많이 사용되던 ethers js 라이브러리에 이어, 최근 viem이라는 라이브러리가 새로 등장하였습니다!
본 포스팅에서는 ethers js와의 비교를 중심으로 viem에 대해 살짝 들여다 보고자 합니다 :)
잘못된 내용에 대한 피드백은 언제나 감사드립니다! (_ _)
물론 아직 ethers의 다운로드 횟수가 훨씬 높지만,
viem이 2023년 7월에 1.0.0버전이 공개된 라이브러리인 걸 감안하면 역시 많이 사용되고 있는 편이 아닌가 싶네요! :)
viem 공식문서에 따르면, viem은 보다 상세하고(verbose), 명료한(clarity) 형태의 API를 지향한다고 합니다!
이를 위해, ethers js와 비교했을 때 API의 형태 및 메서드 이름 등이 조금씩 달라진 경우가 많은 것 같습니다.
viem이 ethers에서의 migration 가이드 부분에서 소개하고 있는, 예시들 중 몇 가지를 간단히 살펴보고 넘어가려 합니다 :)
import { providers } from 'ethers'
const provider = new providers.JsonRpcProvider("https://polygon.llamarpc.com")
import { createPublicClient, http } from 'viem'
import { mainnet } from 'viem/chains'
const client = createPublicClient({
chain: mainnet,
transport: http("https://polygon.llamarpc.com")
import { providers, Wallet } from 'ethers'
const provider = new providers.Web3Provider(window.ethereum)
const wallet = new Wallet('0x...', provider)
wallet.sendTransaction({ ... })
import { createWalletClient, custom } from 'viem'
import { privateKeyToAccount } from 'viem/accounts'
import { mainnet } from 'viem/chains'
const account = privateKeyToAccount('0x...')
const client = createWalletClient({
account,
chain: mainnet,
transport: custom(window.ethereum)
})
client.sendTransaction({ ... })
import { getDefaultProvider } from 'ethers'
const provider = getDefaultProvider();
const contract = new Contract(address, abi, provider);
const supply = await contract.totalSupply(); // function name
import { createPublicClient, http } from 'viem'
import { mainnet } from 'viem/chains';
const client = createPublicClient({
chain: mainnet,
transport : http()
});
const supply = await client.readContract({
abi: abi,
address: address,
functionName: 'totalSupply'
});
개인적으로는
Contract 라는 클래스 명에 비해 Client 가 조금 더 직관적으로 느껴지는 점등이 마음이 드네요 :)
성능적인 측면은 viem이 공식문서에서 다른 라이브러리들과의 비교를 통해 꽤나 자신감을 내비치던 부분 같았는데요!
encoding/parsing 알고리즘의 최적화 등을 통해 실행 속도를 개선했다고 합니다.
문서를 읽다 보니 궁금해져서ㅎㅎ ethers에서 자주 사용하던 메서드 몇 가지에 대해 간단히 실행 시간을 비교해 보려고 합니다!
benchmark js 라이브러리를 활용하여 실행 시간을 측정하였습니다!
function ethersFunction() {
const iface = new ethers.utils.Interface(ERC_20);
iface.encodeFunctionData(functionName, []);
}
function viemFunction() {
encodeFunctionData({
abi: ERC_20,
functionName: functionName,
args: [],
});
}

function ethersFunction() {
ethers.utils.isAddress(TOKENS.POLYGON_USDC);
}
function viemFunction() {
isAddress(TOKENS.POLYGON_USDC);
}

function ethersFunction() {
const iface = new ethers.utils.Interface(ERC_20);
iface.decodeFunctionResult(functionName, encodedData);
}
function viemFunction() {
decodeFunctionResult({
abi: ERC_20,
functionName: functionName,
data: encodedData,
});
}

테스트로 실행해 본 횟수가 많지 않아서, 어디까지나 간단한 참고 목적으로만 생각해야 할 것 같지만 그래도 테스트해 본 3가지 함수에 대해 모두 viem이 훨씬 빠른 실행 속도를 보여주었네요!
기존에 거대한 경쟁자(?)가 있는 상황에서, 실행 속도나 최적화 등을 무기로 나타난 것 같은 viem을 보니 뭔가 Bun 이 등장했을 때와 비슷하지 않나ㅎㅎ 하는 생각이 들었습니다~!
아직은 둘 다 신생 런타임, 신생 라이브러리 같은 느낌이지만, 빠르게 업데이트가 이루어지고 있는 모습을 보면 앞으로가 조금 더 기대되는 느낌이네요! :)