이타인클럽

web3.js를 이용한 간단한 Dapp 구축 따라하기 1/3

토픽 이타인클럽 > Blockchain > Blockchain 개발

참고서적: 이더리움을 활용한 블록체인 프로젝트 구축

이번에는 문서 소유권을 관리하는 스마트 컨트랙트를 만들고 웹에서 이를 활용하는 부분을 만들어 보겠습니다. 본 내용은 <이더리움을 활용한 블록체인 프로젝트 구축> 4장에 나와 있는 내용입니다. 책 설명이 부실하여 제가 직접 해보고 이해를 바탕으로 작성합니다~

큰 순서는 다음과 같습니다. 이번 포스팅에서는 분량상 2번까지 다루고 나머지는 이어서 다른 포스팅으로 다루겠습니다.

  1. 문서 소유권 스마트 컨트랙트 코딩
  2. 스마트 컨트랙트 배포
  3. 웹서비스 백엔드 구축
  4. 웹서비스 프론트엔드 구축
  5. 동작 테스트

원래는 스마트 컨트랙트 주요 문법 내용을 설명했어야 하는데 그부분은 그냥 패스하기로 합니다. 이미 많은 자료들이 나와있고, 예제를 통해 문법을 읽힐 수가 있기 때문입니다.

1. 문서 소유권 스마트 컨트랙트 코딩

책에는 초보자가 따라할 정도로 설명해 주지 않아서 좀 헷갈립니다. 그냥 책만 보면 따라하기 쉽지 않네요. 먼저 문서 소유권 관리를 위한 스마트 컨트랙트를 코딩합니다.

여기서는 로컬 컴퓨터에서 이더리움 클라이언트 노드를 구동하고, 즉 이더리움 메인 네트워크나, 테스트 네트워크가 아니라 자신의 컴퓨터에 프라이빗 네트워크를 구축하고 그것을 이용할 것입니다. 또 솔리디티 코딩은 오프라인으로 remix를 이용할 것입니다. 오프라인 remix는 remix 소스가 있는 github 페이지를 방문해서 gh-pages 브랜치 내용을 다운로드 받은 후 index.html를 실행시키면 됩니다. 이 부분도 검색하면 많은 자료가 있습니다.

이더리움 클라이언트: 로컬 컴퓨터(localhost:8545)

이더리움 클라이언트 geth 설치하는 부분은 생략하도록 하겠습니다.
자신의 pc에 geth가 설치 및 데이터 저장 경로가 지정되어 있다고 가정하고 아래와 같이 geth 를 구동합니다.

etain@etainclub$ nohup geth --networkid 4649 --nodiscover --maxpeers 0 --datadir ~/Blockchain/data_testnet --mine --minerthreads 1 --rpc --rpcaddr "0.0.0.0" --rpcport 8545 --rpccorsdomain "*" --rpcapi "admin,db,eth,debug,miner,net,shh,txpool,personal,web3" --unlock 0,1 --password ~/Blockchain/data_testnet/passwd --verbosity 6 2>> ~/Blockchain/data_testnet/geth.log &

위 명령 사용법과 관련하여 <블록체인 애플리케이션 개발 실전 입문>에 상세히 나와 있으니 참고하세요.

위와 같이 geth구동하고 아래와 같이 geth 콘솔에 접속하서 제대로 돌아가는지 확인해 봅니다. 여기서는 mining이 되는지 확인합니다.

etain@etainclub$ geth attach rpc:http://localhost:8545`
Welcome to the Geth JavaScript console!

instance: Geth/v1.5.5-stable-ff07d548/linux/go1.6.2
coinbase: 0x9751574414138b22986eb80ce2713cd2f5508c5c
at block: 4481 (Sun, 25 Mar 2018 13:26:31 KST)
 datadir: /home/etain/Blockchain/data_testnet
 modules: admin:1.0 debug:1.0 eth:1.0 miner:1.0 net:1.0 personal:1.0 rpc:1.0 txpool:1.0 web3:1.0

> eth.mining
true

솔리디티 코딩: 오프라인 remix 설치 및 설정

아래 사이트에 접속합니다.
https://github.com/ethereum/browser-solidity

!주의: 위 페이지에서 Branch를 gh-pages로 선택하신 후, 오른쪽에 Clone or download를 클릭하여 Download ZIP를 클릭해서 소스 코드를 다운로드 받습니다.

적당한 위치에 압축을 푼 후, index.html를 실행시키면 됩니다. 이것은 일반적으로 웹페이지의 시작 페이지(index 페이지)를 클릭하여 여는 것과 동일합니다. 그러면 Remix가 오프라인으로 실행될 것입니다.

그러면 아래와 같은 화면이 나타납니다. 먼저 로컬컴퓨터의 geth에 web3로 접속할 수 있게끔 합니다.

위 그림의 오른쪽 상단에서 메뉴에서 Run 탭을 선택한 후에 Environment부분 Web3 Provider를 선택 후 아래와 같이 로컬컴퓨터의 ip와 서비스 포트 번호를 입력합니다. localhost는 로컬컴퓨터의 ip인 127.0.0.0의 이름입니다.

http://localhost:8545

솔리디티 코딩

아래와 같이 remix 브라우저에 코딩합니다. 브라우저에서 새롭게 파일을 proof.sol이라는 이름으로 생성합니다.

pragma solidity ^0.4.0;

contract Proof
{
    struct FileDetails
    {
        uint timestamp;
        string owner;
    }
    mapping (string => FileDetails) files;
    event logFileAddedStatus(bool status, uint timestamp, string owner, string fileHash);
    
    //this is used to store the owner of file at the block
    function set(string owner, string fileHash) public
    {
        if(files[fileHash].timestamp == 0)
        {
            files[fileHash] = FileDetails(block.timestamp, owner);
            logFileAddedStatus(true, block.timestamp, owner, fileHash);
        }
        else
        {
            logFileAddedStatus(false, block.timestamp, owner, fileHash);
        }
    }
    //this is used to get file information
    function get(string fileHash) public returns (uint timestamp, string owner)
    {
        return (files[fileHash].timestamp, files[fileHash].owner);
    }
}

코드의 주요 부분만 간단히 설명하면 이렇습니다.
struct FileDetails { uint timestamp; string owner; }
파일 소유자를 관리하기 위한 구조체로 단순히 블락의 타임스탬프와 파일 소유자를 저장합니다.

mapping (string => FileDetails) files;
mapping이라는 키워드는 key-value 구조를 갖는 데이터를 가리킵니다. 이때 key값으로 0, 1, 2 를 사용하지 않고, address나 다른 데이터 타입으로 key를 설정할 때 사용합니다.
mapping의 의미대로 어떤 데이터 타입을 다른 데이터 타입으로 연결(mapping)하주는 역할을 합니다.
여기서는 files이라는 변수를 mapping이라는 데이터 타입으로 선언하고, 그것의 key 타입은 string이고, value 타입은 FileDetails라는 구조체 타입니다.

mapping이라는 개념이 데이터 타입이 다른 프로그래밍 언어에도 존재하는데, 그 문법 형태가 다르고, 중간에 =>와 같은 기호도 들어가보니 의미를 파악하기 헷갈리는데 단순히 key-value를 저장하는 데이터 타입이라고 보시면 쉽습니다.

나머지 솔리티디 코딩 내용은 소유자를 set하는 기능을 하는 함수와 get하는 기능을 하는 get 함수입니다. 단순히 상태변수인
구조체에 값을 읽고 쓰는 것입니다.

솔리디티 컴파일

remix 브라우저의 오른쪽 상단 메뉴중 Compile 탭에서 "Start Compile"를 누르면 아래와 같이 됩니다.

자세히 보면 느낌표가 몇 개 보입니다. 솔리티디는 업데이트가 매우 빠르게 되고 있어서 업데이트에 따라 호환성 이슈가 있어서 warning을 띄웁니다. 여기서는 함수나 변수의 가시성 (visibility) 문제와 event 함수 이름에 대해 이슈를 제기합니다. 아직은 호환이 되지만 미래에는 사용되지 않을 거란 메시지가 나타납니다.

event와 관련하여 잠시 찾아보니 기존에 event 함수를 아무거나 사용할 수 있었는데, 솔리디티 자체 키워드와 중복되어 사용하는 사용자들이 있어서 event함수는 'emit'란 함수로 통일한다는 내용입니다. 일단 여기서는 혼동을 피하기 위해서 무시하겠습니다.

2. 스마트 컨트랙트 배포

remix 브라우저 상단 메뉴중 Run 탭에서 아래와 같이 Create 버튼을 누르면 솔리디티로 작성한 스마트 컨트랙트가 생성 및 배포가 됩니다. 배포되는데 약간의 시간이 소요됩니다. 이 때 화면 하단에 상태가 표시됩니다. pending상태가 몇 초 지속된 후 스마트 컨트랙트가 생성되어 배포됩니다. 오른쪽 화면에서 배포된 스마트 컨트랙트의 주소를 확인할 수 있습니다.

우리가 작성한 스마트 컨트랙트가 블락체인의 하나의 블락에 포함된 것입니다. 따라서 해당 블락에 접근하는 것이 가능합니다., 엄밀히는 해당 스마트 컨트랙트에 배포된 주소로 접근할 수 있습니다.

그럼 다음 포스팅에서 배포된 스마트 컨트랙트 주소를 이용하여 Web3 API를 이용하여 파일 소유자를 기록하고, 읽어오는 웹 서비스를 구축해 보겠습니다.


오늘의 실습: 내용 이해가 안되더라도 그냥 따라해 보세요. 또 그것을 글로 기록해 보세요. 이해는 정도가 급격하게 증가할 것입니다.

댓글

댓글 본문
  1. etainclub@gmail.com
    아마도 web3 버전문제일거 같습니다.
    대화보기
    • 가은아빠
      안녕하세요? 요즘 Dapp 을 열심히 하고 있는데...

      app.js 파일 중 이런 에러가 뜨네요.. 펑션이 아니라고 나오는데 ㅜ ㅜ

      /home/oknsk/truffles/src/js/app.js:18
      var proof = proofContract.at("0x063e57b540a860faDfe97f768C01A44986a0795A");
      ^

      TypeError: proofContract.at is not a function
      at Object.<anonymous> (/home/oknsk/truffles/src/js/app.js:18:27)
    • ㄱㅂ1ㄱ1
    • ㅎㅎ
      http://remix.ethereum.org 로 접속해서 하시면 될겁니다ㅎㅎ
    • bobby
      Remix에서 Web3 로 provider를 변경하면 아래와 같이 오류가 발생합니다.

      Not possible to connect to the Web3 provider. Make sure the provider is running and a connection is open (via IPC or RPC).

      찾아보니, https ==> http 로 하라고 하던데 대체 어디서 변경을 해야 하는건지 모르겠네요..
      geth로 구동중인 port와 관련이 있는건지요...?
    • 세계최고프로그래머
      으악. 그거였네요. ^^ 우와아아아앜ㅋㅋㅋ 멋집니다. ㅎㅎㅎ 감격입니다. 감사합니다. ㅎㅎㅎㅎㅎ 저는 그만 정신을 잃고 말았습니다.