[블록 코딩 개발] Blockly 설치 및 Fixed Size Workspace 만들기
* 공부 메모용~
이번에는 Blockly가 담긴 HTML을 만들기 전에 이를 구동시킬 Node.js로 서버를 간단히 만들고, Blockly를 Github에서 소스를 직접 내려받아서 설치한 다음, Getting Started의 일부인 Injecting fixed-size Blockly를 만들어보도록 한다.
Blockly에서 Workspace를 만들 수 있는 방법은 두 가지가 있는 듯 하다. 하나는 웹 브라우저의 사이즈가 변하더라도 지정한 영역만큼의 사이즈를 유지하는 Fixed-size 방식과, 웹 브라우저의 사이즈가 변하면 그에 맞춰 Workspace의 크기가 변하는 반응형인 Resizable 방식이다.
이번에는 Document에 가장 먼저 나오는 Fixed-Size Workspace를 만들어보도록 한다. 그 전에 틀부터 먼저 만들어야한다. 시작해보자!
0. 준비물
- Visual Studio Code
- Node.js
- HTML과 JavaScript에 대한 기초 지식
개발을 위해서 사용하는 툴로는 VSCODE를 사용할 것이다.
또한, Node.js를 통해 HTML을 서비스할 수 있는 형태로 구성해볼 것이다. 이때 Node.js 서버는 매우 기초적인 수준으로만 작성할 것이므로, 이에 대해서 잘 모른다면 다른 포스팅을 보고 오면 좋을 것 같다.
그 다음으로는 Blockly를 탑재하기 위한 HTML 파일을 만들건데, 이때 HTML와 JavaScript에 대한 기초적인 이해가 있어야 한다.
1. VSCODE Workspace와 Node.js 서버 만들기
VSCODE를 킨 후, Workspace를 만들어준다. 나는 blockly-tutorial 이라는 디렉토리를 생성해주었다.
이제 Node.js 환경을 구성하기 위해서 npm 명령어를 통해 Workspace를 초기화해주자.
npm init
Entry Point는 npm init의 기본 설정과 동일하게 index.js로 설정하였다. 추후 이곳에 서버 파일을 작성할 것이다.
그 다음으로는 Node.js에서 서버를 열기 위해 NPM 패키지를 통해 Express를 설치해주고, 또한, 서버 로직이 변경될 경우 이를 재감지해서 바로바로 반영해주는 Nodemon이라는 모듈을 설치할 것이다.
npm install express --save
npm install nodemon --save-dev
설치가 모두 완료되었다면, 다음과 같이 화면이 구성되어 있을 것이다.
이제 본격적으로 Workspace에 내용물을 채워넣어주자. Entry Point는 index.js 이므로 루트 디렉토리에 index.js 파일을 만들어준다.
그 다음으로는 HTML을 생성한다.
구성은 <Fig. 5>와 같다. Blockly를 보여주기 위한 페이지를 views 디렉토리 내에 fixedSizeWs.html로 만들어주었다.
이제 서버 파일(index.js) 을 작성해보자.
const express = require('express');
const app = express();
const path = require('path');
const port = 3000;
app.get('/', (req, res) => {
return res.sendFile(path.join(__dirname, 'views', 'fixedSizeWs.html'));
})
app.listen(port, (res, req) => {
console.log(`Server is running at ${port} for blockly.`);
})
index.js의 구성은 상기 코드와 같다. 3000번 포트로 서버를 열어주었고, 가장 루트 경로인 /로 접근하였을 때 views 폴더 내에 위치한 fixedSizeWs.html을 보여주도록 하였다. Node.js 서버의 가장 기초적인 형태이다.
마지막으로 서버를 구동하기 위해서 package.json에 서버 시작 명령어만 작성해주면 된다.
"scripts": {
"start": "node index.js",
"dev": "nodemon index.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
npm run start로 실행하였을 때는 node index.js 명령어를 통해 서버를 실행하도록 하였고, npm run dev로 실행하였을 때는 nodemon index.js를 통해 실행하도록 하였다. 이제 npm run dev(또는 start)를 통해 서버를 실행할 수 있다.
2. Blockly Github에서 내려받기
가장 먼저 하단의 링크를 통해서 Blockly를 Zip 파일로 다운받자.
GitHub - google/blockly: The web-based visual programming editor.
The web-based visual programming editor. Contribute to google/blockly development by creating an account on GitHub.
github.com
깃허브에 접근한 후, <Fig. 1>과 같이 ZIP 파일로 내려받으면 된다.
3. Blockly 압축 풀기
파일을 다운 받았으면 Workspace에 압축을 해제해주어야한다. 나는 libs 디렉토리 내에 blockly 디렉토리를 생성 후, 여기에 압축을 해제해주었다.
4. Express 정적 파일 라우팅
libs/blockly에 압축을 해제하였으므로, 추후 HTML에서 해당 리소스를 불러올 때 Blockly 리소스를 제대로 찾아가기 위한 라우팅을 지정해주자.
const express = require('express');
const app = express();
const path = require('path');
const port = 3000;
// 정적 파일 라우팅
app.use('/libs', express.static(path.join(__dirname, 'libs')));
app.get('/', (req, res) => {
return res.sendFile(path.join(__dirname, 'views', 'fixedSizeWs.html'));
})
app.listen(port, (res, req) => {
console.log(`Server is running at ${port} for blockly.`);
})
다음과 같이 app.use 함수를 통해 정적 파일을 라우팅해주었다. 이제 HTML에서 /libs 경로로 접근하면 자동으로 루트 디렉토리 내의 libs 디렉토리를 바라보게 된다. (사실 어차피 폴더 명이 libs로 동일하므로 굳이 안 해주어도 되지만 왠지 하고 싶었다.)
5. Blockly Fixed Sized Workspace 만들기
Fixed-sized Workspace | Blockly | Google Developers
The simplest way to put Blockly into a webpage is to inject it into an empty 'div' tag. Injection First, include the core Blockly script and the core blocks set. Note that the path may vary, depending on where your page is in relation to Blockly: Then incl
developers.google.com
이제 시작이다! Getting Started 페이지에서 뻗어나오는 Fixed-sized Workspace Document를 참고하여 Blockly 환경을 구성해보자!
<head>
<!-- 생략 -->
<script src="/libs/blockly/blockly_compressed.js"></script>
<script src="/libs/blockly/blocks_compressed.js"></script>
</head>
가장 먼저, HTML 상에 Blockly의 핵심 파일과, Blockly에 내장된 블록 파일들을 임포트해와야한다. 여기서는 <head> 태그에 정의해주었다.
여기에서 Blockly 구동에 필요한 핵심 기능들이 포함된 blockly_compress.js를 불러왔으며, Blockly의 블록들이 포함된 blocks_compressed.js 파일 역시 불러왔다.
그 다음으로는 블록에 표시될 언어팩을 설정해보자. Blockly에서는 엄청나게 많은 언어들을 지원한다!
<head>
<!-- 생략 -->
<!-- Blockly 언어 팩 임포트 -->
<script src="/libs/blockly/msg/js/ko.js"></script>
</head>
생략된 부분에는 당연히 방금 불러온 blocks_compressed.js, blockly_compressed.js가 포함되어 있다. 나는 그 하단에 언어팩을 지정해주었는데, 이러한 언어팩은 blockly 패키지 내의 msg/js 디렉토리 내에 있다. 여기에서는 한국어가 있길래 한국어로 지정해주었다
이제 workspace를 생성해보자.
<body>
<!-- Blockly Workspace -->
<div id="fixed_workspace" style="width: 1000px; height: 700px; border: 1px solid red;"></div>
</body>
이게 끝이다. Blockly에서 Workspace를 정의하기 위해서는 <div> 태그를 통해 표현할 영역을 잡아준 후, 해당 영역의 ID를 잡아와서 Workspace를 넣어줄 것이다. 이 작업은 아래에서 진행한다.
참고로, Fixed-sized Workspace이므로 여기에서 <div> 태그에 스타일을 인라인으로 width와 height 영역을 잡아주었고, 또한 표시될 영역을 확인하기 위해 border를 세팅해주었다.
서버를 실행시키고 영역이 제대로 잡혔는지 확인해보자!
영역은 잘 잡힌 것 같다. 이제 이 안에 Workspace를 넣어주면 된다.
Workspace를 넣어주기 전에! Toolbox 라는 것을 먼저 정의해야한다고 한다. Toolbox는 아래 그림처럼 생긴 것 같다.
블록을 실제 Workspace에 배치하기 위해서 블록을 갖고 있는 영역이 Toolbox로 보인다. Document에서는 자세한 내용은 이하의 링크를 참조하라고 하지만, 살펴보니 깊은 내용인 것 같아 추후 이에 대한 내용을 따로 포스팅 하는 것이 더 나을 것 같다.
Toolbox | Blockly | Google Developers
The toolbox is the side menu from whence the user may create new blocks. The structure of the toolbox is specified with either XML or JSON. This toolbox definition will be passed to Blockly when it is injected into the page. Note: For more information on h
developers.google.com
일단은 Document에 충실하게 하라는대로 해보자! 이제 Toolbox를 만들어보자. Toolbox는 XML의 형태로 정의할 수 있는 것으로 보인다. <body> 태그 안에 Toolbox XML을 정의해보자.
<body>
<!-- Blockly Workspace -->
<div id="fixed_workspace" style="width: 1000px; height: 700px; border: 1px solid red;"></div>
<!-- Toolbox 정의 -->
<xml id="toolbox" style="display: none">
<block type="controls_if"></block>
<block type="controls_repeat_ext"></block>
<block type="logic_compare"></block>
<block type="math_number"></block>
<block type="math_arithmetic"></block>
<block type="text"></block>
<block type="text_print"></block>
</xml>
</body>
사실 Document에 있는 코드를 그대로 복사해서 Workspace 영역 하단에 붙여넣은 것 뿐이다.
이제 마지막으로 JavaScript를 통해 실제 Blockly Workspace를 생성하고, 이를 <div>에 주입시키면 된다. 이를 위해 <body>태그 내에 <script> 태그를 생성해서 코드를 작성한다.
<body>
<!-- 생략-->
<script>
let fixedWorkspace = Blockly.inject('fixed_workspace', {
toolbox: document.getElementById('toolbox')
})
</script>
</body>
6. 결과 확인
마지막으로 서버를 실행시킨 후, 제대로 Workspace가 생성되었는지 확인해보자.
지정된 영역에 Workspace가 잘 생성됨을 확인하였다! Fixed-sized 이므로 화면의 크기를 변경해도 해당 영역만큼만을 차지한다.
7. Workspace Options
Blockly는 Workspace를 정의할 때 사용할 수 있는 다양한 옵션들을 제공한다. 이에 대해서는 이하의 링크를 참조하자.
Injection Options | Blockly | Google Developers
Injection You can inject a Blockly workspace with a call to Blockly.inject(location, options). The first argument tells Blockly where to inject the workspace in the DOM. The second argument is a dictionary of name-value pairs that is used for configuration
developers.google.com
다양한 옵션들을 적용하기 위해서는 Blockly.inject() 함수의 두 번째 인자에서 설정할 수 있다.
내가 사용한 옵션은 zoom, move, grid, trashcan이다. 어떻게 사용했는지는 하단에 코드를 참고하자. (사실 대부분 Document에서 가져온 코드다.)
function updateSoundTest() {
let volumn = document.getElementById('volumn').value;
modifiedSound = volumn;
}
let fixedWorkspace = Blockly.inject('fixed_workspace', {
toolbox: document.getElementById('toolbox'),
zoom: {
controls: true,
wheel: true,
scaleSpeed: 1.05
},
move: {
scrollbars: {
horizontal: true,
vertical: true
},
drag: true,
wheel: false
},
grid: {
spacing: 40,
length: 2,
snap: true
},
trashcan: true,
})
1) Zoom
zoom 옵션을 통해서 Workspace에서 마우스 휠을 통해 블록을 줌 인/아웃을 설정할 수 있도록 wheel 속성을 사용하였다.
controls 속성을 사용하면 다음 그림과 같이 Workspace에 컨트롤 할 수 있는 Element가 생성된다.
그리고 scaleSpeed 속성을 사용하면 마우스 휠을 통해 줌 인/아웃 할 때의 속도를 정할 수 있다. Default 값은 1.2이며, 나는 상당히 속도가 빠르다고 생각해 1.05로 지정하였다.
2) move
해당 옵션을 통해 Workspace 내의 Canvas를 마우스 드래그를 통해 이동할 수 있다. drag 속성을 통해 이를 활성화할 수 있으며, 이때 전제 조건은 Workpsace에 스크롤바가 붙어있어야 한다는 점이다.
스크롤바는 move 옵션 내의 scrollbars 속성을 추가하여 설정할 수 있다. 나는 가로와 세로 스크롤바를 추가하였다.
wheel 속성은 워크스페이스 내의 Canvas를 마우스 휠을 통해 제어할 것인지 정할 수 있도록 한다. 나의 경우, 해당 옵션은 Zoom 옵션의 wheel 속성과 겹치므로 false로 지정하였다.
3) Grid
Grid 옵션은 Workspace의 Canvas에 선을 정의할지 말지를 의미한다.
상단의 그림과 같이, Grid를 적용할 수 있다.
Spacing 속성을 통해 각 Grid Point들의 거리를 지정할 수 있다. 값이 작을 수록 Grid는 더 조밀해지며, 클 수록 Grid의 거리가 더 멀어진다. 나의 경우는 40으로 지정하였다.
length 속성을 통해 각 Grid Point의 크기를 설정할 수 있다. 나의 경우 2로 지정하였다.
마지막으로 나는 snap 속성을 지정하였는데, 이는 블록을 배치하였을 때 Grid의 위치에 맞게 자동으로 블록을 위치시킬 것인지에 대한 여부로, Boolean 값을 통해 설정할 수 있다.
8. 마무리
지금까지 Blockly의 가장 간단한 Fixed Sized Workspace를 정의해보았다. 가장 먼저 Workspace를 정의할 <div> 영역을 만들고, JavaScript를 통해 해당 영역에 Blockly Workspace를 주입(Injection)하였다.
또한, 툴 박스를 정의하고 Workspace를 주입 시 toolbox 속성을 통해 툴 박스가 표시될 수 있도록 하였다.
마지막으로 다양한 Inject Option을 통해 Workspace에 여러 기능을 넣어주었다.
다음 시간에는 뭐하지... 툴 박스에 대해서 좀 더 알아볼지, 아니면 Resizable Workspace에 대해서 좀 더 알아볼지 고민해야겠다.