myKlaytnContract – 컨트랙 소스없이 스마트컨트랙 배치 및 함수 호출하기

 

 


 

 개요

소스 저장소: https://github.com/andrwj/myKlaytnContract/tree/wp1https://github.com/andrwj/myKlaytnContract/tree/wp

 

Klaytn2https://www.klaytn.com/ Baobab 네트워크에 스마트컨트랙을 설치하고 원격 호출을 실험하는 앱이다. Functional Programming3https://www.npmjs.com/package/@andrwj/fp을 적용한 첫번째 React 코드인데 다른 업무와 병행하며 짧은 시간동안 만들었던 것이라 크게 내세울만한 기능은 없다. 그래도 컨트랙 ABI 정보와 배치된 주소를 알기만 하면 해당 컨트랙의 API를 호출할 수 있다는 점이 나름 유용한데,  Klaytn IDE4https://ide.klaytn.com/에서는 컨트랙 소스없이는 원격 호출관련 처리가 불가능 하기 때문이다.

 

 

 실습해보기

 

1) 자신이 만들어둔 컨트랙 소스를 컴파일해서 바이트 코드를 준비한다. 이때 주의할 점은 소스의 바이트코드가 아니라, 인스턴스의 바이트코드가 필요하다는 점이다. 이 차이는 명백히 다르다. 아래의 코드에서 보듯 어떤 클래스를 컴파일 한 코드와 그 클래스의 인스턴스를 생성한 코드는 전혀 다른 것과 같다.


contract MyContract {
  function totalSupply() public view returns (uint256);
  function balanceOf(address who) public view returns (uint256);
  function transfer(address to, uint256 value) public returns (bool);
  event Transfer(address indexed from, address indexed to, uint256 value);

  constructor(string _name, string _symbol, uint _initialSupply, uint _decimals, bool _mintable) public ERC20 () {

  }
}

 

소스를 컴파일한 바이트코드는 owner 정보가 없다. owner 정보는 constructor()가 실행될 때야 비로소 설정되기 때문이다. 따라서, 여러분은 반드시 컨트랙을 Deploy 했을 때의 바이트코드를 사용해야 한다. 이 코드를 얻는 가장 쉬운 방법은 Ganache5https://www.trufflesuite.com/ganache, Remix6https://remix.ethereum.org, Klaytn IDE등으로 테스트 네트워크에 배치를 했을 때 나오는 바이트코드를 복사해두는 것이다.

 

손쉬운 테스트를 위해 오덕Oh Duck Token토큰을 소개한다.  1 ODK == 오리 다섯마리 가치에 상응하는 토큰인데 아직 ICO는 거치지 않았다.

 

 ODK Bytecode 다운로드: bytecode.hex

 

 

2) 해당 컨트랙의 ABI 내용을 준비한다.

 

 0DK ABI 다운로드: ABI.json

 

3)  기존에 사용중인 클래이튼 계정이 없다면 새로운 계정을 만들고 keystore 파일을 받아 둔다.7https://wallet.klaytn.com/create

 

 

4) 위 어플리케이션 탭에서 Deploy Contract 탭을 클릭한다음, bytecode.hex 내용을 복사해서 넣자. Klaytn 계정 로그인은 이전/이후 언제 해도 상관없다. 테스트 네트워크에 컨트랙을 배치할 것이므로 부담없이 컨트랙에 Sign Transacton 버튼을 누르고 DEPLOY CONTRACT 버튼을 클릭한다.

 

5) 성공적으로 컨트랙을 배치했다면 배치한 주소를 잘 기록해두거나 복사해둔다.  (복사후 메세지 패널의 오른쪽 부분을 클릭하면 사라진다)

 

6)  이제 앱의 Interact With Contract 탭을 눌러 배치된 컨트랙의 주소를 복사해 넣고 ABI.json 파일의 내용도 넣는다. 로그인한 상태에서  두개의 정보를 다 넣고 Access 버튼을 누르면 호출 가능한 함수 목록이 선택 박스에 나열된다. (함수 이름을 입력할 때마다 근접검색을 해주므로 마우스보다 빨리 접근할 수 있다)

 

7)  위의 0DK 토큰에서는 반드시 setTransgerAgent 부터 설정해야 한다. 그런 뒤 ReleaseAgent 를 설정하고 releaseTokenTransfer를 진행하게되면 토큰 거래가 가능해진다. 

 

 

 주요 파일
  • mason.js 8https://github.com/andrwj/myKlaytnContract/blob/wp/src/Utils/mason.js – Klaytn 관련 함수를 모아둔 파일
  • Contract.js9https://github.com/andrwj/myKlaytnContract/blob/wp/src/Contract/Contract.js: React Component, Contract 관련 기능 호출
  • RunCommand.js10https://github.com/andrwj/myKlaytnContract/blob/wp/src/Contract/RunCommand.js – 유효성 검사 동적 함수 호출
  • @andrwj/fp11https://www.npmjs.com/package/@andrwj/fp – Either  Monad 구현체

 

Web3JS를 사용해본 사용자라면 Klaytn 툴킷 caver-js12https://docs.klaytn.com/sdk/caverjs 를 쓰는데 별 어려움 없을 것이다.  다음 번 게시물에는 이런 예제보다 수수료 대납기능등을 구현한 것들을 올려볼 예정인데 대납구조를 실습하려면 백엔드 서버가 필요하므로 시간이 좀 걸릴듯.   이런 종류의 앱은 너무 초보적이지만 시간이 지나고 되돌아 봤을 때를 대비해 올려둔다.

References   [ + ]

1. https://github.com/andrwj/myKlaytnContract/tree/wp
2. https://www.klaytn.com/
3, 11. https://www.npmjs.com/package/@andrwj/fp
4. https://ide.klaytn.com/
5. https://www.trufflesuite.com/ganache
6. https://remix.ethereum.org
7. https://wallet.klaytn.com/create
8. https://github.com/andrwj/myKlaytnContract/blob/wp/src/Utils/mason.js
9. https://github.com/andrwj/myKlaytnContract/blob/wp/src/Contract/Contract.js
10. https://github.com/andrwj/myKlaytnContract/blob/wp/src/Contract/RunCommand.js
12. https://docs.klaytn.com/sdk/caverjs

서버사이드 React 렌더링으로 PHP/JS 간에 양방향 함수 호출이 가능한 워드프레스 관리자용 플러그인 만들기

 뻘짓하게된 동기

지난번 회사에서 누적된 과로가 퇴사한 후 몇일 쉬는 동안 갑자기 허리 디스크로 찾아와 꽤 오래 누워있었다.  덥고 습한데 누워있자니 죽을맛..   몇일 동안은 그저 잠으로 일관하다 한 귀퉁이에 밀어뒀던 ‘그 문제’를 다시 꺼내기로 했다. 글쓰는 플랫폼으로써 뿐만 아니라 두루 활용도 높은 워드프레스 플러그인을 React로 구현하는 것인데,  서버사이드 렌더링을 거치면서 WP의 모든 API를 React에서 호출할 수 있고, PHP 쪽에서도 JS/React 로 작성된 함수를 상호 호출할 수 있다면 상당히 재미난 것들을 만들 수 있을 것이라 생각해왔다.  그러나 난 WP Plugin/Theme 관련된 API에 대해선 쥐뿔만큼 알고 있는데다 PHP 코드를 보고있자면 육두문자를 자연스럽게 방출할 만큼 싫어하는 편이다. 그저 WP를 글쓰는 플랫폼으로써 또한 개인정보 관리 시스템으로 잘 활용하고 싶다는 욕심이 있을 뿐. 

 

구글도 지원하는 WP, 내가 필요한 건 JavaScript Bridge!

인터넷에서 WP가 차지하는 비율은 30%가 넘기 때문에 근시일 내에 사장될 수 없다는 여기저기 글들을 봐왔지만 레드오션도 고인 레드오션 급 아니던가.  그런데 작년에 구글이 워드프레스를 지원하겠다는 계획을 발표할 때는 상당히 혹하게 하더니 먹튀하는데 둘쨰라면 구글이 Site Kit1https://sitekit.withgoogle.com 이라는 구글 서비스관련한 공식 툴을 내놓았다. 기능이나 디자인은 둘째치고 내가 인상깊게 받은 건 어떤 서비스나 시스템이 ‘워프프레스 안’으로 들어온 후에 발생 가능한 시너지였다. 나는 워드프레스를 글쓰는 것과 개인정보 관리쪽에만 사용하고 있으나 만약 쭉 생각만 해오던  JavaScript Bridge를 만들어서 PHP 사용을 최소화 하고 모든 영역에서 JS를 사용해보기로 했다.

 

 과정 요약

만들긴 뭘 만들어.. 걍 가져다 잘 사용하면 된다.

모든 잡스런 설명을 줄이고 직접적인 코드로 설명하자면: 1) PHP extension으로써 V8Js를 추가하고, 2) React 코드를 작성해서 잘 잘라둔 다음, 3) 최소한의 PHP로 메뉴와 형틀을 잡고, 4) 나머지는 JS로 코딩하면 된다.

 

 

1) V8Js 설치는 극히 평범하다… -_-)  언제나 그렇듯 개삽질을 하게 해주니 말이다.   따로 정리해둔 글2http://andrwj.com/env/phpv8/을 참조하자.

 

2) React 코드를 잘 자르는게 핵심이다.  Webpack과 친하게 지내야 한다. 칼로 자르던 가위로 자르던 잘 자르자.  몇 번의 삽질을 하다보니 어떻게 / 어느 부분에서 잘라야 좋은지 감이 왔다. 아마 PHP쪽 개발자는 이 과정을 즐겁게 하긴 힘들 것이라 추측한다. 구성하는 방식은 제 각각이므로 자세한 설명은 패스. 내 경우는 myEtherWallet3https://vintage.myetherwallet.com/과 유사한 API를 제공하는 myKlaytnContract4https://github.com/andrwj/myKlaytnContract 이라는 이미 작성해뒀던 어플을 관리자 패널에 넣기위해  세 부분으로 나눴다. 

 

 

3) 최소한의 형틀은 WP Admin UI5https://www.wpadminui.net/ 플러그인을 사용했다. 가져다 쓸만한 게 너무 많아 문제다. 

 

4) 브릿지 부분과 이를 불러 쓰는 부분으로 나눈다

 

// 브릿지를 사용하는 쪽에서 호출하는 부분. 
// $library_js는 webpacket으로 컴파일되서 하나로 모아진 React App 소스.
// $application_js는 ReactJS를 React를 Rendering 하는 부분 
public static function setup( $application_js, $library_js, $stylesheet_url) {
      if ( empty( self::$instance ) ) {
            self::$instance = new self();
            self::$instance->application_js = $application_js;
            self::$instance->library_js     = $library_js;
            self::$instance->stylesheet_url = $stylesheet_url;
            self::$instance->init();
            self::$instance->attach_php_api();
      }
    return self::$instance;
}

 

 

// 위의 브릿지를 호출하는 부분
$bridge = \JSBridge\App::setup( __DIR__ . '/js/app.js', __DIR__ . '/js/bundle.js', get_plugin_url() . '/css/style.css' );

 

 

// React로 작성된 코드를 Snapshot으로 만들고 JS쪽에 전달할 Global Scope(PHP)를 만든다
$library_js = file_get_contents( self::$instance->library_js );
$library = V8Js::createSnapshot( $library_js );
$this->$v8 = new \V8Js('PHP', array(), array(), true, $library);
$this->v8->context = new \stdClass();

// JS에서 호출할 PHP함수 맵핑. JS에서도 동일한 이름으로 호출할 수 있게된다.
$this->register_func( 'wp_head', function() {
  ob_start();
  wp_head();
  return ob_get_clean();
} );

// React 코드를 DOM에다 렌더링 하는게 아니라 문자열로 받아 화면에 출력하면 ok 
$application_js = file_get_contents( self::$instance->application_js );
//내용 예: print(includes.ReactDOMServer.renderToStaticMarkup()
echo $v8->executeString($application_js);

 

보다시피, 어이가 없이 간단한 것이었다;;;;

 

 WP의 DB 접근 및 활용은 너무 간단하지만 충분히 실용적이라 어떤 것이든 쉽게 저장하고 업데이트/삭제할 수 있다

이 점이 젤 큰 매력중에 하나가 아닐까 생각한다. myKlaytnContract 어플리케이션에서는 저장하는게 세가지다. 

  • Application Binary Interface: JSON 포맷으로써 제법 긴 문자열이다. Contract의 API를 기술하는 내용이다
  • Owner Private Key: 물론 프라이빗 키를 이렇게 저장하는 건 분명히 문제가 될 소지가 있지만, 뭐 어때; 어차피 내 블로그는 외부에서 접근 못한다.6http://andrwj.com/post/2019/07/wordpress-as-static-site-generator/
  • Deployed Address of Contract: Klaytn Network 상의 주소 값이다. 테스트 할 때마다 바뀔 수 있어서 저장은 필수! 아님 너무 귀찮아진다.

 

입력한 정보는 Custom Post Type으로 저장되서 WP 안에서는 일반 문서로 취급되서 좋다. Custom Field를 적용해서 프로그래밍 없이 부가 정보를 달아둘 수도 있고. 또 다른 어플로 연결하는 것도 쉬운 일이다. 그야말로 재미난 놀이터;;;ㅎ

 

 

 컨셉은 증명됐다. 이젠 재미를 내려놓고 생활을 위해 구직활동을 해야 할 때

지금껏 재직했던 회사중에선 워드프레스를 활용하는 회사는 단 한군데도 없었다. 걔중 두군데서 BackOffice 제작에 WP를 활용해보자고 운을 띄워봤지만 찬밥;;  모르는 바 아니다ㅋ WP에 익숙해 지는건 FrontEnd 학습하는 것 만큼이나 시간이 걸릴 수 있는데다 이런 Hybrid Type을 솔류션으로 쓰자고 주장하는게 아니다.  오랬동안 머리속에서 맴돌던 걸 정리하는 차원에서 만들어 보았다. 속 후련한다;;

아마 이후로도 시간날 때마다 관련 프로세스를 정립하고 자동화 시키며 완전히 자동화 할 수 있게 만들어 나갈 걸로 생각한다. 그러나 한동안은 이걸 손에서 떼 놓아야 나중에 더 나은 생각이 들수도 있겠지.

 

PHP 문법에서 그 놈의 변수명 앞 ‘$‘ 표기좀 없어지기만 해도 한결 보기 좋을 텐데;;

 

References   [ + ]

1. https://sitekit.withgoogle.com
2. http://andrwj.com/env/phpv8/
3. https://vintage.myetherwallet.com/
4. https://github.com/andrwj/myKlaytnContract
5. https://www.wpadminui.net/
6. http://andrwj.com/post/2019/07/wordpress-as-static-site-generator/