즐코

truffle - 스마트 컨트랙트 개발 프레임워크 본문

BlockChain

truffle - 스마트 컨트랙트 개발 프레임워크

YJLEE_KR 2022. 7. 12. 23:56

스마트컨트랙트 개발할 때 많이 쓰는 프레임워크에는 Hardhat과 Truffle이 있다고 한다.

요즘은 Hardhat이 핫하다곤하지만, 익숙한 web3 라이브러리 기반의 프레임워크인 truffle을 쓰는게 통일성 있으니 truffle을 사용해보려고 한다. 해당 포스팅에선 truffle 설치 및 스마트 컨트랙트 배포, 실행을 간단하게 정리해본다.

 

1/ Truffle 설치

truffle은 전역으로 설치해주었다.

$ npm i -g truffle
// 디렉토리 하나 만들어서 그 안에서 init
$ npx truffle init

init 명령어를 실행한 truffle 폴더 하에 아래 디렉토리들이 자동 생성되었다.

 

- build : 솔리디티 코드를 컴파일한 내용이 json 형태로 들어간다 (해당 디렉토리는 맨 처음엔 없다, 빌드 후에 생긴다)

- contracts : solidity 코드 넣는 공간

- migrations : deploy 전용 코드 (배포할 코드를 컨트랙트별로 넣는 공간이라고 보면 된다)

- test : 배포된 컨트랙트들을 실행시켜보는 테스트 공간

- truffle-config.js : 네트워크 및 컴파일러 등등 설정값 

 

truffle-config.js 설정파일 수정

 

자동 생성된 파일인데 보면 주석 처리된 부분이 많다. 살릴부분은 살리면 된다.

private 네트워크로 geth를 돌리고 있다면, host/port/network_id 등을 수정해주면 된다.

추가로, 나같은 경우는 ws으로 geth를 실행했기 때문에, websockets: true 옵션도 추가해주었다.

가나쉬 같은 테스트 네트워크와 연결시엔 port#를 8545로 해주면 되겠다..

// truffle-config.js

module.exports = {
   networks: {
    	development: {
            host: "127.0.0.1",
            port: 7979,
            network_id: 1004, // default "*"
            websockets: true, 
        },
    }
    mocha: {},
    compilers:{
        solc: {
            version: "0.8.15",
           }
    }
}

 

 

2/ Truffle로 솔리디티 코드 컴파일해보기 

우선 이전에 작성한 HelloWorld.sol 파일을 가져와서 contracts 디렉토리에 추가해준다.

$ npx truffle compile

 

build / contracts / HelloWorld.json이 자동생성되었다. 컴파일된 내용을 보면 내부에 abi, bytecode등이 들어있다!

저번 포스팅에서 자바스크립트로 클래스를 만들어서 스마트 컨트랙트 내용을 컴파일 해줬었는데, truffle을 사용하니 이렇게 간단하게 만들어진다..ㅋ

 

3/ Truffle로 스마트 컨트랙트 배포 

 

Migration 작성

 

스마트 컨트랙트를 truffle을 이용해서 배포하려면 마이그레이션을 작성해줘야한다.

마이그레이션이란? 계약을 배포하고 변경하는 일련의 과정을 js로 기술한 것을 의미한다고 한다.

 

1. 마이그레이션 파일명 지정

 

위에서 언급했듯이 스마트 컨트랙트 배포를 위해 migrations 디렉토리에 배포할 코드를 컨트랙트별로 넣어줘야한다.

파일 형식은 init할 때 자동생성되었던, 1_initial_migration.js 파일 형식을 따라하면 된다. 

여기선 HelloWorld 코드를 배포할 것이므로 2_deploy_HelloWorld.js 파일을 만들어준다.

 

** 보통 숫자는 마이그레이션이 생성된 시점의 타임스탬프를 넣어준다고함.. 같은 이름의 마이그레이션을 여러개 생성해도 다른 것으로 인식하고 타임스탬프 순서에 따라 차례대로 마이그레이션이 실행되는 것을 보장해준다고 한다.

 

2. 마이그레이션 파일 작성

// migrations/2_deploy_HelloWorld.js

const helloWorld = artifacts.require("HelloWorld");

module.exports = function (deployer) {
  deployer.deploy(helloWorld);
};

- artifacts.require("솔리디티 코드 컴파일한 json 파일명")

: 계약정보를 읽어오는 코드라고 보면 된다. 

- deployer : truffle이 제공해주는 배포를 위한 툴

- deployer.deploy("위에서 읽어온 계약정보") 

 

$ npx truffle migration
// 또는
$ npx truffle migration --reset

명령어 실행과 동시에 타이머가 돌아가고, 콘솔창에 아래와 같은 내용이 찍힌다.

 

이때 마이닝을 해주면,

애초에 init할 때 생성되었던 migrations.js 가 배포되고, 그 이후에 내가 만든 HelloWorld.js 가 배포됨을 확인할 수 있다.

 

 

4/ truffle 콘솔창 또는 test 코드 작성하여 컨트랙트 배포 및 실행 확인

1. truffle console

 

geth 콘솔창처럼 truffle 콘솔창을 이용해서 배포 및 실행내용을 확인해볼 수 있다.

$ truffle console
truffle(development)> HelloWorld

 

=> 기존 HelloWorld 컨트랙트 내용이 쫘악 나온다.

truffle(development)> HelloWorld. tab 2번 때리기

=> 여러 메소드 및 속성들이 등장한다.

 

truffle(development)> HelloWorld.address

> '0x48072aCFc5Cfd98C6B3915B400A4880Af04d288E'

배포 시 반환되는 CA 값이다. 이게 나와야 배포가 완료되었다고 볼 수 있다.

truffle(development)> HelloWorld.deployed().then(instance=>hello=instance)

> 위의 메소드들 중 프로미스 객체를 반환하는 deployed() 메소드를 사용하여 전역변수 hello에다가 instance를 담아주었다.

따라서, 콘솔창에 hello.address 를 해주어도 CA 값을 받아낼 수 있다. 근데 truffle console 창은 한줄한줄 실행되기 때문에 굳이 비동기 처리를 해주지 않아도 된다. 즉 HelloWorld.deployed() 해도 된다.

truffle(development)> hello.value()

'Hello World' 출력

truffle(development)> hello.setValue("바뀌나??!")

마이닝해주면 아래와 같이 출력됨

 

위의 setValue 함수 실행 즉, 컨트랙트 실행으로 상태변수값이 변경되었다.

 

 

2. test 디렉토리 내에서 test 코드 작성

 

test 코드를 작성해보자. 이전에 작성했던 jest test 코드와 거의 같다. 

jest와 다른점이라고 한다면, contract라는 함수를 써서 두번째 인자인 콜백함수 내에서 테스트 코드를 작성해준다.

contract("컨트랙트명", 콜백함수) 

이 때 해당 콜백함수는 account를 인자로 받아올수있다. account를 출력해보면, 현재 노드에서 가지고 있는 계정이 출력된다.

** contract 콜백함수에서 테스트 코드를 작성하면 실제 컨트랙트 배포가 된다고 하니, 다음번 테스트 코드 작성에선 이걸 빼주고 describe 부터 작성하면 된다.

 

우선 컨트랙트 정보를 읽어오기 위해 artifacts.require("HelloWorld") 작성

 

위에서 truffle console 상에 실행했던대로 전역변수 hello에 컨트랙트 인스턴스를 담아주는 것부터 시작해서 상태변수 뽑아내기 및 상태변수 바꾸는 것까지 테스트해준다.

// test/HelloWorld.test.js

const HelloWorld = artifacts.require("HelloWorld");

contract("HelloWorld", (account) => {
  console.log("계정출력: ", account);
  let hello;

  describe("Hello Contract", () => {
    it("Hello World Contract", async () => {
      hello = await HelloWorld.deployed();
    });

    it("get value", async () => {
      console.log(await hello.value());
    });
    it("set value", async () => {
      await hello.setValue("바껴라^___^");
      console.log(await hello.value());
    });
  });
});

테스트 실행 명령어

$ truffle test

테스트를 시작하면 마이닝을 꼭 해서 모든 컨트랙트마다 배포를 해줘야하고,

모든 컨트랙트 실행에 관련된 마이닝이 다 완료되면, 아래와 같이 테스트 결과가 출력된다.

 

 

Comments