티스토리 뷰

1. web3 개념

2. web3 설치


1. web3 개념

[그림 1] web3 변천사

초기 웹 1.0은 서버-클라이언트 방식으로 각 인터넷 기업별로 독자적인 시스템을 구축해서 운영하는 방식이었다. 인터넷 홈페이지를 운영하는 모든 회사들은 독자적으로 서버를 갖추고 시스템을 운영하거나 웹호스팅이라 불리는 업체에 일정 사용료를 내고 서버를 임대해서 사용했다. 서버에는 홈페이지의 운영에 필요한 모든 파일이 저장되어 있고 홈페이지에서 제공되는 각종 서비스의 구동과 운영을 위한 프로그램들이 설치되어 있다.

 

이렇게 개별적으로 수 천만 개, 수 억 개의 인터넷 홈페이지가 운영되면서 서버는 늘어가고 이를 운영하는데 필요한 시스템도 복잡해졌다. 이러한 비효율을 없애기 위해 클라우드가 대두되었고 2000년대 중반부터 클라우드 방식의 중앙화된 효율적 웹이 기존의 인터넷 운영 시스템을 대체했다. 즉, 개별 기업들의 분산된 웹이 클라우드에 집중되면서 중앙화된 웹으로 효율화되었다.

 

시스템만 변화한 것이 아니라 웹 서비스 사용자의 경험도 크게 바뀌었다. 웹 1.0 대비 2.0은 사용자들의 참여가 기반이므로 기업이 제공하는 정보와 서비스를 일방적으로 보고 듣기만 하는 것이 아니라 능동적으로 서비스에 참여해 쓰고 말하는 것이 가능하다. 또한, 웹에 게재된 각종 정보와 데이터들은 개방되어서 다른 웹 서비스나 시스템에서 쉽게 활용하고 가져갈 수 있도록 개방화된 생태계로 바뀌었다. 

 

웹 2.0에서 더 나아가 웹 3.0은 탈중앙화, 상호운용성, 그리고 자율화를 보장하는 평등한 시스템을 지향한다. 기존의 웹처럼 플랫폼 기업이 독점적인 권한을 행사하며 사용자 위에 군림하는 것을 지양한다. 클라우드처럼 모든 데이터와 정보를 클라우드 위에 올려두고 이를 기업이 독점적으로 활용하는 것이 아닌 분산된 컴퓨팅 환경에서 시스템을 운영해 데이터의 이용 내역 등을 투명하게 관리한다.

 

 

2. web3 설치

$ npm init -y
$ npm i -D jest

위 명령어를 실행하여 jest를 설치한다. jest는 JavaScript 테스트 프레임워크이다.

 

$ npm i -g web3 ethereumjs-tx

위 명령어를 실행하여 web3와 ethereumjs-tx를 설치한다.

 

ethereumjs-tx는 트랜잭션 객체를 Ethereum Client가 이해할 수 있게 만들어주는 라이브러리이다.

 

/* jest.config.js */

const config = {
  verbose: true,
  testMatch: ["<rootDir>/**/*.test.js"],
};

module.exports = config;

jest.config.js라는 파일을 생성한 뒤 위의 내용을 적어준다. 이는 테스트를 진행할 파일의 위치를 지정하는데 필요하다.

 

[그림 2] package.json 수정

패키지 설치가 완료되었다면, 위와 같이 package.json 파일을 수정한다. 이제 npm run jest 명령어를 실행하여 JavaScript 테스트를 진행할 수 있다.

 

이제 본격적으로 web3를 이용한 테스트 코드를 작성해 보겠다.

/* web3.test.js */

const Web3 = require('web3');
const ethTx = require('ethereumjs-tx').Transaction;

describe('web3 test', () => {
    let web3, accounts, sender, receiver;

    it('Create web3 Instance', () => {
        web3 = new Web3(
            new Web3.providers.HttpProvider('http://127.0.0.1:8545')
        );
    });

    it('Latest Block Height', async () => {
        const latestBlock = await web3.eth.getBlockNumber();
    });

    it('accounts', async () => {
        accounts = await web3.eth.getAccounts();
        sender = accounts[0];
        receiver = accounts[1];
    });

    it('getBalance', async () => {
        const balance = await web3.eth.getBalance(accounts[0]);
        console.log('ETH : ', balance / 10 ** 18);
    });

    it('Unit Modification', () => {
        console.log(web3.utils.toWei('1', 'gwei'));
        console.log(web3.utils.toWei('1', 'ether'));
    });

    it('Transaction Count', async () => {
        const txCount = await web3.eth.getTransactionCount(sender);
        console.log(web3.utils.toHex(txCount));
    });

    it('Transaction Execution', async () => {
        const txCount = await web3.eth.getTransactionCount(sender);
        const privateKey = Buffer.from(
            '33d05a2d85f347f632860af17ee01c71d5275a82d4dbea85dd965f451c81f4d8',
            'hex'
        );
        const txObject = {
            nonce: web3.utils.toHex(txCount),
            from: sender,
            to: receiver,
            value: web3.utils.toHex(web3.utils.toWei('1', 'ether')),
            gasLimit: web3.utils.toHex(6721975),
            gasPrice: web3.utils.toHex(web3.utils.toWei('1', 'gwei')),
            data: web3.utils.toHex(''),
        };
        const tx = new ethTx(txObject);
        tx.sign(privateKey);
        const serializedTx = tx.serialize();
        console.log(serializedTx.toString('hex'));
        const TransactionObject = await web3.eth.sendSignedTransaction(
            '0x' + serializedTx.toString('hex')
        );
        console.log(TransactionObject);
    });

    it('Balance Check', async () => {
        const SenderBalance = await web3.eth.getBalance(sender);
        const ReceiverBalance = await web3.eth.getBalance(receiver);
        console.log('sender Balance : ', SenderBalance / 10 ** 18);
        console.log('receiver Balance : ', ReceiverBalance / 10 ** 18);
    });
});

코드 해석에 앞서 주의할 점은 위 코드를 실행할 때 ganache가 실행 중인 상태여야 한다는 것이다.

 

첫 번째 테스트에서는 new Web3()를 이용하여 새 인스턴스를 생성하였다.

 

최신 블록의 height를 구하려면 getBlockNumber()를 사용하면 된다.

 

getAccounts()는 ganache에서 제공한 임의의 주소 10개를 반환한다.

 

getBalance()는 해당 계좌의 balance 값을 반환한다.

 

우리나라 화폐의 개념에서 1억 원 = 100,000,000 원을 의미하듯이 이더리움 화폐에도 여러 단위가 존재한다. 이더리움의 가장 작은 단위는 wei로, 1 ether = 10 ^ 9 gwei = 10 ^ 18 wei를 의미한다.

 

getTransactionCount()는 해당 계정의 트랜잭션 수를 알려준다. 이 값은 nonce와 동일하다.

 

트랜잭션을 실행하기 위해 ethTx()로 새 인스턴스를 생성하여 sign()으로 서명한 후 serialize()한다.

그 값을  sendSignedTransaction()로 web3에 보내면 아래 그림과 같은 트랜잭션 객체가 생성된다.

 

[그림 3] TransactionObject 출력 값

TransactionObject에는 해당 트랜잭션에 대한 hash 값을 비롯하여 블록 해시, 가스 사용량 등의 정보가 담겨 있다.

 

트랜잭션이 제대로 실행되었다면 sender와 receiver의 balance 값에 변화가 생겼을 것이다. 이를 점검하는 것이 마지막 테스트이다.

 

[그림 4] balance 변화 확인

sender와 receiver에 대한 balance 값이 나타난다. 둘다 원래 100 ether를 갖고 있었지만 sender가 receiver에 2 ether를 주고 sender는 수수료를 지불했기 때문에 위와 같은 결과가 나오게 된다.

'BlockChain' 카테고리의 다른 글

[BlockChain] ganache-cli, MetaMask 설치  (0) 2022.06.28
[BlockChain] UTXO vs. Account Model  (0) 2022.06.21
[BlockChain] ECDSA  (0) 2022.06.20
블록체인 기초  (0) 2022.06.10
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2024/09   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30
글 보관함