자바스크립트 함수형 프로그래밍 – 루이스 아텐시오

이 글은 리뷰가 아니다.

 

2019년 4월 초에 구입했다. 가볍게 읽고 넘어간 부분과 함께 어떤 부분은 10번 이상, 어떤 부분은 수술하듯 단어를 분해하며 학습했다.  이 책이 다른 여타의 입문서나 Medium 글과 비교해 다른 건 체계적으로 함수형 프로그래밍을 어떻게 하는지 기술했다는 점이다. 소위 말하는 ‘초보자’를 위한 책은 아니다. 생각하고 고민하며 구현해가면서 봐야하는 책이었다. 분명하고 확실한 정의를 제공하지만 아는만큼 보이기 때문에 이해하지 못하는 부분은 결국 나중에서야 혀를 차게되는 경우가 제법 있었다.  

함수형 학습 초반에는 FxJS1https://github.com/marpple/FxJS 소스를 분석하고 같은 기능을 직접 구현하면서 ‘함수형이 무엇을 해결하려고 하는지’를 배워갔다면 실전에 가장 영향을 미쳤던 건 Either Monad 구현2https://github.com/andrwj/FPJS이었다. 과하게 Either를 적용하면서 문제가 생길 때마다 FolkTale3https://folktale.origamitower.com/ 구현 하나 하나를 적용하는 계기가 됐다. 그리고 6월 중순을 지나며 Lambda Calculus 구현4https://www.youtube.com/watch?v=3VQ382QG-y4을 볼 때 함수형 코딩론의 밑바닥에 손이 닿인 기분이 들었고 무엇을 어떻게 어떤 식으로 해야할지 완전히 이해했다.

 

.forEach(), .map() , .filter(), .reduce() … 이런 것에 촛점을 맞출 수 밖에 없게한 기존의 책과 Medium 글, 옆집 개가 짖으니 나도 짖는다 식의 블로그 글들,  함수형 코딩 무용론,..  OOP 방법론과의 비교글, ..  오래 전부터 함수형을 배우고 싶었으나 늘 그 언저리에서 머물 수 밖에 없었던 이유를 깨달았고 병신짓인지 모르고 읊어대는 교회 방언마냥 욕을 해대고 싶었으나, 비난의 대상이 너무 넓어 스스로에게 침뱉는 격이었다.

 

생각지 않았던 프로그래밍 언어에 대한 해방감이 찾아온 건 뜻밖의 수확. 라인 한 줄을 코딩하더라도 확실한 지침이 있기때문에 코딩하면 할수록 쌓이는 즐거움. 무엇이 잘못되고 무엇이 올바른 가에 대한 명확한 지침. 덤으로 찾아온 회춘.  나의 지난 시간들이 너무나 억울하다. 코딩의 세상에도 사회주의 공산주가 존재한다고 표현하면 너무 과하다 생각할지 모르겠지만, 내 옆에 있던 동료와 소위 열정을 불살랐던 스터디그룹과 한가닥 한다는 개발자의 선호도와 의견들, 무엇보다 개발자가 생각하지 못하게 여러 요구조건을 강제한 회사와 대표의 요구들… 그 모든게 좀 처럼 생각을 자유롭게 적용하지 못하도록 서로에게 영향을 끼쳤다.  설령 내가 억울하다 여기는 과거의 시간동안 함수형 코딩을 할 수 있었다해도 동료라는 인간들과 무형의 팀원과 일에 치여 귀찮은 팀장과 돈이 궁한 사장의 압력을 버티지 못했을 것이라 생각한다. 늦었지만 지금이라도 제대로 알게된 것에 힘입어 얼마 남지 않았을지도 모를 내 앞의 시간을 함수형 개발을 하며 기쁨을 계속 누려가고 싶다. 

 

함수형 코딩을 배우려는 개발자에게 몇 마디 하자면, 결국엔 함수형 코딩이 지켜야할 몇 안되는 이 규칙Rule에 귀결한다는 사실을 반지로 삼아 항상 끼고 학습하면 너무 돌아가지 않고 신속히 적응할 수 있을 것이다:

 

  • Declarative
  • Purity
  • Transparency
  • Immutability

 

위의 네가지 규칙의 코딩by 그리고 규칙을 위해for , 또한 룰에 의해of 코딩하는 방법이 함수형 프로그래밍이다.  학습 초반에 너무 ‘정의’에 매달리지 말고 해당 ‘정의’가 어떤 상황에서 적용되는 것인가를 주의 깊게 보는게 더 낫다. 정의는 결국 이해한 뒤에야 인정하는 동감일 뿐이다. 그러자면 남들이 작성한 FP 스타일 코드를 무조건 많이 보는게 확실한 방법. 무수하게 사용하는 if..then..else 조차도 함수형 방법론에 의해 대체되면 인지적 자유와 해방감을 얻게된다. 이내 한번 코딩하면 그 부분은 논리 오류가 아닌 이상 문제가 없음을 확신하므로 더 이상 자신의 코드에 불안을 가지는 경우가 드물어간다.  작게 쌓아올리지만 결국엔 거대한 모습을 형성하게 됨을 볼 때, OOP는 후쿠시마산 농수산물과 같다는 생각이 들지도 모른다. 값 싸고 그럴듯해 보이는데 내부피폭을 유발하는 OOP.  그 내부 피폭에 해당하는게 OOP의 핵심이론이라니…ㅋ  아마도 깊은 빡침을 느낄지도 모른다.

 

FP를 반대하는 개발자는 OOP의 우수성과 비교하며 제발 OOP에 안주해주길 바란다. 적자생존 아니던가.. 사실 나도 FP를 OOP와 공존시키는 방법이 있는가 엄청 찾아보고 고민했었다.  원래 불가능한 것이며 하지 말아야 할 시도인데도 불구하고 그렇게 끈덕지게 달라붙었던 건, 아직까지 ‘현업’에서 OOP를 쓰기 때문이었다.  역시나 병신 짓을 반복했던 나. 그 ‘현업’이란게 나를 속여온 원흉 중 큰 부분인데 거기에 또 미련을 가진 이유가 뭐냐…  그러나 이제 OOP도 문제되지 않는다고하면 뭔 궤변같은 개소리냐 하겠지만, 사실 그렇다. 문제가 뭔지 알고 난 후에는 얼마든지 피해가는 방법이 보이기 때문이다.  쉽다고는 하지 않는다. 단지 비용이 들어갈 뿐이지. 그 비용은 회사 대표가 지출하는 것이고 문제삼지 않는다면 굳이 거기에 기를 쓰고 반대할 필요가 없다. 

 

시간… 시간이 필요하다.  함수형 코딩론은 이해가 된 시점부터 시간 싸움인 것 같다. 좀만 더 일찍 알았더면…  즐겁게 내가 만들고자 하는 것들을 구현하는 기쁨에 나이가 들던말던 개발자로서 살아가는 재미가 더 했을 텐데..

References   [ + ]

1. https://github.com/marpple/FxJS
2. https://github.com/andrwj/FPJS
3. https://folktale.origamitower.com/
4. https://www.youtube.com/watch?v=3VQ382QG-y4

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/