끄적끄적

이더리움 개발을 위한 Truffle & Ganache 설치 및 구조 설명 본문

개발/블록체인

이더리움 개발을 위한 Truffle & Ganache 설치 및 구조 설명

코리이 2022. 9. 13. 18:26

Truffle

이더리움 dapp 을 개발하고 배포하기 위해서는 solidity 로 스마트 컨트랙트를 작성하고 이더리움 위에 그 코드를 올리는 작업이 필요하다.

또한 대부분의 개발자라면  테스트 코드를 반드시 짜면서 개발하는 습관이 있을 것이다. 물론 단순한 스마트 컨트랙트의 코드만 작성한다면 vscode 와 같은 에디터만 이용해도 되지만 스마트 컨트랙트 코드를 짜면서 테스트를 돌리고 할 프레임워크 혹은 도구들이 필요하다. 

이렇게 이더리움 코드를 짜고 테스트를 돌리고, 이렇게 개발한 코드를 이더리움 위에 올리는 것을 도와주는 도구가 바로 truffle 이다. 

공식문서에서는 아래처럼 EVM 을 사용하는 블록체인 개발자를 위한 개발 환경이자 프레임워크라고 한다.

A world class development environment, testing framework and asset pipeline for blockchains using the Ethereum Virtual Machine (EVM), aiming to make life as a developer easier

Ganache

하지만 만약 우리가 계속해서 이더리움 위에서 배포 테스트를 하면 어떻게 될까? 이더리움 가격이 100 만원이 넘어가는데 개발 자체를 돈이 없어서 못하는 상황이 계속해서 발생할 것으로 생각한다. 그렇기 때문에 작성자의 경우 초기에는 geth를 테스트 버전으로 내부에 올리고 테스트하는 과정을 거쳤었다. 만약 이러한 작업이 싫다면 공개적으로 오픈되어 있는 테스트넷을 사용해야 하지만 faucet을 통해 테스트넷 코인을 받아야 하는 등 개발할 때 많은 어려움이 따르게 된다.

이러한 과정을 줄여줄 수 있는 도구가 바로 ganache 이다. ganache 를 이용하면 ui 버전이라면 클릭만으로, cli 버전이라면 명령어 한 줄로 앞에서 말했던 geth와 똑같은 환경을 쉽게 로컬에 만들어 준다. 그리고 종료시키는 것도 쉬워지고 깨끗한 환경에서 계속 테스트해볼 수 있게 도와준다. 

결론적으로는 이더리움 환경을 쉽게 로컬에 만들어주고 제거할 수 있다고 생각하면 된다.

설치

truffle 과 ganache 를 설치하는 방법은 간단하다. 

node 가 다운되어 있다면 global 로 설치하면 끝이다.

ganache 의 경우 모든 포스팅은 cli 환경을 이용할 예정이다.

$ npm install -g truffle
$ npm install -g ganache

 

그 후에 아래 명령어로 설치가 잘 되었는지 확인할 수 있다.

$ truffle -v

아래처럼 설치되어 있는 버전들을 알려준다.

 

$ ganache

ganache 를 실행시키면 다른 설정 필요 없이 EVM 환경을 실행시킬 수 있다.

Ganache 실행하기

위에서 처럼 ganache 환경을 실행하면 초반에 10개의 지갑 주소를 만들어 주는데 직접 테스트하다 보면 같은 지갑 정보가 필요한 경우가 생긴다. 따라서 같은 seed 로 만들어주는 과정이 필요한데 -m 의 옵션을 활용해서 mnemonic 을 고정시켜 같은 주소를 만들어 낼 수 있다. 또한 개인적으로는 포트도 다른 번호로 자주 실행시킨다.

$ ganache -m "pawmi" --port 9555

이제 ganache cli 환경을 실행시켰다면 이 ganache 로 만든 환경에 명령어를 전달할 console 이 필요하다.

이 console 은 truffle console 을 활용한다면 쉽게 사용 가능하다.

Truffle console 실행하기

간단하게 아래처럼 console 명령어를 통해 원하는 네트워크에 붙을 수 있다.

현재는 앞에서 만든 8555 포트 및 로컬 호스트로 만들어져 있는 환경에서 실습하려고 한다. url 환경변수를 주어 실행할 수 있으며 아래 사진과 같이 네트워크에 잘 연결되었음을 알 수 있다.

$ truffle console --url http://127.0.0.1:8555

이제 truffle 콘솔은 web3.js 가 내장되어 있어 이 라이브러리에서 사용할 수 있는 여러 명령어를 사용할 수 있다.

예를 들어 아래처럼 account를 가져올 수 있다.

> web3.eth.getAccounts()

물론 다른 계정으로 이더 전송도 가능하다. js 언어를 알고 있다면 편하게 사용 가능하다. 

// 아래는 truffle 콘솔에서 입력한 명령어이다.

// 주소 정보를 저장
const myWallet = await web3.eth.getAccounts()

// 잔고 확인
await web3.eth.getBalance(myWallet[0])
await web3.eth.getBalance(myWallet[1])

// transaction 전송
await web3.eth.sendTransaction({ from: myWallet[0], to: myWallet[1], value: 100000, gas:210000 })

// 전송 후 잔고 확인
await web3.eth.getBalance(myWallet[0])
await web3.eth.getBalance(myWallet[1])

이제 이더리움 개발환경 위에서 간단한 조작이 필요한 경우에는 truffle console 을 활용해서 명령어를 입력할 수 있게 되었다.

Truffle 프로젝트 설정하기

truffle 과 ganache 를 이용해서 이더리움 위에서 명령어를 작성하는 법을 알아보았다.

하지만 실제로 하고 싶은 것은 솔리디티를 활용해서 스마트 컨트랙트를 개발하고 테스트하는 것이므로 truffle 프로젝트 환경을 만들어 주어야 한다. 참고로 트러플 프로젝트는 기본적으로 node 프로젝트 위에서 실행된다.

 

개발할 디렉터리에서 truffle init 명령어를 활용해 프로젝트를 만들 수 있다.

$ truffle init

다만 init 은 프로젝트 구조만 잡아주므로 이번 포스팅에서는 가장 기본적으로 제공해주는 프로젝트인 MetaCoin 프로젝트를 사용하고자 한다.

$ truffle unbox MetaCoin

이 명령어를 사용하면 아래와 같은 파일들이 생성된다. 이전에는 migration 을 위한 파일들이 기본적으로 생성되었지만 현재는 내장되어서 실행된다.

contracts
  |- ConvertLib.sol
  |- MetaCoin.so
migrations
  |- 1_deploy_contracts.js
test
  |- metacoin.js
  |- TestMetaCoin.sol
truffle-config.js

우선 컨트랙트 컴파일을 해보자

그러면 추가적으로 build 디렉터리에 abi 파일들이 생겨날 것이다. 이 abi 파일에는 예제에서 만들어져 있는 metacoin 관련된 abi들이 들어가 있다. 

$ truffle compile

 

이제 배포를 해보자. 우리는 이더리움 포트를 다르게 올렸기 때문에 설정을 조금 바꿔주어야 한다.

truffle-conifig.js 파일에서 네트워크 설정을 바꿔주면 된다. 기본적으로 네트워크 설정이 디폴트로는 127.0.0.1:8545 로 url 이 정해져 있으니 이 부분을 8555 로 바꿔주자

// truffle-config.js
module.exports = {
    networks: {
        development: {
          host: "127.0.0.1",
          // port: 8545,
          port: 8555, 
          network_id: "*",
        },
    }
  }

그 이후에 프로젝트 루트에서 아래 명령어를 입력하면 배포가 된다.

$ truffle migrate

그 후에 아래 명령어를 통해서 metacoin 의 balance 를 가져와보자. 이 코인은 constructor 에서 아래 코드를 통해 가장 처음 wallet 주소에 1000 코인을 넣어준다.

// MetaCoin.sol
balances[tx.origin] = 10000;

truffle console 을 통해 아래와 같은 명령어를 치면 첫 번째 wallet에 1000 코인이 들어가 있는 것을 확인할 수 있다.

// 아래는 truffle console 에서 수행

// wallet 정보를 변수로 지정 (앞에서 했다면 생략)
> const myWallet = await web3.eth.getAccounts()

// 배포된 contract 정보를 가져온다.
> const metaCoinContract = await MetaCoin.deployed()

// abi 를 통해 method 가 잘 존재하는지 확인
> metaCoinContract.abi

// balance 를 가져오기
> (await metaCoinContract.getBalance(myWallet[0])).toString() // 1000
> (await metaCoinContract.getBalance(myWallet[1])).toString() // 0

Truffle 구조 알아보기 

truffle 프로젝트는 크게 솔리디티 코드를 담고 있는 contracts, 이 컨트랙트 배포 파이프라인을 담고 있는 migrations, 그리고 이 컨트랙트 코드 테스트를 위한 test 로 나누어져 있다.

contracts

컨트랙트 코드를 담고 있는 디렉터리이다. 이 디렉터리에서 원하는 컨트랙트를 작성하면 된다. 

예제 코드에서는 library 와 metacoin 이 정의되어 있다.

migrations

여기서는 컨트랙트 배포 파이프라인을 스크립트화 해서 만들 수 있다.

이 예제와 같이 ConvertLib 라이브러리 코드를 배포하고 이 코드를 MetaCoin 과 링크를 걸고 다시 MetaCoin 을 배포하게끔 되어 있다. 

이것 말고도 promise (혹은 async, await) 기반으로 배포 후 작업을 수행할 수도 있다. 예를 들어 metacoin 을 배포하고 처음 balance 를 다른 지갑에 넣는다던가 등의 작업을 할 수 있다. 

즉, 아래처럼 배포 방식을 살짝 바꾼다면 배포 후에 생성된 두 번째 주소로 10 코인을 보내는 작업을 추가할 수 있다.

const ConvertLib = artifacts.require("ConvertLib");
const MetaCoin = artifacts.require("MetaCoin");

module.exports = async function(deployer, network, accounts) {
  await deployer.deploy(ConvertLib);
  deployer.link(ConvertLib, MetaCoin);
  const metacoin = await deployer.deploy(MetaCoin);

  // 두번째 주소로 코인 전송
  await metacoin.sendCoin(accounts[1], 10);
};

다시 truffle console 에서 이전과 같은 작업을 동일하게 수행해보면 (ganache 와 truffle console 은 아예 다시 실행시키자) 두 번째 지갑에 10 코인이 들어가 있음을 알 수 있다.

test

이 디렉터리에서는 내가 개발한 스마트컨트랙트를 테스트해볼 수 있다. 

테스트하는 방식은 solitity 코드로 수행하는 방법, js 로 수행하는 방법이 있는데 개인적으로는 js 테스트가 조금 더 많은 라이브러리들을 가져올 수 있고, 쉽기 때문에 추천하고 싶다. js 테스트의 경우 mocha 와 chai 를 안다면 쉽게 접근할 수 있다. 코드를 보면 알겠지만 truffle console 에서 작업한 것과 거의 비슷한 구조를 띄고 있음을 알 수 있다.

예를 들어 간단하게 작성되어 있는 한 가지 테스트 코드를 뜯어보면 다음과 같다. 아래 코드는 만약 migration 파일을 변경하였다면 분명히 실패할 것이다. 9990 이어야 하기 때문이다.

  it('should put 10000 MetaCoin in the first account', async () => {
    // metacoin 컨트랙트 인스턴스를 가져온다.
    const metaCoinInstance = await MetaCoin.deployed();
    
    // 첫번째 주소의 balance 정보를 가져온다.
    const balance = await metaCoinInstance.getBalance.call(accounts[0]);

    // 실제로 balance 가 10000 이 맞는지 확인한다.
    assert.equal(balance.valueOf(), 10000, "10000 wasn't in the first account");
  });

마무리

ganache 와 truffle 에 대해서 간략하게나마 사용법을 알아보았다. 컨트랙트를 개발할 때 가장 기본이 되는 환경 설정이기 때문에 외워두고 쓸 수 있으면 좋을 듯 싶다.

 

'개발 > 블록체인' 카테고리의 다른 글

이더리움 dApp 개발을 위한 Hardhat 시작하기  (0) 2023.06.03