이타인클럽

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

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

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

 

이전글에서 스마트 컨트랙트 코딩과 배포를 설명했고, 이번에는 3번에 대해서 설명하겠습니다. 이번 내용을 따라하기 위해서는 이전 1, 2번을 하셔야 합니다.

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

이번에는 콘솔에서 스마트 컨트랙트 호출하는 방식이 아니라 웹 상에서 버튼 클릭으로 스마트 컨트랙트를 호출하는 방법을 설명하려고 합니다. 이 때 이용되는 것이 web3.js입니다. 그래서 geth를 실행할 때 web3.js를 지원하도록 옵션을 설정했습니다.
etain@etainclub$ nohup geth --rpc --rpcaddr "0.0.0.0" --rpcport 8545

위 옵션은 web에서 eth 클라이언트를 8545 포트를 이용하여 접속할 수 있도록 한 것입니다.

제가 웹 프로그래밍에 대한 지식은 많지 않기 때문에 웹 관련 설명을 하기 보다는 따라하실 수 있도록 간략한 설명만 붙이는 식으로 하겠습니다. 웹 프로그래밍관련 정보들은 검색하시면 많은 자료를 찾으실 수 있습니다.

아래 설명하는 코드는 완전한 코드가 아닙니다. 아래 설명에 빠진 부분이 있으니, 다음 사이트에서 소스 코드를 확인하셔야 합니다. 웹 프로그래밍관련된 부분에서 중요하지 않는 부분은 생략했습니다.
https://github.com/PacktPublishing/Building-Blockchain-Projects/tree/master/Chapter04/Final

3. 웹서비스 백엔드 구축

특정 웹페이지에 접속하며 스마트 컨트랙트를 호출하려면 웹페이지를 서비스는 하는 서버가 필요합니다. 여기서는 이 부분에 대해서 설명합니다. 백엔드라는 말은 서버단에서 돌아가는 프로그램이며, 사용자에게 직접적으로 드러나지 않는다고 해서 백엔드(Back End)로 불립니다. 반면에 사용자에게 직접적으로 노출되어 서비스하는 부분을 프로트 엔드(Front End)라고 합니다.

백엔드에서 사용하는 코딩 언어는 javascript입니다. 또 서버를 구동하기 위해서는 node.js라는 프로그램 설치가 필요합니다. 이것은 코딩을 다 마친 후에 설명드리겠습니다.

3.1 웹페이지 서비스 서버 코딩

적당한 폴더에 app.js라는 파일로 아래와 같이 코딩합니다. 웹페이지를 서비스하는 코드입니다.

var express = require("express");  
var app = express();  
var server = require("http").createServer(app);
var io = require("socket.io")(server);
server.listen(8080);

다음으로 브라우저에 접속할 때 표시되는 라우팅을 코딩합니다. 여기서 웹페이지 접속할 때 표시되는 index.html라는 파일의 내용은 프론트 엔드에서 코딩하도록 하겠습니다. 여기서는 파일 경로와 이름만 정해놓겠습니다.

app.use(express.static("public"));
app.get("/", function(req, res){
    res.sendFile(__dirname + "/public/html/index.html");
})

3.2 스마트 컨트랙트 접속을 위한 코딩

다음으로 배포된 스마트 컨트랙트에 접속하는 코딩을 합니다.

var Web3 = require("web3");
web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"));  
var proofContract = web3.eth.contract([{"constant":false,"inputs":[{"name":"fileHash","type":"string"}],"name":"get","outputs":[{"name":"timestamp","type":"uint256"},{"name":"owner","type":"string"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"owner","type":"string"},{"name":"fileHash","type":"string"}],"name":"set","outputs":[],"payable":false,"type":"function"},{"anonymous":false,"inputs":[{"indexed":false,"name":"status","type":"bool"},{"indexed":false,"name":"timestamp","type":"uint256"},{"indexed":false,"name":"owner","type":"string"},{"indexed":false,"name":"fileHash","type":"string"}],"name":"logFileAddedStatus","type":"event"}]);
var proof = proofContract.at("0x57da6aee3eb32c7c9192d52e374f05a12d449ff0");

주의할 것은 위 코드의 마지막에 proofContract.at("xxxxxxxx") 부분에 여러본의 컨트랙트 주소를 넣어야 하는 것입니다. 아래와 같이 remix에서 "run" 탭에서 컨트랙트를 생성하고, 배포한 후 얻어지는 컨트랙트 주소를 복사하여 붙여 넣습니다.

3.3 웹페이지 버튼 서비스 코딩

웹페이지에서 사용될 "submit" 버튼과 "get info"버튼 서비스를 담당하는 코드를 작성합니다.
먼저 "submit"버튼 서비스 코딩입니다.

app.get("/submit", function(req, res){
    var fileHash = req.query.hash;
    var owner = req.query.owner;
    proof.set.sendTransaction(owner, fileHash, {
        from: web3.eth.accounts[0],
    }, function(error, transactionHash){
        if (!error)
        {
            res.send(transactionHash);
        }
        else
        {
            res.send("Error");
        }
    })
})

윗 코드 중 아래 부분에서 스마트 컨트랙트의 set함수를 통해서 sendTransaction함수를 호출하고 있습니다. 여기서는 트랜잭션을 생성하고, 이 트랜잭션의 해쉬를 웹페이지에 표시합니다.

proof.set.sendTransaction(owner, fileHash, {
        from: web3.eth.accounts[0],
    }, function(error, transactionHash){

다음으로 "get info"버튼 서비스 코딩입니다. 여기서는 스마트 컨트랙트의 get함수를 호출하여 스마트 컨트랙트에 저장된 timestamp와 ower값을 웹페이지 출력합니다.

app.get("/getInfo", function(req, res){
    var fileHash = req.query.hash;
    var details = proof.get.call(fileHash);
    res.send(details);
})

3.4 로그를 위한 코딩

스마트 컨트랙트의 이벤트를 감시하는 코드를 작성합니다.

proof.logFileAddedStatus().watch(function(error, result){
    if(!error)
    {
        if(result.args.status == true)
        {
            io.send(result);
        }
    }
})

댓글

댓글 본문
  1. ㅁㅁ
    웹서비스 버튼 코딩도 어디서 해야하는지 알려주세요..... 글은 너무 좋은데 위치들이 어렵네요
    대화보기
    • ㅁㅁ
      혹시 위의 라우팅 코딩 부분은 어디다가 적어놓는건지 여쭤봐도 될까요??? 계속 app.js에 하는건지요?