‘이더리움 댑 개발’ 세미나 6. 9장. Connecting the UI to Our Contracts
이번 세미나는 9장. Connecting the UI to Our Contracts를 다룹니다.
댑 UI는 리액트를 사용해서 작성합니다. 이더리움 댑 개발에서는 프론트엔드 프레임워크로 리액트를 선호합니다. 트러플은 리액트로 댑 프론트엔드 개발을 빠르게 시작할 수 있도록 react box를 제공합니다.
리액트 내용을 다루고는 있지만 매우 단순한 UI를 작성하는 수준입니다. 리액트를 모르더라도 책 내용을 따라가는데는 지장이 없습니다. 하지만 이후 세미나에서는 좀 더 복잡한 UI를 작성하기 때문에 리액트를 모르신다면 간단하게나마 리액트 학습을 해 두시기를 권합니다.
프로젝트 셋업
- greeter-dapp 디렉토리를 생성하고, 해당 디렉토리에서 react 트러플 박스를 언박스합니다.
- truffle unbox react
트러플 개발 모드에서 컨트랙트 컴파일 및 배포
- truffle-config.js의 networks의 develop 부분을 작성합니다.
- host: “127.0.0.1”, port: 8545, network_id: “*”
- truffle develop 명령을 실행해서 개발 모드를 시작합니다.
- truffle develop은 ganache-cli로 로컬 블록체인을 실행합니다.
- 로컬 블록체인 실행 url과 니모닉을 복사해 둡니다.
- truffle develop은 truffle 명령들을 개별적으로 사용하지 않고 통합적으로 사용할 수 있는 개발 환경을 제공합니다.
- truffle compile과 같이 실행할 필요 없이 compile 명령을 실행하면 됩니다.
- truffle develop은 ganache-cli로 로컬 블록체인을 실행합니다.
- 개발 모드에서 compile 명령을 실행해서 컨트랙트를 컴파일하고, migrate 명령을 실행해서 컨트랙트를 배포합니다.
메타마스크의 네트워크 연결을 변경, 계정 임포트
- 네트워크 연결을 ‘로컬 호스트 8545’로 변경합니다.
- 로그아웃하고, 로그인 화면의 하단에서 계정 시드 구문으로 가져오기를 클릭합니다.
- 트러플 개발환경에서 생성된 니모닉을 복사해서 붙여넣기 하고 비밀번호를 설정한 후 복구 버튼을 클릭합니다.
- 계정이 임포트되었음을 볼 수 있습니다.
웹 클라이언트 실행
- 프로젝트 디렉토리 하위 디렉토리인 client로 이동합니다.
- 웹 클라이언트 프로젝트를 설치하고 실행합니다.
- npm install
- npm start
- 웹 클라이언트 페이지가 뜨고 메타마스크에 연결이 요청되고, 메타마스크에 연결하면 트랜잭션 승인이 요청됩니다. 승인하면 트랜잭션이 처리되고 결과가 페이지에 나타납니다.
Greeter 컨트랙트 작성, 배포 스크립트 작성
- 이전 세미나 내용을 참조해서 현재 프로젝트에 작성된 내용을 Greeter 프로젝트 내용으로 변경합니다.
- 컨트랙트 변경, 배포 스크립트 변경
Greeter 웹 클라이언트 작성
- App.js
- SimpleStorageContract를 GreeterContract로 변경합니다.
- storageValue 값을 저장할 필요가 없습니다. greeting을 저장해야 합니다.
- state = { greeting: ”, web3: null, accounts: null, contract: null };
- runExample 함수를 Greeter에 맞게 변경합니다.
- Greeter 컨트랙트의 greet 함수를 호출해서 현재 설정된 인삿말을 구합니다. greet 함수는 읽기에 해당함으로 call()을 사용합니다.
-
12const response = await contract.methods.greet().call()this.setState({ greeting: response });
- render 함수의 return 부분을 Greeter에 맞게 변경합니다.
- “Greeter”를 헤더로 출력합니다.
- <h1>Greeter</h1>
- Greeter 컨트랙트의 greet 함수 실행 결과를 헤더 밑에 출력합니다.
- {this.state.greeting}
- 새로운 인사말을 받을 수 있는 폼과 제출 버튼을 작성합니다.
-
12345678<form><label>New Greeting:<input type="text" value={this.state.greeting} onChange={e => this.handleGreetingChange(e)} /></label></form><button onClick={this.formSubmitHandler}> Submit </button>
- 입력 값이 변경될 때(onChange)에 대한 이벤트 핸들러(handleGreetingChange)를 작성합니다.
- 변경된 값을 greeting 상태로 설정해야 합니다.
-
1234handleGreetingChange = (e) => {const inputVal = e.target.valuethis.setState({ greeting: inputVal })}
-
- 변경된 값을 greeting 상태로 설정해야 합니다.
- 입력 값이 변경될 때(onChange)에 대한 이벤트 핸들러(handleGreetingChange)를 작성합니다.
- 제출 버튼이 눌렸을 때(onClick )에 대한 이벤트 핸들러(formSubmitHandler)를 작성합니다.
- setGreeting은 쓰기 함수임으로 send()를 사용합니다.
- 인삿말은 owner만 변경가능합니다.
-
1234formSubmitHandler = async () => {const { accounts, contract, greeting } = this.state;await contract.methods.setGreeting(greeting).send({from: accounts[0]});}
-
-
- “Greeter”를 헤더로 출력합니다.
App.js web3관련 부분 좀 더 자세히 살펴보기
- import getWeb3 from “./getWeb3”;
- getWeb3.js
- web3 인스턴스를 리턴합니다.
- 주입된 web3를 리턴하거나 로컬 블록체인을 연결하는 provider로 설정된 web3를 리턴합니다.
- web3 인스턴스를 리턴합니다.
- getWeb3.js
-
123456const networkId = await web3.eth.net.getId();const deployedNetwork = FundraiserFactoryContract.networks[networkId];const instance = new web3.eth.Contract(FundraiserFactoryContract.abi,deployedNetwork && deployedNetwork.address);
- web3.eth.Contract 객체는 컨트랙트와 상호작용을 매우 쉽게 하도록 해 줍니다. 마치 컨트랙트를 자바 스크립트 객체처럼 다룰 수 있게 해 줍니다. web3.eth.Contract 객체를 생성하려면 컨트랙트의 abi와 주소가 필요합니다.
- 개발과정 중에 다양한 네트워크에 배포될 수 있기 때문에 어떤 네트워크에 배포되었는지를 알아야 하고, 컨트랙트 함수를 호출하려면 컨트랙트 주소와 함수 시그니처를 알아야 합니다. 컨트랙트의 함수 시그니처는 컨트랙트 abi로 작성됩니다.
- 컴파일하면 컨트랙트에 대한 json 객체가 생성됩니다. 환경 설정에 따라 빌디 디렉토리에 “컨트랙트이름.json” 파일로 저장됩니다. 이 객체에 컨트랙트의 abi와 networks 정보가 포함되어 있습니다.
- 현재 web3에 연결된 networkId는 web3.eth.net.getId()로 구합니다. 현재 연결된 networkId로 컨트랙트 json 객체에서 network 정보를 구합니다. 컨트랙트의 전체 배포 네트워크에 대한 정보는 networks 배열로 작성되어 있습니다. 컨트랙트 주소는 network 객체 address속성으로 작성되어 있습니다.
- networks에 networkId에 해당하는 network 정보가 있으면 network 객체의 address 값을 주소로 사용합니다.
- 개발과정 중에 다양한 네트워크에 배포될 수 있기 때문에 어떤 네트워크에 배포되었는지를 알아야 하고, 컨트랙트 함수를 호출하려면 컨트랙트 주소와 함수 시그니처를 알아야 합니다. 컨트랙트의 함수 시그니처는 컨트랙트 abi로 작성됩니다.
- web3.eth.Contract 객체는 컨트랙트와 상호작용을 매우 쉽게 하도록 해 줍니다. 마치 컨트랙트를 자바 스크립트 객체처럼 다룰 수 있게 해 줍니다. web3.eth.Contract 객체를 생성하려면 컨트랙트의 abi와 주소가 필요합니다.