SlideShare ist ein Scribd-Unternehmen logo
1 von 58
Downloaden Sie, um offline zu lesen
● Eric Kim, Developer Evangelist
at Ground X
Meetup Topic
● 19:00 ~ 19:30 (30") 등록 확인
● 19:30 ~ 20:20 (50") Klaytn 세션
● 20:20 ~ 20:50 (30") Q&A
● 20:50 ~ 21:30 (40") 네트워킹
Klaytn 101 #2 Blockchain Application(BApp) 동작원리와 구성요소 이해하기
Klaytn 101 #2 Blockchain Application(BApp) 동작원리와
구성요소 이해하기
Eric Kim, Ground X
Developer Evangelist
Klaytn Developer Meetup #2
Blockchain Application(BApp) 동작원리와 구성요소 이해하기
Today’s Agenda
● BApp의 동작원리와 BApp을 구성하는 요소들에 대해 알아봅니다
● 예제와 함께 웹기반 BApp 구현방법을 알아봅니다
○ 오늘 구현할 BApp은 Count Bapp입니다
○ 코드는 여기에: github.com/w3kim/countbapp
○ 구현 예시는 여기에: countbapp.herokuapp.com
5
BApp의 동작원리와
BApp을 구성하는 요소
6
Blockchain Application (BApp)
● 블록체인 어플리케이션(BApp)은 블록체인을 사용하는 어플리케이션
○ 기존의 기술로 풀기 어려운 문제들을 블록체인의 특성을 활용하여 풀어내는 것이 목적
● 불변성과 투명성이 대표적인 블록체인의 특성
○ 한번 기록된 정보는 변경할 수 없으며
○ 정해진 규칙(e.g., 블록체인 프로토콜, 컨트랙트에 구현된 로직)에 따라 상태를 변경
○ 기록의 내역이 블록에 공개되어 있으므로 누구든지 정보의 진실여부를 확인 가능
7
BApp의 동작원리
● 쓰기 (Write)
○ 블록체인에 데이터를 쓰는 모든 행위는 트랜잭션(TX)으로 표현
○ e.g., 어카운트 간 KLAY의 전송
○ e.g., 스마트 컨트랙트 배포
○ e.g., 스마트 컨트랙트의 상태를 변경하는 함수를 호출
● 읽기 (Read)
○ 누구든지 블록 정보를 가지고 있다면 쓰여진 데이터를 확인 가능
○ e.g., TX 확인
○ e.g., 스마트 컨트랙트 상태 확인
8
BApp의 구성요소
9
Client
(Frontend)
Service Server/Proxy
(Backend)
Klaytn
(Blockchain)
Fully decentralized
Semi-decentralized w/ proxy
BApp 개발 형태
1. Fully decentralized
○ 사용자(클라이언트)가 직접 블록체인과 통신
2. Semi-decentralized with (centralized) proxy
○ 클라이언트가 블록체인과 통신하기 위해 중개 서버와 통신
○ 블록체인 기반으로 만들어진 서비스가 있고 그 서비스를 사용자들이 사용하는 형태
○ 클라이언트 ⇔ 중개서버 ⇔ 블록체인
10
BApp 개발 형태: Fully Decentralized
● 장점:
○ 높은 투명성, 신뢰형성에 필요한 추가 비용 없음
○ 사용자의 익명성 보장 가능
○ (설치형 BApp의 경우) 관리 비용 낮음
● 단점:
○ 사용자 책임 증가, 어려운 UX
○ 로직 변경 어려움
○ 사용자가 블록체인에 상시 접속할 필요 및 블록을 복제할 필요 있음
11
BApp 개발 형태: Semi-Decentralized with Proxy
● 장점:
○ (기존의 서비스들과 동일한) 높은 수준의 UX
○ 사용자가 블록체인과 직접 통신할 필요 없음
○ 로직 변경 비교적 쉬움
● 단점:
○ 신뢰비용 발생
○ 일부 중앙화 ⇒ 서비스가 Single Point of Failure (SPoF)가 됨
○ 관리 비용 높음
12
목적에 맞는
BApp 개발 형태를
선택하는 것이 중요
13
BApp 개발 구분
● 프론트엔드(Frontend)
○ 사용자가 직접 사용하는 프로그램 (e.g., mobile app, web page/app)
○ 키관리, TX 생성, 서명, 전송 등을 프론트엔드에서 처리
● 백엔드(Backend)
○ 사용자에 눈에 보이지 않는 상시 동작하는 서비스
○ 프론트엔드가 사용자 요청을 전달하면 백엔드가 처리하는 구조
○ 블록체인 동기화 등 컴퓨팅 리소스가 많이 필요한 일을 처리하는데 적합
○ 블록체인 동기화, 블록 파싱(parsing), TX 전달, 가스비 대납 등을 백엔드에서 처리
14
개발 형태 별 BApp 개발 조합
● Fully decentralized = Frontend + Blockchain
○ e.g., Web/Android/Windows + Klaytn
● Semi-decentralized = Frontend + Backend + Blockchain
○ e.g., Web + Java Server on AWS + Klaytn
○ e.g., Android + Node.js Server on Azure + Klaytn
15
프론트엔드 개발
● BApp이 실행되는 환경에 따라 개발방법이 달라짐
○ 실행환경: Web, Mobile (Android, iOS), Native (Windows, Linux, macOS)
○ 어느 환경에서 개발하느냐에 따라 개발 언어와 UI/UX 디자인, 사용 SDK가 달라짐
○ Klaytn은 Javascript, Java (Android, Native) SDK를 제공
● 프론트엔드 개발에 영향을 끼치는 실행환경 중 하나가 지갑
○ 지갑의 존재유무, 지갑의 선택에 따라 개발방법이 변경될 수 있음
○ 특정 지갑을 사용할 경우 해당 지갑이 제공하는 라이브러리를 사용
16
지갑 (Wallet)
● TX를 서명하려면 키가 필요
○ 키 → 어카운트; 서로 다른 키는 다른 어카운트에 매핑
○ 하나의 어카운트로 여러 BApp을 사용하려는 사용자의 니즈가 존재
● 지갑 = 키를 관리하는 프로그램
○ 키를 보관하고 BApp이 요청할 때마다 보관 중인 키로 TX를 서명
○ 여러 유형의 지갑이 존재
○ e.g., 브라우저 플러그인, Dapp 브라우저 내장 지갑, 클라우드 지갑, 디바이스 지갑
17
지갑을 고려한 BApp 개발
● 어떤 지갑을 사용하느냐에 따라 사용자 환경이 변화
○ 어떤 형태로 BApp을 만들 것인지? 웹앱? 모바일 웹? 모바일 네이티브? 데스크탑?
○ BApp에 지갑을 내장할 것인지 아니면 외부 지갑을 사용할 것인지
○ 외부 지갑을 쓸 경우 개발하려는 BApp 형태와 맞는 지갑이 어떤 것인지?
○ e.g., 웹앱의 경우 Metamask를 사용 가능 (Ethereum)
○ e.g., 모바일 웹 또는 모바일 네이티브의 경우 삼성 블록체인 키스토어를 사용 가능 (Klaytn)
BApp의 목적 및 타겟 사용자를 분석하여 어느 형태로 키를 관리할지 결정
18
백엔드
● 블록체인 프로토콜 이외의 정보를 관리할 경우 필요
○ UX 향상 및 서비스 구현을 위해 TX 외 다른 정보가 필요할 경우 백엔드를 운영
● 서비스 제공자가 실행환경을 결정
○ 개발방법 선택이 비교적 자유로운편이나 대부분의 경우 플랫폼 SDK 존재유무에 따라 방향을 결정
19
예제로 배우는 BApp 개발
20
Count BApp
블록체인에 숫자를 기록하는 BApp
● Count BApp 사용자는 다음을 할 수 있어야 합니다.
○ 가장 마지막 블록 높이를 확인
○ 블록체인에 기록된 숫자를 확인
○ 자신의 어카운트 비밀키를 입력하여 어카운트 주소를 확인
○ (자신의 어카운트 비밀키를 사용하여) 숫자를 1 더할 수 있음
○ (자신의 어카운트 비밀키를 사용하여) 숫자를 1 뺄 수 있음
Count BApp 화면구성예시
Private Key Enter user key here Set
Address 0xADDRESS_OF_THE_PROVIDED_KEY
Block# #########
#########Count
+
-
Last
Participant
0xADDRESS_OF_THE_LAST_PARTICIPANT
Result https://baobab.scope.klaytn.com/tx/...
Count 스마트 컨트랙트 (Count.sol)
pragma solidity ^0.5.6;
contract Count {
uint public count = 0;
address public lastParticipant;
function plus() public {
count++;
lastParticipant = msg.sender;
}
function minus() public {
count--;
lastParticipant = msg.sender;
}
}
Count 스마트 컨트랙트 with Comments
pragma solidity ^0.5.6;
contract Count {
uint public count = 0;
address public lastParticipant;
function plus() public {
count++;
lastParticipant = msg.sender;
}
function minus() public {
count--;
lastParticipant = msg.sender;
}
}
숫자를 기록하는 상태를 만듭니다.
마지막에 숫자를 변경한 사람의 주소를
기록하는 상태를 만듭니다.
숫자를 1 증가시키고 변경한 사람의
주소를 기록합니다.
숫자를 1 감소시키고 변경한 사람의
주소를 기록합니다.
Count BApp 실행예시
count.sol @ 0xCONTRACT
---
plus()
minus()
---
uint count
address lastParticipant
User A @ 0xADDR1
User B @ 0xADDR2
User C @ 0xADDR2
0xADDR1 → plus() // count = 1
0xADDR2 → count() → 1
0xADDR3 → minus() // count = 0
0xADDR1 → plus() // count = 1
0xADDR1 → count() → 1
개발 스택
다음 소프트웨어 및 라이브러리를 사용하여 Count BApp을 개발합니다
항목 선택
개발 언어 Javascript
소프트웨어 플랫폼 Node.js
사용자 인터페이스 React*
Klaytn SDK caver-js
개발 순서
1. Baobab에서 어카운트 만들기
2. KLAY Faucet에서 테스트 KLAY 받기
3. IDE로 Count.sol 작성, 배포, 테스트 실행하기
4. caver-js + React로 프론트엔드 만들기
1. Baobab 어카운트 생성
● Klaytn Wallet을 사용 -
baobab.wallet.klaytn.com
2. KLAY Faucet
● 5 KLAY/day
● IP당 1,000회 리밋 설정
3. Klaytn IDE
● 손쉬운 컨트랙트 작성, 컴파일, 배포, 테스트를 위한 도구
● ide.klaytn.com
3-1. 컨트랙트 컴파일
3-2. 컨트랙트 배포 1/4
3-2. 컨트랙트 배포 2/4
3-2. 컨트랙트 배포 3/4
3-2. 컨트랙트 배포 4/4
3-3. 컨트랙트 실행
4. 프론트엔드 개발
1. caver-js 불러오기
2. BlockNumber 컴포넌트
3. KeyAndAddress 컴포넌트
4. Count 컴포넌트
4-1. caver-js 불러오기
import Caver from 'caver-js'
const BAOBAB_TESTNET_RPC_URL = 'https://api.baobab.klaytn.net:8651/'
const caver = new Caver(BAOBAB_TESTNET_RPC_URL)
export default caver
4-2. BlockNumber 컴포넌트 1/3
import React from 'react'
import caver from '../klaytn/caver'
class BlockNumber extends React.Component {
state = {
currentBlockNumber: '...loading',
}
getBlockNumber = async () => {
const blockNumber = await caver.klay.getBlockNumber()
this.setState({ currentBlockNumber: blockNumber })
}
// more on next slide
}
export default BlockNumber
4-2. BlockNumber 컴포넌트 2/3
// import statements
class BlockNumber extends React.Component {
// omitted things from previous slide
intervalId = null
componentDidMount() {
this.intervalId = setInterval(this.getBlockNumber, 1000)
}
componentWillUnmount() {
if (this.intervalId) clearInterval(this.intervalId)
}
// more on next slide
}
export default BlockNumber
4-2. BlockNumber 컴포넌트 3/3
// import statements
class BlockNumber extends React.Component {
// omitted things from previous slide
render() {
const { currentBlockNumber } = this.state
return (
<div>
<h4>
<span>Block No. {currentBlockNumber}</span>
</h4>
</div>
)
}
}
export default BlockNumber
4-3. KeyAndAddress 컴포넌트
import React from 'react';
import caver from '../klaytn/caver';
class PrivateKeyInput extends React.Component { … }
class KeyAndAddress extends React.Component { … }
export default KeyAndAddress
4-3. PrivateKeyInput 1/2
// import statements
class PrivateKeyInput extends React.Component {
constructor(props) {
super(props); // assume parent component has passed a function `reloadAddress(key)`
this.state = {
privateKey: ''
};
}
handleChange = (e) => {
this.setState({
privateKey: e.target.value
});
}
// more on next slide
}
// omitted for brevity
4-3. PrivateKeyInput 2/2
// import statements
class PrivateKeyInput extends React.Component {
// things from previous slide
render() {
const { privateKey } = this.state;
return (<div><form><div>
<label for='inputKey'>Private Key</label>
<input type='text' placeholder="your private key starting with 0x"
onChange={this.handleChange} id="inputKey" />
</div>
<button onClick={() => this.props.reloadAddress(privateKey)}>Set</button>
</form></div>);
}
// more on next slide
}
// omitted for brevity
4-3. KeyAndAddress 1/4
// import statements
class KeyAndAddress extends React.Component {
constructor(props) {
super(props);
this.state = {
privateKey: '',
address: ''
};
}
reloadAddress = (key) => { … }
render() { … }
}
// omitted for brevity
4-3. KeyAndAddress 2/4
// import statements
class KeyAndAddress extends React.Component {
// things from previous slide
reloadAddress = (key) => {
let account;
try {
account = caver.klay.accounts.privateKeyToAccount(key);
} catch (e) {
console.error(e);
}
// more on next slide
}
}
// omitted for brevity
4-3. KeyAndAddress 3/4
// import statements
class KeyAndAddress extends React.Component {
// things from previous slide
reloadAddress = (key) => {
// continued from the previous slide
if (account) {
this.setState({ privateKey: key, address: account.address });
this.props.propagateKey(key);
} else {
this.setState({ privateKey: '', address: '' });
this.props.propagateKey(false);
}
}
}
// omitted for brevity
4-3. KeyAndAddress 4/4
// import statements
class KeyAndAddress extends React.Component {
// things from previous slide
render() {
const { address } = this.state;
return (<div>
<PrivateKeyInput reloadAddress={this.reloadAddress} /><hr />
<form><div>
<label for='addressField'>My Address</label>
<input id='addressField' type='text' disabled value={address} />
</div></form></div>
);
}
}
// omitted for brevity
4-4. Count 컴포넌트
import React from 'react'
import caver from "../klaytn/caver"
const ABI = require("../assets/abi.json");
class Count extends React.Component {
constructor() { … }
setPrivateKey(key) { … }
getCount = async () => { … }
callPlus = () => { … }
callMinus = () => { … }
componentDidMount() { … }
componentWillUnmount() { … }
render() { … }
}
export default Count
4-4. Count 1/7
// import statements and ABI
class Count extends React.Component {
constructor() {
super();
// assume .env file contains REACT_APP_CONTRACT_ADDRESS variable
this.countContract = process.env.REACT_APP_CONTRACT_ADDRESS && ABI &&
new caver.klay.Contract(ABI, process.env.REACT_APP_CONTRACT_ADDRESS);
this.state = { count: '', lastParticipant: '', privateKey: '' };
this.wallet = caver.klay.accounts.wallet;
}
// more on next slide
}
export default Count
4-4. Count 2/7
class Count extends React.Component {
// exposed function allowing anyone with the right reference can call this function
setPrivateKey(key) {
this.wallet.clear();
if (key) {
this.wallet.add(key);
}
this.setState({
privateKey: key
});
}
// more on next slide
}
export default Count
4-4. Count 3/7
class Count extends React.Component {
getCount = async () => {
const count = await this.countContract.methods.count().call();
const lastParticipant = await this.countContract.methods.lastParticipant().call();
this.setState({
count,
lastParticipant,
});
}
// more on next slide
}
export default Count
class Count extends React.Component {
callPlus = () => {
const walletInstance = this.wallet[0];
if (!walletInstance) return;
this.countContract.methods.plus().send({
from: walletInstance.address,
gas: '200000',
})
.once('transactionHash', (txHash) => { console.log(`Sending a transaction... ('plus') txHash: ${txHash}`); })
.once('receipt', (receipt) => {
console.log(`Received receipt!`, receipt);
this.setState({ txHash: receipt.transactionHash, });
})
.once('error', (error) => { alert(error.message); });
}
// more on next slide
}
export default Count
4-4. Count 4/7
class Count extends React.Component {
callPlus = () => {
const walletInstance = this.wallet[0];
if (!walletInstance) return;
this.countContract.methods.minus().send({
from: walletInstance.address,
gas: '200000',
})
.once('transactionHash', (txHash) => { console.log(`Sending a transaction... (minus) txHash: ${txHash}`); })
.once('receipt', (receipt) => {
console.log(`Received receipt!`, receipt);
this.setState({ txHash: receipt.transactionHash, });
})
.once('error', (error) => { alert(error.message); });
}
// more on next slide
}
export default Count
4-4. Count 5/7
class Count extends React.Component {
intervalId = null
componentDidMount() {
this.intervalId = setInterval(this.getCount, 1000)
}
componentWillUnmount() {
clearInterval(this.intervalId)
}
// more on next slide
}
export default Count
4-4. Count 6/7
class Count extends React.Component {
render() {
const { lastParticipant, count, txHash, privateKey } = this.state;
return (<div>
{!privateKey && (<div>User must provide a private key to start</div>)}
<div><h1>{count}</h1></div>
{privateKey && (<div><div>
<span><button onClick={this.callPlus}>+</button></span>
<span><button onClick={this.callMinus} disabled={count === 0}>-</button></span></div><br />
{txHash && (<div><h4>Done!</h4>
<p>You can check your last transaction in klaytnscope:</p><hr />
<a target="_blank" rel="noopener noreferrer" href={`https://baobab.scope.klaytn.com/tx/${txHash}`}>open</a>
</div>)}
</div>)}<br />
{Number(lastParticipant) !== 0 && (<div>last participant: {lastParticipant}</div>)}</div>);
}
}
4-4. Count 7/7
Count BApp 결과물
● 실행하려면:
countbapp.herokuapp.com
● 코드는 다음 저장소를 참조:
github.com/w3kim/countbapp
끝!
58

Weitere ähnliche Inhalte

Was ist angesagt?

[Main Session] 카프카, 데이터 플랫폼의 최강자
[Main Session] 카프카, 데이터 플랫폼의 최강자[Main Session] 카프카, 데이터 플랫폼의 최강자
[Main Session] 카프카, 데이터 플랫폼의 최강자Oracle Korea
 
Service mesh(istio) monitoring
Service mesh(istio) monitoringService mesh(istio) monitoring
Service mesh(istio) monitoringJeong-Ho Na
 
Oracle Blockchain_JaeHo Park_CTO
Oracle Blockchain_JaeHo Park_CTOOracle Blockchain_JaeHo Park_CTO
Oracle Blockchain_JaeHo Park_CTOOracle Korea
 
ChainHero web application hyperledger fabric analysis v 1.0
ChainHero web application hyperledger fabric analysis v 1.0ChainHero web application hyperledger fabric analysis v 1.0
ChainHero web application hyperledger fabric analysis v 1.0병준 김
 
Block chain architecture and hyperledger fabric overview
Block chain architecture and hyperledger fabric overviewBlock chain architecture and hyperledger fabric overview
Block chain architecture and hyperledger fabric overview병준 김
 
Hyperledger fabric - tuna fishing analysis
Hyperledger fabric - tuna fishing analysisHyperledger fabric - tuna fishing analysis
Hyperledger fabric - tuna fishing analysis병준 김
 
Prometheus Project Journey
Prometheus Project JourneyPrometheus Project Journey
Prometheus Project JourneyJinwoong Kim
 
멀티클라우드 Service Mesh
멀티클라우드 Service Mesh멀티클라우드 Service Mesh
멀티클라우드 Service MeshJeong-Ho Na
 
Cosmos&amp;tendermint (kr,en) by jeon chang suk
Cosmos&amp;tendermint (kr,en) by jeon chang sukCosmos&amp;tendermint (kr,en) by jeon chang suk
Cosmos&amp;tendermint (kr,en) by jeon chang suk창석 전
 
GS Neotek aws_Amazon_CloudFrontDay2018_session4
GS Neotek aws_Amazon_CloudFrontDay2018_session4GS Neotek aws_Amazon_CloudFrontDay2018_session4
GS Neotek aws_Amazon_CloudFrontDay2018_session4GS Neotek
 
OpenStack summit austin 2016
OpenStack summit austin 2016OpenStack summit austin 2016
OpenStack summit austin 2016Yongyoon Shin
 
introduce to spring cloud
introduce to spring cloudintroduce to spring cloud
introduce to spring cloudDoo Sung Eom
 
Going asynchronous with netty - SOSCON 2015
Going asynchronous with netty - SOSCON 2015Going asynchronous with netty - SOSCON 2015
Going asynchronous with netty - SOSCON 2015Kris Jeong
 
AWS기반 서버리스 데이터레이크 구축하기 - 김진웅 (SK C&C) :: AWS Community Day 2020
AWS기반 서버리스 데이터레이크 구축하기 - 김진웅 (SK C&C) :: AWS Community Day 2020 AWS기반 서버리스 데이터레이크 구축하기 - 김진웅 (SK C&C) :: AWS Community Day 2020
AWS기반 서버리스 데이터레이크 구축하기 - 김진웅 (SK C&C) :: AWS Community Day 2020 AWSKRUG - AWS한국사용자모임
 
[MeetUp][1st] 오리뎅이의_쿠버네티스_네트워킹
[MeetUp][1st] 오리뎅이의_쿠버네티스_네트워킹[MeetUp][1st] 오리뎅이의_쿠버네티스_네트워킹
[MeetUp][1st] 오리뎅이의_쿠버네티스_네트워킹InfraEngineer
 
Kubernetes in action
Kubernetes in actionKubernetes in action
Kubernetes in actionBingu Shim
 
kubernetes : From beginner to Advanced
kubernetes : From beginner to Advancedkubernetes : From beginner to Advanced
kubernetes : From beginner to AdvancedInho Kang
 
대용량 로그분석 Bigquery로 간단히 사용하기
대용량 로그분석 Bigquery로 간단히 사용하기대용량 로그분석 Bigquery로 간단히 사용하기
대용량 로그분석 Bigquery로 간단히 사용하기Jaikwang Lee
 
[164] pinpoint
[164] pinpoint[164] pinpoint
[164] pinpointNAVER D2
 
Luniverse Partners Day - Game Case Study & Partnership (Evan)
Luniverse Partners Day - Game Case Study & Partnership (Evan)Luniverse Partners Day - Game Case Study & Partnership (Evan)
Luniverse Partners Day - Game Case Study & Partnership (Evan)Luniverse Dunamu
 

Was ist angesagt? (20)

[Main Session] 카프카, 데이터 플랫폼의 최강자
[Main Session] 카프카, 데이터 플랫폼의 최강자[Main Session] 카프카, 데이터 플랫폼의 최강자
[Main Session] 카프카, 데이터 플랫폼의 최강자
 
Service mesh(istio) monitoring
Service mesh(istio) monitoringService mesh(istio) monitoring
Service mesh(istio) monitoring
 
Oracle Blockchain_JaeHo Park_CTO
Oracle Blockchain_JaeHo Park_CTOOracle Blockchain_JaeHo Park_CTO
Oracle Blockchain_JaeHo Park_CTO
 
ChainHero web application hyperledger fabric analysis v 1.0
ChainHero web application hyperledger fabric analysis v 1.0ChainHero web application hyperledger fabric analysis v 1.0
ChainHero web application hyperledger fabric analysis v 1.0
 
Block chain architecture and hyperledger fabric overview
Block chain architecture and hyperledger fabric overviewBlock chain architecture and hyperledger fabric overview
Block chain architecture and hyperledger fabric overview
 
Hyperledger fabric - tuna fishing analysis
Hyperledger fabric - tuna fishing analysisHyperledger fabric - tuna fishing analysis
Hyperledger fabric - tuna fishing analysis
 
Prometheus Project Journey
Prometheus Project JourneyPrometheus Project Journey
Prometheus Project Journey
 
멀티클라우드 Service Mesh
멀티클라우드 Service Mesh멀티클라우드 Service Mesh
멀티클라우드 Service Mesh
 
Cosmos&amp;tendermint (kr,en) by jeon chang suk
Cosmos&amp;tendermint (kr,en) by jeon chang sukCosmos&amp;tendermint (kr,en) by jeon chang suk
Cosmos&amp;tendermint (kr,en) by jeon chang suk
 
GS Neotek aws_Amazon_CloudFrontDay2018_session4
GS Neotek aws_Amazon_CloudFrontDay2018_session4GS Neotek aws_Amazon_CloudFrontDay2018_session4
GS Neotek aws_Amazon_CloudFrontDay2018_session4
 
OpenStack summit austin 2016
OpenStack summit austin 2016OpenStack summit austin 2016
OpenStack summit austin 2016
 
introduce to spring cloud
introduce to spring cloudintroduce to spring cloud
introduce to spring cloud
 
Going asynchronous with netty - SOSCON 2015
Going asynchronous with netty - SOSCON 2015Going asynchronous with netty - SOSCON 2015
Going asynchronous with netty - SOSCON 2015
 
AWS기반 서버리스 데이터레이크 구축하기 - 김진웅 (SK C&C) :: AWS Community Day 2020
AWS기반 서버리스 데이터레이크 구축하기 - 김진웅 (SK C&C) :: AWS Community Day 2020 AWS기반 서버리스 데이터레이크 구축하기 - 김진웅 (SK C&C) :: AWS Community Day 2020
AWS기반 서버리스 데이터레이크 구축하기 - 김진웅 (SK C&C) :: AWS Community Day 2020
 
[MeetUp][1st] 오리뎅이의_쿠버네티스_네트워킹
[MeetUp][1st] 오리뎅이의_쿠버네티스_네트워킹[MeetUp][1st] 오리뎅이의_쿠버네티스_네트워킹
[MeetUp][1st] 오리뎅이의_쿠버네티스_네트워킹
 
Kubernetes in action
Kubernetes in actionKubernetes in action
Kubernetes in action
 
kubernetes : From beginner to Advanced
kubernetes : From beginner to Advancedkubernetes : From beginner to Advanced
kubernetes : From beginner to Advanced
 
대용량 로그분석 Bigquery로 간단히 사용하기
대용량 로그분석 Bigquery로 간단히 사용하기대용량 로그분석 Bigquery로 간단히 사용하기
대용량 로그분석 Bigquery로 간단히 사용하기
 
[164] pinpoint
[164] pinpoint[164] pinpoint
[164] pinpoint
 
Luniverse Partners Day - Game Case Study & Partnership (Evan)
Luniverse Partners Day - Game Case Study & Partnership (Evan)Luniverse Partners Day - Game Case Study & Partnership (Evan)
Luniverse Partners Day - Game Case Study & Partnership (Evan)
 

Ähnlich wie Klaytn Developer Meetup_20191022

2. klaytn developer meetup #2 univ chain
2. klaytn developer meetup #2 univ chain2. klaytn developer meetup #2 univ chain
2. klaytn developer meetup #2 univ chain전 민규
 
[NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기
[NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기[NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기
[NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기현철 조
 
REST API Development with Spring
REST API Development with SpringREST API Development with Spring
REST API Development with SpringKeesun Baik
 
장고로 웹서비스 만들기 기초
장고로 웹서비스 만들기   기초장고로 웹서비스 만들기   기초
장고로 웹서비스 만들기 기초Kwangyoun Jung
 
카사 공개세미나1회 W.E.L.C.
카사 공개세미나1회  W.E.L.C.카사 공개세미나1회  W.E.L.C.
카사 공개세미나1회 W.E.L.C.Ryan Park
 
Flipper 불완전 정복
Flipper 불완전 정복Flipper 불완전 정복
Flipper 불완전 정복Sewon Ann
 
Javascript 조금 더 잘 알기
Javascript 조금 더 잘 알기Javascript 조금 더 잘 알기
Javascript 조금 더 잘 알기jongho jeong
 
Kubernetes on GCP
Kubernetes on GCPKubernetes on GCP
Kubernetes on GCPDaegeun Kim
 
Hoons 닷넷 정기세미나
Hoons 닷넷 정기세미나Hoons 닷넷 정기세미나
Hoons 닷넷 정기세미나병걸 윤
 
코틀린 멀티플랫폼, 미지와의 조우
코틀린 멀티플랫폼, 미지와의 조우코틀린 멀티플랫폼, 미지와의 조우
코틀린 멀티플랫폼, 미지와의 조우Arawn Park
 
20170813 django api server unit test and remote debugging
20170813 django api server unit test and remote debugging20170813 django api server unit test and remote debugging
20170813 django api server unit test and remote debuggingJongwon Han
 
Kubernetes on Premise Practical Guide
Kubernetes on Premise Practical GuideKubernetes on Premise Practical Guide
Kubernetes on Premise Practical GuideChan Shik Lim
 
.NET에서 비동기 프로그래밍 배우기
.NET에서 비동기 프로그래밍 배우기.NET에서 비동기 프로그래밍 배우기
.NET에서 비동기 프로그래밍 배우기Seong Won Mun
 
React Native를 사용한
 초간단 커뮤니티 앱 제작
React Native를 사용한
 초간단 커뮤니티 앱 제작React Native를 사용한
 초간단 커뮤니티 앱 제작
React Native를 사용한
 초간단 커뮤니티 앱 제작Taegon Kim
 
Meetup tools for-cloud_native_apps_meetup20180510-vs
Meetup tools for-cloud_native_apps_meetup20180510-vsMeetup tools for-cloud_native_apps_meetup20180510-vs
Meetup tools for-cloud_native_apps_meetup20180510-vsminseok kim
 
[KGC2014] DX9에서DX11로의이행경험공유
[KGC2014] DX9에서DX11로의이행경험공유[KGC2014] DX9에서DX11로의이행경험공유
[KGC2014] DX9에서DX11로의이행경험공유Hwan Min
 
Jenkins와 Gitlab으로 쉽고 빠르게 구축하는 협업시스템
Jenkins와 Gitlab으로 쉽고 빠르게 구축하는 협업시스템Jenkins와 Gitlab으로 쉽고 빠르게 구축하는 협업시스템
Jenkins와 Gitlab으로 쉽고 빠르게 구축하는 협업시스템Park JoongSoo
 

Ähnlich wie Klaytn Developer Meetup_20191022 (20)

2. klaytn developer meetup #2 univ chain
2. klaytn developer meetup #2 univ chain2. klaytn developer meetup #2 univ chain
2. klaytn developer meetup #2 univ chain
 
[NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기
[NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기[NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기
[NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기
 
REST API Development with Spring
REST API Development with SpringREST API Development with Spring
REST API Development with Spring
 
장고로 웹서비스 만들기 기초
장고로 웹서비스 만들기   기초장고로 웹서비스 만들기   기초
장고로 웹서비스 만들기 기초
 
카사 공개세미나1회 W.E.L.C.
카사 공개세미나1회  W.E.L.C.카사 공개세미나1회  W.E.L.C.
카사 공개세미나1회 W.E.L.C.
 
Flipper 불완전 정복
Flipper 불완전 정복Flipper 불완전 정복
Flipper 불완전 정복
 
Javascript 조금 더 잘 알기
Javascript 조금 더 잘 알기Javascript 조금 더 잘 알기
Javascript 조금 더 잘 알기
 
Kubernetes on GCP
Kubernetes on GCPKubernetes on GCP
Kubernetes on GCP
 
Hoons 닷넷 정기세미나
Hoons 닷넷 정기세미나Hoons 닷넷 정기세미나
Hoons 닷넷 정기세미나
 
코틀린 멀티플랫폼, 미지와의 조우
코틀린 멀티플랫폼, 미지와의 조우코틀린 멀티플랫폼, 미지와의 조우
코틀린 멀티플랫폼, 미지와의 조우
 
K8s in action02
K8s in action02K8s in action02
K8s in action02
 
20170813 django api server unit test and remote debugging
20170813 django api server unit test and remote debugging20170813 django api server unit test and remote debugging
20170813 django api server unit test and remote debugging
 
Kubernetes on Premise Practical Guide
Kubernetes on Premise Practical GuideKubernetes on Premise Practical Guide
Kubernetes on Premise Practical Guide
 
.NET에서 비동기 프로그래밍 배우기
.NET에서 비동기 프로그래밍 배우기.NET에서 비동기 프로그래밍 배우기
.NET에서 비동기 프로그래밍 배우기
 
OpenStack Swift Debugging
OpenStack Swift DebuggingOpenStack Swift Debugging
OpenStack Swift Debugging
 
React Native를 사용한
 초간단 커뮤니티 앱 제작
React Native를 사용한
 초간단 커뮤니티 앱 제작React Native를 사용한
 초간단 커뮤니티 앱 제작
React Native를 사용한
 초간단 커뮤니티 앱 제작
 
Meetup tools for-cloud_native_apps_meetup20180510-vs
Meetup tools for-cloud_native_apps_meetup20180510-vsMeetup tools for-cloud_native_apps_meetup20180510-vs
Meetup tools for-cloud_native_apps_meetup20180510-vs
 
[KGC2014] DX9에서DX11로의이행경험공유
[KGC2014] DX9에서DX11로의이행경험공유[KGC2014] DX9에서DX11로의이행경험공유
[KGC2014] DX9에서DX11로의이행경험공유
 
Spring boot DI
Spring boot DISpring boot DI
Spring boot DI
 
Jenkins와 Gitlab으로 쉽고 빠르게 구축하는 협업시스템
Jenkins와 Gitlab으로 쉽고 빠르게 구축하는 협업시스템Jenkins와 Gitlab으로 쉽고 빠르게 구축하는 협업시스템
Jenkins와 Gitlab으로 쉽고 빠르게 구축하는 협업시스템
 

Mehr von Klaytn

TXGX 2019_Kai_Klaytn Blockchain Application (BApp) Development
TXGX 2019_Kai_Klaytn Blockchain Application (BApp) DevelopmentTXGX 2019_Kai_Klaytn Blockchain Application (BApp) Development
TXGX 2019_Kai_Klaytn Blockchain Application (BApp) DevelopmentKlaytn
 
TXGX 2019_Albert_High Availability Architecture of Klaytn Service Chain
TXGX 2019_Albert_High Availability Architecture of Klaytn Service ChainTXGX 2019_Albert_High Availability Architecture of Klaytn Service Chain
TXGX 2019_Albert_High Availability Architecture of Klaytn Service ChainKlaytn
 
TXGX 2019_Ethan_Horizontal Scaling through Service Chain in Klaytn
TXGX 2019_Ethan_Horizontal Scaling through Service Chain in KlaytnTXGX 2019_Ethan_Horizontal Scaling through Service Chain in Klaytn
TXGX 2019_Ethan_Horizontal Scaling through Service Chain in KlaytnKlaytn
 
TXGX 2019_Colin_Account and Transaction Model in Klaytn
TXGX 2019_Colin_Account and Transaction Model in KlaytnTXGX 2019_Colin_Account and Transaction Model in Klaytn
TXGX 2019_Colin_Account and Transaction Model in KlaytnKlaytn
 
TXGX 2019_Sam_Challenges for Blockchain Mass Adoption
TXGX 2019_Sam_Challenges for Blockchain Mass AdoptionTXGX 2019_Sam_Challenges for Blockchain Mass Adoption
TXGX 2019_Sam_Challenges for Blockchain Mass AdoptionKlaytn
 
TXGX 2019_Jun_Klaytn World: From Inception to Completion
TXGX 2019_Jun_Klaytn World: From Inception to CompletionTXGX 2019_Jun_Klaytn World: From Inception to Completion
TXGX 2019_Jun_Klaytn World: From Inception to CompletionKlaytn
 
TXGX 2019_Jason_Welcome Speech
TXGX 2019_Jason_Welcome SpeechTXGX 2019_Jason_Welcome Speech
TXGX 2019_Jason_Welcome SpeechKlaytn
 
Klaytn Developer Meetup_20190827
Klaytn Developer Meetup_20190827Klaytn Developer Meetup_20190827
Klaytn Developer Meetup_20190827Klaytn
 

Mehr von Klaytn (8)

TXGX 2019_Kai_Klaytn Blockchain Application (BApp) Development
TXGX 2019_Kai_Klaytn Blockchain Application (BApp) DevelopmentTXGX 2019_Kai_Klaytn Blockchain Application (BApp) Development
TXGX 2019_Kai_Klaytn Blockchain Application (BApp) Development
 
TXGX 2019_Albert_High Availability Architecture of Klaytn Service Chain
TXGX 2019_Albert_High Availability Architecture of Klaytn Service ChainTXGX 2019_Albert_High Availability Architecture of Klaytn Service Chain
TXGX 2019_Albert_High Availability Architecture of Klaytn Service Chain
 
TXGX 2019_Ethan_Horizontal Scaling through Service Chain in Klaytn
TXGX 2019_Ethan_Horizontal Scaling through Service Chain in KlaytnTXGX 2019_Ethan_Horizontal Scaling through Service Chain in Klaytn
TXGX 2019_Ethan_Horizontal Scaling through Service Chain in Klaytn
 
TXGX 2019_Colin_Account and Transaction Model in Klaytn
TXGX 2019_Colin_Account and Transaction Model in KlaytnTXGX 2019_Colin_Account and Transaction Model in Klaytn
TXGX 2019_Colin_Account and Transaction Model in Klaytn
 
TXGX 2019_Sam_Challenges for Blockchain Mass Adoption
TXGX 2019_Sam_Challenges for Blockchain Mass AdoptionTXGX 2019_Sam_Challenges for Blockchain Mass Adoption
TXGX 2019_Sam_Challenges for Blockchain Mass Adoption
 
TXGX 2019_Jun_Klaytn World: From Inception to Completion
TXGX 2019_Jun_Klaytn World: From Inception to CompletionTXGX 2019_Jun_Klaytn World: From Inception to Completion
TXGX 2019_Jun_Klaytn World: From Inception to Completion
 
TXGX 2019_Jason_Welcome Speech
TXGX 2019_Jason_Welcome SpeechTXGX 2019_Jason_Welcome Speech
TXGX 2019_Jason_Welcome Speech
 
Klaytn Developer Meetup_20190827
Klaytn Developer Meetup_20190827Klaytn Developer Meetup_20190827
Klaytn Developer Meetup_20190827
 

Klaytn Developer Meetup_20191022

  • 1.
  • 2. ● Eric Kim, Developer Evangelist at Ground X Meetup Topic ● 19:00 ~ 19:30 (30") 등록 확인 ● 19:30 ~ 20:20 (50") Klaytn 세션 ● 20:20 ~ 20:50 (30") Q&A ● 20:50 ~ 21:30 (40") 네트워킹 Klaytn 101 #2 Blockchain Application(BApp) 동작원리와 구성요소 이해하기
  • 3. Klaytn 101 #2 Blockchain Application(BApp) 동작원리와 구성요소 이해하기 Eric Kim, Ground X Developer Evangelist
  • 4. Klaytn Developer Meetup #2 Blockchain Application(BApp) 동작원리와 구성요소 이해하기
  • 5. Today’s Agenda ● BApp의 동작원리와 BApp을 구성하는 요소들에 대해 알아봅니다 ● 예제와 함께 웹기반 BApp 구현방법을 알아봅니다 ○ 오늘 구현할 BApp은 Count Bapp입니다 ○ 코드는 여기에: github.com/w3kim/countbapp ○ 구현 예시는 여기에: countbapp.herokuapp.com 5
  • 7. Blockchain Application (BApp) ● 블록체인 어플리케이션(BApp)은 블록체인을 사용하는 어플리케이션 ○ 기존의 기술로 풀기 어려운 문제들을 블록체인의 특성을 활용하여 풀어내는 것이 목적 ● 불변성과 투명성이 대표적인 블록체인의 특성 ○ 한번 기록된 정보는 변경할 수 없으며 ○ 정해진 규칙(e.g., 블록체인 프로토콜, 컨트랙트에 구현된 로직)에 따라 상태를 변경 ○ 기록의 내역이 블록에 공개되어 있으므로 누구든지 정보의 진실여부를 확인 가능 7
  • 8. BApp의 동작원리 ● 쓰기 (Write) ○ 블록체인에 데이터를 쓰는 모든 행위는 트랜잭션(TX)으로 표현 ○ e.g., 어카운트 간 KLAY의 전송 ○ e.g., 스마트 컨트랙트 배포 ○ e.g., 스마트 컨트랙트의 상태를 변경하는 함수를 호출 ● 읽기 (Read) ○ 누구든지 블록 정보를 가지고 있다면 쓰여진 데이터를 확인 가능 ○ e.g., TX 확인 ○ e.g., 스마트 컨트랙트 상태 확인 8
  • 10. BApp 개발 형태 1. Fully decentralized ○ 사용자(클라이언트)가 직접 블록체인과 통신 2. Semi-decentralized with (centralized) proxy ○ 클라이언트가 블록체인과 통신하기 위해 중개 서버와 통신 ○ 블록체인 기반으로 만들어진 서비스가 있고 그 서비스를 사용자들이 사용하는 형태 ○ 클라이언트 ⇔ 중개서버 ⇔ 블록체인 10
  • 11. BApp 개발 형태: Fully Decentralized ● 장점: ○ 높은 투명성, 신뢰형성에 필요한 추가 비용 없음 ○ 사용자의 익명성 보장 가능 ○ (설치형 BApp의 경우) 관리 비용 낮음 ● 단점: ○ 사용자 책임 증가, 어려운 UX ○ 로직 변경 어려움 ○ 사용자가 블록체인에 상시 접속할 필요 및 블록을 복제할 필요 있음 11
  • 12. BApp 개발 형태: Semi-Decentralized with Proxy ● 장점: ○ (기존의 서비스들과 동일한) 높은 수준의 UX ○ 사용자가 블록체인과 직접 통신할 필요 없음 ○ 로직 변경 비교적 쉬움 ● 단점: ○ 신뢰비용 발생 ○ 일부 중앙화 ⇒ 서비스가 Single Point of Failure (SPoF)가 됨 ○ 관리 비용 높음 12
  • 13. 목적에 맞는 BApp 개발 형태를 선택하는 것이 중요 13
  • 14. BApp 개발 구분 ● 프론트엔드(Frontend) ○ 사용자가 직접 사용하는 프로그램 (e.g., mobile app, web page/app) ○ 키관리, TX 생성, 서명, 전송 등을 프론트엔드에서 처리 ● 백엔드(Backend) ○ 사용자에 눈에 보이지 않는 상시 동작하는 서비스 ○ 프론트엔드가 사용자 요청을 전달하면 백엔드가 처리하는 구조 ○ 블록체인 동기화 등 컴퓨팅 리소스가 많이 필요한 일을 처리하는데 적합 ○ 블록체인 동기화, 블록 파싱(parsing), TX 전달, 가스비 대납 등을 백엔드에서 처리 14
  • 15. 개발 형태 별 BApp 개발 조합 ● Fully decentralized = Frontend + Blockchain ○ e.g., Web/Android/Windows + Klaytn ● Semi-decentralized = Frontend + Backend + Blockchain ○ e.g., Web + Java Server on AWS + Klaytn ○ e.g., Android + Node.js Server on Azure + Klaytn 15
  • 16. 프론트엔드 개발 ● BApp이 실행되는 환경에 따라 개발방법이 달라짐 ○ 실행환경: Web, Mobile (Android, iOS), Native (Windows, Linux, macOS) ○ 어느 환경에서 개발하느냐에 따라 개발 언어와 UI/UX 디자인, 사용 SDK가 달라짐 ○ Klaytn은 Javascript, Java (Android, Native) SDK를 제공 ● 프론트엔드 개발에 영향을 끼치는 실행환경 중 하나가 지갑 ○ 지갑의 존재유무, 지갑의 선택에 따라 개발방법이 변경될 수 있음 ○ 특정 지갑을 사용할 경우 해당 지갑이 제공하는 라이브러리를 사용 16
  • 17. 지갑 (Wallet) ● TX를 서명하려면 키가 필요 ○ 키 → 어카운트; 서로 다른 키는 다른 어카운트에 매핑 ○ 하나의 어카운트로 여러 BApp을 사용하려는 사용자의 니즈가 존재 ● 지갑 = 키를 관리하는 프로그램 ○ 키를 보관하고 BApp이 요청할 때마다 보관 중인 키로 TX를 서명 ○ 여러 유형의 지갑이 존재 ○ e.g., 브라우저 플러그인, Dapp 브라우저 내장 지갑, 클라우드 지갑, 디바이스 지갑 17
  • 18. 지갑을 고려한 BApp 개발 ● 어떤 지갑을 사용하느냐에 따라 사용자 환경이 변화 ○ 어떤 형태로 BApp을 만들 것인지? 웹앱? 모바일 웹? 모바일 네이티브? 데스크탑? ○ BApp에 지갑을 내장할 것인지 아니면 외부 지갑을 사용할 것인지 ○ 외부 지갑을 쓸 경우 개발하려는 BApp 형태와 맞는 지갑이 어떤 것인지? ○ e.g., 웹앱의 경우 Metamask를 사용 가능 (Ethereum) ○ e.g., 모바일 웹 또는 모바일 네이티브의 경우 삼성 블록체인 키스토어를 사용 가능 (Klaytn) BApp의 목적 및 타겟 사용자를 분석하여 어느 형태로 키를 관리할지 결정 18
  • 19. 백엔드 ● 블록체인 프로토콜 이외의 정보를 관리할 경우 필요 ○ UX 향상 및 서비스 구현을 위해 TX 외 다른 정보가 필요할 경우 백엔드를 운영 ● 서비스 제공자가 실행환경을 결정 ○ 개발방법 선택이 비교적 자유로운편이나 대부분의 경우 플랫폼 SDK 존재유무에 따라 방향을 결정 19
  • 21. Count BApp 블록체인에 숫자를 기록하는 BApp ● Count BApp 사용자는 다음을 할 수 있어야 합니다. ○ 가장 마지막 블록 높이를 확인 ○ 블록체인에 기록된 숫자를 확인 ○ 자신의 어카운트 비밀키를 입력하여 어카운트 주소를 확인 ○ (자신의 어카운트 비밀키를 사용하여) 숫자를 1 더할 수 있음 ○ (자신의 어카운트 비밀키를 사용하여) 숫자를 1 뺄 수 있음
  • 22. Count BApp 화면구성예시 Private Key Enter user key here Set Address 0xADDRESS_OF_THE_PROVIDED_KEY Block# ######### #########Count + - Last Participant 0xADDRESS_OF_THE_LAST_PARTICIPANT Result https://baobab.scope.klaytn.com/tx/...
  • 23. Count 스마트 컨트랙트 (Count.sol) pragma solidity ^0.5.6; contract Count { uint public count = 0; address public lastParticipant; function plus() public { count++; lastParticipant = msg.sender; } function minus() public { count--; lastParticipant = msg.sender; } }
  • 24. Count 스마트 컨트랙트 with Comments pragma solidity ^0.5.6; contract Count { uint public count = 0; address public lastParticipant; function plus() public { count++; lastParticipant = msg.sender; } function minus() public { count--; lastParticipant = msg.sender; } } 숫자를 기록하는 상태를 만듭니다. 마지막에 숫자를 변경한 사람의 주소를 기록하는 상태를 만듭니다. 숫자를 1 증가시키고 변경한 사람의 주소를 기록합니다. 숫자를 1 감소시키고 변경한 사람의 주소를 기록합니다.
  • 25. Count BApp 실행예시 count.sol @ 0xCONTRACT --- plus() minus() --- uint count address lastParticipant User A @ 0xADDR1 User B @ 0xADDR2 User C @ 0xADDR2 0xADDR1 → plus() // count = 1 0xADDR2 → count() → 1 0xADDR3 → minus() // count = 0 0xADDR1 → plus() // count = 1 0xADDR1 → count() → 1
  • 26. 개발 스택 다음 소프트웨어 및 라이브러리를 사용하여 Count BApp을 개발합니다 항목 선택 개발 언어 Javascript 소프트웨어 플랫폼 Node.js 사용자 인터페이스 React* Klaytn SDK caver-js
  • 27. 개발 순서 1. Baobab에서 어카운트 만들기 2. KLAY Faucet에서 테스트 KLAY 받기 3. IDE로 Count.sol 작성, 배포, 테스트 실행하기 4. caver-js + React로 프론트엔드 만들기
  • 28. 1. Baobab 어카운트 생성 ● Klaytn Wallet을 사용 - baobab.wallet.klaytn.com
  • 29. 2. KLAY Faucet ● 5 KLAY/day ● IP당 1,000회 리밋 설정
  • 30. 3. Klaytn IDE ● 손쉬운 컨트랙트 작성, 컴파일, 배포, 테스트를 위한 도구 ● ide.klaytn.com
  • 37. 4. 프론트엔드 개발 1. caver-js 불러오기 2. BlockNumber 컴포넌트 3. KeyAndAddress 컴포넌트 4. Count 컴포넌트
  • 38. 4-1. caver-js 불러오기 import Caver from 'caver-js' const BAOBAB_TESTNET_RPC_URL = 'https://api.baobab.klaytn.net:8651/' const caver = new Caver(BAOBAB_TESTNET_RPC_URL) export default caver
  • 39. 4-2. BlockNumber 컴포넌트 1/3 import React from 'react' import caver from '../klaytn/caver' class BlockNumber extends React.Component { state = { currentBlockNumber: '...loading', } getBlockNumber = async () => { const blockNumber = await caver.klay.getBlockNumber() this.setState({ currentBlockNumber: blockNumber }) } // more on next slide } export default BlockNumber
  • 40. 4-2. BlockNumber 컴포넌트 2/3 // import statements class BlockNumber extends React.Component { // omitted things from previous slide intervalId = null componentDidMount() { this.intervalId = setInterval(this.getBlockNumber, 1000) } componentWillUnmount() { if (this.intervalId) clearInterval(this.intervalId) } // more on next slide } export default BlockNumber
  • 41. 4-2. BlockNumber 컴포넌트 3/3 // import statements class BlockNumber extends React.Component { // omitted things from previous slide render() { const { currentBlockNumber } = this.state return ( <div> <h4> <span>Block No. {currentBlockNumber}</span> </h4> </div> ) } } export default BlockNumber
  • 42. 4-3. KeyAndAddress 컴포넌트 import React from 'react'; import caver from '../klaytn/caver'; class PrivateKeyInput extends React.Component { … } class KeyAndAddress extends React.Component { … } export default KeyAndAddress
  • 43. 4-3. PrivateKeyInput 1/2 // import statements class PrivateKeyInput extends React.Component { constructor(props) { super(props); // assume parent component has passed a function `reloadAddress(key)` this.state = { privateKey: '' }; } handleChange = (e) => { this.setState({ privateKey: e.target.value }); } // more on next slide } // omitted for brevity
  • 44. 4-3. PrivateKeyInput 2/2 // import statements class PrivateKeyInput extends React.Component { // things from previous slide render() { const { privateKey } = this.state; return (<div><form><div> <label for='inputKey'>Private Key</label> <input type='text' placeholder="your private key starting with 0x" onChange={this.handleChange} id="inputKey" /> </div> <button onClick={() => this.props.reloadAddress(privateKey)}>Set</button> </form></div>); } // more on next slide } // omitted for brevity
  • 45. 4-3. KeyAndAddress 1/4 // import statements class KeyAndAddress extends React.Component { constructor(props) { super(props); this.state = { privateKey: '', address: '' }; } reloadAddress = (key) => { … } render() { … } } // omitted for brevity
  • 46. 4-3. KeyAndAddress 2/4 // import statements class KeyAndAddress extends React.Component { // things from previous slide reloadAddress = (key) => { let account; try { account = caver.klay.accounts.privateKeyToAccount(key); } catch (e) { console.error(e); } // more on next slide } } // omitted for brevity
  • 47. 4-3. KeyAndAddress 3/4 // import statements class KeyAndAddress extends React.Component { // things from previous slide reloadAddress = (key) => { // continued from the previous slide if (account) { this.setState({ privateKey: key, address: account.address }); this.props.propagateKey(key); } else { this.setState({ privateKey: '', address: '' }); this.props.propagateKey(false); } } } // omitted for brevity
  • 48. 4-3. KeyAndAddress 4/4 // import statements class KeyAndAddress extends React.Component { // things from previous slide render() { const { address } = this.state; return (<div> <PrivateKeyInput reloadAddress={this.reloadAddress} /><hr /> <form><div> <label for='addressField'>My Address</label> <input id='addressField' type='text' disabled value={address} /> </div></form></div> ); } } // omitted for brevity
  • 49. 4-4. Count 컴포넌트 import React from 'react' import caver from "../klaytn/caver" const ABI = require("../assets/abi.json"); class Count extends React.Component { constructor() { … } setPrivateKey(key) { … } getCount = async () => { … } callPlus = () => { … } callMinus = () => { … } componentDidMount() { … } componentWillUnmount() { … } render() { … } } export default Count
  • 50. 4-4. Count 1/7 // import statements and ABI class Count extends React.Component { constructor() { super(); // assume .env file contains REACT_APP_CONTRACT_ADDRESS variable this.countContract = process.env.REACT_APP_CONTRACT_ADDRESS && ABI && new caver.klay.Contract(ABI, process.env.REACT_APP_CONTRACT_ADDRESS); this.state = { count: '', lastParticipant: '', privateKey: '' }; this.wallet = caver.klay.accounts.wallet; } // more on next slide } export default Count
  • 51. 4-4. Count 2/7 class Count extends React.Component { // exposed function allowing anyone with the right reference can call this function setPrivateKey(key) { this.wallet.clear(); if (key) { this.wallet.add(key); } this.setState({ privateKey: key }); } // more on next slide } export default Count
  • 52. 4-4. Count 3/7 class Count extends React.Component { getCount = async () => { const count = await this.countContract.methods.count().call(); const lastParticipant = await this.countContract.methods.lastParticipant().call(); this.setState({ count, lastParticipant, }); } // more on next slide } export default Count
  • 53. class Count extends React.Component { callPlus = () => { const walletInstance = this.wallet[0]; if (!walletInstance) return; this.countContract.methods.plus().send({ from: walletInstance.address, gas: '200000', }) .once('transactionHash', (txHash) => { console.log(`Sending a transaction... ('plus') txHash: ${txHash}`); }) .once('receipt', (receipt) => { console.log(`Received receipt!`, receipt); this.setState({ txHash: receipt.transactionHash, }); }) .once('error', (error) => { alert(error.message); }); } // more on next slide } export default Count 4-4. Count 4/7
  • 54. class Count extends React.Component { callPlus = () => { const walletInstance = this.wallet[0]; if (!walletInstance) return; this.countContract.methods.minus().send({ from: walletInstance.address, gas: '200000', }) .once('transactionHash', (txHash) => { console.log(`Sending a transaction... (minus) txHash: ${txHash}`); }) .once('receipt', (receipt) => { console.log(`Received receipt!`, receipt); this.setState({ txHash: receipt.transactionHash, }); }) .once('error', (error) => { alert(error.message); }); } // more on next slide } export default Count 4-4. Count 5/7
  • 55. class Count extends React.Component { intervalId = null componentDidMount() { this.intervalId = setInterval(this.getCount, 1000) } componentWillUnmount() { clearInterval(this.intervalId) } // more on next slide } export default Count 4-4. Count 6/7
  • 56. class Count extends React.Component { render() { const { lastParticipant, count, txHash, privateKey } = this.state; return (<div> {!privateKey && (<div>User must provide a private key to start</div>)} <div><h1>{count}</h1></div> {privateKey && (<div><div> <span><button onClick={this.callPlus}>+</button></span> <span><button onClick={this.callMinus} disabled={count === 0}>-</button></span></div><br /> {txHash && (<div><h4>Done!</h4> <p>You can check your last transaction in klaytnscope:</p><hr /> <a target="_blank" rel="noopener noreferrer" href={`https://baobab.scope.klaytn.com/tx/${txHash}`}>open</a> </div>)} </div>)}<br /> {Number(lastParticipant) !== 0 && (<div>last participant: {lastParticipant}</div>)}</div>); } } 4-4. Count 7/7
  • 57. Count BApp 결과물 ● 실행하려면: countbapp.herokuapp.com ● 코드는 다음 저장소를 참조: github.com/w3kim/countbapp