[JavaScript] Rete.js๋?
Rete.js
Rete.js๋ ๋น์ฃผ์ผ ํ๋ก๊ทธ๋๋ฐ ๋ฐ ๋ ธ๋ ๊ธฐ๋ฐ ํธ์ง๊ธฐ(Node-based Editor)๋ฅผ ์ ์ํ ์ ์๋ ์คํ์์ค JavaScript ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ด๋ค. ํ ์คํธ ๊ธฐ๋ฐ ์ฝ๋ฉ์ด ์๋ Visual Flow Programming ๋๊ตฌ๋ก, ์ฌ์ฉ์๊ฐ ํ ์ค์ ์ฝ๋ ์์ด ํธ์ง๊ธฐ์์ ๋ฐ์ดํฐ ์ฒ๋ฆฌ ๋ฐฉ์์ ์ ์ํ์ฌ ๋ธ๋ผ์ฐ์ ์์ ์๊ฐ์ ์ผ๋ก ํ๋ก๊ทธ๋๋ฐ์ ํ ์ ์๋ค.
Rete.js
rete.js.org
Drag & Drop ์ธํฐํ์ด์ค๋ฅผ ์ ๊ณตํ์ฌ ๊ทธ๋ํฝ์ ์ผ๋ก ๋ ธ๋๋ฅผ ๋ฐฐ์นํ๊ณ ์ฐ๊ฒฐํ ์ ์์ผ๋ฉฐ, ์ํฌํ๋ก์ฐ ์์คํ , AI ํ๋ก์ฐ, ๋ฐ์ดํฐ ํ๋ก์ฐ ๊ธฐ๋ฐ ์ฑ์ ๊ฐ๋ฐํ๋ ๋ฐ ์ ์ฉํ๋ค.
ํน์ง
- ๋
ธ๋ ๊ธฐ๋ฐ UI ์ ์
- ์ฌ์ด ๊ตฌํ : ๋ธ๋ก์ ๋ฐฐ์นํ๊ณ ์ ์ผ๋ก ์ฐ๊ฒฐํ๋ ํํ
ex) ๋ธ๋กํ ์ฝ๋ ํธ์ง๊ธฐ, ์๊ฐ์ ๋ฐ์ดํฐ ํ๋ฆ ๊ด๋ฆฌ ์์คํ
- ์ฌ์ด ๊ตฌํ : ๋ธ๋ก์ ๋ฐฐ์นํ๊ณ ์ ์ผ๋ก ์ฐ๊ฒฐํ๋ ํํ
- ๋ชจ๋ํ๋ ํ๋ฌ๊ทธ์ธ ์์คํ
- ๊ธฐ๋ณธ ์์ง์ ํ๋ฌ๊ทธ์ธ์ ์ถ๊ฐํ์ฌ ๊ธฐ๋ฅ ํ์ฅ ๊ฐ๋ฅ
ex) Drag & Drop ๊ธฐ๋ฅ, ๋ฏธ๋๋งต, ๋ฏธ๋ฆฌ๋ณด๊ธฐ ์ฐฝ ๋ฑ์ ์ถ๊ฐ ๊ธฐ๋ฅ
- ๊ธฐ๋ณธ ์์ง์ ํ๋ฌ๊ทธ์ธ์ ์ถ๊ฐํ์ฌ ๊ธฐ๋ฅ ํ์ฅ ๊ฐ๋ฅ
- ์ปค์คํ
๋
ธ๋ ์ ์ ๊ฐ๋ฅ
- HTML, Vue, React ๋ฑ๊ณผ ์ฐ๋ํ์ฌ ์ํ๋ UI ์์๋ฅผ ์ถ๊ฐํ ์ ์์
- ์น ๊ธฐ๋ฐ
- ๋ธ๋ผ์ฐ์ ์์ ์คํ๋๋ JavaScript ๋ผ์ด๋ธ๋ฌ๋ฆฌ
- ์ถ๊ฐ์ ์ธ ์ํํธ์จ์ด ์ค์น ์์ด ์น ์ ํ๋ฆฌ์ผ์ด์ ์ผ๋ก ์ ์ ๊ฐ๋ฅ
- ์คํ์์ค ๋ฐ ํ์ฅ์ฑ
- ๋๊ตฌ๋ ์ฌ์ฉํ ์ ์๋ MIT ๋ผ์ด์ ์ค ๊ธฐ๋ฐ ์คํ์์ค
- ๋ณต์กํ ๋ฐ์ดํฐ ํ๋ฆ์ ๊ฐ๋จํ๊ฒ ๊ตฌ์ฑํ ์ ์์
์ค์น
npm์ ์ด์ฉํ์ฌ ๋ค์๊ณผ ๊ฐ์ด ์ค์นํ๋ค.
# Rete๋ง ์ค์น
$ npm install rete
# ํ๋ฌ๊ทธ์ธ ํฌํจ ์ค์น (๊ณต์ ๋ฌธ์ ๋ด์ฉ)
$ npm install rete rete-vue-render-plugin rete-connection-plugin
# ๋๋ yarn์ ์ด์ฉํ์ฌ ๋ค์๊ณผ ๊ฐ์ด ์ค์น ๊ฐ๋ฅ
$ yarn add rete rete-connection-plugin rete-vue-render-plugin
์ดํ ๋ค์๊ณผ ๊ฐ์ด importํ์ฌ ์ฌ์ฉํ๋ค.
import Rete from "rete";
import ConnectionPlugin from 'rete-connection-plugin';
import VueRenderPlugin from 'rete-vue-render-plugin';
ํ๋ฌ๊ทธ์ธ
๋ ธ๋ ๊ฐ ์ฐ๊ฒฐ์ ์ ์์ฑํ๋ ํ๋ฌ๊ทธ์ธ
import ConnectionPlugin from "rete-connection-plugin";
editor.use(ConnectionPlugin);
Vue.js๋ฅผ ์ฌ์ฉํด UI๋ฅผ ๋ ๋๋งํ๋ ํ๋ฌ๊ทธ์ธ
import VueRenderPlugin from "rete-vue-render-plugin";
editor.use(VueRenderPlugin);
์ฐํด๋ฆญ ๋ฉ๋ด๋ฅผ ์ถ๊ฐํ๋ ํ๋ฌ๊ทธ์ธ
import ContextMenuPlugin from "rete-context-menu-plugin";
editor.use(ContextMenuPlugin);
JSON ์ ์ฅ ๋ฐ ๋ถ๋ฌ์ค๊ธฐ
Rete.js๋ JSON ํ์์ผ๋ก ๋ ธ๋ ํธ์ง๊ธฐ์ ์ํ๋ฅผ ์ ์ฅํ๊ณ ๋ถ๋ฌ์ฌ ์ ์๋ค.
์ ์ฅ
const json = editor.toJSON();
localStorage.setItem("reteData", JSON.stringify(json));
๋ถ๋ฌ์ค๊ธฐ
const data = JSON.parse(localStorage.getItem("reteData"));
editor.fromJSON(data);
์์
import Rete from "rete";
import ConnectionPlugin from "rete-connection-plugin";
import VueRenderPlugin from "rete-vue-render-plugin";
// HTML ์์ ์ ํ (๋
ธ๋ ํธ์ง๊ธฐ๊ฐ ๋ค์ด๊ฐ div)
const container = document.getElementById("rete");
// ๋
ธ๋ ํธ์ง๊ธฐ ์์ฑ (ID๋ 'demo@0.1.0'์ผ๋ก ์ง์ )
const editor = new Rete.NodeEditor("demo@0.1.0", container);
editor.use(ConnectionPlugin);
editor.use(VueRenderPlugin);
// ์์ผ ์ ์ (๋
ธ๋ ๊ฐ ์ฐ๊ฒฐ์ ์ํ ์ธํฐํ์ด์ค)
const numSocket = new Rete.Socket("Number");
// ์ปค์คํ
๋
ธ๋ ์ ์
class NumComponent extends Rete.Component {
constructor() {
super("Number");
}
builder(node) {
const out = new Rete.Output("num", "Number", numSocket);
return node.addOutput(out);
}
worker(node, inputs, outputs) {
outputs["num"] = node.data.num;
}
}
// ์์ง ์์ฑ ๋ฐ ๋
ธ๋ ์ถ๊ฐ
const engine = new Rete.Engine("demo@0.1.0");
const numComponent = new NumComponent();
editor.register(numComponent);
engine.register(numComponent);
// ๊ธฐ๋ณธ ๋
ธ๋ ์ถ๊ฐ
(async () => {
const node1 = await numComponent.createNode();
node1.position = [80, 200];
editor.addNode(node1);
})();
- Rete.NodeEditor : ๋ ธ๋ ํธ์ง๊ธฐ ์ธ์คํด์ค ์์ฑ (์ด๊ธฐํ)
- editor.use(ConnectionPlugin) : ๋ ธ๋ ๊ฐ ์ฐ๊ฒฐ ๊ธฐ๋ฅ์ ์ถ๊ฐ
- editor.use(VueRenderPlugin) : Vue.js๋ฅผ ์ฌ์ฉํ์ฌ ๋ ธ๋ UI๋ฅผ ๋ ๋๋ง
- Rete.Socket : ๋ ธ๋ ๊ฐ ์ฐ๊ฒฐํ ์ ์๋ ์์ผ์ ์ ์
- Rete.Component : ์ปค์คํ ๋ ธ๋๋ฅผ ์ ์ํ๋ ํด๋์ค
- builder(node) : ๋ ธ๋์ ์ ์ถ๋ ฅ ์ธํฐํ์ด์ค๋ฅผ ๊ตฌ์ฑ
- worker(node, inputs, outputs) : ์ ๋ ฅ ๊ฐ์ ์ฒ๋ฆฌํ๊ณ ์ถ๋ ฅ์ ์์ฑํ๋ ๋ก์ง
- editor.addNode(node1) : ๋ ธ๋๋ฅผ ํธ์ง๊ธฐ์ ์ถ๊ฐ
ํ์ฉ ์ฌ๋ก
- ๋น์ฃผ์ผ ์คํฌ๋ฆฝํ ๋๊ตฌ
- AI ํ๋ก์ฐ ์ฐจํธ (TensorFlow, ๋จธ์ ๋ฌ๋ ๋ ธ๋ ํธ์ง๊ธฐ)
- ๊ฒ์ ๊ฐ๋ฐ (Unity, Unreal Engine์ ๋ธ๋ฃจํ๋ฆฐํธ ์คํ์ผ ์์คํ )
- IoT ๋ฐ์ดํฐ ํ๋ฆ ๊ด๋ฆฌ
- ๋น์ฃผ์ผ ๋ฐ์ดํฐ ๋ถ์ ๋๊ตฌ (BIํด)
- ๋ ธ์ฝ๋(No-Code) ๋ฐ ๋ก์ฐ ์ฝ๋(Low-Code) ์ฑ ๊ฐ๋ฐ