์‚ฌ์ง„ํŽธ์ง‘ํˆด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ imoji editor ๊ฐœ๋ฐœ๊ธฐ

2021-07-062021-07-06
  • Javascript
  • Project
  • Vue

preview

๐Ÿ‘‰ Documentation ๐Ÿ‘‰ npm ๐Ÿ‘‰ GitHub

6์›” ํ•œ ๋‹ฌ๊ฐ„ ๋ฉ”๋””์ŠคํŠธ๋ฆผ์—์„œ ๊ธฐ์—…ํ˜‘์—…์œผ๋กœ ์‚ฌ์ง„ํŽธ์ง‘ํˆด ๊ฐœ๋ฐœ์„ ์ง„ํ–‰ํ–ˆ๋‹ค. ์‚ฌ์ง„์— ๋Œ€ํ•œ ๊ธฐ๋Šฅ๋“ค์„ ๋‹ด์€ ๋ชจ๋“ˆ์€ core js๋กœ, ๊ธฐ๋Šฅ๋“ค์„ ์‚ฌ์šฉํ•  UI๋Š” vue.js๋กœ ๊ฐœ๋ฐœํ–ˆ์œผ๋ฉฐ ์˜คํ”ˆ์†Œ์Šค ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋กœ npm ํŒจํ‚ค์ง•ํ•˜์—ฌ ๋ฐฐํฌ๊นŒ์ง€ ์™„๋ฃŒํ–ˆ๋‹ค. ๊ธฐ์–ต๋ ฅ์ด ์•ˆ ์ข‹์€ ๋‚˜ ์Šค์Šค๋กœ๋ฅผ ์œ„ํ•ด ๊ฐœ๋ฐœ ํ•œ ๋‹ฌ ๋™์•ˆ์˜ ์ด์•ผ๊ธฐ๋ฅผ ์ •๋ฆฌํ•˜๊ณ ์ž ํ•œ๋‹ค. ์ด๊ฑด ๋‚ด๊ฐ€ ํˆฌ๋จธ์น˜ํ† ์ปค๋ผ ๊ธ€์ด ์งฑ์งฑ ๊ธธ์–ด์งˆ ๊ฒƒ์— ๋Œ€ํ•œ ๋ฐ‘๋ฐฅ์ด๋‹ค.

๋ชฉ์ฐจ

๐Ÿ“ ํ”„๋กœ์ ํŠธ ๊ฐœ์š”

  • ๊ตฌํ˜„ ๊ธฐ๋Šฅ : ์ž์œ  ํฌ๋กญ, ๋น„์œจ ํฌ๋กญ, ํšŒ์ „, ๋ฐ˜์ „, ํ™•๋Œ€/์ถ•์†Œ, ์Šคํ‹ฐ์ปค ์ถ”๊ฐ€, ๊ฒฐ๊ณผ๋ฌผ png ์ด๋ฏธ์ง€ ๊ฐ์ฒด๋กœ ๋ฐ˜ํ™˜
  • ์‚ฌ์šฉ ์Šคํƒ : core js ES6, vue.js 2.x
  • ์‚ฌ์šฉ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ : cropper.js 1.5.11, fabric.js 4.5

ํšŒ์‚ฌ ํ”„๋กœ๋•ํŠธ์˜ ๊ธ€์“ฐ๊ธฐ ๊ธฐ๋Šฅ์—์„œ ์‚ฌ์šฉํ•  ์‚ฌ์ง„ํŽธ์ง‘ํˆด์ด ํ•„์š”ํ•ด ๋‹จ๋… ๋ชจ๋“ˆ๋กœ ๊ฐœ๋ฐœ์„ ์ง„ํ–‰ํ–ˆ๋‹ค. ์ด์™•์ด๋ฉด ํšŒ์‚ฌ์˜ ๋ธŒ๋žœ๋”ฉ์—๋„ ๋„์›€์ด ๋˜๊ณ ์ž ํšŒ์‚ฌ์˜ ์บ๋ฆญํ„ฐ๋กœ ์Šคํ‹ฐ์ปค๋ฅผ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ๊ฒŒ๋” ํ–ˆ๋‹ค.

๋”ฑ ์‚ฌ์ง„ ํŽธ์ง‘์— ๊ธฐ๋ณธ์ ์œผ๋กœ ํ•„์š”ํ•œ ๊ธฐ๋Šฅ๋“ค๋งŒ ์ปดํŒฉํŠธํ•˜๊ฒŒ ๋‹ด๊ณ , ์Šคํ‹ฐ์ปค๋ฅผ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋Šฅ๊นŒ์ง€ ์žˆ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ฐพ์•„๋ณด์•˜์œผ๋‚˜ ๋งˆ๋•…ํ•œ ๊ฒƒ์ด ์—†์—ˆ๋‹ค. ์Šคํ‹ฐ์ปค ๊ธฐ๋Šฅ์ด ์žˆ์œผ๋ฉด ๋‹ค๋ฅธ ๋ถˆํ•„์š”ํ•œ ๊ธฐ๋Šฅ๋“ค๋„ ๋งŽ์ด ์žˆ๊ณ , ๋”ฑ ์ปดํŒฉํŠธํ•˜๊ฒŒ ์šฐ๋ฆฌ๊ฐ€ ์›ํ•˜๋Š” ๊ธฐ๋Šฅ๋งŒ ์žˆ๋‹ค ์‹ถ์œผ๋ฉด ์Šคํ‹ฐ์ปค ๊ธฐ๋Šฅ์ด ์—†์—ˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ๋”ฐ๋ผ์„œ ๋งŒ๋“  ๊ฒƒ์„ ์˜คํ”ˆ ์†Œ์Šค ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋กœ ๋ฐฐํฌํ•˜๊ธฐ๋กœ ํ–ˆ๊ณ  ์ด๋ฅผ ํ†ตํ•ด ํ‰์†Œ ์•„๋ฌด ์ƒ๊ฐ์—†์ด npm install ํ•˜๋˜ ๊ฒƒ์—์„œ๋„ ๋ฒ—์–ด๋‚˜๋ณด๊ธฐ๋กœ ํ–ˆ๋‹ค.

๐ŸŽจ Canvas API

HTML 5์˜ Canvas API๋Š” ๊ทธ๋ฆผ, ์ด๋ฏธ์ง€ ๋ฟ ์•„๋‹ˆ๋ผ ๋™์˜์ƒ๊ณผ ๊ฐ™์€ ๋ฏธ๋””์–ด๋ฅผ ๋‹ค๋ฃฐ ์ˆ˜ ์žˆ๊ฒŒ ๋„์™€์ฃผ๋Š” API์ด๋‹ค. ํ™”๋ คํ•œ ๊ทธ๋ž˜ํ”ฝ์ด๋‚˜ ๊ฒŒ์ž„์„ ๋งŒ๋“œ๋Š” ๋“ฑ Canvas API๋ฅผ ๊ฐ€์ง€๊ณ  ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์€ ๋ฌด๊ถ๋ฌด์ง„ํ•˜์ง€๋งŒ ์ดˆ๋ณด(=๋‚˜)๋ฅผ ์œ„ํ•œ ํ”„๋กœ์ ํŠธ๋กœ๋Š” ๊ทธ๋ฆผํŒ ๋งŒ๋“ค๊ธฐ ๋“ฑ์ด ์žˆ๋‹ค ^0^.

์šฐ๋ฆฌ๋Š” ์œ ์ €๊ฐ€ ์—…๋กœ๋“œํ•˜๋Š” ์‚ฌ์ง„, ์ฆ‰ ์ด๋ฏธ์ง€๋ฅผ ๋‹ค๋ฃจ์–ด์•ผ ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— Canvas API๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ๋กœ ํ–ˆ์œผ๋‚˜ ์›น ๊ฐœ๋ฐœ์ด๋ž‘์€ ๋˜ ๋‹ค๋ฅธ ๋ณ„์ฒœ์ง€ ์„ธ๊ณ„๋ผ๊ณ  ํ•ด์„œ Canvas API๋ฅผ ์‰ฝ๊ฒŒ ๋‹ค๋ฃจ๊ฒŒ ๋„์™€์ฃผ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ๋กœ ํ–ˆ๋‹ค. (๋ˆ„๊ตฐ๊ฐ€์˜ ๋ง์— ์˜ํ•˜๋ฉด ์ด๊ฑธ ์“ฐ๋ผ๊ณ  ๋งŒ๋“ค์–ด ๋‘” ๊ฒƒ์ธ์ง€ ์˜์‹ฌ์ด ๋˜๋Š” ์ •๋„๋ผ๊ณ โ€ฆ๐Ÿ˜‚)

๊ฐœ๋ฐœ์— ์‚ฌ์šฉํ–ˆ๋˜ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์— ๋Œ€ํ•œ ๋ถ€๋ถ„์€ ํ›„์ˆ ํ•  ๊ฒƒ์ด๊ณ , ์ด ํŒŒํŠธ์—์„  ๋‚  ๊ฒƒ์˜ Canvas API๋ฅผ ์‚ฌ์šฉํ•œ ๋ถ€๋ถ„๋งŒ ๊ฐ„๋‹จํžˆ ๋˜์งš์–ด ๊ธฐ๋กํ•ด๋ณธ๋‹ค.

How To Use

์šฐ์„  ์บ”๋ฒ„์Šค ์š”์†Œ๋ฅผ ์ƒ์„ฑํ•œ๋‹ค. div๋‚˜ img์ฒ˜๋Ÿผ <canvas id="canvas"></canvas>๋กœ ๋งŒ๋“ค์–ด๋‚ผ ์ˆ˜ ์žˆ๋Š”๋ฐ ๊ธฐ๋ณธ ์‚ฌ์ด์ฆˆ๋Š” 300x150 ํ”ฝ์…€์ด๋‹ค. ์ผ๋ฐ˜์ ์ธ html ํƒœ๊ทธ๋“ค์ฒ˜๋Ÿผ css๋กœ ์กฐ์ •ํ•  ์ˆ˜๋„ ์žˆ์ง€๋งŒ canvas ํƒœ๊ทธ์˜ width, height๋กœ ์„ค์ •ํ•˜๊ธธ ๊ถŒ์žฅํ•œ๋‹ค. css๋กœ width, height๊ฐ’์„ ๋ณ€๊ฒฝํ•ด๋„ ๋ ˆ์ด์•„์›ƒ์˜ ํฌ๊ธฐ๋Š” ๊ทธ๋Œ€๋กœ๋ผ ๋•Œ๋ฌธ์— ๊ทธ๊ฒƒ์— ๋งž์ถฐ์„œ ๐Ÿ“Ž์™œ๊ณก๋˜๋Š” ํ˜„์ƒ์ด ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

์ด์ œ ์ด ์บ”๋ฒ„์Šค๋ฅผ ์กฐ์ž‘ํ•  ์ฐจ๋ก€~!

์šฐ๋ฆฌ๊ฐ€ ๊ทธ๋ฆผ์„ ๊ทธ๋ฆด ๋•Œ ํฐ ์Šค์ผ€์น˜๋ถ ์œ„์— ์ƒ‰์—ฐํ•„๋กœ ์„ ์„ ๊ธ‹๋“ฏ์ด ์บ”๋ฒ„์Šค๋„ ๋งˆ์ฐฌ๊ฐ€์ง€์ด๋‹ค. ์บ”๋ฒ„์Šค์—์„œ ํฐ ์Šค์ผ€์น˜๋ถ์€ Context๋ผ๊ณ  ํ•˜๊ณ , getContext()๋ผ๋Š” ์บ”๋ฒ„์Šค์˜ ๋ฉ”์†Œ๋“œ๋ฅผ ์ด์šฉํ•ด ์ ‘๊ทผํ•œ๋‹ค. ๋„ค์ด๋ฐ๋„ ๊ด€์Šต์ ์œผ๋กœ context๋ผ๊ณ  ํ•˜๊ฑฐ๋‚˜ ctx๋ผ๊ณ  ํ•œ๋‹ค.

๊ทธ๋ฆผ์„ ๊ทธ๋ฆด ์˜์—ญ์„ ์ง€์ •ํ–ˆ์œผ๋‹ˆ ์ด์ œ ๊ทธ ์œ„์— ๊ทธ๋ฆด ์ฐจ๋ก€์ด๋‹ค. ๊ฐ€์žฅ ๊ธฐ๋ณธ์ด ๋˜๋Š” ์ ์ด๋‚˜ ์„ ์„ ๊ทธ๋ฆด ์ˆ˜๋„ ์žˆ์ง€๋งŒ ์šฐ๋ฆฌ๋Š” ์ด๋ฏธ์ง€๋ฅผ ๋‹ค๋ฃฐ ๊ฒƒ์ด๋ฏ€๋กœ, drawImage()๋ผ๋Š” ๋ฉ”์†Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•  ๊ฒƒ์ด๋‹ค. ์ฒซ ๋ฒˆ์งธ ์ธ์ž๋กœ๋Š” ๊ทธ๋ ค๋‚ผ ์ด๋ฏธ์ง€ ๊ฐ์ฒด, ๋‘ ๋ฒˆ์งธ์™€ ์„ธ ๋ฒˆ์งธ ์ธ์ž๋กœ๋Š” ์ขŒํ‘œ๋ฅผ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.

๊ทธ๋Ÿผ ์ด๋Ÿฐ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.

//add sticker image on canvas
const canvas = document.querySelector('#canvas');
const context = canvas.getContext('2d');
context.drawImage(stickerImage, 0, 0);

๊ทธ๋ฆฌ๊ณ  ํ•ด๋‹น ์บ”๋ฒ„์Šค๋ฅผ ์ด๋ฏธ์ง€๋กœ ๋‚ด๋ณด๋‚ผ ์ˆ˜ ์žˆ๋‹ค. toDataURL๋ฉ”์†Œ๋“œ๋ฅผ ์ด์šฉํ•˜๋ฉด data URL๋ฅผ ๋ฐ˜ํ™˜ํ•ด์ค€๋‹ค. ์ฒซ๋ฒˆ์งธ ์ธ์ž๋กœ ์ด๋ฏธ์ง€ ํฌ๋งท๋„ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋Š”๋ฐ ๊ธฐ๋ณธ๊ฐ’์€ png์ด๋‹ค. ์ด๋ฅผ ํ™œ์šฉํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ด๋ฏธ์ง€ ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ๋‹ค. (new Image()์™€ html image element๋Š” ๋‹ค๋ฅด๋‹ค!)

const result = new Image();
result.src = canvas.toDataURL('image/png');
return result;

์ด๋Ÿฐ ์ž‘์—…์€ ์ „๋ถ€ ์Šค์ผ€์น˜๋ถ ์œ„์— ์˜ฌ๋ฆฌ๋Š” ์ด๋ฏธ์ง€, ์„ , ์  ๋“ฑ์„ ์›€์ง์—ฌ ํ•˜๋Š” ๊ฒƒ์ด๋ผ๊ธฐ๋ณด๋‹ค ์Šค์ผ€์น˜๋ถ์„ ์›€์ง์—ฌ ์„ ์„ ๊ทธ๋ ค๋‚ด๊ณ  ์ด๋ฏธ์ง€๋ฅผ ๊ทธ๋ ค๋‚ด๋Š” ์‹์ด๋‹ค. ๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— ์ง๊ด€์ ์ด์ง€ ์•Š๊ณ  ์–ด๋ ต๊ฒŒ ๋‹ค๊ฐ€์˜จ๋‹ค. ์ด๋Ÿฐ ๋ถ€๋ถ„์„ ์ข€ ๋” ์‰ฝ๊ฒŒ ์ด์šฉํ•˜๊ฒŒ ํ•ด์ค„ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ฐพ์•„๋ณด์•˜๋‹ค.

๐Ÿ‘ฉ๐Ÿปโ€๐Ÿ’ป ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๋ฆฌ์„œ์น˜

๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ๋ฆฌ์„œ์น˜ ํ•˜๋Š” ๊ณผ์ •์—์„œ ์ œ์ผ ๊ณ ๋ฏผ์ด ๋˜์—ˆ๋˜ ๋ถ€๋ถ„์€ ์ˆ˜ ๋งŽ์€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ค‘์—์„œ ๋ฌด์—‡์„ ๊ธฐ์ค€์œผ๋กœ ์„ ํƒํ•ด์•ผํ•˜๋Š” ์ง€์˜€๋‹ค. ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ฒ˜์Œ ์จ๋ด์„œ ๊ฐ๋„ ์•ˆ ์™”๋‹ค. ๊ทธ๋ž˜์„œ ๊ทธ๋ƒฅ ์•„๋ฌด๊ฑฐ๋‚˜ ๊ฒ€์ƒ‰ํ•ด์„œ ๋‹ฅ์น˜๋Š” ๋Œ€๋กœ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์— ๋Œ€ํ•œ ๊ธ€๋“ค์„ ์ฝ์—ˆ๋‹ค. A๋ผ๋Š” ์‚ฌ๋žŒ์€ ์–ด๋–ค ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์„ ํ˜ธํ•˜๋Š”๋ฐ ๊ทธ ์ด์œ ๋Š” ๋ฌด์—‡์ธ์ง€ ๊ฐ™์€๊ฑฐ? ๊ทธ๋Ÿฐ ๊ฒƒ์— ๋”ํ•ด์„œ ํšŒ์˜ ๋•Œ ์ด์•ผ๊ธฐ ๋‚˜๋ˆˆ ๊ฒƒ์„ ๋ฐ”ํƒ•์œผ๋กœ ์•„๋ž˜์™€ ๊ฐ™์€ ์ฒดํฌ๋ฆฌ์ŠคํŠธ๋“ค์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ์—ˆ๋‹ค.

โœ… ๋ฐฐ๋ณด๋‹ค ๋ฐฐ๊ผฝ์ด ๋” ํฌ์ง„ ์•Š์€๊ฐ€? ํ•„์š” ๊ธฐ๋Šฅ๋งŒ ์ปดํŒฉํŠธํ•˜๊ฒŒ ๋“ค์–ด์žˆ๋Š”๊ฐ€?
โœ… ์‹ค์งˆ์ ์ธ ์—…๋ฐ์ดํŠธ๊ฐ€ ๊พธ์ค€ํžˆ ์ด๋ค„์ง€๊ณ  ์žˆ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ธ๊ฐ€?
โœ… ๋ฌธ์„œํ™”๊ฐ€ ์˜์–ด ๋˜๋Š” ํ•œ๊ตญ์–ด๋กœ ์ƒ์„ธํ•˜๊ฒŒ ๋˜์–ด์žˆ๋Š”๊ฐ€?
โœ… Core ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋กœ ๊ฐœ๋ฐœ๋œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ธ๊ฐ€?
โœ… ์ƒํƒœ๊ณ„๊ฐ€ ํ™œ์„ฑํ™” ๋˜์–ด ์žˆ๋Š”๊ฐ€? ๊นƒํ—™ ์ด์Šˆ, ์Šคํƒ์˜ค๋ฒ„ํ”Œ๋กœ์šฐ ๋“ฑ
โœ… ๋งŽ์ด ์‚ฌ์šฉ๋˜๋Š”๊ฐ€? star, npm download ์ˆ˜ ๋“ฑ
โœ… ์‚ฌ์šฉ์ด ์–ด๋ ค์šธ ์ •๋„์˜ ํฌ๋ฆฌํ‹ฐ์ปฌํ•œ ์ด์Šˆ๊ฐ€ ์žˆ๋Š”๊ฐ€?
โœ… ๋ชจ๋ฐ”์ผ์„ ์ง€์›ํ•˜๋Š”๊ฐ€?

์œ„์™€ ๊ฐ™์€ ๊ธฐ์ค€๋“ค๋กœ ๋ฆฌ์„œ์น˜๋ฅผ ํ•ด๋ณด๋‹ˆ ์˜์™ธ๋กœ ํ›„๋ณด๊ฐ€ ๋งŽ์ง€ ์•Š์•˜๋‹ค. ๋ฌผ๋ก  crop์ด๋‚˜ rotate๊ฐ™์ด ๊ธฐ๋Šฅ ํ•œ ๊ฐ€์ง€๋งŒ ๊ฐ€์ง„ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊นŒ์ง€ ํฌํ•จํ•œ๋‹ค๋ฉด ํ›„๋ณด๊ฐ€ ๋” ๋งŽ์•„์กŒ๊ฒ ์ง€๋งŒ, ์˜ˆ์ธกํ•  ์ˆ˜ ์—†๋Š” ์‚ฌ์ด๋“œ ์ดํŽ™ํŠธ๋ฅผ ์ตœ์†Œํ™” ํ•˜๊ธฐ ์œ„ํ•ด ์ตœ์†Œํ•œ์˜ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋งŒ์„ ์‚ฌ์šฉํ•˜๊ธฐ๋กœ ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ํƒˆ๋ฝ์‹œ์ผฐ๋‹ค.

๊ทธ๋ ‡๊ฒŒ ํ™•์ •๋œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ๐Ÿ“Žcropper.js์˜€๋‹ค. 2014๋…„์— jquery๋กœ ์ฒ˜์Œ ๊ฐœ๋ฐœ๋œ ์ด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” ์ œ์ž‘์ž๊ฐ€ ์ง€์†์ ์œผ๋กœ ํŒ”๋กœ์—…ํ•˜์—ฌ ํ˜„์žฌ๋Š” ์ตœ์‹  ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ๋ฌธ๋ฒ•์œผ๋กœ ์—…๋ฐ์ดํŠธ ๋˜์–ด์žˆ๋‹ค. ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ฐพ๋‹ค ๋ณด๋ฉด ๋ ˆ๊ฑฐ์‹œ ์ฝ”๋“œ๋ฅผ ๋งŽ์ด ๋ณด๊ฒŒ ๋˜๋Š”๋ฐ ๊ทธ๋ ‡์ง€ ์•Š์€ ์ ์ด ์ธ์ƒ์ ์ด์—ˆ๋‹ค.

๐Ÿšง ์Šคํ‹ฐ์ปค ๊ธฐ๋Šฅ ๊ตฌํ˜„์— ๋Œ€ํ•œ ๊ณ ๋ฏผ

๊ฒฐ๋ก ๋ถ€ํ„ฐ ๋งํ•˜๋ฉด ์‚ฌ์ง„ ํŽธ์ง‘์šฉ ์บ”๋ฒ„์Šค์™€ ์Šคํ‹ฐ์ปค ์ถ”๊ฐ€์šฉ ์บ”๋ฒ„์Šค๋ฅผ ๋”ฐ๋กœ ๋‘์–ด ๋‘ ์บ”๋ฒ„์Šค๋ฅผ ์Šค์œ„์นญํ•˜๊ธฐ๋กœ ํ–ˆ๋‹ค.

์‚ฌ์ง„ ํŽธ์ง‘์„ cropper๋ฅผ ์ด์šฉํ•ด์„œ ํ•  ๊ฒƒ์ด์ง€๋งŒ, ์Šคํ‹ฐ์ปค๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ๋„ ๊ฒฐ๊ตญ์—” ์Šคํ‹ฐ์ปค๋ผ๋Š” ์‚ฌ์ง„์„ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ƒ๋Š” ์ด์•ผ๊ธฐ๊ฐ€ ํšŒ์˜ ๋•Œ ๋‚˜์™”๋‹ค. ๋•Œ๋ฌธ์— ์Šคํ‹ฐ์ปค๋Š” ์ง์ ‘ ๊ตฌํ˜„ํ•˜๊ธฐ๋กœ ์ด์•ผ๊ธฐ๊ฐ€ ๋๊ณ  ์ด๋ฅผ ์œ„ํ•ด ์—ฌ๋Ÿฌ ๋ฐฉ๋ฒ•์„ ๋ฆฌ์„œ์น˜ํ•ด๊ฐ€๋ฉฐ 4๊ฐœ์˜ ๋ฐ๋ชจ๋ฅผ ๋งŒ๋“ค์—ˆ์—ˆ๋‹ค. ์•„์ฃผ์•„์ฃผ ๋‚  ๊ฒƒ์˜ ๋ฐ๋ชจ๋ฅผ ๋งŒ๋“ค์–ด ๋ณด๋Š” ๊ฒƒ์€ ์•„์ง์€ ๋‚ฏ์„ค๊ธฐ๋งŒ ํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์— ๊ฐ€์žฅ ๋น ๋ฅด๊ฒŒ ์ ์‘ํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์ด์—ˆ๋‹ค. ํšŒ์˜ ๋•Œ ์„ค๋ช…์„ ํ•˜๊ธฐ์—๋„ ์ง์ ‘ ๋ณด๋ฉด์„œ ์ด์•ผ๊ธฐ๋ฅผ ํ•  ์ˆ˜ ์žˆ์œผ๋‹ˆ ๋” ์ข‹์•˜๋‹ค. ๐Ÿ“Ž ๋ฐ๋ชจ ์ฝ”๋“œ์ƒŒ๋“œ๋ฐ•์Šค ๐Ÿ“Ž ์ฐธ๊ณ ํ•œ ๋ฐฉ๋ฒ• ์ค‘ ํ•˜๋‚˜

์Šคํ‹ฐ์ปค ๊ธฐ๋Šฅ์„ ์ง์ ‘ ๊ตฌํ˜„ํ•˜๋ฉด์„œ ๋งˆ์ฃผํ•œ ์˜ˆ์ƒํ•˜์ง€ ๋ชปํ–ˆ๋˜ ๋ฌธ์ œ์ ์€ cropper.js๊ฐ€ ํ•œ ์บ”๋ฒ„์Šค ์•ˆ์— ์—ฌ๋Ÿฌ ๊ฐœ์˜ ๊ฐ์ฒด๋ฅผ ์ถ”๊ฐ€ํ•˜์ง€ ๋ชปํ•œ๋‹ค๋Š” ๊ฒƒ์ด์—ˆ๋‹ค. ๋‚˜์™€ ๋น„์Šทํ•œ ๋‹ˆ์ฆˆ๋ฅผ ๊ฐ€์ง„ ์–ด๋–ค ๊ฐœ๋ฐœ์ž๊ฐ€ ๋ฌธ์˜๋ฅผ ํ–ˆ์—ˆ๋Š”๋ฐ ์ œ์ž‘์ž๊ฐ€ ๋ฏธ์•ˆ, ๊ทธ๊ฑด ์ง€์› ์•ˆ ํ•ด๋ผ๊ณ  ๋Œ€๋‹ตํ•œ ๊ฒƒ์„ ๋ณด์•˜๋‹ค. cropper์˜ ์‚ฌ์ง„์„ ์กฐ์ž‘ํ•˜๋Š” ๊ธฐ๋Šฅ์„ ์ด์šฉํ•ด์„œ ์Šคํ‹ฐ์ปค๋ฅผ ์กฐ์ž‘ํ•˜๊ณ  ์‹ถ์€ ๋‹ˆ์ฆˆ์™€ ํ•œ ์บ”๋ฒ„์Šค ์•ˆ์—์„œ ์—ฌ๋Ÿฌ ๊ฐœ์˜ ์Šคํ‹ฐ์ปค๋ฅผ ์กฐ์ž‘ํ•˜๊ณ  ์‹ถ์€ ๋‹ˆ์ฆˆ๋Š” ๊ณต์กดํ•  ์ˆ˜ ์—†๋Š” ๋‹ˆ์ฆˆ์˜€๋˜ ๊ฒƒ์ด๋‹ค.

์ •๋ง ๋ณ„ ๊ฒƒ ์•„๋‹ˆ์ง€๋งŒ, ๋‚ด๊ฐ€ ๋งŒ๋“ค์—ˆ๋˜ ๋ฐ๋ชจ๋Š” ๊ทธ ๋ฌธ์ œ์˜ ํ•ด๊ฒฐ์— ๋Œ€ํ•œ ๊ฒƒ์ด์—ˆ๋‹ค. ์Šคํ‹ฐ์ปค ๋‹น ์บ”๋ฒ„์Šค๋ฅผ ๋งŒ๋“ค๊ณ  z-index๋ฅผ ์ค˜์„œ ๋ ˆ์ด์–ด์ฒ˜๋Ÿผ ์Œ“๊ณ , ์ตœ์ข… ์ €์žฅ ์‹œ์—๋Š” ์บ”๋ฒ„์Šค๋“ค์„ ํ•ฉ์ณ์„œ ํ•˜๋‚˜์˜ ์ด๋ฏธ์ง€๋ฅผ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค. ๊ทธ์น˜๋งŒ ๊ทธ๋ ‡๊ฒŒ ๋˜๋ฉด ์šฐ๋ฆฌ๊ฐ€ ์ผ๋ฐ˜์ ์œผ๋กœ ์ƒ๊ฐํ•˜๋Š” ์Šคํ‹ฐ์ปค ๊ธฐ๋Šฅ(=ํ•œ ๋ฒˆ์— ์—ฌ๋Ÿฌ ์Šคํ‹ฐ์ปค๋ฅผ ์ถ”๊ฐ€ ๊ฐ€๋Šฅ)๊ณผ ๋ฉ€์–ด์งˆ ๋ฟ๋”๋Ÿฌ ์‚ฌ์šฉ์ž ์ž…์žฅ์—์„  ์“ฐ๋‹ค๊ฐ€ ๋นก์ณ์„œ ๋” ์ด์ƒ ์•ˆ ์“ธ ๊ฒƒ ๊ฐ™์•˜๋‹ค. ์ € ๋ฐฉ๋ฒ•์€ ๊ฒฐ๊ตญ ํ•œ ๋ฒˆ์— ํ•˜๋‚˜์˜ ์Šคํ‹ฐ์ปค๋งŒ ์กฐ์ž‘์ด ๊ฐ€๋Šฅํ•˜๊ณ , ๋‘ ๋ฒˆ์งธ ์Šคํ‹ฐ์ปค๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋ฉด ์ฒซ ๋ฒˆ์งธ ์Šคํ‹ฐ์ปค๋ฅผ ์‚ฌ์šฉํ•œ ๊ฒƒ์„ ์ €์žฅํ•˜๋Š” ๊ณผ์ •์„ ๊ผญ ๊ฑฐ์ณ์•ผ ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

๊ทธ๋Ÿฌ๋ฉด cropper๋ฅผ ์“ฐ์ง€ ์•Š๊ณ  ์Œฉ Canvas๋ฅผ ์จ์„œ ๊ตฌํ˜„ํ•œ๋‹ค๋ฉด?

์Šคํ‹ฐ์ปค๋ฅผ ์บ”๋ฒ„์Šค ์œ„์— ์ถ”๊ฐ€ํ•˜๊ณ  ๋“œ๋ž˜๊ทธ์•ค ๋“œ๋ž์œผ๋กœ ์›ํ•˜๋Š” ์œ„์น˜๋กœ ์ด๋™์‹œํ‚ค๋Š” ๊ฒƒ๊นŒ์ง€๋Š” ๊ตฌํ˜„์„ ํ–ˆ์ง€๋งŒ, ์Šคํ‹ฐ์ปค๊ฐ€ ์—ฌ๋Ÿฌ ๊ฐœ๊ฐ€ ๋˜๊ฑฐ๋‚˜ ํŠน์ • ์Šคํ‹ฐ์ปค๋ฅผ ๋Œ๋ฆฌ๊ฑฐ๋‚˜ ๋ฆฌ์‚ฌ์ด์ง•ํ•˜๊ฑฐ๋‚˜ ๋ฐ˜์ „ํ•˜๊ฑฐ๋‚˜ ํ•˜๋Š” ๊ฒƒ์€ ๋˜ ๋‹ค๋ฅธ ๋ฌธ์ œ์˜€๋‹ค. ๊ทธ๊ฒƒ๋“ค์„ ๋‹ค ์ง์ ‘ ๊ตฌํ˜„์„ ํ•˜๋ฉด ๋ฌผ๋ก  ๋„ˆ๋ฌด ์ข‹๊ฒ ์ง€๋งŒโ€ฆ๐Ÿ˜‡ ๊ทธ๋Ÿฌ๋ฉด ๊ฒฐ๊ตญ ์‚ฌ์ง„ ํŽธ์ง‘๋„ ์ง์ ‘ ๊ตฌํ˜„ํ•œ ๊ฑธ๋กœ ํ•˜๋ฉด ๋๊ธฐ์— ์• ์ดˆ์— cropper.js๋ฅผ ์“ฐ๊ธฐ๋กœ ๊ฒฐ์ •ํ–ˆ๋˜ ๊ฒƒ์—์„œ ๋„ˆ๋ฌด ๋งŽ์ด ๋ฒ—์–ด๋‚˜๋Š” ๊ฒƒ ๊ฐ™์•˜๋‹ค. ์šฐ๋ฆฌ ํ”„๋กœ์ ํŠธ์˜ ๋ชฉํ‘œ๋Š” โ€˜๋ฌด์กฐ๊ฑด ์™„์„ฑโ€™ ์ด์—ˆ๋Š”๋ฐ ๋””๋ฒ„๊น…๊ณผ ๋ฐฐํฌ, ๋ฌธ์„œํ™”๊นŒ์ง€ ๊ณ ๋ คํ•œ๋‹ค๋ฉด ๋‚จ์€ ์‹œ๊ฐ„์ด 2์ฃผ๊ฐ€๋Ÿ‰๋ฐ–์— ๋˜์ง€ ์•Š๋Š” ๋‹ค๋Š” ๊ฒƒ๋„ ๋ฌธ์ œ์˜€๋‹ค.

๊ทธ๋ ‡๊ฒŒ ๋ฆฌ์„œ์น˜๋ฅผ ๊ณ„์† ํ•˜๋˜ ์ค‘, fabric.js์— ๋Œ€ํ•ด ์•Œ๊ฒŒ๋˜์–ด ์ด๊ฒƒ์„ ์“ฐ๊ธฐ๋กœ ํ–ˆ๋‹ค. core javascript๋กœ ๋“œ๋ž˜๊ทธ ์ด๋ฒคํŠธ์™€ ์Œฉ Canvas API๋ฅผ ์ด์šฉํ•ด ๊ตฌํ˜„ํ•ด๋ณด๋ ค ํ–ˆ๋˜ ์ € ๋ฐ๋ชจ๋Š”, ๋™์ž‘ ์›๋ฆฌ๋ฅผ ์•Œ๊ฒŒ ํ•ด์ฃผ๋Š” ์†Œ์ค‘ํ•œ ์‹œ๋„์˜€์ง€๋งŒ, fabric.js๋Š” ํ™•์‹คํžˆ โœจ์‹ ์„ธ๊ณ„โœจ์˜€๋‹ค.

๋˜‘๊ฐ™์ด canvas๋ฅผ ์ธ์Šคํ„ด์Šค๋กœ ์ƒ์„ฑํ•˜๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ด๊ณ  cropper์™€ ์ถฉ๋Œํ•  ์ผ์ด ์—†์—ˆ๋‹ค. ๋‹ค๋งŒ ์ƒˆ๋กœ์šด ์บ”๋ฒ„์Šค๊ฐ€ ์ƒ์„ฑ๋˜๋Š” ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์— ๋‘ ๊ฐ€์ง€ ์•„์ด๋””์–ด ์ค‘์— ๊ณ ๋ฏผํ–ˆ๋‹ค.

  • ์Šคํ‹ฐ์ปค ํŽธ์ง‘ ๋ชจ๋“œ ์ง„์ž…์‹œ ํ•˜๋˜ ํŽธ์ง‘์„ ์ €์žฅํ•˜์—ฌ ์Šคํ‹ฐ์ปค ์บ”๋ฒ„์Šค์˜ ๋ฐฐ๊ฒฝ์œผ๋กœ ๊น”๊ฒŒ ํ•จ. ๋‹ค์‹œ ์‚ฌ์ง„ ํŽธ์ง‘์œผ๋กœ ๋Œ์•„๊ฐˆ ๊ฒฝ์šฐ์—๋„ ์Šคํ‹ฐ์ปค ์บ”๋ฒ„์Šค์˜ ๋‚ด์šฉ์„ ์ €์žฅํ•˜์—ฌ ์‚ฌ์ง„ ํŽธ์ง‘ ์บ”๋ฒ„์Šค๋กœ ๋กœ๋“œํ•จ.
  • ์Šคํ‹ฐ์ปค ์บ”๋ฒ„์Šค์™€ ์‚ฌ์ง„ ์บ”๋ฒ„์Šค๋ฅผ ๋”ฐ๋กœ ๋‘๊ณ  ํด๋ฆญํ•œ ๋ชจ๋“œ์— ๋”ฐ๋ผ ์บ”๋ฒ„์Šค๋ฅผ ์Šค์œ„์นญํ•จ. ์Šคํ‹ฐ์ปค ์บ”๋ฒ„์Šค๊ฐ€ ์‚ฌ์ง„ ์บ”๋ฒ„์Šค ์œ„๋กœ ์œ„์น˜ํ•ด์„œ ๋งˆ์น˜ ์‚ฌ์ง„ ์บ”๋ฒ„์Šค๊ฐ€ ๋ฐฐ๊ฒฝ์ธ ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด๊ณ  ์Šคํ‹ฐ์ปค๋ฅผ ๋†“๊ฒŒ ํ•จ. ์ €์žฅ์‹œ์—๋Š” ๋‘ ์บ”๋ฒ„์Šค๋ฅผ ํ•ฉ์ณ ํ•˜๋‚˜์˜ ์ด๋ฏธ์ง€๋กœ ๋งŒ๋“ค์–ด ์ €์žฅํ•จ.

์ฒ˜์Œ์—๋Š” ์ฒซ ๋ฒˆ์งธ ๋ฐฉ๋ฒ•์œผ๋กœ ํ•˜๋ ค๊ณ  ํ–ˆ์œผ๋‚˜ ๋ชจ๋“œ ๋ณ€๊ฒฝ์‹œ๋งˆ๋‹ค ์บ”๋ฒ„์Šค๋ฅผ ๋”ฐ๋กœ ์ €์žฅํ•˜์—ฌ ๋ฐฐ๊ฒฝ์œผ๋กœ ๊นŒ๋Š” ๊ฒƒ๊ณผ ์ „์ฒด์ ์ธ ๋กœ์ง์˜ ๋ณต์žก๋„๊ฐ€ ๋‘ ๋ฒˆ์งธ ๋ฐฉ๋ฒ•๋ณด๋‹ค ๋†’๋‹ค๊ณ  ํŒ๋‹จ๋˜์–ด ๋‘ ๋ฒˆ์งธ ๋ฐฉ๋ฒ•์œผ๋กœ ๋ณ€๊ฒฝ๋˜์—ˆ๋‹ค.

๐ŸŽจ fabric.js

fabric.js๋Š” ์ง๊ด€์ ์ด์ง€ ๋ชปํ–ˆ๋˜ Canvas API์˜ ๋™์ž‘ ๋ฐฉ์‹์„ ์ง๊ด€์ ์ด๊ฒŒ ํ•ด์ค€๋‹ค. Canvas API๋ฅผ ๊ทธ๋ƒฅ ์“ฐ๋Š” ๊ฒƒ๊ณผ ๊ฐ€์žฅ ํฐ ์ฐจ์ด์ ์€ ํฐ ์Šค์ผ€์น˜๋ถ ์œ„์— ์˜ฌ๋ฆฌ๋Š” ์ , ์„ , ์ด๋ฏธ์ง€ ๋“ฑ์˜ ๊ฐ์ฒดํ™”์ด๋‹ค. ๊ธฐ์กด์—๋Š” ํฐ ์Šค์ผ€์น˜๋ถ์„ ์กฐ์ž‘ํ•˜์—ฌ ์ , ์„ , ์ด๋ฏธ์ง€ ๋“ฑ์„ ๊ทธ๋ ค๋‚ด์—ˆ๋‹ค๋ฉด Fabric.js๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ํฐ ์Šค์ผ€์น˜๋ถ์€ ๊ทธ๋Œ€๋กœ ์žˆ๊ณ  ์ , ์„ , ์ด๋ฏธ์ง€๋ฅผ ์›ํ•˜๋Š” ๋ชจ์Šต์œผ๋กœ ์„ธํŒ…ํ•ด ์˜ฌ๋ฆด ์ˆ˜ ์žˆ๋‹ค.

์ด๋ ‡๊ฒŒ ํ•˜๋‹ˆ๊นŒ ๊ทธ๋Ÿผ cropper.js๋„ ์‚ฌ์šฉํ•˜์ง€ ๋ง๊ณ  ์ „๋ถ€ fabric์œผ๋กœ ํ•ด๋ณผ๊นŒ?ํ•˜๋Š” ์ƒ๊ฐ์ด ๋“ค์—ˆ์ง€๋งŒ ์ด๋ฏธ ์‹œ๊ฐ„์ด ์ข€ ํ๋ฅธ ๋’ค๋ผ์„œ, ๊ทธ๊ฑด ํ•œ ๋‹ฌ์ด๋ผ๋Š” ํ”„๋กœ์ ํŠธ ๊ธฐ๊ฐ„ ์™ธ์ ์œผ๋กœ ํ•ด๋ณด๊ธฐ๋กœ ํ–ˆ๋‹ค. ์–ด๋””๊นŒ์ง€๋‚˜ ์šฐ๋ฆฌ์˜ ๋ชฉํ‘œ๋Š” ์™„์„ฑ์ด์—ˆ๊ธฐ์—!

cropper.js๋ณด๋‹ค๋Š” rawํ•ด์„œ ๋ฉ”์†Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•ด ์ปค์Šคํ„ฐ๋งˆ์ด์ง•์ด ๊ฐ€๋Šฅํ•œ ๋ฒ”์œ„๊ฐ€ ๋” ๋„“์—ˆ๋‹ค. ๋‹ค๋งŒ ์šฐ๋ฆฌ์—๊ฒŒ ๋ถˆํ•„์š”ํ•œ ๊ธฐ๋Šฅ๋„ ๋งŽ์•„์„œ ์ปค์Šคํ…€ ๋นŒ๋“œ๋ฅผ ํ•ด๋ณด๋ ค ํ–ˆ์ง€๋งŒ, fabric์˜ ์ปค์Šคํ…€ ๋นŒ๋“œ๋Š” npm install์„ ํ•œ ํ›„ ๋ชจ๋“ˆ ๋‚ด๋ถ€์˜ ํŒŒ์ผ๋งŒ ๋ฐ”๊พธ๋Š” ์‹์ด์—ˆ๊ธฐ์— ์ถ”ํ›„ ์—…๋ฐ์ดํŠธ๊ฐ€ ์žˆ๋‹ค๋ฉด ์ˆ˜๋™์œผ๋กœ ์ง„ํ–‰ํ•ด์•ผ ํ•˜๋Š” ๋ฌธ์ œ๊ฐ€ ์žˆ์—ˆ๋‹ค. ๊ทธ๋ ‡๊ฒŒ ํ•˜์ง€ ์•Š๊ณ  npm์„ ํ†ตํ•ด ํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ์•„์ง ์ฐพ์ง€ ๋ชปํ•ด ๋ณด๋ฅ˜ํ•ด๋‘” ์ƒํ™ฉ์ด๋‹ค.

์–ด์จŒ๋“  ๋‹ค์‹œ ๋Œ์•„์™€์„œ, fabric.js๋Š” ๋‚ด๊ฐ€ ํ–ˆ๋˜ ๊ณ ๋ฏผ๋“ค์„ ์™„๋ฒฝํ•˜๊ฒŒ ํ•ด๊ฒฐํ•ด์ฃผ๋Š” ๋งˆ๋ฒ•๊ฐ™์€ ์กด์žฌ์˜€๋‹ค.

  • ํ•˜๋‚˜์˜ ์บ”๋ฒ„์Šค ์•ˆ์— ์—ฌ๋Ÿฌ๊ฐœ์˜ ์Šคํ‹ฐ์ปค ๊ฐ์ฒด๋ฅผ ์˜ฌ๋ฆด ์ˆ˜ ์žˆ๋‹ค
  • ์˜ฌ๋ฆฌ๋Š” ๊ฒƒ ๋งŒ์œผ๋กœ๋„ ๋ฐ˜์ „,๋ฆฌ์‚ฌ์ด์ง•,์ด๋™,ํšŒ์ „ ๋“ฑ์˜ ์กฐ์ž‘์„ ํ•  ์ˆ˜ ์žˆ๋‹ค

์ด๋ฅผ ์œ„ํ•œ ์ฝ”๋“œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

  /**
   * Add sticker image on canvas
   * @param {string} src - The src of sticker image
   * @param {Object} options - The options of sticker image
   */
  addSticker(src, options) {
    fabric.Image.fromURL(
      src,
      sticker => {
        sticker.scaleToWidth(this.stickerCanvas.width * 0.2);
        sticker.scaleToHeight(this.stickerCanvas.width * 0.2);
        this.stickerCanvas.add(sticker).renderAll();
      },
      {
        borderColor: '#39f',
        cornerColor: '#39f',
        cornerSize: 5,
        transparentCorners: false,
        ...options
      }
    );
  }

๋ฐ๋ชจ์—์„œ์ฒ˜๋Ÿผ ์Šคํ‹ฐ์ปค๋ฅผ ์ถ”๊ฐ€ํ•  ๋•Œ๋งˆ๋‹ค ๋žœ๋คํ•œ ์œ„์น˜์— ์ƒ์„ฑ๋˜๊ฒŒ๋” ํ•ด๋ณด๋ ค๊ณ  ํ–ˆ๋Š”๋ฐโ€ฆ ์ƒ๊ฐํ•ด๋ณด๋‹ˆ ๊ทธ๊ฒƒ๋ณด๋‹ค๋Š” 0,0 ์ด๋ผ๋Š” ์˜ˆ์ธกํ•  ์ˆ˜ ์žˆ๋Š” ์œ„์น˜์— ์ถ”๊ฐ€๋˜๋Š” ๊ฒƒ์ด ๋” ์ข‹์€ ์‚ฌ์šฉ์ž ๊ฒฝํ—˜์ผ ๊ฒƒ ๊ฐ™์•„์„œ ๋”ฐ๋กœ ์˜ต์…˜์„ ์ฃผ์ง€ ์•Š๊ณ  ๊ธฐ๋ณธ ์œ„์น˜์ธ 0,0์— ์ƒ์„ฑ๋˜๊ฒŒ ํ–ˆ๋‹ค. ๋งˆ์น˜ ์‚ฌ์šฉ์ž๋ฅผ ์ƒ๊ฐํ•œ ๊ฒƒ์ฒ˜๋Ÿผ ์ผ๋Š”๋ฐ ์‚ฌ์‹ค ๊ฑ ๋‚˜๋ผ๋ฉด ๊ทธ๋Ÿด ๊ฒƒ ๊ฐ™์•˜๋‹ค. version 0.1.7์—์„œ ์Šคํ‹ฐ์ปค๊ฐ€ ์ • ๊ฐ€์šด๋ฐ์— ์ƒ์„ฑ๋˜๊ฒŒ ๋ฐ”๊พธ์—ˆ๋‹ค. ํ™•๋Œ€๋œ ์ด๋ฏธ์ง€๊ฐ€ ui ๋ฐ‘์œผ๋กœ ๊น”๋ ค๋ฒ„๋ฆฌ๋ฉด 0,0์— ๋†“์ธ ์Šคํ‹ฐ์ปค์— ์œ ์ €๊ฐ€ ์ ‘๊ทผํ•  ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

์Šคํ‹ฐ์ปค์˜ ์‚ฌ์ด์ฆˆ๊ฐ€ ๋„ˆ๋ฌด ํฌ์ง€๋„ ์ž‘์ง€๋„ ์•Š๊ฒŒ ์บ”๋ฒ„์Šค ์ƒ์—์„œ ๋ณด์ผ ์ˆ˜ ์žˆ๋„๋ก fabric์˜ scaleToWidth(), scaleToHeight() ๋ฉ”์†Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•ด ์ƒ๋Œ€์ ์ธ ํฌ๊ธฐ๋ฅผ ์ง€์ •ํ–ˆ๋‹ค. ๋งˆ์ง€๋ง‰์œผ๋กœ cropper์˜ ์Šคํƒ€์ผ๊ณผ ๋˜‘๊ฐ™์ด ํ•˜๊ธฐ ์œ„ํ•ด์„œ ์ฝ”๋„ˆ ์‚ฌ์ด์ฆˆ์™€ ํ…Œ๋‘๋ฆฌ ์ƒ‰์ƒ์„ ์˜ต์…˜์œผ๋กœ ์ง€์ •ํ–ˆ๋‹ค. ์›๋ž˜๋Š” ํฐ์ƒ‰์œผ๋กœ ํ†ต์ผํ•˜๋ ค ํ–ˆ๋Š”๋ฐ, cropper์˜ ๊ฒฝ์šฐ ๊ทธ๋ ‡๊ฒŒ ํ•˜๋ฉด ์ปค์Šคํ…€ ๋นŒ๋“œ๋ฅผ ํ•ด์•ผํ•ด์„œ ๋ณด๋ฅ˜ํ–ˆ๋‹ค. ์ด ์™ธ์—๋„ ๋ชจ๋“ˆ์„ ์‚ฌ์šฉํ•˜๋Š” ์‚ฌ์šฉ์ž๊ฐ€ ์ถ”๊ฐ€๋กœ ์ง€์ •ํ•˜๊ณ  ์‹ถ์€ ์˜ต์…˜์ด ์žˆ๋‹ค๋ฉด ๋ฐ›์•„์˜ฌ ์ˆ˜ ์žˆ๊ฒŒ๋” ํ–ˆ๋‹ค.

์ด๋Ÿฐ ์‹์œผ๋กœ ์šฐ๋ฆฌ์—๊ฒŒ ํ•„์š”ํ•œ ๊ธฐ๋Šฅ๋“ค์„ ๋ชจ์•„์„œ class๋กœ ๋ชจ๋“ˆ์„ ๋งŒ๋“ค์—ˆ๋‹ค. cropper๊ณผ fabric์ด ์บ”๋ฒ„์Šค ์ธ์Šคํ„ด์Šค๋ฅผ ๋งŒ๋“ค์–ด๋‚ด์„œ ๋™์ž‘ํ•˜๋Š” ๋ฐฉ์‹์ด๋ผ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ๋ฉ”์†Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋ฉด ๊ฐ ์ธ์Šคํ„ด์Šค๊ฐ€ ํ•„์š”ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

์›๋ž˜๋Š” ๋‚ด ํ•  ์ผ์€ ์—ฌ๊ธฐ์„œ ๋์ธ ์ค„ ์•Œ์•˜๋‹ค. ๊ทธ๋ž˜์„œ '์ญ? ๋‚˜ ๋„ˆ๋ฌด ํ•  ์ผ์ด ์—†๋Š”๋ฐ? ์ผ์€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋“ค์ด ๋‹ค ํ–ˆ๋Š”๋ฐ?' ์‹ถ์–ด์„œ ์ž๊ดด๊ฐ์— ๋น ์ง€๋ ค๋˜ ์ฐธ์—โ€ฆ ๋ชจ๋“ˆ์ด ์ œ๋Œ€๋กœ ๋™์ž‘ํ•˜๋Š”์ง€ ํ…Œ์ŠคํŠธํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” UI๊ฐ€ ํ•„์š”ํ–ˆ๊ณ , Vue๋ฅผ ์‚ฌ์šฉํ•ด UI๋ฅผ ๋งŒ๋“ค๊ธฐ๋กœ ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ๊ฒฐ๊ตญ ๋‚˜๋„ Vue๋ฅผ ์“ธ ์ค„ ์•Œ์•„์•ผ ํ–ˆ๋‹ค. ์›๋ž˜๋Š” ๋ชจ๋“ˆ๋งŒ ๋งŒ๋“ค๋ฉด ๋˜๋Š”์ค„ ์•Œ์•˜๋Š”๋ฐ ์•„๋‹ˆ์—ˆ์Œ. Vue UI๋Š” ํ•จ๊ป˜ ํ”„๋กœ์ ํŠธ๋ฅผ ์ง„ํ–‰ํ•œ ์ค€ํ˜„๋‹˜์ด ๋งก์•„์ฃผ์…จ๊ณ , ์ค€ํ˜„๋‹˜์ด UI ์ž‘์—…์„ ์ง„ํ–‰ํ•˜์‹œ๋Š” ๋™์•ˆ UI์— ์—ฐ๊ฒฐํ•  vue์—์„œ์˜ ๊ธฐ๋Šฅ ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“œ๋Š” ๊ฒƒ์€ ๋‚ด๊ฐ€ ์ง„ํ–‰ํ–ˆ๋‹ค.

๐Ÿ•ณ UI ๊ตฌ์กฐ

์ค€ํ˜„๋‹˜์ด Vue๋กœ UI๋ฅผ ๋งŒ๋“œ์‹œ๋Š” ๊ณผ์ •์—์„œ Vue Slot ๊ตฌ์กฐ์— ๋Œ€ํ•ด ํ•จ๊ป˜ ๊ณ ๋ฏผํ–ˆ๋Š”๋ฐ ์ข‹์€ ๊ฒฝํ—˜์ด์—ˆ์–ด์„œ ๊ธฐ๋กํ•˜๊ณ ์ž ํ•œ๋‹ค.

์šฐ๋ฆฌ๊ฐ€ ๊ฐœ๋ฐœํ•˜๋ ค๋Š” ์‚ฌ์ง„ ํŽธ์ง‘ํˆด์€ ๊ฑฐ๋Œ€ํ•œ ๊ทœ๋ชจ๊ฐ€ ์•„๋‹ˆ๊ธฐ๋„ ํ•˜๊ณ , ๋‹จ๋… ๊ธฐ๋Šฅ ๋ชจ๋“ˆ์ด๊ธฐ์— UI๊ฐ€ ๋ณต์žกํ•˜์ง€๋„ ์•Š์•˜๋‹ค. ์ฝ”๋“œ์˜ ์–‘๋„ ๋งŽ์ง€ ์•Š์•„ ํ•˜๋‚˜์˜ ํŒŒ์ผ ์•ˆ์—์„œ ์ฝ”๋“œ ์ž‘์„ฑ์„ ๋งˆ์น  ์ˆ˜ ์žˆ์—ˆ๋‹ค.

๊ทธ๋ ‡์ง€๋งŒ ๋ช…์‹œ์ ์œผ๋กœ ์ด๊ฒŒ UI์  ๋ถ€๋ถ„์ธ์ง€, ๋ชจ๋“ˆ์„ ์ด์šฉํ•˜๋Š” ๋ถ€๋ถ„์ธ์ง€ ๊ตฌ๋ถ„ํ•˜๊ธฐ ์œ„ํ•ด์„œ ๋‘ ๊ฐœ์˜ ์ปดํฌ๋„ŒํŠธ๋กœ ๋‚˜๋ˆ„์—ˆ๋‹ค. ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋‚˜๋ˆ„๋Š” ๊ฒƒ์€ ์žฌ์‚ฌ์šฉ์„ฑ์ด ์žˆ์„ ๋•Œ๋ผ๊ณ ๋งŒ ์•Œ๊ณ  ์žˆ์—ˆ๋Š”๋ฐ, ํšŒ์˜ ๋•Œ ๋‹จ์ˆœํžˆ ๊ทธ ๋ฟ๋งŒ์ด ์•„๋‹ˆ๋ผ ๋ช…์‹œ์ ์œผ๋กœ ๊ธฐ๋Šฅ์„ ๊ตฌ๋ถ„ํ•˜๊ธฐ ์œ„ํ•ด ๋‚˜๋ˆ„๊ธฐ๋„ ํ•œ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๊ฒŒ๋˜์—ˆ๋‹ค.

๋ฆฌ์•กํŠธ๋ฅผ ๊ณต๋ถ€ํ•˜๋‹ค ์™€์„œ ๊ทธ๋Ÿฐ์ง€ vue์˜ ๊ธฐ๋Šฅ๋“ค์„ ์“ธ ๋•Œ๋งˆ๋‹ค ๋ฆฌ์•กํŠธ๋ฅผ ๋– ์˜ฌ๋ฆฌ๊ฒŒ ๋˜๋Š” ๊ฒƒ์€ ์–ด์ฉ” ์ˆ˜ ์—†๋Š” ๊ฒƒ ๊ฐ™๋‹ค. slot์€ ๋ฆฌ์•กํŠธ์˜ props children๊ณผ ์œ ์‚ฌํ–ˆ๋‹ค. ImojiEditor.vue๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ImojiEditorCanvas.vue ์ปดํฌ๋„ŒํŠธ๋ฅผ ํ•˜์œ„๋กœ ๊ฐ–๊ณ , named slot์œผ๋กœ ๊ฐ ํŒŒํŠธ์˜ UI๋ฅผ ๊ทธ๋ ค๋‚ธ ํ›„ ImojiEditorCanvas.vue์˜ ๊ธฐ๋Šฅ๋“ค์„ ๋„˜๊ฒจ๋ฐ›์•„ ์—ฐ๊ฒฐํ•œ๋‹ค.

// ImojiEditor.vue ๊ฐ„์†Œํ™” ์ฝ”๋“œ
<template>
  <imoji-editor-canvas>
    <template
      #controllerBar="{reset, stickerCanvas, onInputImage, crop, layout, photoCanvas}"
    >
    </template>
    <template #toolBar="{photoCanvas, layout, zoom, rotate, clearCrop}">
    </template>
    <template #stickerToolBar="{stickerCanvas , layout}"> </template>
    <template #toolNavigation="{openImageEditor, openStickerEditor}">
    </template>
  </imoji-editor-canvas>
</template>

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๋ชจ๋“ˆ์„ ์ด์šฉํ•ด์„œ ์‚ฌ์ง„ ํŽธ์ง‘ ๊ธฐ๋Šฅ๊ณผ ๊ด€๋ จ๋œ ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“œ๋Š” ๋ถ€๋ถ„์€ ImojiEditorCanvas.vue์—์„œ๋งŒ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค. ์ด๊ฑธ๋กœ ๋‚˜๋Š” ImojiEditorCanvas.vue์—์„œ๋งŒ ์ฃผ๋กœ ์ž‘์—…ํ•˜์—ฌ UI๋ฅผ ์ž‘์—…ํ•˜์‹œ๋Š” ์ค€ํ˜„๋‹˜๊ณผ ์„œ๋กœ ์ถฉ๋Œํ•˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ์—ˆ๋‹ค.

๐Ÿ‘€ ๊ธฐ๋Šฅ ํ•จ์ˆ˜ ๋งŒ๋“ค๊ธฐ

ImojiEditorCanvas.vue์—์„œ๋Š” ๋ชจ๋“ˆ์„ ๋ถˆ๋Ÿฌ์™€์„œ ๊ธฐ๋Šฅ ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ค์—ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณค ๊ฐ๊ฐ์˜ UI์— slot props๋กœ ํ•„์š”ํ•œ ํ•จ์ˆ˜ ๋˜๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ๋„˜๊ฒจ์ฃผ์—ˆ๋Š”๋ฐ, ํ•ด๋‹น ๋ถ€๋ถ„์€ ๊ฐ„๋žตํ•จ์„ ์œ„ํ•ด ์•„๋ž˜์˜ ์ฝ”๋“œ์—์„œ๋Š” ์ง€์› ๋‹ค.

์ด ์ปดํฌ๋„ŒํŠธ์˜ ํฌ์ธํŠธ๋Š” ์บ”๋ฒ„์Šค๋ฅผ ๋‹ค๋ฃจ๋Š” ๋ถ€๋ถ„์ด์—ˆ๋‹ค.

// ImojiEditorCanvas.vue ๊ฐ„์†Œํ™” ์ฝ”๋“œ
<template>
  <section
    :style="{
      width: `${width}px`,
      height: `${height}px`,
      position: 'relative'
    }"
  >
    <slot name="controllerBar"></slot>
    // Point !
    <div class="imoji-editor-wrapper">
      <div class="imoji-editor-container">
        <div id="sticker-wrapper" :class="[hide ? 'hide' : '']">
          <canvas id="sticker-canvas"></canvas>
        </div>
        <div
          id="uploaded-photo-wrapper"
          :style="{
            width: `${width}px`,
            height: `${height}px`
          }"
        >
          <img id="user-photo" ref="uploadedPhoto" :src="uploadedImageSrc" />
        </div>
      </div>
    </div>
    <div class="all-tool-bar-wrapper">
      <slot name="toolBar"></slot>
      <slot name="stickerToolBar"></slot>
      <slot name="ratioCropToolBar"></slot>
      <slot name="toolNavigation"></slot>
    </div>
  </section>
</template>

์‚ฌ์ง„ ํŽธ์ง‘๋งŒ์„ ๋‹ด๋‹นํ•˜๋Š” uploaded-photo-wrapper๊ฐ€ ์žˆ๊ณ , ์Šคํ‹ฐ์ปค ํŽธ์ง‘์„ ๋‹ด๋‹นํ•˜๋Š” sticker-wrapper๊ฐ€ ์žˆ๋‹ค. ๊ฐ๊ฐ์˜ ์บ”๋ฒ„์Šค๋Š” ๋ชจ๋“ˆ์— ์˜ํ•ด ์ƒ์„ฑ๋  ๊ฒƒ์ด๊ณ  ๊ฑด๋“œ๋ฆด ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์— ๊ฐ๊ฐ์„ ๊ฐ์‹ธ๋Š” div๋ฅผ ๋งŒ๋“ค์–ด์„œ ์œ„์น˜ ์กฐ์ • ๋“ฑ ์›ํ•˜๋Š” ์ž‘์—…์„ ํ–ˆ๋‹ค.

๊ธฐ๋ณธ์€ ์‚ฌ์ง„ ํŽธ์ง‘ ์บ”๋ฒ„์Šค์ด๊ณ  ์Šคํ‹ฐ์ปค ๋ชจ๋“œ๋กœ ์ง„์ž…์‹œ์—๋Š” ์Šคํ‹ฐ์ปค ์บ”๋ฒ„์Šค๊ฐ€ ๊ทธ ์œ„์— ์Œ“์—ฌ ์•„๋ž˜์— ๋†“์ธ ์‚ฌ์ง„ ํŽธ์ง‘ ์บ”๋ฒ„์Šค๋ฅผ ๋ณด๋ฉด์„œ ์›ํ•˜๋Š” ์œ„์น˜์— ์Šคํ‹ฐ์ปค๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ–ˆ๋‹ค. ์œ„์— ๋†“์—ฌ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์Šคํ‹ฐ์ปค ๋ชจ๋“œ์—์„œ๋Š” ์‚ฌ์ง„ ํŽธ์ง‘ ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋‹ค. ๋‹ค์‹œ ์‚ฌ์ง„ ํŽธ์ง‘ ๋ชจ๋“œ๋กœ ์ง„์ž…ํ•˜๋ฉด ์Šคํ‹ฐ์ปค ์บ”๋ฒ„์Šค๊ฐ€ ์ˆจ๊ฒจ์ง€๋ฉฐ ์‚ฌ์ง„ ํŽธ์ง‘์„ ๋‹ค์‹œ ํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด ๋ถ€๋ถ„์€ Vue์˜ reactive data๋ฅผ ํ™œ์šฉํ•˜์—ฌ display:none ์†์„ฑ์˜ class๋ฅผ ์ถ”๊ฐ€ํ–ˆ๋‹ค ์ œ๊ฑฐํ–ˆ๋‹ค ํ•œ ๊ฒƒ์ธ๋ฐ, ๋ฆฌ์•กํŠธ ์ด์šฉ์ž๋ผ๋ฉด setState๋ฅผ ํ™œ์šฉํ•œ ๊ฒƒ์ด๋ผ๊ณ  ๋ณด๋ฉด ์‰ฝ๋‹ค.

UI์— ๋ชจ๋“ˆ์„ ์—ฐ๊ฒฐํ•˜๋Š” ๊ณผ์ •์€ ๋””๋ฒ„๊น…์˜ ์—ฐ์†์ด๊ธฐ๋„ ํ–ˆ๋‹ค. ์ƒ๊ฐ๋ณด๋‹ค ๋‹ค์–‘ํ•œ ๊ฒฝ์šฐ์˜ ์ˆ˜๊ฐ€ ์žˆ์—ˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

debugingmeme

2์ฃผ์ฐจ๊นŒ์ง€ ํ•„์ˆ˜ ๊ธฐ๋Šฅ๋“ค์„ ๋‹ด์€ 1์ฐจ ํ”„๋กœํ† ํƒ€์ž…์„ ์™„์„ฑํ•œ ํ›„์—๋Š” ์—๋Ÿฌ์—†์ด ์ž˜ ๋Œ์•„๊ฐ€๋„๋ก ๋‹ค์–‘ํ•œ ์‚ฌ์šฉ ํ๋ฆ„์„ ํ™•์ธํ•˜๊ณ  ์•ˆ๋“œ๋กœ์ด๋“œ/ios/๊ตฌ๊ธ€ํฌ๋กฌ/์›จ์ผ/์‚ผ์„ฑ์ธํ„ฐ๋„ท ๋“ฑ ๋‹ค์–‘ํ•œ ํ™˜๊ฒฝ์—์„œ ํ…Œ์ŠคํŠธํ•ด๋ณด๋ฉฐ ์ด์Šˆ๋ฅผ ์ฒดํฌํ•˜๊ณ  fixํ•˜๋Š”๋ฐ ์ง‘์ค‘ํ–ˆ๋‹ค. ์•„๋ž˜๋Š” ์ด์Šˆ๋ณด๋“œ์ธ๋ฐ ์ด์Šˆ ํ•˜๋‚˜๋ฅผ ํ•ด๊ฒฐํ•˜๋ฉด ์ง‘์— ๊ฐˆ ๋•Œ ์ฏค ์ƒˆ๋กœ์šด ์ด์Šˆ๊ฐ€ ์ƒ๊ฒจ๋‚˜๋Š” ํ•˜๋ฃจํ•˜๋ฃจ๋ฅผ ๋ณด๋ƒˆ๋‹คโ€ฆ๐Ÿ˜‡

issueboard

ํŠนํžˆ ์‚ฌ์šฉ์ž ์ž…์žฅ์—์„œ ์ด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ์–ด๋–ค ํ๋ฆ„์„ ๊ฐ€์ง€๊ณ  ์žˆ์–ด์•ผ ์ข‹์„์ง€, ์˜คํ”ˆ ์†Œ์Šค์ธ๋งŒํผ ๊ฐœ๋ฐœ์ž๋“ค์ด ์ฝ”๋“œ๋งŒ ๋ณด๊ณ ๋„ ์•Œ์•„์ฐจ๋ฆด ์ˆ˜ ์žˆ๊ฒŒ๋” ๋„ค์ด๋ฐ๊ณผ ๊ตฌ์กฐ์ ์ธ ๋ถ€๋ถ„ ๋˜๋Š” ์ž์ž˜ํ•œ ์ˆœ์„œ๊ฐ™์€ ๊ฒƒ์—๋„ ์‹ ๊ฒฝ์ผ๋‹ค. ์ด ๊ธฐ๊ฐ„๋™์•ˆ ๋‚ด๊ฐ€ ๊ฒช์—ˆ๋˜ ๋ธ”๋กœ์ปค๋Š” ์•„๋ž˜์™€ ๊ฐ™๋‹ค. ์†”์งํžˆ ์ง€๊ธˆ์™€์„œ ์ƒ๊ฐํ•ด๋ณด๋ฉด ์™œ ๊ทธ๋ ‡๊ฒŒ ๋™๋™๋Œ”์„๊นŒ ์‹ถ๊ธฐ๋„ ํ•˜์ง€๋งŒโ€ฆ ํ˜„์žฌ์˜ ๋‚ด๊ฐ€ ๊ทธ๋•Œ์˜ ๋‚˜๋ณด๋‹ค ์„ฑ์žฅํ•ด์„œ ๊ทธ๋Ÿฐ๊ฑฐ๋ผ๊ณ  ๋ฏฟ๊ณ  ์‹ถ๋‹ค ๐Ÿคฆโ€โ™€๏ธ

๐Ÿ”ฅ Blocker

๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์‚ฌ์šฉ์— ๋Œ€ํ•œ ์–ด๋ ค์›€

๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์“ฐ๋ฉด ๋ฌด์กฐ๊ฑด ์‰ฝ๊ณ  ํŽธํ•˜๊ณ  ์ข‹๊ธฐ๋งŒ ํ•  ์ค„ ์•Œ์•˜๋‹ค. ์ ˆ๋Œ€ ๊ทธ๋ ‡์ง€ ์•Š๊ณ  ์˜คํžˆ๋ ค ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์“ฐ๋ฉด ํ‹€ ์•ˆ์— ๊ฐ‡ํžˆ๊ฒŒ ๋  ์ˆ˜๋„ ์žˆ๋‹ค๋Š” ์ ์„ ์ด๋ฒˆ์— ์ข€ ๋งŽ์ด ๋Š๊ผˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด์„œ cropper.js์˜ ํŠน์ • ์บ”๋ฒ„์Šค๋ฅผ position relative๋กœ ๋‘๊ณ  ์Šคํ‹ฐ์ปค ์บ”๋ฒ„์Šค๊ฐ€ cropper์˜ ์บ”๋ฒ„์Šค๋ฅผ ๋”ฐ๋ผ๊ฐ€๋„๋ก ๋งŒ๋“ค๊ณ  ์‹ถ์€๋ฐ, cropper์˜ ์บ”๋ฒ„์Šค๋Š” ๋ฌด์กฐ๊ฑด position absolute์—ฌ์•ผ๋งŒ ํ•˜๋Š” ์ƒํ™ฉ์ด ์žˆ์—ˆ๋‹ค. ๋˜, cropper์˜ ์ƒ‰์ƒ ์Šคํƒ€์ผ์„ ํฐ์ƒ‰์œผ๋กœ ๋ฐ”๊พธ๊ณ  ์‹ถ์€๋ฐ, ๊ทธ๋Ÿด๋ผ๋ฉด ์ปค์Šคํ…€ ๋นŒ๋“œ๋ฅผ ํ•ด์•ผํ•˜๋Š” ์ƒํ™ฉ๋„ ์žˆ์—ˆ๋‹ค.

์ด๋Ÿฐ์‹์œผ๋กœ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ์ธ์Šคํ„ด์Šค๋ฅผ ์ œ๊ณตํ•˜๊ณ  ๊ทธ์— ๋”ฐ๋ฅธ ๋ฉ”์†Œ๋“œ๋“ค์„ ์ œ๊ณตํ•œ๋‹ค๋ฉด, ๊ทธ๋ฆฌ๊ณ  ๊ทธ๋Ÿฐ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋“ค์„ ์—ฌ๋Ÿฌ ๊ฐœ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด ํ‹€ ์•ˆ์˜ ํ‹€ ์•ˆ์— ๊ฐ‡ํžˆ๊ฒŒ ๋˜์–ด ๋‹ต๋‹ตํ•ด์ง€๋Š” ์ƒํ™ฉ์„ ๋งˆ์ฃผํ•  ์ˆ˜๋„ ์žˆ๊ฒ ๋‹ค ์‹ถ์—ˆ๋‹ค. ์ด๋Ÿฐ ๋ถ€๋ถ„์„ ๊ฒฝ๊ณ„ํ•˜๋ฉฐ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๊ณ , ์„ ํƒํ•ด์•ผ ํ•˜์ง€ ์•Š์•˜์„๊นŒ? ๋‹ค์Œ์— ๋˜ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์“ธ ์ผ์ด ์žˆ๋‹ค๋ฉด ์–ผ๋งˆ๋‚˜ ์ž์œ ๋กœ์šด์ง€๋ฅผ ๊ผญ ํ™•์ธํ•ด์•ผ๊ฒ ๋‹ค ์‹ถ์—ˆ๋‹ค.

์ด๋ฏธ์ง€ ์ตœ์ข… ์ €์žฅ๊ณผ ๋น„๋™๊ธฐ

์ด๋ฒˆ ํ”„๋กœ์ ํŠธ์—์„œ ์ œ์ผ ๊ฐ„๊ณผํ–ˆ๋˜ ๋ถ€๋ถ„์€ ๋น„๋™๊ธฐ์˜€๋‹ค. ๋งŒ์•…์˜ ๊ทผ์›

asyncmeme

์™ธ๋ถ€์—์„œ ์ด๋ฏธ์ง€๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๋Š” ๊ฒƒ ์ž์ฒด๊ฐ€ ๋น„๋™๊ธฐ๋กœ ์ฒ˜๋ฆฌ๋˜๊ธฐ ๋•Œ๋ฌธ์—, ๋‚ด๊ฐ€ ์›ํ•˜๋Š” ์ˆœ์„œ๋กœ ์ผ๋ จ์˜ ์ฝ”๋“œ๋“ค์ด ์‹คํ–‰๋˜๊ฒŒ ๋ณด์žฅํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”ํ–ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์šฐ๋ฆฌ๊ฐ€ ๊ฐœ๋ฐœํ•˜๋Š” ์ด ํ”„๋กœ์ ํŠธ๊ฐ€ ์ด๋ฏธ์ง€๋ฅผ ๋‹ค๋ฃจ๋Š” ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์—, ๋‚ด๊ฐ€ ๋งˆ์ฃผํ•œ ๋ฌธ์ œ๋“ค์˜ ํ•œ 80%๋Š” ์›์ธ์ด ๋น„๋™๊ธฐ์˜€๋˜ ๊ฒƒ ๊ฐ™๋‹ค.

๊ทธ ์ค‘์—์„œ ๊ธฐ์–ต๋‚˜๋Š” ๊ฒƒ์„ ๊ผฝ์ž๋ฉด ์ด๋ฏธ์ง€์˜ ์ตœ์ข… ์ €์žฅ๊ณผ ๊ด€๋ จ๋œ ๋ถ€๋ถ„์ด์—ˆ๋‹ค. ๋‚˜๋Š” ์œ ์ €๊ฐ€ ์„ ํƒํ•œ ๋ชจ๋“œ์— ๋”ฐ๋ผ ๋‘ ์บ”๋ฒ„์Šค๋ฅผ ์Šค์œ„์นญํ•˜๊ณ  ์žˆ์—ˆ๊ณ , ์ตœ์ข… ์ €์žฅ์‹œ์—๋Š” ๋‘ ์บ”๋ฒ„์Šค๋ฅผ ํ•˜๋‚˜๋กœ ํ•ฉ์ณ์„œ ์ด๋ฏธ์ง€ ๊ฐ์ฒด๋กœ ๋‚ด๋ณด๋‚ด์•ผ ํ–ˆ๋‹ค. ํ•ฉ์น˜๋Š” ๋ฐฉ๋ฒ•์€ ๋‘ ๊ฐ€์ง€๊ฐ€ ์žˆ์—ˆ๋‹ค. (1) ํŽธ์ง‘๋œ ์‚ฌ์ง„์„ ์ด๋ฏธ์ง€๋กœ ๋‚ด๋ณด๋‚ด ์Šคํ‹ฐ์ปค ์บ”๋ฒ„์Šค์˜ ๋ฐฐ๊ฒฝ์œผ๋กœ ๊นŒ๋Š๋ƒ, (2) ์Šคํ‹ฐ์ปค ์บ”๋ฒ„์Šค๋ฅผ ์ด๋ฏธ์ง€๋กœ ๋‚ด๋ณด๋‚ด ์‚ฌ์ง„ ํŽธ์ง‘ ์บ”๋ฒ„์Šค ์ œ์ผ ์ƒ์œ„์— ๋‘๋Š๋ƒ.

๊ฒฐ๋ก ๋ถ€ํ„ฐ ๋งํ•˜์ž๋ฉด ํ›„์ž์˜ ๋ฐฉ๋ฒ•์„ ์ ์šฉํ–ˆ๋‹ค. ์‚ฌ์ง„ ํŽธ์ง‘ ์บ”๋ฒ„์Šค์—์„œ๋Š” ๋ณด์—ฌ์ง€๋Š” ๊ฒƒ๋งŒ ๋ ˆ์ด์•„์›ƒ์˜ ํฌ๊ธฐ์— ๋”ฐ๋ผ ์ค„์–ด๋ณด์ด๋Š” ๊ฒƒ์ผ ๋ฟ ์•„์›ƒํ’‹์€ ์‹ค์ œ ์‚ฌ์ง„์˜ ํฌ๊ธฐ์˜€๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ๋ฐ˜๋ฉด ์Šคํ‹ฐ์ปค ์บ”๋ฒ„์Šค์˜ ํฌ๊ธฐ๋Š” ๋ ˆ์ด์•„์›ƒ์˜ ํฌ๊ธฐ์™€ ์™„๋ฒฝํžˆ ์ผ์น˜ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ํŽธ์ง‘๋œ ์‚ฌ์ง„์„ ์Šคํ‹ฐ์ปค ์บ”๋ฒ„์Šค์˜ ๋ฐฐ๊ฒฝ์œผ๋กœ ์„ค์ •ํ•˜๋Š” ๊ฒฝ์šฐ, ์ตœ์ข… ์ €์žฅ์‹œ ์‚ฌ์ง„์ด ์›๋ณธ ํฌ๊ธฐ๋กœ ์ €์žฅ๋˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ์œ ์ €๊ฐ€ ์–ด๋Š ์‚ฌ์ด์ฆˆ์˜ ์—๋””ํ„ฐ๋ฅผ ์“ฐ๊ณ  ์žˆ๋ƒ์— ๋”ฐ๋ผ ํฌ๊ธฐ๊ฐ€ ๊ฒฐ์ •๋˜๋Š” ๋ฌธ์ œ๊ฐ€ ์žˆ์—ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ๋ชจ๋ฐ”์ผ์—์„œ ํŽธ์ง‘ํ•˜๊ณ  ์žˆ๋‹ค๋ฉด ๋”ฑ ๋ชจ๋ฐ”์ผ ํ™”๋ฉด๋งŒํ•œ ์‚ฌ์ด์ฆˆ์˜ ์‚ฌ์ง„์ด ๋ฐ˜ํ™˜๋˜๊ณ , ๋ฐ์Šคํฌํƒ‘์—์„œ ํŽธ์ง‘ํ•˜๊ณ  ์žˆ๋‹ค๋ฉด ๋ฐ์Šคํฌํƒ‘ UI์˜ ๋ชจ๋‹ฌ์ฐฝ ์‚ฌ์ด์ฆˆ์˜ ์‚ฌ์ง„์ด ๋ฐ˜ํ™˜๋˜๊ฒŒ ์ƒ๊ธด ๊ฒƒ์ด๋‹ค. ์ด๊ฑด ์šฐ๋ฆฌ๊ฐ€ ์›ํ•˜๋Š” ๊ฒƒ๋„ ์•„๋‹ˆ๊ณ , ์‚ฌ์šฉ์ž๋„ ์ ˆ๋Œ€๋กœ ์›ํ•˜์ง€ ์•Š์„ ๊ฒƒ์ด๋‹ค.

ํ›„์ž์˜ ๋ฐฉ๋ฒ•์€ ๊ทธ๋Ÿฐ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค. ์•„๋ž˜์™€ ๊ฐ™์ด ๋ชจ๋“ˆ์—์„œ fabric์˜ ๋ฉ”์†Œ๋“œ๋ฅผ ์จ์„œ ๋ฆฌ์‚ฌ์ด์ง• ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ค์—ˆ๋‹ค. ๋ชฉํ‘œํ•˜๋Š” ํฌ๊ธฐ (์›๋ณธ ์‚ฌ์ง„์˜ ํฌ๊ธฐ)์— ๋งž๊ฒŒ ์บ”๋ฒ„์Šค์˜ ํฌ๊ธฐ์™€ ์บ”๋ฒ„์Šค ์•ˆ์˜ ์Šคํ‹ฐ์ปค ๊ฐ์ฒด๋“ค์˜ ํฌ๊ธฐ๋ฅผ ๋Š˜๋ ธ๋‹ค.

  resizeStickerToNatural(naturalWidth) {
    if (this.stickerCanvas.width != naturalWidth) {
      const scaleMultiplier = naturalWidth / this.stickerCanvas.width;
      const objects = this.stickerCanvas.getObjects();
      for (let i in objects) {
        objects[i].scaleX = objects[i].scaleX * scaleMultiplier;
        objects[i].scaleY = objects[i].scaleY * scaleMultiplier;
        objects[i].left = objects[i].left * scaleMultiplier;
        objects[i].top = objects[i].top * scaleMultiplier;
        objects[i].setCoords();
      }

      this.stickerCanvas.discardActiveObject();
      this.stickerCanvas.setWidth(
        this.stickerCanvas.getWidth() * scaleMultiplier
      );
      this.stickerCanvas.setHeight(
        this.stickerCanvas.getHeight() * scaleMultiplier
      );
      this.stickerCanvas.renderAll();
      this.stickerCanvas.calcOffset();
    }
  }

์ด๋ ‡๊ฒŒ ํ–ˆ์„ ๋•Œ ์Šคํ‹ฐ์ปค๊ฐ€ svgํŒŒ์ผ์ด๋ผ ํ™”์งˆ์˜ ์ €ํ•˜๋Š” ๋ฐœ์ƒํ•˜์ง€ ์•Š์•˜๋‹ค. ๊ทธ๋ž˜์„œ ๋ฌธ์„œ์— ์šฐ๋ฆฌ๋Š” ์Šคํ‹ฐ์ปค์˜ ํ˜•์‹์„ svg๋ฅผ ๊ถŒ์žฅํ•œ๋‹ค๊ณ  ๊ฐ•์กฐํ•ด๋†จ๋‹ค. ์ด์ œ ๋‹ค๋ฅธ ๋ฌธ์ œ์ ์€ ์Šคํ‹ฐ์ปค ์บ”๋ฒ„์Šค๋ฅผ ์ด๋ฏธ์ง€๋กœ ๋ณ€ํ™˜ํ•œ ๊ฒƒ(=์ดํ•˜ ์Šคํ‹ฐ์ปค ์ด๋ฏธ์ง€)์„ ๋ถˆ๋Ÿฌ์˜ค๋Š” ๊ณผ์ •์ด ๋น„๋™๊ธฐ๋ผ๋Š” ๊ฒƒ์ด์—ˆ๋‹ค. ์ด ๋ถ€๋ถ„์„ ๋ฌด์‹œํ•˜๋ฉด ์Šคํ‹ฐ์ปค ์—†๋Š” ๊ฒฐ๊ณผ๋ฌผ์ด ๋ฐ˜ํ™˜๋˜์—ˆ๋‹ค ๐Ÿคฆโ€โ™€๏ธ

์Šคํ‹ฐ์ปค ์ด๋ฏธ์ง€์˜ ๋กœ๋”ฉ์ด ๋๋‚œ ํ›„, ์‚ฌ์ง„ ํŽธ์ง‘ ์บ”๋ฒ„์Šค์— ๊ทธ๋ ค๋‚ด์–ด์•ผ ํ–ˆ๋Š”๋ฐ ๊ทธ ์ˆœ์„œ๋ฅผ ๋ณด์žฅํ•˜๊ธฐ ์œ„ํ•ด promise๋ฅผ ๋งŒ๋“ค์–ด ์ฒ˜๋ฆฌํ•˜๋‹ˆ ํ•ด๊ฒฐ ๋๋‹ค.

// ImojiEditor.js
 exportResultPhoto(stickerImage) {
   // ์Šคํ‹ฐ์ปค ํŽธ์ง‘ ์—†์ด ์‚ฌ์ง„ ํŽธ์ง‘๋งŒ ํ•˜๋Š” ๊ฒฝ์šฐ์—” ๊ทธ๋Œ€๋กœ ์ด๋ฏธ์ง€ ๊ฐ์ฒด๋กœ ๋งŒ๋“ค์–ด ๋ฐ˜ํ™˜ํ•œ๋‹ค.
    const canvas = this.cropper.getCroppedCanvas();
    const editedPhoto = new Image();
    editedPhoto.src = canvas.toDataURL('image/png');
    //return Image Object
    if (!stickerImage) return editedPhoto;

    //add sticker image on photo canvas
    const context = canvas.getContext('2d');

    let loadResultPhoto = new Promise(resolve => {
      stickerImage.onload = () => {
        context.drawImage(stickerImage, 0, 0);
        resolve(canvas);
      };
    });

    //return promise
    return loadResultPhoto.then(res => {
      const withStickerImage = new Image();
      withStickerImage.src = res.toDataURL('image/png');
      return withStickerImage;
    });
  }

๋ฐ˜ํ™˜๋œ promise๋Š” vue ์ปดํฌ๋„ŒํŠธ์—์„œ ์•„๋ž˜์™€ ๊ฐ™์ด ์ฒ˜๋ฆฌํ•˜๊ณ  ์žˆ๋‹ค.

// ImojiEditorCanvas.vue
    async exportResultPhoto() {
      // case 1. only Edit
      if (!this.stickerCanvas && this.photoCanvas) {
        return this.photoCanvas.exportResultPhoto();
      }
      // case 2. only Sticker
      if (!this.photoCanvas && this.stickerCanvas) {
        const width = this.photoCanvas.getNaturalSize()[0];
        return await this.photoCanvas.exportResultPhoto(
          this.stickerCanvas.saveStickerImage(width)
        );
      }
      // case 3. Edit & Sticker
      if (this.photoCanvas && this.stickerCanvas) {
        const width = this.photoCanvas.getNaturalSize()[0];
        return await this.photoCanvas.exportResultPhoto(
          this.stickerCanvas.saveStickerImage(width)
        );
      }
    },

// ImojiEditor.vue
    async done() {
      const resultImage = await this.$refs.Imoji.exportResultPhoto();
      this.$emit('done', resultImage);
    }

$refs๋ฅผ ์‚ฌ์šฉํ•œ ์ด์œ ๋Š” vue์˜ ๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ์—์„œ ์ž์‹ ์ปดํฌ๋„ŒํŠธ์˜ ๋ฉ”์†Œ๋“œ๋ฅผ ์ด์šฉํ•˜๊ธฐ ์œ„ํ•จ์ด๋‹ค. ๊ฒ€์ƒ‰ํ•ด๋ดค์„ ๋•Œ ์ด๋ฒคํŠธ ๋ฒ„์Šค๋ฅผ ์ด์šฉํ•˜๊ธฐ๋„ ํ•œ๋‹ค๋Š”๋ฐ, ๋‚ด ์งง์€ ๊ฒ€์ƒ‰ ์‹ค๋ ฅ์œผ๋กœ๋Š” ์ด๋ฒคํŠธ ๋ฒ„์Šค๋กœ ๋ฐ์ดํ„ฐ๋Š” ์ฃผ๊ณ ๋ฐ›์•„๋„ ์ž์‹ ์ปดํฌ๋„ŒํŠธ ๋ฉ”์†Œ๋“œ์˜ ์‹คํ–‰ ์ œ์–ด๋ฅผ ์ฃผ๊ณ ๋ฐ›๋Š” ์˜ˆ์ œ๋Š” ์ฐพ์•„๋ณด์ง€ ๋ชปํ–ˆ๋‹ค. ๊ทธ๋ ‡๋‹ค๊ณ  ์ปค์Šคํ…€ ์ด๋ฒคํŠธ๋ฅผ ๋งŒ๋“ค์–ด์„œ emit์„ ๋‘ ๋ฒˆ ๋„˜๊ธฐ๊ณ  ๊ทธ๋Ÿฌ๋Š๋‹ˆ, ๊ทธ๋ƒฅ $refs๋ฅผ ์ผ๋‹ค.

์–ด์จŒ๋“  ! ์ด์ œ ์ž˜ ์ €์žฅ๋œ๋‹ค ๐Ÿ˜†

itworkswell

์„œ๋กœ ๋‹ค๋ฅธ ๋‘ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ์ œ๊ณตํ•˜๋Š” ์บ”๋ฒ„์Šค ์—ฐ๋™ํ•˜๊ธฐ

์‚ฌ์ง„ ํŽธ์ง‘์„ ๋‹ด๋‹นํ•˜๋Š” ์บ”๋ฒ„์Šค ํ•˜๋‚˜, ์Šคํ‹ฐ์ปค ํŽธ์ง‘์„ ๋‹ด๋‹นํ•˜๋Š” ์บ”๋ฒ„์Šค ํ•˜๋‚˜, ์ด๋ ‡๊ฒŒ ๋‘ ์บ”๋ฒ„์Šค๋ฅผ ๋†“๊ณ  ์“ฐ๋‹ค ๋ณด๋‹ˆ๊นŒ ๋‘ ์บ”๋ฒ„์Šค์˜ ์‚ฌ์ด์ฆˆ๋ฅผ ์—ฐ๋™๋˜๊ฒŒ ํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”ํ–ˆ๋‹ค. ์ •ํ™•ํžˆ๋Š” ์Šคํ‹ฐ์ปค ์บ”๋ฒ„์Šค๊ฐ€ ์‚ฌ์ง„ ํŽธ์ง‘ ์บ”๋ฒ„์Šค๋ฅผ ๋”ฐ๋ผ๊ฐ€๊ฒŒ ํ•ด์•ผ ํ–ˆ๋‹ค. ์™œ๋ƒํ•˜๋ฉด ์Šคํ‹ฐ์ปค๋Š” ์‚ฌ์ง„ ์œ„์—์„œ๋งŒ ์›€์ง์ด๊ฒŒ ํ•˜๋Š” ๊ฒƒ์ด ์ž์—ฐ์Šค๋Ÿฌ์šฐ๋‹ˆ๊นŒ!

์ด ๊ณผ์ •์—์„œ ์‚ฌ์ง„ ํŽธ์ง‘ ์บ”๋ฒ„์Šค ์‚ฌ์ด์ฆˆ์˜ ๋ณ€ํ™”๋ฅผ ๊ฐ์ง€ํ•˜์—ฌ ์Šคํ‹ฐ์ปค ์บ”๋ฒ„์Šค์˜ ์‚ฌ์ด์ฆˆ๊ฐ€ ์ž๋™์œผ๋กœ ์žฌ์กฐ์ •๋˜๋„๋ก vue์˜ watch๋ฅผ ์‚ฌ์šฉํ• ๊นŒ๋„ ์‹ถ์—ˆ์œผ๋‚˜, ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ด์œ ๋กœ ์‚ฌ์šฉํ•˜์ง€ ์•Š์•˜๋‹ค.

  • watch๋ฅผ ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ ๋””๋ฒ„๊น… ์‹œ ํ๋ฆ„์„ ์ถ”์ ํ•˜๊ธฐ ์–ด๋ ค์›€. watch๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ๋Š”์ง€ ์ตœ๋Œ€ํ•œ ์ฐพ์•„๋ณด๊ณ , ์ • ๋ฐฉ๋ฒ•์ด ์—†์„ ๊ฒฝ์šฐ ์ตœํ›„์˜ ์ˆ˜๋‹จ์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์„ ๊ถŒ์žฅํ•จ
  • ํ•˜์ง€๋งŒ ์ปดํฌ๋„ŒํŠธ ์™ธ๋ถ€์˜ ๋™์ž‘์ด๋‚˜ ๋น„๋™๊ธฐ๋ฅผ ์ฒ˜๋ฆฌํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ์—๋Š” watch๋ฅผ ์‚ฌ์šฉํ•˜๋„๋ก ๊ถŒ์žฅํ•จ
  • ๊ทธ๋ฆฌ๊ณ  ์ž˜๋ชป ์“ฐ๋ฉด ๋ฆฌ์•กํŠธ useEffect์ฒ˜๋Ÿผ ๋ฌดํ•œ๋ฃจํ”„๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค ๐Ÿ˜… ์•„๋ž˜๋Š” ์ˆœ์‹๊ฐ„์— ์—๋Ÿฌ๊ฐ€ ๋ช‡๋ฐฑ๊ฐœ ์Œ“์—ฌ์„œ ๊นœ๋†€ํ•ด์„œ ์ฐ์–ด๋‘” ์Šค์ƒท.

watch ๋Œ€์‹  ์‚ฌ์ง„ ํŽธ์ง‘ ์บ”๋ฒ„์Šค์˜ ์‚ฌ์ด์ฆˆ๋ฅผ ์–ป๋Š” ํ•จ์ˆ˜์™€, ์Šคํ‹ฐ์ปค ์บ”๋ฒ„์Šค์˜ ์‚ฌ์ด์ฆˆ๋ฅผ ๋ฆฌ์‚ฌ์ด์ง• ํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ค์—ˆ๋‹ค. ํ•ต์‹ฌ์€ cropํ•  ๋•Œ ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ์‚ฌ์ง„ ์žฌ์—…๋กœ๋“œ, rotate ์‹œ์—๋„ ๋ณ€๊ฒฝ๋œ ์‚ฌ์ด์ฆˆ๋ฅผ ์–ป์–ด์•ผ ํ•˜๋Š” ๊ฒƒ์ด์—ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์—ญ์‹œ ๋น„๋™๊ธฐ๊ฐ€ ๋ง์ฝ์ด์˜€๋‹ค ใ…Žใ…Ž

์–ด๋–ค ์กฐ์ž‘์ด ์ด๋ฃจ์–ด์ง„ ์ด๋ฏธ์ง€๊ฐ€ ๋กœ๋“œ๋œ ํ›„์—, ๊ทธ์— ๋งž๊ฒŒ ์žฌ์กฐ์ •๋œ ์บ”๋ฒ„์Šค์˜ ์‚ฌ์ด์ฆˆ๋ฅผ ๊ฐ€์ ธ์™€์•ผ ํ–ˆ๊ณ , ๊ทธ ์‚ฌ์ด์ฆˆ๋ฅผ ๊ฐ€์ ธ์˜จ ํ›„์— data์— ์ €์žฅํ•ด์•ผ ํ–ˆ๋‹ค. ๊ทธ๋Ÿฐ๋ฐ ์ด๊ฒŒ ์ˆœ์„œ๊ฐ€ ๋ณด์žฅ์ด ๋˜์งˆ ์•Š์œผ๋‹ˆ ์ž๊พธ undefined๊ฐ€ ๋œจ๊ณ , ์Šคํ‹ฐ์ปค ์บ”๋ฒ„์Šค์˜ ์‚ฌ์ด์ฆˆ๊ฐ€ ๋ณ€ํ•˜์งˆ ์•Š๊ณ  ๊ทธ๋žฌ๋˜ ๊ฒƒ์ด๋‹ค. ์–˜๋„ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ promise, await, cropper.js์—์„œ ์ œ๊ณตํ•˜๋Š” โ€˜readyโ€™์ด๋ฒคํŠธ๋ฅผ ์ด์šฉํ•ด์„œ ํ•ด๊ฒฐํ–ˆ๋‹ค.

// ImojiEditor.js
 getPhotoCanvasSize() {
    return new Promise((resolve, reject) => {
       try {
          this.userImage.addEventListener(
             'ready',
          () => {
             const { width, height } = this.cropper.getCanvasData();
            resolve([width, height]);
          },
          { once: true }
        );
      } catch (error) {
         reject(error);
      }
    });
  }

// ImojiEditorCanvas.vue
  async setPhotoCanvasSize() {
  const [width, height] = await this.photoCanvas.getPhotoCanvasSize();

  this.$set(this.photoCanvasSize, 0, width);
  this.$set(this.photoCanvasSize, 1, height);
  this.resizeStickerCanvas();
},

๋‹ค์–‘ํ•œ ์ผ€์ด์Šค์— ๋Œ€์‘ํ•˜๊ธฐ

๋งŒ๋“ค์–ด๋‘” ๊ธฐ๋Šฅ๋“ค์„ ์—๋Ÿฌ์—†์ด ์ œ๊ณตํ•˜๊ธฐ ์œ„ํ•ด ๋‹ค์–‘ํ•œ ์ผ€์ด์Šค๋ฅผ ํ…Œ์ŠคํŠธํ•ด๋ณด์•˜๋Š”๋ฐ, ์ƒ๊ฐ๋ณด๋‹ค ๊ฒฝ์šฐ์˜ ์ˆ˜๊ฐ€ ๋งŽ์Œ์„ ์•Œ๊ฒŒ ๋˜์—ˆ๋‹ค. ๋‚˜์˜ ๋‡Œ๐Ÿง  ์šฉ๋Ÿ‰์œผ๋กœ๋Š” ๋„์ €ํžˆ ์“ฐ์ง€ ์•Š๊ณ ๋Š” ๊ธฐ์–ตํ•˜๊ธฐ ์–ด๋ ค์›Œ ํ๋ฆ„๋„๋ฅผ ๋Œ€์ถฉ์ด๋ผ๋„ ์จ์„œ ์˜ˆ์™ธ์ฒ˜๋ฆฌ ํ•  ๋ถ€๋ถ„์€ ์˜ˆ์™ธ์ฒ˜๋ฆฌ ํ•˜๊ณ  if๋ฌธ์„ ์จ์„œ ์กฐ๊ฑด ๋ถ„๊ธฐ๋ฅผ ํ•˜๊ธฐ๋„ ํ–ˆ๋‹ค.

whatIDo

์ด ๊ณผ์ •์—์„œ ์šฐ๋ฆฌ์˜ ์˜๋„์™€ ๋งž์ง€ ์•Š๊ฒŒ ํ–‰๋™ํ•˜๋Š” ์ฝ”๋“œ๋“ค์„ ๋ฐ”๋กœ์žก๋Š๋ผ ์‹œ๊ฐ„์„ ๋งŽ์ด ์ผ๋‹ค. ๊ฐœ๋ฐœ์ž์˜ ๊ท€์ฐฎ์Œ์„ ์‚ฌ์šฉ์ž์˜ ๋ถˆํŽธํ•จ์œผ๋กœ ๋– ๋„˜๊ธฐ๋ฉด ์•ˆ๋˜๋‹ค๋Š” ์–ด๋””์„œ ์ฃผ์›Œ๋“ค์€ ๋ฉ‹์ง„ ๋ง์„ ์‹ค์ฒœํ•˜๋Š๋ผ ๊ทธ๋žฌ๋‹ค. ํ•ญ์ƒ ์ฃผ์–ด์ง„ ์ผ์ •(์‹œ๊ฐ„)์•ˆ์— ์™„์„ฑ์„ ์šฐ์„ ์‹œ ํ•  ๊ฒƒ์ธ์ง€ ์™„์„ฑ๋„๋ฅผ ์šฐ์„ ์‹œ ํ•  ๊ฒƒ์ธ์ง€ ๋”œ๋ ˆ๋งˆ์— ๋น ์ง€๋Š” ๊ฒƒ ๊ฐ™๋‹ค. ๋‚œ ์–ธ์ œ์ฏค ๋‘ ๊ฐ€์ง€๋ฅผ ์™„๋ฒฝํ•˜๊ฒŒ ๋งŒ์กฑ์‹œํ‚ฌ ์ˆ˜ ์žˆ๋Š” ์‚ฌ๋žŒ์ด ๋  ์ˆ˜ ์žˆ์„๊นŒ? ๐Ÿคง

โšก npm ๋ฐฐํฌ

npm ๋ฐฐํฌ๋Š” npm ๊ณ„์ •์„ ๋งŒ๋“  ๋’ค ์šฐ๋ฆฌ ํ”„๋กœ์ ํŠธ๋ฅผ build, ํŒจํ‚ค์ง•ํ•ด์„œ ๋“ฑ๋กํ•˜๋ฉด ๋œ๋‹ค. vue์˜ ๊ฒฝ์šฐ์—๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ํ•ด์„œ ์‚ฌ์šฉ์ž๊ฐ€ ํ”Œ๋Ÿฌ๊ทธ์ธ์ฒ˜๋Ÿผ ์šฐ๋ฆฌ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ปดํฌ๋„ŒํŠธ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ–ˆ๋‹ค.

import ImojiEditor from '@/components/ImojiEditor.vue';

export default {
  install(Vue) {
    Vue.component('imoji-editor', ImojiEditor);
  },
};

//usage
import ImojiEditor from 'imoji-editor';

Vue.use(ImojiEditor);

๊ทธ๋ฆฌ๊ณ  ์šฐ๋ฆฌ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ์—…๋ฐ์ดํŠธ๋˜๋ฉด (master๋ธŒ๋žœ์น˜ ์—…๋ฐ์ดํŠธ) npm ๋ฐฐํฌ๋„ ์ž๋™์œผ๋กœ ์ง„ํ–‰๋  ์ˆ˜ ์žˆ๋„๋ก ๊นƒํ—ˆ๋ธŒ ์•ก์…˜์„ ์ด์šฉํ–ˆ๋‹ค.

name: Npm Publish
on:
  push:
    branches:
      - master
jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
      with:
        ref: master
    - uses: actions/setup-node@v2
      with:
        node-version: '14'
    - name: Install Dependencies
      run: npm install

    - name: Webpack build
      run: npm run build

    - uses: JS-DevTools/npm-publish@v1
      with:
        token: ${{ secrets.NPM_TOKEN }}

์ด๋Ÿฐ ํŒจํ‚ค์ง• ๊ณผ์ •์€ ๋ณดํ˜„๋‹˜์ด ๋„์™€์ฃผ์…จ๋Š”๋ฐ, ๋งˆ์ฃผํ–ˆ๋˜ ๋ฌธ์ œ์ ์€ ๊ธฐ๋ณธ ์Šคํ‹ฐ์ปค๋กœ ๋„ฃ์–ด๋‘” ๋ฉ”๋””์ŠคํŠธ๋ฆผ ์บ๋ฆญํ„ฐ svg๊ฐ€ ํŒจํ‚ค์ง€์— ํฌํ•จ๋˜์ง€ ์•Š๋Š”๋‹ค๋Š” ์ ์ด์—ˆ๋‹ค. ํŒจํ‚ค์ง•-๋ฐฐํฌ ๊ณผ์ •์—์„  ์›นํŒฉ๊ณผ์˜ ์‹ธ์›€์ด ๊ฐ€์žฅ ํฐ ์ง€๋ถ„์„ ์ฐจ์ง€ํ•˜๋Š” ๋Š๋‚Œ์ด์—ˆ๋‹ค.

์ด ๋ถ€๋ถ„์„ ์–ด๋–ป๊ฒŒ ํ•ด๊ฒฐํ–ˆ๋Š”์ง€ ๐Ÿ“Œ์ด์Šˆ ํƒญ์— ์ž์„ธํ•˜๊ฒŒ ๊ณต์œ ํ•ด์ฃผ์…จ๋‹ค. ๋‚˜๋Š” ๊ทธ๋™์•ˆ ๋งˆ์ฃผํ–ˆ๋˜ ์ด์Šˆ๋“ค์„ ํŠธ๋ ๋กœ์˜ ์ด์Šˆ ๋ณด๋“œ์— ๋“ฑ๋ก๋งŒ ํ•ด๋‘๊ณ  ์ž์„ธํ•œ ๋‚ด์šฉ์€ ๋งค์ผ ๊ฐ€์กŒ๋˜ ์Šคํฌ๋Ÿผ ๋ฏธํŒ…์ด๋‚˜ ์ฃผ๊ฐ„ ํšŒ์˜, ๋˜๋Š” ์˜† ์ž๋ฆฌ์˜ ์ค€ํ˜„๋‹˜๊ณผ ๋ง๋กœ๋งŒ ์ฃผ๊ณ  ๋ฐ›์œผ๋ฉฐ ํ•ด๊ฒฐํ–ˆ์—ˆ๋Š”๋ฐโ€ฆ ์ €๋ ‡๊ฒŒ ์ด์Šˆํƒญ์— ๋ฌธ์„œํ™”๋ฅผ ํ•ด๋‘๋Š” ๊ฒƒ์„ ๋˜ ํ•œ ๋ฒˆ ๋ฐฐ์›Œ๊ฐ”๋‹ค ๐Ÿ‘๐Ÿป๐Ÿ˜‡

โœ README ์ž‘์„ฑ

vue๋กœ ui ๋žฉํ•‘์„ ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— vue์—์„œ๋Š” ๊ทธ๋ƒฅ ์„ค์น˜ํ•ด์„œ ํ”Œ๋Ÿฌ๊ทธ์ธ์ฒ˜๋Ÿผ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋˜๋‹ˆ๊นŒ ์–ด๋–ค ์˜ต์…˜๋“ค์„ ์ปดํฌ๋„ŒํŠธ์— prop์œผ๋กœ ๋„˜๊ฒจ์ค„ ์ˆ˜ ์žˆ๋Š”์ง€๋ฅผ ๋ฌธ์„œ์— ๋‚จ๊ฒผ๋‹ค. ์–ด๋–ค ๊ธฐ๋Šฅ๋“ค์„ ์ง€์›ํ•˜๋Š”์ง€๋„ ๋ฌธ์„œ๋กœ ๋‚จ๊ฒผ๋‹ค.

ํ—ท๊ฐˆ๋ ธ๋˜ ๋ถ€๋ถ„์€ ๋ชจ๋“ˆ์— ๋Œ€ํ•œ ๊ฒƒ๋„ ๋ฌธ์„œํ™”๋ฅผ ํ•˜๋Š” ๊ฒƒ์ธ์ง€ ์•„๋‹Œ์ง€์˜€๋‹ค. ๋ชจ๋“ˆ ์ž์ฒด๋Š” ๋ฆฌ์•กํŠธ๋‚˜ ์•ต๊ทค๋Ÿฌ ๊ฐœ๋ฐœ์ž๋„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ๋” core javascript๋กœ ๊ฐœ๋ฐœํ–ˆ๋Š”๋ฐ ์ด ๋ถ€๋ถ„๋„ ๋ฆฌ๋“œ๋ฏธ์— ๋‚จ๊ธฐ๋Š” ๊ฑด๊ฐ€? ํ•˜๊ณ  ๋ง‰ ์“ฐ๋‹ค๊ฐ€, ํšŒ์˜ ๋•Œ ์—ฌ์ญค๋ณด๋‹ˆ๊นŒ ๋ฌผ๋ก  ๊ทธ๋ ‡๊ฒŒ ๊ฐœ๋ฐœ์ž๋ฅผ ์œ„ํ•œ ๋ฌธ์„œ๋ฅผ ๋‚จ๊ธฐ๊ธฐ๋„ ํ•˜์ง€๋งŒ ๋Œ€๋ถ€๋ถ„์€ ์ฝ”๋“œ์˜ ์ฃผ์„์„ ๋ณด๊ณ ๋„ ์•Œ ์ˆ˜ ์žˆ๊ฒŒ ํ•˜๋Š” ๊ฒƒ์ด ๋ฒ ์ŠคํŠธ์ด๊ณ  ๋‹น์žฅ ๊ธ‰ํ•œ ์šฐ์„ ์ˆœ์œ„๋Š” ์•„๋‹ˆ๋ผ ํ•ด์„œ ๋ณด๋ฅ˜ํ•˜๊ธฐ๋กœ ํ–ˆ๋‹ค. ๋ชจ๋“ˆ์—์„œ ์ฃผ์„์€ ๋‹ฌ์•„๋‘๊ธด ํ–ˆ์ง€๋งŒ ์‚ฌ์šฉ ์˜ˆ์ œ๊นŒ์ง€ ๋”ฐ๋กœ ์‹œ๊ฐ„๋˜๋ฉด ์ •๋ฆฌํ•˜๊ณ  ์‹ถ๋‹ค.

๊นƒํ—ˆ๋ธŒ์˜ README์™€ Vuepress ๋‘ ๊ฐ€์ง€๋กœ ์ž‘์„ฑํ–ˆ๋Š”๋ฐ, ๊นƒํ—ˆ๋ธŒ์˜ README๋Š” npm์˜ readme๋กœ ํ•จ๊ป˜ ์˜ฌ๋ผ๊ฐ€๊ณ  vuepress๋Š” ๋”ฐ๋กœ ํด๋” ๊ตฌ์„ฑ์„ ํ•ด์„œ(docs) ์ž‘์„ฑํ–ˆ๋‹ค. ๊นƒํ—ˆ๋ธŒ ํŽ˜์ด์ง€์™€ ์—ฐ๊ฒฐ๋œ๋‹ค. ๊ธฐ์กด ๊นƒํ—ˆ๋ธŒ ๋ฆฌ๋“œ๋ฏธ์™€์˜ ์ฐจ์ด์ ์€ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ง์ ‘ ๋ถˆ๋Ÿฌ์™€์„œ playground๋ฅผ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์ธ๋ฐ, ์•„์ง ํ•˜์ง€๋Š” ๋ชปํ–ˆ๊ณ  ๋‚˜์˜ ํˆฌ๋‘๋ฆฌ์ŠคํŠธ์— ๋‹ด๊ฒจ์žˆ๋‹ค. ์•„๋งˆ๋„ ๊ณงโ€ฆ๐Ÿ˜… playground ๋Œ€์‹  ์šฐ์„ ์€ gif๋กœ ์–ด๋–ค ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ธ์ง€๋ฅผ ๋ณด์—ฌ์ค„ ์ˆ˜ ์žˆ๊ฒŒ ํ•ด๋‘์—ˆ๋‹ค.

๐Ÿค๐Ÿป ์ง€์†์ ์ธ ํŒ”๋กœ์—…

์šฐ๋ฆฌ๊ฐ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ๋ฆฌ์„œ์น˜ํ•˜๋ฉด์„œ ์„ธ์› ๋˜ ๊ธฐ์ค€ ์ค‘ ํ•˜๋‚˜๊ฐ€ ์ง€์†์ ์œผ๋กœ ์—…๋ฐ์ดํŠธ ๋˜๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ธ์ง€, ์•„๋‹Œ์ง€์˜€๋‹ค. ์‚ฌ์‹ค ํ•œ ๋‹ฌ๊ฐ„์˜ ํ”„๋กœ์ ํŠธ ๋์— ์ดˆ๊ธฐ๋ฒ„์ „์„ ๋ฐฐํฌํ•˜๊ธด ํ–ˆ์ง€๋งŒ, ์ข€ ๋” ์ˆ˜์ •ํ•˜๊ณ  ๋ณด์™„ํ•ด์•ผํ•˜๋Š” ๋ถ€๋ถ„์ด ๋งŽ๋‹ค. ๋‹น์žฅ ํ•ด๊ฒฐํ•ด์•ผ ํ•˜๋Š” ์—๋Ÿฌ๋„ ์ด์Šˆํƒญ์— ๋‹ฌ์•„๋‘์—ˆ๊ณ โ€ฆ ํฐ ์ด๋ฏธ์ง€์ผ์ˆ˜๋ก, ํ˜•์‹์ด png๊ฐ€ ์•„๋‹์ˆ˜๋ก ์ž‘์—…์ด ์ง€์—ฐ๋˜๋Š” ํ˜„์ƒ์ด ์žˆ๋Š”๋ฐ ๊ทธ ๋ถ€๋ถ„๋„ ์˜์‹ฌ๋˜๋Š” ๋ถ€๋ถ„์ด ์žˆ์–ด์„œ ํ•ด๊ฒฐํ•˜๊ณ  ๋กœ๋”ฉ์ค‘ ui๋„ ๋ณด์—ฌ์ฃผ์–ด์•ผ ํ•œ๋‹ค.

์ง€์†์ ์ธ ํŒ”๋กœ์—…์„ ์œ„ํ•ด ๊ฐ€์žฅ ์ค‘์š”ํ•œ ์ฝ”๋“œ์˜ ๊ฐ€๋…์„ฑ๋„ ๋” ๊ณ ๋ฏผํ•˜๊ณ  ์ˆ˜์ •ํ•ด์•ผํ•  ๋ถ€๋ถ„์ด ๋งŽ๋‹ค. ๊ฐ€๋…์„ฑ์„ ์œ„ํ•ด ๊ตฌ์กฐ๋ถ„ํ•ดํ• ๋‹น์„ ์‹œ๋„ํ–ˆ์—ˆ์œผ๋‚˜ ์ ์šฉ์— ์‹คํŒจํ–ˆ๋‹ค.

vue์—์„œ์˜ ํ•ต์‹ฌ์€ this์˜€๋Š”๋ฐ, ์ด this๊ฐ€ ๋„ˆ๋ฌด ๋งŽ์ด ๋ณด์ด๋Š” ๊ฒƒ์ด ์ง€์ €๋ถ„ํ•ด ๋ณด์—ฌ์„œ ๊ตฌ์กฐ๋ถ„ํ•ด๋ฅผ ์“ฐ๊ณ  ์‹ถ์—ˆ๋‹ค. ๋‚˜๋งŒ ์ด๋Ÿฐ ์ƒ๊ฐ์„ ํ•˜๋Š” ๊ฑด๊ฐ€? this๋ฅผ ๊ตฌ์กฐ๋ถ„ํ•ดํ•˜๋Š” ๊ฑด ๋ทฐ์Šค๋Ÿฝ์ง€ ์•Š์€ ์ผ์ธ๊ฐ€? ์‹ถ์–ด์„œ ๊ฒ€์ƒ‰ํ•ด๋ณด๋‹ˆ ๋‹คํ–‰ํžˆ ๋‚˜๋ž‘ ๋˜‘๊ฐ™์€ ์ƒ๊ฐ์„ ํ•˜๋Š” ์‚ฌ๋žŒ๋“ค์ด ์žˆ์—ˆ๋‹ค.

๐Ÿ‘‰๐Ÿป ๋งํฌ

๊ทธ๋Ÿฐ๋ฐ ๋ง‰์ƒ ์จ๋ณด๋‹ˆ๊นŒ, reactive data๊ฐ’์„ ์—…๋ฐ์ดํŠธ ํ•  ๋•Œ์—๋Š” ๊ตฌ์กฐ๋ถ„ํ•ด๋ฅผ ์“ธ ์ˆ˜๊ฐ€ ์—†์—ˆ๋‹ค.

์™œ๋ƒ๋ฉด constant๊ฐ€ ๋˜์–ด๋ฒ„๋ฆฌ๊ธฐ ๋•Œ๋ฌธ์ด๋‹คโ€ฆ ๋ทฐ๋Š” ๋ฆฌ์•กํŠธ์ฒ˜๋Ÿผ state๊ฐ’์„ ์—…๋ฐ์ดํŠธํ•  ๋•Œ ์“ฐ๋Š” setState๊ฐ™์€ ๊ฒŒ ์—†๊ณ  ๊ทธ๋ƒฅ this.something = 'update' ์ด๋Ÿฐ์‹์œผ๋กœ ์“ฐ๊ธฐ ๋•Œ๋ฌธ์— ๋ฐœ์ƒํ•œ ์ผ์ด์—ˆ๋‹ค.

๊ทธ๋ž˜์„œ ๋‚˜๋Š” ์„ ํƒ์„ ํ•ด์•ผ ํ–ˆ๋‹ค. ์—…๋ฐ์ดํŠธ๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ๋ถ€๋ถ„๋งŒ ๊ตฌ์กฐ๋ถ„ํ•ด๋ฅผ ์“ฐ์ง€ ์•Š๊ณ  ๋‹ค๋ฅธ ๊ฒƒ๋“ค์€ ๊ตฌ์กฐ๋ถ„ํ•ด๋ฅผ ์“ธ์ง€, ์•„๋‹ˆ๋ฉด ์•„์˜ˆ ์ „์ฒด์ ์œผ๋กœ ๊ตฌ์กฐ๋ถ„ํ•ด๋ฅผ ์“ฐ์ง€ ์•Š์„์ง€. ์•„๋ฌด๋ฆฌ ์ƒ๊ฐํ•ด๋ด๋„ ์ผ๋ถ€๋ถ„๋งŒ ๊ตฌ์กฐ๋ถ„ํ•ด๋ฅผ ์“ฐ๋Š” ๊ฑด ์ด์ƒํ•œ ๊ฒƒ ๊ฐ™์•˜๋‹ค. ์•ˆ ์“ธ๊ฑฐ๋ฉด ์ „์ฒด ๋‹ค ์•ˆ ์“ฐ๋Š”๊ฒŒ ํ†ต์ผ๊ฐ ์žˆ๊ณ  ์ฝ”๋“œ๋ฅผ ์ฝ๋Š” ์‚ฌ๋žŒ์ด ์˜ˆ์ธก๊ฐ€๋Šฅํ•ด์„œ ์ข‹์€ ๊ฒƒ ๊ฐ™์•˜๋‹ค. ๊ทธ๋ž˜์„œ ์•ˆ ์“ฐ๊ธฐ๋กœ ๊ฒฐ์ •ํ•จ. ์ด๊ฒƒ ๋•Œ๋ฌธ์— vue ์ฝ”๋“œ๋“ค์—์„œ this๋ฅผ ๊ตฌ์กฐ๋ถ„ํ•ดํ•˜๋Š” ๊ฒฝ์šฐ๋ฅผ ์ฐพ๊ธฐ ์–ด๋ ค์› ๋˜ ๊ฑฐ์˜€๋‚˜๋ณด๋‹ค ์‹ถ์—ˆ๋‹ค. ๋‹ค๋ฅธ ๋ฐฉ๋ฒ•์„ ์•„์ง ๋ชป ์ฐพ์€ ์ƒํ™ฉ์ธ๋ฐ ๋” ์ฐพ์•„๋ด์•ผ์ง€.

๋ถ€์กฑํ•จ์ด ๋งŽ์€ ์™„์„ฑ์ด๋ผ๊ณ  ์ƒ๊ฐํ•œ๋‹ค. ์—ฌ๊ธฐ์„œ ๋์ธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ์•„๋‹ˆ๋ผ ์ง€์†์ ์œผ๋กœ ์ˆ˜์ • ๋ณด์™„ํ•˜์—ฌ ๋” ์•ˆ์ •์ ์ธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์œ„ํ•ด ํŒ”๋กœ์—…ํ•˜๊ฒ ๋‹ค ๐Ÿฆพ๐Ÿ’ช

๐Ÿ‘ฉ๐Ÿปโ€๐ŸŽ“ ๋ฐฐ์šด์ 

์œ„์—์„œ ์–ธ๊ธ‰ํ•˜์ง€ ์•Š์€ ๋ถ€๋ถ„๋“ค ๋ช‡ ๊ฐ€์ง€๋งŒ ๊ผฝ์•„๋ณด๊ฒ ๋‹ค.

์„ค๊ณ„์ ์ธ ๊ด€์ ์„ ๊ฐ€์ง€๋Š” ๊ฐœ๋ฐœ์ž๊ฐ€ ๋˜๊ธฐ

ํŒ€์žฅ๋‹˜ ๋ง์”€ ์ค‘์— ๊ฐ€์žฅ ์ธ์ƒ๊นŠ์—ˆ๋˜ ๋ถ€๋ถ„์ด๋‹ค.
๊ธฐ๋Šฅ ๊ตฌํ˜„์€ ๋ˆ„๊ตฌ๋‚˜ ํ•  ์ˆ˜ ์žˆ๋‹ค. ์ค‘์š”ํ•œ ๊ฒƒ์€ ์„ค๊ณ„์ ์ธ ๊ด€์ ์„ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๋ƒ, ์•„๋‹ˆ๋ƒ์ด๋‹ค.

๊ธฐ๋Šฅ ๊ตฌํ˜„์—๋งŒ ๊ธ‰๊ธ‰ํ•œ ์‚ฌ๋žŒ์ด ์•„๋‹ˆ๋ผ ๋„“์€ ์‹œ์•ผ๋ฅผ ๊ฐ€์ง€๊ณ  ๋ฏธ๋ž˜๊นŒ์ง€ ์ƒ๊ฐํ•˜์—ฌ ์„ค๊ณ„ํ•˜๋Š” ๊ฐœ๋ฐœ์ž๊ฐ€ ๋˜์–ด์•ผ ํ•œ๋‹ค๋Š” ๊ฒƒ์„ ๋Š๊ผˆ๋‹ค. ๋‹จ์ˆœํžˆ ์™ธ์ฃผ ๊ฐœ๋ฐœ์„ ํ•˜๊ณ  ๋~! ํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ, ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ๊ฒฝ์šฐ์—๋Š” ์ง€์†์ ์ธ ์—…๋ฐ์ดํŠธ๊ฐ€ ์ด๋ฃจ์–ด์ ธ์•ผ ํ•˜๊ณ  ์ž์ฒด์„œ๋น„์Šค๋ฅผ ๊ฐœ๋ฐœํ•˜๋Š” ๊ฒฝ์šฐ์—๋„ ์œ ์ง€-๋ณด์ˆ˜-์—…๋ฐ์ดํŠธ๊ฐ€ ์ง€์†์ ์œผ๋กœ ์ด๋ฃจ์–ด์ ธ์•ผ ํ•œ๋‹ค. ์ด๋ ‡๊ฒŒ ๋ฒ„์ „์—…์„ ํ•  ๋•Œ๋ฅผ ๋Œ€๋น„ํ•ด์„œ ์ดˆ๊ธฐ๋‹จ๊ณ„์—์„œ๋ถ€ํ„ฐ ๋ฏธ๋ž˜๋ฅผ ์ œํ•œํ•  ์ˆ˜๋„ ์žˆ๋Š” ๋„ค์ด๋ฐ์„ ์ง€์–‘ํ•˜๊ณ , deprecated๋  ์šฐ๋ ค๊ฐ€ ์žˆ๋Š” ์ฝ”๋“œ๋‚˜ ๊ตฌ์กฐ์ธ์ง€ ํ•ญ์ƒ ์ƒ๊ฐํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•จ์„ ๋ฐฐ์› ๋‹ค. ๊ฐ„๋‹จํ•œ ๊ธฐ๋Šฅ์ด๋ผ๋„ ์ด๋Ÿฐ ๊ฒƒ์„ ํ•ญ์ƒ ์ƒ๊ฐํ•˜๋Š” ๊ฐœ๋ฐœ์ž๊ฐ€ ๋˜์–ด์•ผ ํ•œ๋‹ค.

๋ฏธ๋ž˜์— ์ผ์–ด๋‚  ์ผ์€ ์•„๋ฌด๋„ ์˜ˆ์ธกํ•  ์ˆ˜ ์—†๋‹ค. ๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— ๋‹น์žฅ์˜ ๋‹จ๊ณ„์—์„œ ์ด๊ฒŒ deprecated๋  ์ฝ”๋“œ์ธ์ง€ ์•„๋‹Œ์ง€๋„ ์ •ํ™•ํžˆ ์˜ˆ์ƒํ•  ์ˆ˜ ์—†์ง€๋งŒ, ๊ทธ๋ž˜์„œ ์–ด๋ ต์ง€๋งŒ, ๊ทธ๋Ÿผ์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ  ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์— ๊ธฐ์—ฌํ•  ๋ˆ„๊ตฐ๊ฐ€์™€ ๋ฏธ๋ž˜์— ์œ ์ง€-๋ณด์ˆ˜-ํ™•์žฅํ•  ๋‚˜๋ฅผ ์œ„ํ•ด ์ง€๊ธˆ ๋ฏธ๋ฆฌ๋ฏธ๋ฆฌ ์ƒ๊ฐ์„ ๋งŽ์ด ํ•˜๊ณ  ์ฝ”๋“œ๋ฅผ ์งœ์•ผํ•จ์„ ๋‹ค์‹œ ํ•œ ๋ฒˆ ๊นจ๋‹ซ๋Š”๋‹ค.

์‚ฌ์šฉ์ž flow๋ฅผ ์ƒ๊ฐํ•ด์•ผ ํ•จ์€ ์—ฌ๋Ÿฌ ๋ฒˆ ๊ฐ•์กฐํ•ด๋„ ์ง€๋‚˜์น˜์ง€ ์•Š๋‹ค

ํŠนํžˆ ํ”„๋ก ํŠธ์—”๋“œ ๊ฐœ๋ฐœ์„ ๊ณต๋ถ€ํ•œ๋‹ค๋ฉด ์ง€๊ฒน๋„๋ก ๋“ค์—ˆ์„ ๋ง์ด๋ผ๊ณ  ์ƒ๊ฐํ•œ๋‹ค. ์•„๋ฌด๋ฆฌ ๋ฉ‹์ง€๊ณ  ์ข‹์€ ๊ธฐ์ˆ ์ด๋ผ๋„ ์‚ฌ์šฉ์ž๊ฐ€ ์•ˆ ์“ฐ๋ฉด ์•ˆ ์“ฐ๋Š”๊ฑฐ๋‹ค. ๋ถˆํŽธํ•ด์„œ ์†์ด ์•ˆ ๊ฐ€๋ฉด ๊ทธ ํ”„๋กœ์ ํŠธ๋Š” ๊ทธ๋ƒฅ ์ฝ”๋”ฉ ์ง€์‹ ์ž๋ž‘๋ฐ–์— ๋˜์ง€ ์•Š๋Š”๋‹ค. ์‚ฌ์‹ค ์ฒ˜์Œ ๋“ค์—ˆ์„ ๋•Œ ๋ฌด์Šจ ๋ง์ธ์ง€๋Š” ์•Œ๊ฒ ๋Š”๋ฐ, ๋จธ๋ฆฌ๋กœ๋Š” ์ดํ•ด๋Š” ๋˜๋Š”๋ฐ ์˜จ ๋ชธ์œผ๋กœ ์ฒด๊ฐ์€ ์ž˜ ์•ˆ๋์—ˆ๋‹ค. ๊ทธ๋Ÿฐ๋ฐ ์ด๋ฒˆ์— imoji editor ํ”„๋กœ์ ํŠธ๋ฅผ ์ง„ํ–‰ํ•˜๋ฉด์„œ ํ•ญ์ƒ ๋ชจ๋“  ํšŒ์˜์—์„œ 1์ˆœ์œ„๋กœ ์ƒ๊ฐํ•œ ๊ฒƒ์ด ์ด๊ฑฐ์˜€๋‹ค๋ณด๋‹ˆ๊นŒ ์ด์ œ๋Š” ์™€๋‹ฟ๋Š”๋‹ค. ์—ญ์‹œ ๋ญ๋“ ์ง€ ์ง์ ‘ ๊ฒช์–ด๋ด์•ผโ€ฆ

์†”์งํžˆ UX ๋””์ž์ด๋„ˆ๋‚˜ PM์ด ํ•˜๋“ฏ์ด ์‚ฌ์šฉํ๋ฆ„์— ๋Œ€ํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ถ„์„ํ•˜๊ณ  ๊ทธ๋กœ๋ถ€ํ„ฐ ๊ฒฐ๊ณผ๋ฅผ ๋„์ถœํ•ด๋‚ด์„œ ๊ทผ๊ฑฐ๋กœ ์“ฐ๋Š” ๊ทธ ์ •๋„๋ฅผ ํ•  ์ค„ ์•„๋Š” ๊ฒƒ์€ ์•„๋‹ˆ์ง€๋งŒ, โ€˜๋‚˜๋ผ๋ฉด ์ด๋ ‡์ง€ ์•Š์„๊นŒ?โ€™ ๋ถ€ํ„ฐ ์‹œ์ž‘ํ•ด์„œ โ€˜์ด๋Ÿฐ ์‚ฌ๋žŒ๋„ ์žˆ์„ ์ˆ˜ ์žˆ์ง€ ์•Š์„๊นŒ?โ€™ ํ•˜๊ณ  ๋„“๊ณ  ๋‹ค์–‘ํ•˜๊ฒŒ ์ƒ๊ฐํ•ด๋ณด๋Š” ์—ฐ์Šต์„ ํ•  ์ˆ˜ ์žˆ์—ˆ๋˜ ๊ฒƒ ๊ฐ™๋‹ค.

๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ๋•Œ์—๋Š” ์ƒ๊ฐ์— ๊ฐ‡ํžˆ๋Š” ๊ฒƒ์„ ๊ฒฝ๊ณ„ํ•˜์ž

์ด์Šˆ๋ณด๋“œ์˜ ์ด์Šˆ๋“ค์„ ํ•ด๊ฒฐํ•˜๋Š” ๊ณผ์ •์—์„œ ํŒ€์˜ ๋„์›€์„ ๋ฐ›๊ธฐ๋„ ํ–ˆ๋‹ค. ์–ด๋–ค ๋ฌธ์ œ๊ฐ€ ์žˆ๋Š”๋ฐ ์‹œ๋„ํ•œ ๊ฒƒ์€ ์ด๊ฑฐ์˜€์ง€๋งŒ ์ด๋ž˜์„œ ์•ˆ๋๋‹คโ€ฆ๋กœ ์‹œ์ž‘ํ•˜๋ฉด ๋ชจ๋‘ ํ•จ๊ป˜ ๊ณ ๋ฏผํ•ด์ฃผ์…จ๋‹ค. ๊ทธ ๊ณผ์ •์—์„œ๋„ ๋˜ ํ•˜๋‚˜ ๋ฐฐ์› ๋˜ ๊ฒƒ์€ ํŠน์ • ์‚ฌ๊ณ ๋‚˜ ์ƒ๊ฐ์— ๊ฐ‡ํžˆ๋Š” ๊ฒƒ์„ ๊ฒฝ๊ณ„ํ•ด์•ผ ํ•œ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค. โ€˜๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ๋ฐฉ๋ฒ•์ด a๊ฐ™์€๋ฐโ€ฆโ€™ ์‹ถ์€ ์ƒ๊ฐ์ด ๋“ค๋ฉด ์ž๊พธ ๊ทธ a๋กœ ๋‹ต์„ ์ •ํ•ด๋‘๊ณ  ์ƒ๊ฐํ•˜๊ณ  ๋ฆฌ์„œ์น˜ํ•˜๊ฒŒ ๋œ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค. ๊ทธ๋Ÿผ ์‚ฌ์‹ค b๋ผ๋Š” ์•„์ฃผ ๊ฐ„๋‹จํ•œ ํ•ด๊ฒฐ์ฑ…์ด ์žˆ์Œ์—๋„ ๊ทธ๊ฑธ ๋ณด์ง€ ๋ชปํ•˜๊ฒŒ ๋œ๋‹ค. ์ด๋Ÿฐ ๋ถ€๋ถ„๋“ค์„ ๊ฒฝ๊ณ„ํ•˜๋ฉฐ ์ข€ ๋–จ์–ด์ ธ์„œ ๊ตฌ์กฐ์ ์ธ ๊ด€์ ์—์„œ๋„ ๋ณด๋Š” ๋“ฑ, ์ง€์—ฝ์ ์ธ ์‚ฌ๊ณ ๋ฅผ ํ”ผํ•ด์•ผ ํ•œ๋‹ค.

๋งˆ๋ฌด๋ฆฌํ•˜๋ฉฐ

์ด ๊ธด ๊ธ€์„ ๋๊นŒ์ง€ ์ฝ์œผ์‹  ์ธ๋‚ด์‹ฌ ๋งŽ์€ ๋‹น์‹ ์—๊ฒŒ ๊ณ ๋ง™๋‹ค๋Š” ๋ง์„ ์ „ํ•ฉ๋‹ˆ๋‹ค. ์–ด์ผ€ ํ–ˆ๋ˆ„