Blockly 블럭 만들기 #1

Blockly는 사용자가 원하는 기능의 블럭을 자유롭게 만들수 있다. 기본 제공된 블럭 외에 사용자의 로봇이나 기타 기능과 연동하기 위한 블럭을 생성하고, 이를 툴박스에 넣어 사용하면 된다.

Blockly는 이러한 블럭들을 쉽게 만들수 있도록 도구를 제공한다. 재밌게도 블럭을 생성하는 것도 블럭으로 만든다. 물론 나중에 좀 익숙해지만 텍스트로 편집하는게 좀더 쉬울 수 있지만, 제공되는 도구를 이용하면 생성되는 블럭 모양을 확인하면서 수정이 가능하다.

먼저 Blockly Developer Tools를 사용해보자. 사파리나 크롬 등 브라우저를 열고 (https://blockly-demo.appspot.com/static/demos/blockfactory/index.html)으로 이동한다.

위와 같은 화면이 나오는데, 왼쪽은 블럭을 생성하기 위한 블럭 코딩 영역, 오른쪽 상단엔 생성된 블럭 모양을 실시간으로 확인이 가능하고, 오른쪽 중앙엔 추후 코드에 삽입하기 위한 JSON 코드, 오른쪽 하단엔 블럭을 실제 코드로 생성하기 위한 generator 코드가 생성된다.

일단 흐름을 보기 위해 아주 간단한 블럭을 생성해보도록 한다. 사용자의 문자열 입력을 받아 console에 출력하는 블럭을 만들어 보록 한다. 먼저 블럭의 name을 수정한다. 여기선 console_print로 한다.

다음으로 이 블럭은 다른 블럭들과 상하 연결하여 사용 가능해야 하므로, connection을 top+bottom connections로 변경한다. 이렇게 되면 미리보기 창의 블럭 모양이 변경됨을 볼 수 있다.

다음으로 사용자의 문자열을 입력 받아야 한다. 왼쪽 툴박스 창에서 Input 카테고리내에 value input 블럭을 inputs에 추가한다. 이 입력을 받아서 내부에서 처리하기 위한 변수명은 value_input 옆에 있는 NAME이다. 이를 필요에 따라 적절하게 수정한다.

이제 블럭에 기능을 설명하기 위한 텍스트 블럭을 추가한다. (Field 카테고리 Text 블럭)

입력은 Text만 받아야 하므로, 입력 type에 String 블럭을 추가한다.

마지막으로 블럭의 색상과, 이 블럭을 사용하는데 필요한 tooltip, help url 등을 입력한다.

이제 생성된 블럭의 모양을 확인해보면,

와 같이 간단한 모양의 블럭이 생성되었다. 생성된 JSON 코드를 확인해보면,

{
  "type": "console_print",
  "message0": "console print %1",
  "args0": [
    {
      "type": "input_value",
      "name": "NAME",
      "check": "String"
    }
  ],
  "previousStatement": null,
  "nextStatement": null,
  "colour": 330,
  "tooltip": "Block for printing the user message",
  "helpUrl": "https://ahnbk.com"
}

그리고, 이와 같이 생성된 Generator stub을 보면,

Blockly.JavaScript['console_print'] = function(block) {
  var value_name = Blockly.JavaScript.valueToCode(block, 'NAME', Blockly.JavaScript.ORDER_ATOMIC);
  // TODO: Assemble JavaScript into code variable.
  var code = '...;\n';
  return code;
};

와 같이 되어 있다. 자 이제 블럭이 생성되었으므로, 이를 지난번에 만들었던 예제에 생성된 블럭을 추가해보도록 한다. 예제 디렉토리로 이동하여, my_blocks.js 파일을 생성하고, 다음과 같이 입력한다.

'use strict';

goog.require('Blockly.Blocks');
goog.require('Blockly');

Blockly.defineBlocksWithJsonArray(
[
    // insert blocks here

]);

이제 “insert blocks here 부분에 위에서 생성된 코드를 붙여 넣는다.

'use strict';

goog.require('Blockly.Blocks');
goog.require('Blockly');

Blockly.defineBlocksWithJsonArray(
[
    {
        "type": "console_print",
        "message0": "console print %1",
        "args0": [
          {
            "type": "input_value",
            "name": "NAME",
            "check": "String"
          }
        ],
        "previousStatement": null,
        "nextStatement": null,
        "colour": 330,
        "tooltip": "Block for printing the user message",
        "helpUrl": "https://ahnbk.com"
      },
]);

저장한 다음, index.html 파일을 열고 위 파일을 로딩하도록 추가한다.

<!DOCTYPE html>
<!-- HTML file to host Blockly in a mobile WebView. -->
<html>
<head>
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
  <style type="text/css">
    html, body, #blocklyDiv {
      border: 0;
      height: 100%;
      margin: 0;
      padding: 0;
      width: 100%;
    }
  </style>
  <script src="blockly_compressed.js"></script>
  <script src="blocks_compressed.js"></script>
  <!-- TODO: Select msg file based on locale. -->
  <script src="msg/js/en.js"></script>
  <script src="toolbox_standard.js"></script>
  <script src="my_blocks.js"></script>
</head>
<body>
  <div id="blocklyDiv"></div>
  <script type="text/javascript">
    var workspacePlayground = Blockly.inject('blocklyDiv', {
          media: 'media/',
          toolbox: BLOCKLY_TOOLBOX_XML['standard'],
          zoom: {controls: true}
        });
  </script>
</body>
</html>

바로 이전 포스팅에서 만든 Custom 카테고리에 생성된 블럭을 추가한다.

+ '<category name="Custom" colour="100">'
+   '<block type="console_print">'
+   '</block>'
+ '</category>'

자, 이제 예제를 다시 열어보면,

Custom 카테고리에 console print 블럭이 추가되어 있음을 볼 수있다. 만약 문자열 입력에 default 값을 넣어 주고 싶다면, 툴박스에 코드를 다음과 같이 수정한다.

+ '<category name="Custom" colour="100">'
+   '<block type="console_print">'
+     '<value name="NAME">'
+       '<shadow type="text">'
+         '<field name="TEXT">Hello Blockly</field>'
+       '</shadow>'
+     '</value>'
+   '</block>'
+ '</category>'

이제 다시 예제를 확인해보면,

와 같이 되어 있음을 확인할 수 있다. 다음엔 좀더 다양한 모양의 블럭을 만들어보록 한다.

Blockly 소개

Blockly (블럭클리?, 블로키?)는 구글에서 오픈소스로 개발하고 있는  visual programming editors (소위 블럭코딩)을 개발하기 위한 Javascript 라이브러리이다. Scratch 3.0도 블럭을 제어하기 위한 부분은 Blockly 라이브러리를 가져와 수정하여 사용하고 있다.

대다수의 블럭코딩 툴들이 Blockly를 기반으로 개발되고 있다. 라이센스는 Apach 2.0을 사용하며, 소스는 https://github.com/google/blockly에 있다. 상업적 사용이 가능하고, 변경 및 배포에 아무런 제약이 없다.

Scratch 3.0이 그만의 프레임웍에 맞추어 개발해야 했다면, Blockly는 사용자가 자유롭게 변형하여 목적에 맞는 프로그램을 개발 가능하다.

블럭으로 만들어놓은 부분을 각종 언어 (Javascript, Pythom, Lua, Dart 등)로 생성이 가능하다. 또 사용자가 원하는 블럭도 생성이 가능하다. 코어가 Javascript로 되어 있어, 웹은 물론 Android, iOS에서도 WebView를 통해 실행이 가능하다. (동일한 코드로)

https://developers.google.com/blockly/ 이 메인 싸이트이며, Blockly에 대한 설명, 사용방법, 개발 방법 등에 대한 부분이 상세하게 적혀있다.

https://groups.google.com/forum/#!forum/blockly 는 Blockly 사용자들이 모여 있는 포럼으로 다수의 사용자들이 Blockly를 Customizing하고, 다양한 사례에 적용할 때 발생하는 문제점을 제시하고 서로 논의 하는 곳이다.