์ฒด๋ฆฌ๋ณด๋๋ ํ์ดํธ๋ณด๋ ํด๋ก, ํผ๊ทธ์ผ์ฒ๋ผ ์ฌ๋ฌ ์ ์ ๋ค์ด ๋ชจ์ฌ์ ์์ ๋กญ๊ฒ ๋๋ก์ํ๊ณ ์ํตํ ์ ์์ด์. UI๋ ์ต๋ํ ๊ท์ฝ๊ณ ์๊ธฐ์๊ธฐํ๊ฒ ๊ฐ์ ธ๊ฐ๊ณ ์ถ์์ด์! ์ด๋ชจํฐ์ฝ์ ๋์ฅ์ฒ๋ผ ์ฐ์ ์๋ ์๊ณ ํ
์คํธ๋ฅผ ์
๋ ฅํ๊ฑฐ๋ ์ฌ์ง์ ์ฌ๋ฆด ์ ์์ต๋๋ค. ๋ํ ํ์ฌ ์บ๋ฒ์ค๋ฅผ ์ด๋ฏธ์ง ํ์ผ๋ก ๋ด๋ณด๋ด์ด ์ ์ฅํ ์๋ ์์ด์. ๊ทธ๋ฆฌ๊ณ /
๋จ์ถํค๋ฅผ ํตํด ์ปค์ ์์ ๋ฉ์์ง๋ฅผ ์
๋ ฅํ ์ ์์ด์.
์ฒด๋ฆฌ๋ณด๋๋ ์ค๋ฒจํธ๋ฅผ ์ฌ์ฉํด์ ๊ฐ๋ฐํ์ต๋๋ค. ์ ๋ ์ด์ ๊น์ง ์ฌ์ฉํด๋ณธ ํ๋ ์์ํฌ๊ฐ ๋ฆฌ์กํธ ๋ฟ์ด์ด์ ์๋กญ์ด ์ปจ์ ๊ณผ ์ฅ์ ๋ค์ ๊ฐ์ง๊ณ ์๋ ์ค๋ฒจํธ๋ฅผ ์ฌ์ฉํด ๋ณด๊ณ ์ถ์์ด์. React์ ๋ค๋ฅธ ํ๋ ์์ํฌ๋ค๊ณผ ์ฐจ๋ณ์ ์ ๊ฐ์ง ์ค๋ฒจํธ๋ ๊ฐ์ DOM์ ์ฌ์ฉํ์ง ์์์ ๋น ๋ฅด๊ณ , ๋ฌด์๋ณด๋ค๋ ํจ์ดํ JavaScript, HTML, CSS์ ์ ์ฌํ ๋ฌธ๋ฒ์ผ๋ก ๊ฐ๋ฐ ๊ฒฝํ์ด ๋งค์ฐ ํธ๋ฆฌํ์ต๋๋ค.
์คํ์ผ์ utility-first ์ปจ์ ์ ๊ฐ์ง Tailwind CSS๋ฅผ ์ ํํ์์ต๋๋ค. CSS-in-JS ์ค Styled-component์ Emotion์ผ๋ก ๊ฐ๋ฐํด๋ณธ ๊ฒฝํ์ผ๋ก , ์๋ฉํฑํ ํด๋์ค ์ด๋ฆ ์ง๊ธฐ์ ๋ํ ๊ธฐ์ค์ด ์ฌ๋๋ง๋ค ๋ค๋ฅด๋ฉฐ, ์ฌ์ง์ด ํ ์ฌ๋์ด ์๋ช ํ๋๋ผ๋ ์๊ฐ์ด ์ง๋จ์ ๋ฐ๋ผ ๋ค๋ฅด๊ฒ ์ง๊ธฐ๋ ํฉ๋๋ค. Component Driven Development์ ์ฌ๋ฌ ํ๋ ์์ํฌ ๋ฑ์ฅ์ผ๋ก ์ธํด์ ์์ ์ ํด๋์ค ์ ํ์๋ก ์คํ์ผ์ ์ฌ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ์ปดํฌ๋ํธ์ ์ฌ์ฌ์ฉ์ผ๋ก ๋์ฒด๋์๊ธฐ ๋๋ฌธ์, ์ด์ ์ฒ๋ผ ํด๋์ค๋ช ์ ์๋ฉํฑํ๊ฒ ์ง์ ํ์๋ ๋ฑํ ์์ด์ก๋ค๊ณ ์๊ฐํฉ๋๋ค. ๋ฌด์๋ณด๋ค๋ ์คํ์ผ๋ง์ ์ํ ํด๋์ค๋ช ์ ๋งค๋ฒ ์๋ช ํ๋ ๊ฒ์ด ๋๋ฌด๋๋ ๊ท์ฐฎ์์ต๋๋ค.
Tailwind CSS๋ utility-first ๋ฐฉ์์ด ์ฃผ๋ ์ด์ ์ ๋ค์๊ณผ ๊ฐ์ด ์ค๋ช ํฉ๋๋ค.
ํด๋์ค ์ด๋ฆ์ ์์ฑํ๋ ๋ฐ ์๋์ง๋ฅผ ๋ญ๋นํ์ง ์์ต๋๋ค.
๋ ์ด์ ์คํ์ผ์ ์ง์ ํ๊ธฐ ์ํด sidebar-inner-wrapper
์ ๊ฐ์ ๋ฐ๋ณด๊ฐ์ ํด๋์ค ์ด๋ฆ์ ์ถ๊ฐํ ํ์๊ฐ ์์ผ๋ฉฐ, ์ค์ ๋ก๋ flex container์ ๊ฐ์ ์์์ ์์ ํ ์ถ์์ ์ธ ํด๋์ค๋ช
์ ๋ํด ๊ณ ๋ฏผํ ํ์๊ฐ ์์ต๋๋ค.
CSS ํ์ผ์ ํฌ๊ธฐ๊ฐ ๋ ์ด์ ์ปค์ง์ง ์์ต๋๋ค. ์ ํต์ ์ธ ์ ๊ทผ ๋ฐฉ์์ ์ฌ์ฉํ๋ฉด ์๋ก์ด ๊ธฐ๋ฅ์ ๊ฐ๋ฐํ ๋ ๋ง๋ค CSS ํ์ผ์ด ์ปค์ง๋๋ค. ์ ํธ๋ฆฌํฐ๋ฅผ ์ฌ์ฉํ๋ฉด ๋ชจ๋ ๊ฒ์ ์ฌ์ฌ์ฉํ ์ ์์ผ๋ฏ๋ก ์ CSS๋ฅผ ์์ฑํ ํ์๊ฐ ๊ฑฐ์ ์์ต๋๋ค.
๋ณํ๋ฅผ ์ฃผ๋ ๊ฒ์ด ์ด์ ๋ณด๋ค ๋ ์์ ํ๋ค๊ณ ๋๋๋๋ค. CSS๋ ์ ์ญ ์ค์ฝ๋ธ์ด๊ธฐ ๋๋ฌธ์ ์ด๋ค ์คํ์ผ์ ๋ณ๊ฒฝํ ๋ ๋ค๋ฅธ ์ด๋ค๊ฒ์์ ๋ฌธ์ ๊ฐ ์๊ธธ์ง ์ ์ ์์ต๋๋ค. HTML์ ํด๋์ค๋ ์ง์ญ์ ์ผ๋ก ๊ด๋ฆฌ๋๋ฏ๋ก ๋ค๋ฅธ ๋ฌธ์ ์ ๋ํด ๊ฑฑ์ ํ์ง ์๊ณ ๋ณ๊ฒฝํ ์ ์์ต๋๋ค.
๋๋ฌธ์ utility-first ์ปจ์ ์ค์ ์ด์ ์ ์ตํ ๋ค์๊ณ npm trends๊ฐ ๋์ TailwindCSS ๋ฅผ ์ ํํ๊ฒ ๋์์ต๋๋ค.
๋ฆฌ์ผํ์ ๋ฉํฐ์ ์ ํ์ดํธ๋ณด๋๋ฅผ ๊ฐ๋ฐํ๊ธฐ ์ํด HTML5 canvas ๋ฅผ ์ฝ๊ฒ ๋ค๋ฃฐ ์ ์๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๋ฆฌ์์นญํ๋์ค Fabric.js ๋ฅผ ์ฌ์ฉํด ํ์ดํธ๋ณด๋๋ฅผ ๊ตฌํํ๋ ์์ ๊ธ์ ์ฝ๊ฒ ๋์์ต๋๋ค.
HTML5 canvas ๋ ๊ฐ๋จํ ๋ํ์ ๊ทธ๋ฆฌ๋ ๊ฒ์ ์ด๋ ต์ง ์์ง๋ง, ๊ทธ ๋ํ์ ์ ํํ๊ฑฐ๋ ์ด๋ํ๋๋ฑ์ ๋ณต์กํ ์์
์ ์ํด ๋ชจ๋ ๊ฑธ ์ง์ ๊ฐ๋ฐํด์ผ ํ๋ค๋ ๋จ์ ์ด ์์ต๋๋ค.
ํนํ ๋ํ์ ์ด๋ํ๊ธฐ ์ํด์๋ ๊ธฐ์กด ๋ํ์ ๊ฐ์ฒด๋ก์ ๋ค๋ฃจ์ง ์๊ธฐ ๋๋ฌธ์ ์ด์ ์ ๊ทธ๋ฆฐ ๋ด์ฉ์ ์ง์ฐ๊ณ ์ด๋ํ ์์น์ ์๋กญ๊ฒ ๋ค์ ๊ทธ๋ ค์ผํฉ๋๋ค. ๋๋ฌธ์ ๋ณต์กํ๊ณ ์ฌ์ธํ ์์
์๋ canvas ์์ ์ ๊ณตํ๋ API ๋ง์ผ๋ก ์ ํฉํ์ง ์์ต๋๋ค.
var canvasEl = document.getElementById('c');
var ctx = canvasEl.getContext('2d');
ctx.fillStyle = 'red';
ctx.translate(100, 100);
ctx.rotate(Math.PI / 180 * 45);
ctx.fillRect(-10, -10, 20, 20);
// ์ ์ฒด ์บ๋ฒ์ค๋ฅผ ์ง์ฐ๊ณ ๋ค์ ์ฌ๊ฐํ์ ๊ทธ๋ ค์ผ ํ๋ค.
ctx.clearRect(0, 0, canvasEl.width, canvasEl.height);
ctx.fillRect(20, 50, 20, 20);
Fabric.js๋ ๋ํ์ ๊ฐ์ฒด๋ก ๊ด๋ฆฌํ๊ธฐ ๋๋ฌธ์ ์๋กญ๊ฒ ์บ๋ฒ์ค๋ฅผ ์ง์ฐ๋ ๊ณผ์ ์ด ํ์ ์์ต๋๋ค.
๊ฐ์ฒด์ ์ง์ ์ ๊ทผํด์ ํ์ ํ๊ฑฐ๋ ์ด๋์ํค๋ฉด ๋๊ธฐ ๋๋ฌธ์ ๋งค์ฐ ํธ๋ฆฌํ์ฃ !
var canvas = new fabric.Canvas('c');
// ํ์ ๋ ์ฌ๊ฐํ
var rect = new fabric.Rect({
left: 100,
top: 100,
fill: 'red',
width: 20,
height: 20,
angle: 45 // ํ์
});
// ์บ๋ฒ์ค์ ์ฌ๊ฐํ ์ถ๊ฐ
canvas.add(rect);
// ์ฌ๊ฐํ ์์น ์ด๋
rect.set({ left: 20, top: 50 });
canvas.renderAll();
์ด๋ ๋ฏ Fabric.js๋ Vanilla Canvas API ๊ธฐ๋ฐ์ผ๋ก Object ๋ชจ๋ธ์ ์ ๊ณตํ์ฌ ์ฝ์ง๋ง ๊ฐ๋ ฅํ ์๋ฐ์คํฌ๋ฆฝํธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ ๋๋ค. Fabric.js๋ drawing mode๋ฅผ ์ ๊ณตํ๋ฉฐ, ์บ๋ฒ์ค์ ๊ทธ๋ ค์ง ๊ทธ๋ฆผ๋ค์ Object๋ก ์์ฑํ๊ณ ๊ด๋ฆฌํ๊ธฐ ๋๋ฌธ์ ๊ฐ๋จํ๊ฒ ์ถ๊ฐ, ์ญ์ ๋ฐ ์์ ํ ์ ์์ต๋๋ค. ๋ํ ์บ๋ฒ์ค์์ Object๊ฐ ์ถ๊ฐ, ์ญ์ ๋ฑ์ ์ด๋ฒคํธ๋ฅผ ๊ฐ์งํ์ฌ ํธ๋ค๋ฌ๋ฅผ ๋ฑ๋กํ ์ ์์ต๋๋ค. ์ค์๊ฐ์ผ๋ก Object์ ๋ณ๊ฒฝ์ฌํญ์ ๊ด๋ฆฌํ๊ธฐ์๋ ์ ํฉํ์์ต๋๋ค.
canvas.on('object:added', function(options) {
// do someting
}
์ค์๊ฐ ๋ฐ์ดํฐ๋ฅผ ์ฃผ๊ณ ๋ฐ์ ์ ์๋ ๊ธฐ์ ๋ก Firebase๋ฅผ ์ ํํ์์ต๋๋ค. ํ์ด์ด๋ฒ ์ด์ค๋ ๊ตฌ๊ธ์ด ์์ ํ๊ณ ์๋ ๋ชจ๋ฐ์ผ ์ ํ๋ฆฌ์ผ์ด์ ๊ฐ๋ฐ ํ๋ซํผ์ผ๋ก ๋ถ์, ์ธ์ฆ, ๋ฐ์ดํฐ๋ฒ ์ด์ค, ํ์ผ ์ ์ฅ, ํธ์ ๋ฉ์์ง ๋ฑ์ ์ฌ๋ฌ ์๋น์ค๋ฅผ ์ ๊ณตํฉ๋๋ค.
ํ์ด์ด๋ฒ ์ด์ค์์ ์ ๊ณตํ๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ Cloud Firestore
๊ณผ Realtime database
๋ ๊ฐ์ง๊ฐ ์์๋๋ฐ, ์๋น์ค์ ๊ธฐ๋ฅ๊ณผ ๋ชฉ์ ์ ๋ง์ถฐ ์ ํํ์ฌ ์ฌ์ฉํด์ผ ํฉ๋๋ค. ๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ฐจ์ด์ ์ ์ฌ๋ฌ๊ฐ์ง๊ฐ ์์ง๋ง, ๊ฐ์ฅ ํฐ ์ฐจ์ด๋ ๊ฐ๊ฒฉ ์ ์ฑ
๊ณผ ์ง์ฐ์๊ฐ ์ธก๋ฉด์์ ๋ด์ค์ฑ ์ฒ๋ผ ํฐ ๋จ์์ ๋ฐ์ดํฐ์ ๋ํ ์์ฒญ์ด ์ข
์ข
๋ฐ์ํ๋ ์ฑ์ ๊ฐ๋ฐํ๋ ๊ฒฝ์ฐ์ Firestore๊ฐ ์ ํฉํ๊ณ , ๋ฐ๋๋ก ์ฝ๊ธฐ/์ฐ๊ธฐ๊ฐ ๋ง์ด ๋ฐ์ํ๋ ํ์ดํธ๋ณด๋ ์ฑ์ Realtime Database๊ฐ ๋ ์ ๋ฆฌํ๋ค๊ณ ํฉ๋๋ค.
๋ฐ๋ผ์ ์ฒด๋ฆฌ๋ณด๋๋ ํ์ด์ด๋ฒ ์ด์ค์ Realtime database
๋ฅผ ์ฌ์ฉํด์ ์บ๋ฒ์ค์ ๋ณ๊ฒฝ์ฌํญ์ ์ ์ฅํ๊ณ ํด๋ผ์ด์ธํธ๋ค์๊ฒ ์ค์๊ฐ์ผ๋ก ๋ณ๊ฒฝ์ฌํญ์ ์ ํํ ์ ์์์ต๋๋ค.
์ฒด๋ฆฌ๋ณด๋๋ ์ค์๊ฐ ๋ฐ์ดํฐ ํธ์ง์ด ๋ฐ์ํ์ง๋ง ๊ทธ์ ๋ํ ๋์์ฑ ์ ์ด๋ฅผ ํ์ง ๋ชปํ์ต๋๋ค.
Realtime database
์์ ์บ๋ฒ์ค ๋ฐฉ ๋ง๋ค ๊ฐ์ฒด ํํ์ CanvasObjects
๋ฅผ ์ ์ฅํ๊ณ ์์ต๋๋ค. ์ฌ์ฉ์๊ฐ ๊ทธ๋ฆผ์ ๊ทธ๋ฆฌ๋ฉด ๊ทธ์ ๋ํ Object
๊ฐ CanvasObjects
์ ์ถ๊ฐ๋ฉ๋๋ค. ๊ทธ๋ฆฌ๊ณ ๊ทธ์ ๋ํ ๋ณ๊ฒฝ์ฌํญ์ด ๋ค๋ฅธ ํด๋ผ์ด์ธํธ๋ค์๊ฒ ์ ํ๋ฉ๋๋ค. ๋ง์ฝ ๋ ์ ์ ๊ฐ ๋์์ ํ๋์ Object
๋ฅผ ์์ /์ญ์ ํ๋ ๊ฒฝ์ฐ์๋ ๊ทธ์ ๋ํ ๋ณ๊ฒฝ์ฌํญ์ ๋ณํฉํ์ฌ ์ ์ฉํ๋ ๋์์ฑ ์ ์ดํ์ง ์์์ต๋๋ค. ๋ฐ๋ผ์ ์ฌ์ฉ์๊ฐ ๋ง์์ง๋ฉด ๋ฐ์ดํฐ๊ฐ ์์ค๋๊ฑฐ๋ ๋ ํด๋ผ์ด์ธํธ๊ฐ ๊ฐ์ ์บ๋ฒ์ค ํ๋ฉด์ ๋ณด์ง ๋ชปํ๋ ๋ฌธ์ ๊ฐ ์๊ธธ ์ ์์ต๋๋ค.
๋์์ฑ ์ ์ด๋ฅผ ์ํ ์ฌ๋ฌ๊ฐ์ง ์๊ณ ๋ฆฌ์ฆ๋ค์ด ์์ต๋๋ค. ๋ํ์ ์ผ๋ก OT(Operstional Transformation)์ CRDT(Confilct free Replicatied Data Types) ๊ฐ ์์ต๋๋ค. OT๋ ์๋ฒ๊ฐ ์ค๊ฐ์์ ๋ฐ์ดํฐ ๋ณ๊ฒฝ์ ๋ํ ๋ณด์ ์ ํตํด ๋์์ฑ์ ์ ์ดํ๊ณ , CRDT๋ ๊ณ ์ id๋ฅผ ๋ถ์ฌํ๋ ๋ฐฉ์์ ํตํด์ ์๋ฒ ์์ด ํด๋ผ์ด์ธํธ๋ผ๋ฆฌ ๋ณ๊ฒฝ์ฌํญ์ ์ ๋ฌ๋ฐ๊ณ ๋๊ธฐํํ ์ ์์ต๋๋ค. OT๋ ์์ ์ ์ฃผ๋ก ์ฌ์ฉ๋ ๊ธฐ์ ์ด์๊ณ , ์ต๊ทผ์๋ CRDT๊ฐ ์ธ๊ธฐ๋ฅผ ์ป๊ณ ์์ต๋๋ค.
์ด์ ๋ํ ์์ธํ ์ค๋ช ์ ์ค์๊ฐ ๋์ ํธ์ง: OT์ CRDT๋ฅผ ์ฐธ๊ณ ํด์ฃผ์ธ์.
CRDT๋ฅผ ์ ์ฉํ๊ธฐ ์ํด์๋ ์น์์ผ๊ณผ ์ ์ฌํ๊ฒ ๋ณ๊ฒฝ์ฌํญ์ ํด๋ผ์ด์ธํธ์๊ฒ ์ ํํ ๋ฐฉ๋ฒ์ด ํ์ํฉ๋๋ค. ํ์ด์ด๋ฒ ์ด์ค๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ๋ณ๊ฒฝ์ฌํญ์ ์ ํํ ์ ์์ง๋ง, ํด๋ผ์ด์ธํธ์ ๋ณ๊ฒฝ์ฌํญ์ ์ด๋๊ฐ์ ์ ์ฅํ์ง ์๊ณ ์ ํํ๊ธฐ์ ํ์ด์ด๋ฒ ์ด์ค๊ฐ ์ ํฉํ์ง ์์์ต๋๋ค.
๋ฐ๋ผ์ CRDT ๊ธฐ๋ฅ์ ์ ๊ณตํ๋ Automerge ๋๋ Yjs๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋์ ์ ๊ณ ๋ คํด๋ณด์์ต๋๋ค. ํนํ Yjs๋ npm trends ์์๊ฐ ๊ฐ์ฅ ๋์๊ณ , ๋คํธ์ํฌ๋ฅผ ํตํด ํด๋ผ์ด์ธํธ๋ฅผ ์ฐ๊ฒฐํด์ฃผ๋ y-websocket์ y-webtc ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ์๊ธฐ ๋๋ฌธ์ ์ฒด๋ฆฌ๋ณด๋์ ๋์ ํ๊ณ ์ถ์์ต๋๋ค.
ํ์ง๋ง ํ
์คํธ์ฒ๋ผ ๊ฐ๋ณ๊ณ ๊ฐ๋จํ ๋ฐ์ดํฐ๋ฅผ ๋ค๋ฃจ๋ ๊ฒ์ด ์๋, fabric.js์ ๋ณต์กํ๊ณ ๋ฌด๊ฑฐ์ด obejct
๋ฅผ ๋ค๋ฃจ์ด์ผ ํ๊ธฐ ๋๋ฌธ์ ๋ฌธ์ ๊ฐ ์๊ฒผ์ต๋๋ค. CRDT์ ๋จ์ ์ค์ ํ๋์ธ ๊ณ ์ id๋ฅผ ์ ์ฅํ๊ณ ์ด๋ฅผ ํธ๋ฆฌ๊ตฌ์กฐ๋ก ๊ด๋ฆฌํ๊ธฐ ์ํ ์ถ๊ฐ์ ์ธ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ํ์๋ก ํ๋ค๋ ์ ๋๋ฌธ์ object
์ ๋ณ๊ฒฝ์ฌํญ์ ๋์ฑ ๋ฌด๊ฑฐ์์ง๊ฒ ๋์์ต๋๋ค.
์ฌ์ค ๋ช
ํํ๊ฒ ์์ธ์ ํ์
ํ๊ฑด ์๋์ง๋ง, ๋ณ๊ฒฝ์ฌํญ์ ํฐ ์ฉ๋๊ณผ ์ ์ ์์ง ๋ฏธ์ํ ๊ฐ๋ฐ ์ค๋ ฅ ๋๋ฌธ์ ํผํฌ๋จผ์ค๊ฐ ๋งค์ฐ ๋ฎ์์ง๊ฒ ๋์๊ณ ๊ฐ๊ฐ์ ํด๋ผ์ด์ธํธ์์ ๋ณ๊ฒฝ์ฌํญ์ด ์ ๋ง ๋๋ฆฌ๊ฒ ๋๊ธฐํ๋๋ ๋ฌธ์ ๊ฐ ์์๊ธฐ ๋๋ฌธ์ ๋๋ด ๋์์ฑ ์ ์ด๋ฅผ ํ์ง ๋ชปํ์์ต๋๋ค.
Fabric.js๋ ๋๋ก์์ ์ต์ ํ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ด๊ธฐ ๋๋ฌธ์ ํ ์คํธ๋ฅผ ์๋ํ ํ๋๋ฐ๋ ์ ํฉํ์ง ์์์ต๋๋ค. ํผ๊ทธ์ผ์ฒ๋ผ ํฌ์คํธ์ ๊ธฐ๋ฅ์ ์ถ๊ฐํ๊ธฐ ์ํด์ ํ ์คํธ ๊ฐ์ฒด๋ฅผ ๋ค๋ค์ผ ํ์ต๋๋ค. ํ์ง๋ง ํ ์คํธ ๊ฐ์ฒด๋ฅผ HTML ์์ CSS๋ก ์คํ์ผ๋ง ํ๋ฏ์ด padding์ ์ฃผ๊ฑฐ๋ width height์ ์ง์ ํ ์ ์์์ต๋๋ค. ๋๋ฌธ์ ์ข ์ด ๋ชจ์์ ์ฌ๊ฐํ ๋ํ ๊ฐ์ฒด์ ํ ์คํธ ๊ฐ์ฒด๋ฅผ ๊ทธ๋ฃนํ ํ์ฌ ํฌ์คํธ์ ์ฒ๋ผ ๋ง๋ค์์ต๋๋ค. ํ์ง๋ง ๊ทธ๋ฃน์ ํด์ ํด์ผ๋ง ํ ์คํธ๋ฅผ ์์ ์ด ๊ฐ๋ฅํ๊ธฐ ๋๋ฌธ์ ๋ฌธ์ ๊ฐ ๋ฐ์ํ์ต๋๋ค. ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ํฌ์คํธ์ ๊ทธ๋ฃน ๊ฐ์ฒด๋ฅผ ์ฌ๋ ค๋์๋๋ฐ, ํ ์คํธ๋ฅผ ์์ ํ๊ธฐ ์ํด ๊ทธ๋ฃน์ ํด์ ํ๋ฉด ๊ทธ๋ฃน ๊ฐ์ฒด๋ ์ญ์ ๋๊ณ ์ฌ๊ฐํ ๋ํ ๊ฐ์ฒด์ ํ ์คํธ ๊ฐ์ฒด๊ฐ ์๋กญ๊ฒ ์์ฑ๋์ด์ ํฌ์คํธ์์ด ์ฐข์ด์ง๋(?) ๋ฒ๊ทธ๊ฐ ๋ฐ์ํ์ต๋๋ค.
๋ํ ๋งํฌ๋ค์ด์ฒ๋ผ -
๋ก ๋ฆฌ์คํธ๋ฅผ ์์ฑํ๋ฉด ์๋์ผ๋ก โ
์ผ๋ก ๋ฐ๊ฟ์ฃผ๋ฉด์ ๊ธ์๊ฐ ๋ค์ฌ์ฐ๊ธฐ๋๋ ๊ฒ๊ณผ ๊ฐ์ ํ
์คํธ ์๋ํ
๊ธฐ๋ฅ์ fabric.js ๋ด์์ ์ ๊ณตํ์ง ์๊ธฐ ๋๋ฌธ์ fabric์ ํ
์คํธ ๊ฐ์ฒด๋ ๋ถ๋ช
ํ๊ณ์ ์ด ์กด์ฌํ์์ต๋๋ค.
๊ทธ๋์ ํ
์คํธ ์๋ํ
์ HTML textarea
๋ฅผ ์ฌ์ฉํด์ ํฌ์คํธ์ ์์ ๋์ฐ๋๋ก ๊ตฌํํด ๋ณด์์ง๋ง, zoom&panning์ textarea
์์ญ์ ์ปค์๊ฐ ๋ค์ด๊ฐ์์ผ๋ฉด zoom&panning ๊ธฐ๋ฅ์ด ์๋ํ์ง ์์๊ณ , pointer-events-none
์ ์ฌ์ฉํ๋ฉด textarea
๋ด๋ถ์์ ์ปค์๋ก ์กฐ์ํ ๋ ์ ์์ ์ผ๋ก ์ปค์ ์ด๋์ด ์๋๋๋ฑ์ ๋ฒ๊ทธ๊ฐ ๋ฐ์ํ์์ต๋๋ค. (๋ง๋ถ์ด์๋ฉด ๋ณต์กํด์ง ์ฝ๋ ๊ตฌ์กฐ ํ์ ๋ฒ๊ทธ์ ๋ํ ์์ธ ํ์
์ด ์ด๋ ค์ ๊ณ ์ ์์ ์ผ๋ก ๋์ํ๋ ์ฝ๋๋ฅผ ์ง๊ธฐ ์ด๋ ค์ ์ต๋๋ค. ใ
ใ
)
๊ฐ๋จํ ๋๋ก์ ๊ธฐ๋ฅ๋ง ๊ตฌํํ์ ๋๋ ์ฝ๋๊ฐ ๊ทธ๋ ๊ฒ ๋ณต์กํด์ง์ง๋ ์์์ง๋ง ๋์์ฑ, ์ปค์, ๋จ์ถํค, zoom & panning ๋ฑ์ ์๋ก์ด ๊ธฐ๋ฅ์ ๋ถ์ผ ์๋ก ์ฝ๋๊ฐ ์ ๋๋์ง ์๊ณ ๋ณต์กํด์ก์ต๋๋ค. ๋๋ฌธ์ ์ฝ๋๋ฅผ ์์ ํ ๋ ๋ง๋ค ์์ธกํ์ง ๋ชปํ ๋ฒ๊ทธ๋ค์ด ์๊ฒจ๋๊ฒ ๋์์ต๋๋ค.
์ด์ ์ ์ค๋ฌด์์ ๊ฐ๋ฐ์ ํ ๋์๋ ์๊ฐ์ด ์ง๋ ๋ ๊ฑฐ์๊ฐ ๋ ์ฝ๋์์ ๋ฒ๊ทธ๊ฐ ๋ฐ๊ฒฌ๋๋ฉด, ์๋๋ ์ ์ ๋์ ํ์๋๋ฐ ๋์ค์ ๋ถ์ํจ๊ณผ๋ก ์ธํด ๋ง๊ฐ์ง๊ฑด์ง, ์๋ ์๋๋ถํฐ ๊ทธ๋ฌ๋๊ฑด์ง, ๋๋์ฒด ์ธ์ ์ด๋๋ถํฐ ๋ฌธ์ ์๋๊ฑด์ง ํ์
ํ๊ธฐ ์ด๋ ค์ ๋ ๊ธฐ์ต์ด ์์ต๋๋ค. ์ฒด๋ฆฌ๋ณด๋์์๋ ์ด์ ์ ์ฌํ ๊ฒฝํ์ ํ๋ฉด์ ๊ธฐ๋ฅ์ด ๋ง์์ง๋ ํ๋ก์ ํธ์์๋ ํด๋ฆฐํ ์ฝ๋๋ฅผ ์ง๋ ๊ฒ์ ์ค์์ฑ๊ณผ ํ
์คํธ์ฝ๋๋ฅผ ํตํ ์ฝ๋์ ์ ๋ขฐ์ฑ์ ์ป์ ํ์๊ฐ ์๋ค๋ ๊ฒ์ ํผ๋ถ๋ก ์ ๊ฒ ๋์์ต๋๋ค.
์ฐธ ์์ฌ์์ด ๋ง์ด ๋จ์ ํ๋ก์ ํธ์ ๋๋ค. ๊ทธ๋ฆผ ๊ทธ๋ฆฌ๋๊ฑธ ์ข์ํด์ ํธ๊ธฐ๋กญ๊ฒ ์ฒด๋ฆฌ๋ณด๋๋ฅผ ์์ํ์ง๋ง, ๊ธฐ์ ๋ถ์ฑ์ ๋ฏธ์ํ ๊ฐ๋ฐ ์ค๋ ฅ์ผ๋ก ๊ธฐ๋ฅ์ ์๋ฒฝํ๊ฒ ๋ง๋ฌด๋ฆฌ ํ์ง ๋ชปํ์์ต๋๋ค. ๊ทธ๋๋ ๋์ ๊ฐ๋ฐ ์ค๋ ฅ์ ์ธ์งํ์์ผ๋ฉฐ ๋ ์ข๊ณ ์ ๋ขฐํ ๋งํ ์ฝ๋๋ฅผ ์ง๊ธฐ ์ํด์๋ ๋ถ์ง๋ฐํ๊ฒ ๊ณต๋ถํด์ผ๊ฒ ๋ค๋ ๊ตํ์ ์ป์ ์ ์์์ต๋๋ค.
.
.
.
๊ทธ๋ฆฌ๊ณ ๊ธฐ๋ก ๋จ๊ธฐ๋๊ฑธ ์ฐธ ์ข์ํ๋ ํธ์ธ๋ฐ ์๋ ๋ง์ฌ์ฃผ๋ ์๊ณ ๊ตญ์ด๋ 3๋ฑ๊ธ์ ๋์ง ๋ชปํ๋ 0๊ฐ ๊ตญ์ด ๊ฐ๋ฐ์์ด๊ธฐ ๋๋ฌธ์ ์ด๋ฒ ํฌ์คํธ๋ ์กฐ๋ฆฌ์๊ฒ ์ ์์ฑํ์ง๋ ๋ชปํ๊ฒ ๊ฐ๋ค์. ๊ธ ์ฐ๊ธฐ์ ๊ดํ ์ฑ
๋ ์ฝ์ด์ผ๊ฒ ์ต๋๋ค. ๊ณต๋ถํ๊ณ ์ถ์ ์์ฌ์ ๋ง์๋ฐ ์ด๋๋ ํ๊ณ ์ถ๊ณ ๋๊ณ ๋ ์ถ๊ณ ํด์ผ ํ ์ผ์ ์ฐ์ ์์๋ฅผ ๋๊ณ ํ๋์ฉ ํด๊ฒฐํด ๋๊ฐ๋๊ฑธ ์ฐ์ตํ ํ์๋ฅผ ๋๋ผ๋ค์. ์๋ฌด์ชผ๋ก ์์ผ๋ก ์กฐ๊ธ์ฉ ๊พธ์คํ ์ฑ์ฅํด์ ๋์ค์ด ๋์ด์ผ๋ดค์ ๋ ์ด๋งํผ์ด๋ ๋ง์ด ๋์์ด! ํ๋ ์ฌ๋์ด ๋๊ณ ์ถ์ต๋๋ค.
์๋
ํ์ธ์! ์ฒด๋ฆฌ๋ณด๋ ๋๋ฌด ๊ท์ฝ๊ณ ๋ฉ์ ธ์ !
๋ค๋ฆ์ด ์๋๋ผ ์ด๋ฒ์ ๊ทธ๋ฆผ์ผ๊ธฐ๋ฅผ ๊ทธ๋ฆฌ๋ ํ ํ๋ก์ ํธ๋ฅผ ์งํํ๊ณ ์๋๋ฐ,
๊ฐ๋ฐ์๋๊ณผ ๋น์ทํ ๊ณ ๋ฏผ์ผ๋ก fabric js๋ฅผ ์ ์ฉํด์ react ํ๊ฒฝ์์ ๊ตฌํํ๊ณ ์์ต๋๋ค.
๊ทธ๋ฐ๋ฐ ์์ง ์ ํฌ๊ฐ ๋๋ฌด๋๋ฌด ๋ณ์๋ฆฌ ๊ฐ๋ฐ์๋ผ์ ์ด๋ ค์ด ๋ถ๋ถ์ด ๋ง์ต๋๋ค 9ใ
9
์ ํฌ๋ ํ ํ๋ก์ ํธ์ ์ฒด๋ฆฌ๋ณด๋์ฒ๋ผ ์ด์๊ณ ๋ฉ์ง ์บ๋ฒ์ค๋ฅผ ๊ตฌํํด๋ณด๊ณ ์ถ์ต๋๋ค..!
ํน์ ๊ด์ฐฎ์ผ์๋ค๋ฉด ์๋ฌธ์ ๊ตฌํ ์ ์์๊น์?
์ฐ์! ๋๋ฌด ๋๋ฌด ๊ณ ์๋ง์์ต๋๋ค! ์์ฌ์์ด ๋ง๋ค๊ณ ํ์ง๋ง ์ฌ๋ฌ๊ฐ์ง ๊ธฐ์ ์คํ์ ์จ๊ฐ๋ฉด์ ๊ฒช์๋ ์ํ์ฐฉ์ค๋ค์ ๋์ค์ ์ฑ์ฅ์ ํฐ ๋ฐ๊ฑฐ๋ฆ์ด ๋ฉ๋๋ค. ์ข์ ๊ฒฝํ์ด ๋์์ ๊ฑฐ๋ผ๊ณ ์ด ๊ฒฝํ์ ์ ์ฉํ๊ฒ ๋ ๋ ์๋ก์ด ํ๋ก์ ํธ๋ฅผ ๋ง๋๊ฒ ๋์์๋์๋ ์ด ๊ฒฝํ์ ํ ๋๋ก ์ฑ๊ณต์ ์ธ ๊ฒฝํ์ ํ ์ ์๊ฒ ๋๊ธฐ๋ฅผ ๊ธฐ๋ํฉ๋๋ค! :)