6. Frontend Code Overview
개요
src/App.js
src/pages
학습 내용
1) 개요
이 장에서는 프론트엔드를 구축하겠습니다. 본 튜토리얼의 주목적은 컨트랙트와 프론트엔드 코드를 연결하는 방법을 알아보는 것입니다. 따라서 간략히 리액트 코드에 대해 설명하고 Klaytn에 배포된 컨트랙트와 상호작용하는 API 함수를 중점적으로 다루겠습니다.
|-- src
|-- klaytn
|-- caver.js
|-- KlaystagramContract.js
|-- redux
|-- auth.js
|-- photos.js
|-- pages
|-- AuthPage.js
|-- FeedPage.js
|-- components
|-- UploadPhoto.js
|-- Feed.js
|-- TransferOwnership.js
|-- ...
|-- App.js
src/klaytn
: Klaytn과의 상호작용을 지원하는 파일을 담고 있습니다.
src/klaytn/caver.js
: 환경설정에 따라 caver-js 인스턴스화합니다.참고) caver-js는 Klaytn 노드와 연결하여 해당 노드나 Klaytn에 배포된 컨트랙트와의 상호작용을 지원해주는 RPC 라이브러리입니다.
src/klaytn/Klaystagram.js
: caver-js API를 사용하여 컨트랙트 인스턴스를 작성합니다. 이 인스턴스를 통해 컨트랙트와 상호작용할 수 있습니다.
src/redux
: 컨트랙트와 상호작용하여 결과 데이터를 추적하는 API 함수를 작성합니다.
redux/actions/auth.js
redux/actions/photos.js
src/pages
: Klaystagram 애플리케이션을 구성하는 두 개의 페이지 파일을 담고 있습니다.
src/pages/AuthPage.js
: 회원가입 및 로그인 양식이 있습니다. 회원가입 시 개인키를 생성하여 애플리케이션에 로그인할 수 있습니다.src/pages/FeedPage.js
: 스마트 컨트랙트로부터 사진을 읽어와 사용자에게 보여주고 업로드 기능을 제공합니다.
src/components
: 페이지를 구성하는 컴포넌트 파일들을 담고 있습니다.
src/components/Feed.js
: 컨트랙트로부터 데이터를 읽어와 사진을 보여줍니다.src/components/UploadPhoto.js
: 컨트랙트에 트랜잭션을 전송하여 사진을 업로드합니다.src/components/TransferOwnership.js
: 트랜잭션을 전송하여 사진의 소유권을 이전합니다.
src/App.js
: 본 튜토리얼의 루트 컴포넌트 파일입니다.
2) App.js
'App.js'
전체 컴포넌트 중 루트 컴포넌트입니다. 이 컴포넌트는 사용자의 로그인 상태에 따라 두 페이지를 렌더링합니다. 각 페이지에는 컨트랙트와 상호작용하는 함수가 있습니다. 블록체인에 트랜잭션을 전송하려면 caver에 지갑 인스턴스를 추가해야 합니다. 자 이제 코드를 간략히 살펴볼게요.
cf. caver-js(or cav
in the code) is a library for interacting with Klaytn blockchain. 이 내용은 다음 장 - 7-1 스마트 컨트랙트를 프론트엔드에 연결에서 자세히 다룰 것입니다.
// src/App.js
import React, { Component } from 'react'
import { connect } from 'react-redux'
import AuthPage from 'pages/AuthPage'
import FeedPage from 'pages/FeedPage'
import Nav from 'components/Nav'
import Footer from 'components/Footer'
import Modal from 'components/Modal'
import Toast from 'components/Toast'
import * as authActions from 'redux/actions/auth'
import './App.scss'
class App extends Component {
constructor(props) {
super(props)
/**
* 1. `isLoggedIn` 상태 초기화
* 참고) sessionStorage는 브라우저 탭이 닫힐 때까지 데이터를 저장하는 인터넷 브라우저의 기능입니다.
*/
const walletFromSession = sessionStorage.getItem('walletInstance')
const { integrateWallet, removeWallet } = this.props
if (walletFromSession) {
try {
/**
* 2-1. 지갑 연동
* 'walletInstance' 값이 있는 경우
* intergrateWallet 메서드가 caver 지갑과 리덕스 스토어에 인스턴스를 추가합니다.
* 참고) redux/actions/auth.js -> integrateWallet()
*/
integrateWallet(JSON.parse(walletFromSession).privateKey)
} catch (e) {
/**
* 2-2. 지갑 제거
* sessionStorage의 값이 유효하지 않은 지갑 인스턴스인 경우
* removeWallet 메서드가 caver 지갑과 리덕스 스토어에서 인스턴스를 제거합니다.
* 참고) redux/actions/auth.js -> removeWallet()
*/
removeWallet()
}
}
}
/**
* 3. 페이지 렌더링
* 리덕스가 walletInstance이 세션 스토리지에 존재하는지 여부에 따라 isLoggedIn의 상태를 true 또는 false로 초기화합니다.
*/
render() {
const { isLoggedIn } = this.props
return (
<div className="App">
<Modal />
<Toast />
{isLoggedIn && <Nav />}
{isLoggedIn ? <FeedPage /> : <AuthPage />}
<Footer />
</div>
)
}
}
const mapStateToProps = (state) => ({
isLoggedIn: state.auth.isLoggedIn,
})
const mapDispatchToProps = (dispatch) => ({
integrateWallet: (privateKey) => dispatch(authActions.integrateWallet(privateKey)),
removeWallet: () => dispatch(authActions.removeWallet()),
})
export default connect(mapStateToProps, mapDispatchToProps)(App)
참고) walletInstance
세션이 JSON 문자열로 저장되기 때문에 JSON.parse
가 필요합니다.
1. Initialize isLoggedIn
state
To initialize state isLoggedIn
, we use constructor
life cycle method on App component. 이는 컴포넌트를 마운트하기 전에 브라우저의 sessionStorage 내의 walletInstance
세션을 확인합니다.
2. Inject/Remove wallet
If you have never logged in before, walletInstance
session may not exist. 로그인했었다면 sessionStorage 내에 walletInstance
세션이 JSON 문자열의 형태로 존재할 것입니다.
삽입 - 지갑 인스턴스가 sessionStorage에 있으면 해당 지갑 인스턴스를 caver와 리덕스 스토어에 추가하세요.
제거 - sessionStorage에 있는 지갑 인스턴스가 유효하지 않으면 caver 지갑과 리덕스 스토어에서 제거하세요.
// redux/actions/auth.js
// 1. 지갑 삽입
export const integrateWallet = (privateKey) => (dispatch) => {
// caver의 privateKeyToAccount API를 이용하여 지갑 인스턴스를 생성합니다.
const walletInstance = cav.klay.accounts.privateKeyToAccount(privateKey)
// 트랜잭션을 보내려면 지갑 인스턴스를 caver에 추가합니다.
cav.klay.accounts.wallet.add(walletInstance)
// 로그인 상태를 유지하려면 walletInstance를 sessionStorage에 저장합니다.
sessionStorage.setItem('walletInstance', JSON.stringify(walletInstance))
// 애플리케이션을 실행하는 동안 walletInstance 정보에 접근하려면 리덕스 스토어에 저장합니다.
return dispatch({
type: INTEGRATE_WALLET,
payload: {
privateKey,
address: walletInstance.address,
},
})
}
// 2. 지갑 제거
export const removeWallet = () => (dispatch) => {
cav.klay.accounts.wallet.clear()
sessionStorage.removeItem('walletInstance')
return dispatch({
type: REMOVE_WALLET,
})
}
cf. For further information about caver's privateKeyToAccount
API, see caver.klay.accounts.privateKeyToAccount.
3. 페이지 렌더링 리덕스는 walletInstance가 세션 스토리지에 존재하는지 여부에 따라 isLoggedIn
상태를 true 또는 false로 초기화합니다.
3) src/pages
src/pages
위에서 설명했듯이 src/pages
는 두 페이지 파일을 포함합니다. 사용자의 로그인 여부에 따라 두 페이지 중 하나가 애플리케이션에 렌더링됩니다.
AuthPage.js
: 회원가입 및 로그인 양식이 있습니다. 회원가입 시 개인키를 생성하여 애플리케이션에 로그인할 수 있습니다.FeedPage.js
: 컨트랙트로부터 사진 데이터를 읽어와 사용자들에게 보여줍니다. 또한 사용자는 사진을 업로드할 수도 있습니다.
4) What we are going to learn?
블록체인 기반 애플리케이션에서 컨트랙트와 상호작용하는 방법이 두 가지 있습니다.
1) Reading data from contract. 2) Writing data to contract.
Reading data from contract is cost-free. On the otherhand, there is cost for writing data to contract (Sending a transaction). 따라서 데이터를 쓰려면 이 비용을 지불할 KLAY가 있는 Klaytn 계정이 있어야 합니다.
AuthPage에 있는 SignupForm
을 통해 Klaytn 계정(개인키)을 생성할 수 있습니다. 이후에 생성한 개인키로 로그인하여 트랜잭션 수수료를 지불할 수 있습니다.
If you want to learn more about the two different login methods (private key / keystore), please refer to the 5.2. Auth Component page.
본 튜토리얼에서는 FeedPage
에 중점을 두어 애플리케이션이 어떻게 컨트랙트에서 데이터를 읽고 쓰는지를 알아봅니다.
Last updated
Was this helpful?