레슨 7 / 8·25분
실전: 비주얼 프로그래밍 에디터
프로젝트 개요 — 미니 코딩 에디터
지금까지 배운 Blockly 지식을 활용하여 커스텀 블록이 포함된 미니 비주얼 프로그래밍 에디터를 구현합니다. HTML 페이지에 Blockly 워크스페이스를 배치하고, 코드 생성 및 실행까지 가능한 완전한 에디터를 만듭니다.
HTML 레이아웃 구성
javascript
// HTML 구조 (코드로 표현)
// <div id="app">
// <div id="toolbar">
// <button id="runBtn">실행</button>
// <button id="saveBtn">저장</button>
// <button id="loadBtn">불러오기</button>
// <button id="clearBtn">초기화</button>
// </div>
// <div id="content">
// <div id="blocklyDiv"></div> <!-- 블록 에디터 -->
// <div id="codeOutput"></div> <!-- 코드 미리보기 -->
// </div>
// <div id="consoleOutput"></div> <!-- 실행 결과 -->
// </div>
// 레이아웃 초기화
var layout = {
toolbar: ["실행", "저장", "불러오기", "초기화"],
editor: "blocklyDiv",
codePreview: "codeOutput",
console: "consoleOutput"
};
window.alert("에디터 레이아웃: " + JSON.stringify(layout));커스텀 블록 정의 — 캐릭터 제어
javascript
// 커스텀 블록 정의: 캐릭터 이동
// Blockly.Blocks["character_move"] = {
// init: function() {
// this.appendDummyInput()
// .appendField("캐릭터를")
// .appendField(new Blockly.FieldDropdown([
// ["위로", "UP"],
// ["아래로", "DOWN"],
// ["왼쪽으로", "LEFT"],
// ["오른쪽으로", "RIGHT"]
// ]), "DIRECTION")
// .appendField("이동");
// this.appendValueInput("STEPS")
// .setCheck("Number")
// .appendField("");
// this.appendDummyInput()
// .appendField("칸");
// this.setPreviousStatement(true, null);
// this.setNextStatement(true, null);
// this.setColour(160);
// this.setTooltip("캐릭터를 지정 방향으로 이동합니다");
// }
// };
// 커스텀 블록의 코드 생성기
// javascriptGenerator.forBlock["character_move"] = function(block) {
// var direction = block.getFieldValue("DIRECTION");
// var steps = javascriptGenerator.valueToCode(
// block, "STEPS", javascriptGenerator.ORDER_ATOMIC
// ) || "1";
// return "moveCharacter(" + JSON.stringify(direction) + ", " + steps + ");\n";
// };
// 캐릭터 이동 실행 함수
var characterX = 0;
var characterY = 0;
function moveCharacter(direction, steps) {
if (direction === "UP") characterY -= steps;
if (direction === "DOWN") characterY += steps;
if (direction === "LEFT") characterX -= steps;
if (direction === "RIGHT") characterX += steps;
window.alert("캐릭터 위치: (" + characterX + ", " + characterY + ")");
}에디터 핵심 기능 구현
javascript
// 코드 생성 및 미리보기 업데이트
function updateCodePreview(workspace) {
// var code = javascriptGenerator.workspaceToCode(workspace);
// document.getElementById("codeOutput").textContent = code;
var code = "// 블록에서 생성된 코드가 여기에 표시됩니다";
window.alert("코드 미리보기 업데이트: " + code);
}
// 실행 버튼
function runCode(workspace) {
// var code = javascriptGenerator.workspaceToCode(workspace);
var output = [];
// console.log를 캡처하여 출력 영역에 표시
var originalAlert = window.alert;
window.alert = function(msg) {
output.push(String(msg));
};
try {
// new Function(code)();
window.alert("실행 성공!");
} catch (error) {
output.push("오류: " + error.message);
}
window.alert = originalAlert;
window.alert("실행 결과:\n" + output.join("\n"));
}
// 워크스페이스 저장
function saveWorkspace(workspace) {
// var state = Blockly.serialization.workspaces.save(workspace);
// localStorage.setItem("blocklyWorkspace", JSON.stringify(state));
window.alert("워크스페이스 저장 완료!");
}
// 워크스페이스 불러오기
function loadWorkspace(workspace) {
// var stateJson = localStorage.getItem("blocklyWorkspace");
// if (stateJson) {
// var state = JSON.parse(stateJson);
// Blockly.serialization.workspaces.load(state, workspace);
// }
window.alert("워크스페이스 불러오기!");
}이벤트 리스너와 실시간 업데이트
javascript
// 워크스페이스 변경 이벤트 감지
// workspace.addChangeListener(function(event) {
// // 블록 변경 시 코드 자동 업데이트
// if (event.type === Blockly.Events.BLOCK_CHANGE ||
// event.type === Blockly.Events.BLOCK_MOVE ||
// event.type === Blockly.Events.BLOCK_DELETE) {
// updateCodePreview(workspace);
// }
// });
// 버튼 이벤트 연결
function setupButtons() {
// document.getElementById("runBtn").onclick = function() {
// runCode(workspace);
// };
// document.getElementById("saveBtn").onclick = function() {
// saveWorkspace(workspace);
// };
// document.getElementById("loadBtn").onclick = function() {
// loadWorkspace(workspace);
// };
// document.getElementById("clearBtn").onclick = function() {
// workspace.clear();
// updateCodePreview(workspace);
// };
window.alert("버튼 이벤트 연결 완료!");
}
// 윈도우 리사이즈 대응
// window.addEventListener("resize", function() {
// Blockly.svgResize(workspace);
// });
// 초기화 실행
setupButtons();
window.alert("에디터 초기화 완료!");- •Blockly.inject() — 워크스페이스를 DOM 요소에 주입
- •workspaceToCode() — 블록을 코드 문자열로 변환
- •addChangeListener() — 블록 변경 이벤트 감지
- •serialization.workspaces.save/load — 워크스페이스 직렬화
- •커스텀 블록 — 도메인 특화 블록을 정의하여 교육/업무 활용
- •localStorage — 브라우저에 작업 내용 저장
💡
이 프로젝트를 확장해 보세요: 블록으로 그림 그리기(Canvas 활용), 게임 캐릭터 제어, 로봇 시뮬레이터, 음악 만들기 등 다양한 도메인에 Blockly를 적용할 수 있습니다. 대상 사용자에 맞는 커스텀 블록을 설계하는 것이 핵심입니다.