본문 바로가기

Blockchain/EOSIO

Elemental Battles로 시작하는 EOS dApp 개발 (2)

LESSON 1. Smart Contract and Frontend Setup

https://battles.eos.io/tutorial/lesson1/chapter1

 

LESSON1부터 본격적으로 개발이 시작됩니다. Elemental Battles는 앞서 언급한 것 같이 C++로 작성되는 스마트 컨트랙트와 Javascript 라이브러리인 React를 이용한 프론트 엔드 프로그램으로 구성되어 있습니다. 프론트 엔드 프로그램에는 state를 효율적으로 관리하기 위해 Redux가 적용되어 있습니다. 

 

스마트 컨트랙트 세팅

Elemental Battles의 스마트 컨트랙트는 기본적으로 3개 파일로 구성됩니다. 

 

첫번째는 cardgame.hpp입니다. cardgame.hpp는 스마트 컨트랙트를 정의하기 위한 헤더 파일에 해당합니다.

두번째는 cardgame.cpp입니다. cardgame.cpp는 스마트 컨트랙트의 액션을 구현해놓은 소스 파일에 해당합니다.

세번째는 gameplay.cpp입니다. gameplay.cpp 파일은 스마트 컨트랙트에서 필요로 하는 내부적 helper 함수들을 구현해놓은 소스 파일입니다. 스마트 컨트랙트를 작동시키는 액션이 아닌 게임 플레이를 위해 필요한 여러 함수들을 구현해놓은 것입니다.

 

프로젝트를 생성하고 디렉토리, 클래스 및 액션 등을 생성하다보면 EOSIO naming convention을 준수해야 합니다. EOSIO에서는 naming rule을 정해놓고 있고, 몇몇 기능은 naming rule이 지켜지지 않을 경우 정상적으로 컴파일이 안되거나 작동되지 않을 수 있습니다. 

 

Naming Conventions

https://developers.eos.io/eosio-cpp/docs/naming-conventions

eosio::contract에서 파생된 형태의 cardgame class를 구현해보도록 하겠습니다.

 

cardgame class는 eosio::contract를 상속하여 작성되며, 기본적으로 eosio::contract 생성자 함수를 호출하는 생성자 함수를 구현해야 합니다. 생성자 함수는 3가지 종류의 인자를 갖게 되는데 1. 액션을 보내는 계정, 2. 컨트랙트를 소유하고 있는 계정, 3. 데이터 스트림이 이에 해당됩니다. 이는 cardgame.hpp에 구현되며, gameplay.cpp는 이를 포함합니다. 그리고 cardgame.cpp는 다시 gameplay.cpp를 포함하게 됩니다.

 

// cardgame.hpp
#include <eosiolib/eosio.hpp>

using namespace std;
using namespace eosio;

class [[eosio::contract]] cardgame : public eosio::contract {
  public:
    cardgame( name receiver, name code, datastream<const char*> ds ):contract(receiver, code, ds) {}
};

 

// gameplay.cpp
#include "cardgame.hpp"

 

// cardgame.cpp
#include "gameplay.cpp"

EOSIO_DISPATCH(cardgame, BOOST_PP_SEQ_NIL)

 

EOSIO_DISPATCH는 스마트 컨트랙트 정보와 action에 대한 정보를 등록하는 매크로입니다. EOSIO_DISPATCH에 컨트랙트 클래스와 액션에 대한 정보를 기록합니다. 현재 구현된 cardgame 클래스를 매크로에 등록하고, 구현된 액션은 없기 때문에 BOOST_PP_SEQ_NIL 매크로를 입력합니다.

 

스마트 컨트랙트를 개발하기 위한 기본적인 세팅을 마친 후에는 웹 기반의 프론트 엔드 개발을 위한 세팅을 진행합니다. Elemental Battles의 프론트 엔드는 React.js로 구성하고 있습니다. React.js는 프론트 엔드 개발을 위한 Javascript library이며 개발을 위해서는 몇 가지 추가적인 라이브러리들과 설정이 필요합니다. 하지만 여기서는 개발 편의를 위해서 create-react-app이라는 보일러 플레이트를 이용합니다. create-react-app을 이용하면 개발을 위한 기본적인 모듈들과 설정이 자동으로 세팅되기 때문에 빠르게 개발할 수 있다는 장점이 있습니다.

 

React.js와 보일러 플레이트인 create-react-app은 Node.js의 패키지 매니저인 npm을 이용하여 설치할 수 있기 때문에 node.js를 설치합니다.

 

Node.js Downloads

https://nodejs.org/en/download/

 

그 후 순차적으로 다음의 명령어를 커맨드라인 혹은 터미널에 입력하여 React.js 어플리케이션을 생성 및 실행합니다.

 

npm init react-app my-app
cd my-app
npm start

 

npm init react-app my-app 이라는 명령어를 입력하는 것만으로도 실행가능한 my-app 어플리케이션이 생성됩니다.  그리고 해당 경로로 접근하여 npm start를 입력하면 최초 생성된 React app 화면을 확인할 수 있습니다. React app이 정상적으로 만들어졌다면 index.html, index.js, App.jsx 파일을 생성해보겠습니다. app이 정상적으로 생성되었다면, 앞서 말한 index.html, index.js는 각각 public 폴더와 src 폴더 아래 생성되어 있습니다. 두 개 파일은 각각 아래의 코드로 수정합니다.

 

<!-- index.html -->
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <meta name="theme-color" content="#000000">
    <title>Elemental Battles Powered by EOSIO</title>
  </head>
  <body>
    <div id="root"></div>
  </body>
</html>

 

// index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { App } from './components';

ReactDOM.render(
  <App />,
  document.getElementById('root')
);

 

코드 상에서 index.html에는 root라는 id를 갖고 있는 div 태그를 갖고 있고, 해당 태그는 index.js에서 document.getElementById 함수를 통해 ReactDOM.render의 매개 변수로 입력됩니다. 여기서 ReactDOM.render의 또다른 매개 변수로 <App /> 이 보이는데 이는 components 폴더 하위에 정의된 React Component를 의미합니다. 이를 위해 src 아래 components 폴더를 생성하고, 그 하위에는 App 폴더를 생성한 뒤, 해당 경로에 App.jsx 파일을 생성해줍니다. 그리고 아래의 코드를 입력합니다.

 

// App.jsx
// React core
import React, { Component } from 'react';

class App extends Component {
  render() {
    return (
      <div className="App">
      </div>
    );
  }
}

export default App;

 

마지막으로 App.jsx를 export 하기 위한 index.js 코드를 작성해주면 됩니다. 여기까지 완성되면 Elemetal Battles 개발을 위한 스마트 컨트랙트 및 프론트 엔드 세팅이 완료되었습니다. 구체적인 프로젝트 구조 및 코드는 github를 참조하시길 바랍니다.

 

Elemental Battles Tutorial Lesson 1

https://github.com/EOSIO/eosio-card-game-repo/tree/lesson-1