Dapp(Decentralized Application) 탈중앙화 어플리케이션..처음에 들을 때는 이해가 되지 않았었다. truffle은 뭔지, Solidity는 뭔지, Ganache는 뭔지,, 앱에 블록체인을 연동하는 것은 또 뭔지.. 공부하다 보니 웹 개발과 크게 다르지 않다. 큰 차이점이 있다면 데이터를 어디에 저장할 것인가? 이다. 기존의 중앙화 방식은 한 기업에서 데이터를 관리 했다면, Dapp에서는 분산 저장을 한다는 것이다. 블록체인 기술을 공부하면 쉽게 이해할 수 있다!
자바 웹 개발 | 이더리움 컨트랙트 개발 | |
---|---|---|
언어 | Java | Solidity |
프레임워크 | Spring | Truffle |
개발환경 | Tomcat, Weblogic, ... | Ganache, geth, ... |
운영환경 | Centralized : 기업이 관리하는 데이터센터 | Decentralized : 분산공유 네트워크 |
Tomcat, Weblogic, ... | 누구나 참여 가능한 이더리움 네트워크에 참여한 노드들이 | |
RDBMS, NOSQL, ... | 데이터를 공유 |
npm install truffle -g
truffle init
vs code로 열어보면 다음과 같은 파일들이 생성 된다.
contracts 디렉토리 : solidity를 이용한 스마트 컨트랙트 디렉토리
migrations 디렉토리 : 배포 스크립트 디렉토리
test 디렉토리 : 테스트 스트립트 디렉토리
truffle-config.js : 트러플 설정
module.exports = {
// 네트워크 설정 (로컬, 테스트넷, 메인넷, ... 등등을 설정 한다.)
networks: {
dev: { // 이름은 아무거나 사용 가능
host: "127.0.0.1", // Localhost
port: 8545, // Standard Ethereum port
network_id: "*", // Any network
},
},
// 컴파일러 설정
compilers: {
solc: {
version: "0.8.9", // 컴파일러 버전
}
},
};
// SPDX-License-Identifier: UNLICENSED
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.9; // 컴파일러 버전 명시
// 컨트랙트 명시
contract HelloWorld {
string public greeting; // 문자열 타입 변수 선언
// 생성자를 통해 값을 초기화 한다.
constructor(string memory _greeting) {
greeting = _greeting;
}
// setter 함수를 통해 값을 변경 할 수있다.
function setGreeting(string memory _greeting) public{
greeting = _greeting;
}
// 변수값 출력
function say() public view returns(string memory){
return greeting;
}
}
const HelloWorld = artifacts.require("HelloWorld");
module.exports = function (deployer) {
// 첫번째 파라미터는 배포할 솔리디티 파일을 명시
// 두번째 파라미터는 HelloWorld.sol의 생성자의 매개변수에 전달한다.
deployer.deploy(HelloWorld, "Hello World!!");
};
fruffle migrate --network dev
truffle console --network dev // 네트워크 이름 지정
const helloWorld = artifacts.require("HelloWorld");
contract("HelloWorld", function(accounts){
// HelloWorld 컨트랙트에 접근
before(async () =>{
this.instance = await helloWorld.deployed();
});
// say() 테스트
it("should be initialized with correct value", async () => {
const greeting = await this.instance.greeting();
assert.equal(greeting, "Hello World!!", "Wrong initialized value!");
});
// setGreeting() 테스트
it("should change the greeting", async () => {
const val = "Hello, Ethereum!";
// 상태를 바꾸는 함수는 계정이 필요하다
await this.instance.setGreeting(val, {from: accounts[0]});
const greeting = await this.instance.say();
assert.equal(greeting, val, "dose not change the value!");
});
});
npm init
npm install @truffle/hdwallet-provider
const HDWalletProvider = require('@truffle/hdwallet-provider');
const fs = require('fs');
const mnemonic = fs.readFileSync(".secret").toString().trim(); // private 키 불러오기
module.exports = {
networks: {
...
ropsten: {
provider: () => new HDWalletProvider(mnemonic, `https://ropsten.infura.io/v3/YOUR-PROJECT-ID`),
network_id: 3, // Ropsten's id
gas: 5500000, // Ropsten has a lower block limit than mainnet
confirmations: 2, // # of confs to wait between deployments. (default: 0)
timeoutBlocks: 200, // # of blocks before a deployment times out (minimum/default: 50)
skipDryRun: true // Skip dry run before migrations? (default: false for public nets )
},
},
...
};
truffle migrate --network ropsten
배포 성공!
소중한 이더가 소모되었다..
ropsten 이더스캔으로 가서 확인할 수 있다.
https://ropsten.etherscan.io/
HelloWorld 의 해시값으로 검색!!
npx truffle unbox react
이러한 기본 구성이 생기고 개발을 시작 할 수 있다.
App.js 에서 프로그램이 실행 될 때 SimpleStorage 컨트랙트의 set 함수를 호출하도록 되어있다.
truffle-config.js 를 살펴보자.
const path = require("path");
module.exports = {
// See <http://truffleframework.com/docs/advanced/configuration>
// to customize your Truffle configuration!
contracts_build_directory: path.join(__dirname, "client/src/contracts"), // 빌드 디렉토리
networks: {
develop: {
host: "127.0.0.1",
port: 8545,
network_id: "*",
}
}
};
truffle migrate --network develop
npm run start