๐Ÿ’ป ๋“œ๋ž˜๊ทธ ์•ค ๋“œ๋กญ

waterglassesยท2022๋…„ 4์›” 29์ผ
0

TIL

๋ชฉ๋ก ๋ณด๊ธฐ
20/50
post-thumbnail

์ด๋ฒˆ ์ฑ•ํ„ฐ๋Š” ๋“œ๋ž˜๊ทธ ์•ค ๋“œ๋กญ API์— ๋Œ€ํ•ด ๋‹ค๋ฃจ์—ˆ์Šต๋‹ˆ๋‹ค.
โš ๏ธ ์ •๋ฆฌํ•œ ๋‚ด์šฉ์€ ์˜คํƒ€๋‚˜ ์ž˜๋ชป๋œ ์ •๋ณด๊ฐ€ ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋Œ“๊ธ€๋กœ ์•Œ๋ ค์ฃผ์‹œ๋ฉด ๊ฐ์‚ฌํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

๐Ÿ“ƒ ์˜ค๋Š˜ ๊ณต๋ถ€ํ•œ ๊ฒƒ

Drag & Drop ์ด๋ฒคํŠธ

HTML ๋“œ๋ž˜๊ทธ ์•ค ๋“œ๋กญ ์ธํ„ฐํŽ˜์ด์Šค๋Š” ๋‹ค๋ฅธ ๋ธŒ๋ผ์šฐ์ €์—์„œ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ๋“œ๋ž˜๊ทธ ์•ค ๋“œ๋กญ ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜๊ฒŒ ํ•ด์ค๋‹ˆ๋‹ค. ์ด ๊ธฐ๋Šฅ์„ ์ด์šฉํ•ด ์‚ฌ์šฉ์ž๋Š” draggable ์š”์†Œ๋ฅผ ๋“œ๋ž˜๊ทธํ•˜๊ณ , ๋งˆ์šฐ์Šค ๋ฒ„ํŠผ์—์„œ ์†์„ ๋—Œ์œผ๋กœ์จ ์š”์†Œ๋ฅผ ๋“œ๋กญํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋“œ๋ž˜๊ทธํ•˜๋Š” ๋™์•ˆ draggable ์š”์†Œ๋Š” ๋ฐ˜ํˆฌ๋ช…ํ•œ ์ฑ„๋กœ ๋งˆ์šฐ์Šค ํฌ์ธํ„ฐ๋ฅผ ๋”ฐ๋ผ๋‹ค๋‹™๋‹ˆ๋‹ค.

๋“œ๋ž˜๊ทธ ์ด๋ฒคํŠธ

HTML ๋“œ๋ž˜๊ทธ ์•ค ๋“œ๋กญ์€ DOM ์ด๋ฒคํŠธ ๋ชจ๋ธ๊ณผ ๋“œ๋ž˜๊ทธ ์ด๋ฒคํŠธ๋ฅผ ๋งˆ์šฐ์Šค ์ด๋ฒคํŠธ๋กœ๋ถ€ํ„ฐ ์ƒ์†๋ฐ›์Šต๋‹ˆ๋‹ค.

drag

  • ์š”์†Œ๋‚˜ ํ…์ŠคํŠธ ๋ธ”๋ก์„ ๋“œ๋ž˜๊ทธ ํ•  ๋•Œ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

dragend

  • ๋“œ๋ž˜๊ทธ๊ฐ€ ๋๋ƒˆ์„ ๋•Œ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

dragleave

  • ๋“œ๋ž˜๊ทธ ํ•˜๋Š” ์š”์†Œ๋‚˜ ํ…์ŠคํŠธ ๋ธ”๋ก์ด ์ ํ•ฉํ•œ ๋“œ๋กญ ๋Œ€์ƒ์—์„œ ๋ฒ—์–ด๋‚ฌ์„ ๋Œ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

dragover

  • ์š”์†Œ๋‚˜ ํ…์ŠคํŠธ ๋ธ”๋ก์„ ์ ํ•ฉํ•œ ๋“œ๋กญ ๋Œ€์ƒ ์œ„๋กœ ์ง€๋‚˜๊ฐˆ ๋•Œ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

dragstart

  • ์‚ฌ์šฉ์ž๊ฐ€ ์š”์†Œ๋‚˜ ํ…์ŠคํŠธ ๋ธ”๋ก์„ ๋“œ๋ž˜๊ทธํ•˜๊ธฐ ์‹œ์ž‘ํ–ˆ์„ ๋•Œ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

drop

  • ์š”์†Œ๋‚˜ ํ…์ŠคํŠธ ๋ธ”๋ก์„ ์ ํ•ฉํ•œ ๋“œ๋กญ ๋Œ€์ƒ์— ๋“œ๋กญํ–ˆ์„ ๋•Œ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

ํˆฌ๋‘๋ฆฌ์ŠคํŠธ๋ฅผ ๋“œ๋ž˜๊ทธ ์•ค ๋“œ๋กญ์œผ๋กœ ์™„๋ฃŒํ•œ TODO๋กœ ์˜ฎ๊ธฐ๊ธฐ

ํˆฌ๋“œ๋ฆฌ์ŠคํŠธ ์˜ˆ์‹œ

  1. li ์š”์†Œ๋ฅผ droppable๋กœ ๋งŒ๋“ค์–ด ์ค๋‹ˆ๋‹ค.
// TodoList.js
<ul>
  ${todosmap(({ _id, content }) =>`
    <li data-id="${_id}" draggable="true">${content}
      <button>x</button>
    </li>`).join('')}
</ul>
  1. dragstart๋กœ ๋“œ๋ž˜๊ทธ ํ•˜๊ธฐ ์‹œ์ž‘ํ•˜๋ฉด ๋ฐ์ดํ„ฐ ์ „๋‹ฌ ๊ฐ์ฒด์— ๋Œ€์ƒ ์š”์†Œ์˜ id๋ฅผ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.
$todoList.addEventListener('dragstart', (e) => {
    const $li = e.target.closest('li');

    e.dataTransfer.setData('todoId', $li.dataset.id);
  });
  1. dropover ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒ๋˜์—ˆ์„ ๋•Œ ํ˜„์žฌ๋กœ .
 $todoList.addEventListener('dragover', (e) => {
    e.preventDefault(); // ์ถ”๊ฐ€์ ์ธ ์ด๋ฒคํŠธ๊ฐ€ ์ผ์–ด๋‚˜์ง€ ์•Š๋„๋ก ํ•จ
    e.dataTransfer.dropEffect = 'move'; // ํ˜„์žฌ ์„ ํƒ๋œ ๋Œ์–ด์„œ ๋†“๊ธฐ ์ž‘์—…์˜ ์œ ํ˜•์„ move(๋ฐ์ดํ„ฐ๊ฐ€ ์ด๋™ํ•  ๊ฒƒ์ž„์„ ์•”์‹œ)๋กœ ์„ค์ •
  });
  1. drop ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒ๋˜๋ฉด ๋Œ€์ƒ์˜ id๋ฅผ ๊ฐ€์ ธ์™€์„œ ๋น„๊ต ํ•œํ›„ onDrop ์ด๋ฒคํŠธ๋กœ App์— id๋ฅผ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.
$todoList.addEventListener('drop', (e) => {
    e.preventDefault();
    const droppedTodoId = e.dataTransfer.getData('todoId');

    // ํ˜„์žฌ TodoList์˜ Todo๊ฐ€ ์•„๋‹Œ ๊ฒฝ์šฐ ์ƒ์œ„ ์ปดํฌ๋„ŒํŠธ์— ์•Œ๋ฆผ
    const { todos } = this.state;
    if (!todos.find((todo) => todo._id === droppedTodoId)) {
      onDrop(droppedTodoId);
    }
  });
  1. onDrop์œผ๋กœ ๊ฐ€์ ธ์˜จ id๋กœ state๋ฅผ ๋ณ€๊ฒฝ์‹œํ‚ต๋‹ˆ๋‹ค.
const inCompletedTodoList = new TodoList({
  onDrop: (todoId) => handleTodoDrop(todoId, false),
  onRemove: handleTodoRemove,
});

const completedTodoList = new TodoList({
  onDrop: (todoId) => handleTodoDrop(todoId, true),
  onRemove: handleTodoRemove,
});

์œ„์™€ ๊ฐ™์€ ์ˆœ์„œ๋กœ droppable ์ด๋ฒคํŠธ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํˆฌ๋‘๋ฆฌ์ŠคํŠธ์—์„œ ๋ฏธ์™„๋ฃŒ -> ์™„๋ฃŒ ํ˜น์€ ์™„๋ฃŒ -> ๋ฏธ์™„๋ฃŒ๋กœ ์ž์œ ๋กญ๊ฒŒ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๐Ÿ˜ฐ ์–ด๋ ค์› ๋˜ ๋‚ด์šฉ

๋“œ๋ž˜๊ทธ ์•ค ๋“œ๋กญ์ด ๋‚ฏ์„ค๋‹ค ๋ณด๋‹ˆ e.preventDefault()๋ผ๋˜์ง€ e.dataTransfer.getData('todoId'); ๋“ฑ์„ ์–ธ์ œ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋Š”์ง€ ์–ด๋–ป๊ฒŒ ์‚ฌ์šฉํ• ์ง€๊ฐ€ ๋„ˆ๋ฌด ํ—ท๊ฐˆ๋ ธ์Šต๋‹ˆ๋‹ค.

๐Ÿ”ฅ ๋Š๋‚€์ (TMI)

Vanilla JS๊ณผ์ •์„ ๋งˆ๋ฌด๋ฆฌํ•˜๋ฉฐ..
์ฒ˜์Œ TodoList ๋งŒ๋“ค๊ธฐ๋ถ€ํ„ฐ ๋งˆ์ง€๋ง‰ ๋“œ๋ž˜๊ทธ ์•ค ๋“œ๋กญ๊นŒ์ง€ ๊ฑฐ์˜ 4์ฃผ๊ฐ€ ๋‹ค ๋˜๋Š” ์‹œ๊ฐ„๋™์•ˆ VanillaJS๋ฅผ ๋ฐฐ์šฐ๊ณ  ๋“œ๋””์–ด ํ•˜๋‚˜์˜ ๊ธฐ๊ฐ„์ด ๋๋‚ฌ์Šต๋‹ˆ๋‹ค!๐Ÿ˜€ ๋ฒŒ์จ ๋ฐ๋ธŒ์ฝ”์Šค๋ฅผ ์‹œ์ž‘ํ•œ์ง€ 6์ฃผ๊ฐ€ ์ง€๋‚œ ๊ฒƒ์ด ๋งค์šฐ ๋†€๋ž๊ณ (์‹œ๊ฐ„ ์ง„์งœ ๋„ˆ๋ฌด๋„ˆ๋ฌด ๋น ๋ฅด๋‹ค) ๊ธฐ๋ณธ ์ง€์‹๋„ ๊ฐ€์ง€๊ณ  ์žˆ์ง€ ์•Š๋˜ ๋‚ด๊ฐ€ VanillaJS๋ฅผ ๋ฐฐ์šฐ๋ฉด์„œ ์ปดํฌ๋„ŒํŠธ ๋ถ„๋ฆฌ, ๋ฐ์ดํ„ฐ ๊ด€๋ฆฌ ๋“ฑ์„ ์ž์œ ๋กญ๊ฒŒ ๋งŒ์งˆ ์ˆ˜ ์žˆ๋Š” ์ˆ˜์ค€์ด ๋˜์—ˆ๋‹ค๋Š” ๊ฒƒ์ด ๋„ˆ๋ฌด ๊ฐ๋™์ ์ด์—ˆ๋‹ค. ์•„๋ฌด๋ž˜๋„ ์ฃผ์œ„์—์„œ ๋งŽ์ด ๋„์›€์„ ์ฃผ์…”์„œ ์ˆ˜์›”ํ•˜๊ฒŒ(?) ๋ฐฐ์šธ ์ˆ˜ ์žˆ์ง€ ์•Š์•˜๋‚˜ ์‹ถ๋‹ค. ์•„์ง๋„ ๋ชจ๋ฅด๋Š” ๊ฐœ๋…์ด ๋„ˆ๋ฌด ๋งŽ๊ณ  ์‰ฝ๊ฒŒ์‰ฝ๊ฒŒ ๊ธฐ๋Šฅ์„ ๋งŒ๋“ค์ง€๋Š” ๋ชปํ•˜์ง€๋งŒ ๊พธ์ค€ํžˆ ๊ณผ์ œ๋„ ํ•˜๊ณ  ๋ฐฐ์šฐ๋‹ค ๋ณด๋ฉด ์–ด๋Š ์ˆœ๊ฐ„ ์„ฑ์žฅํ•ด ์žˆ์ง€ ์•Š์„๊นŒ??

์ €๋ฒˆ์ฃผ๊นŒ์ง€๋งŒ ํ•ด๋„ ํ‹ฐ๋Š” ๋งŽ์ด ์•ˆ๋ƒˆ์ง€๋งŒ(๋ƒˆ๋‚˜..?ใ…Žใ…Ž) 3์ผ์˜ ๋ถ€์žฌ๊ฐ€ ๋งŒ๋“ค์–ด๋‚ธ ์—„์ฒญ๋‚œ ํญํ’๊ฐ™์€ ๋ฐ€๋ฆฐ ๊ณผ์ œ, ๊ฐ•์˜, ์Šคํ„ฐ๋”” ๋“ค์— ๋งŽ์ด ํž˜๋“ค์—ˆ์—ˆ๋‹ค.๐Ÿ˜ญ ๊ทธ๊ฑธ ๋ฉ”๊พธ๊ธฐ ์œ„ํ•ด์„œ 10์ผ๋™์•ˆ ํ•˜๋ฃจ์— 4-5์‹œ๊ฐ„๋„ ๋ชป ์ž๋ฉด์„œ ํ•˜๋‚˜ํ•˜๋‚˜ ํ•ด์น˜์›Œ ๋‚˜๊ฐ”๋‹ค. ์‚ฌ์‹ค ์•„์ง๋„ ๊ฐ•์˜๋„ ๋ฐ€๋ ค์žˆ๊ณ , ๊ทธ๋™์•ˆ ๊พธ์ค€ํžˆ ์“ฐ๋˜ TIL๋„ ํ•œ๋™์•ˆ ๋ชป์ผ๊ณ  ๊ณผ์ œ๋„ ๋งŒ์กฑํ•˜์ง€ ๋ชปํ•˜๋Š” ์ƒํƒœ๋กœ ์ œ์ถœํ•˜์—ฌ ๋งค์šฐ ์†์ƒํ•˜์ง€๋งŒ ๊ทธ๋ž˜๋„ ์ด์ •๋„๊นŒ์ง€ ํ•ด๋‚ธ ๋‚˜์—๊ฒŒ ์นญ์ฐฌํ•ด์ฃผ๊ณ  ์‹ถ๋‹ค.๐Ÿ˜–

ํŒ€์›๋ถ„๋“ค์ด ์˜†์—์„œ ๋งŽ์ด ๋„์›€์„ ์ฃผ๋ ค๊ณ  ํ•˜์…จ๊ณ  ์—ฌ๋Ÿฌ ์Šคํ„ฐ๋””์—์„œ๋„ ๋งŽ์ด ์ œ ์ƒํ™ฉ์„ ๊ณ ๋ คํ•ด์ฃผ์…จ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๊ณ  ์žˆ๋‹ค. ์ด TIL์„ ๋นŒ๋ ค ๊ฐ์‚ฌ ์ธ์‚ฌ๋ฅผ ๋“œ๋ฆฌ๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค!!๐Ÿ™๐Ÿป๐Ÿฅฐ (๊ฐ์‚ฌํ•ด์š” ์ •๋ง๋กœ) ๋•๋ถ„์— ๋ฒ„ํ‹ธ ์ˆ˜ ์žˆ์—ˆ๋˜ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.โค๏ธ

์ด์ œ ํ•œ๋™์•ˆ ๋˜ ๋‹ฌ๋ ค์•ผํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋‚ด์ผ ํ•˜๋ฃจ๋Š” ๋งˆ์Œ๊ป ์‰ฌ๋ ค๊ณ  ํ•œ๋‹ค! ๋“œ๋””์–ด!! ๋ฐ๋ธŒ์ฝ”์Šค ์‹œ์ž‘ํ•˜๊ณ  ์ฒ˜์Œ ์ œ๋Œ€๋กœ ์‰ฌ๋Š” ๋‚ ์ด ๋  ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค!๐Ÿ˜€ ํ•˜๋ฃจ๋™์•ˆ ๋ฆฌํ”„๋ ˆ์‰ฌํ•˜๊ณ  ์žฌ์ •๋น„ํ•ด์„œ ์˜ค๊ฒ ์Šต๋‹ˆ๋‹ค!

Refer

ํ”„๋กœ๊ทธ๋ž˜๋จธ์Šค ๋ฐ๋ธŒ์ฝ”์Šค

์˜ค๋Š˜์˜ ๋‚ด์šฉ ์ •๋ฆฌ

๋ฐ๋ธŒ์ฝ”์Šค Day28

profile
๋งค ์ˆœ๊ฐ„ ์„ฑ์žฅํ•˜๋Š” ๊ฐœ๋ฐœ์ž๊ฐ€ ๋˜๋ ค๊ณ  ๋…ธ๋ ฅํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

1๊ฐœ์˜ ๋Œ“๊ธ€

comment-user-thumbnail
2022๋…„ 4์›” 29์ผ

์ˆ˜๊ฒฝ๋‹˜~~ ์ •๋ง ์ˆ˜๊ณ ๋งŽ์œผ์…จ์–ด์š”ใ… ใ… 
์ง‘์ค‘ํ•˜๊ธฐ ํž˜๋“  ์ƒํ™ฉ์—์„œ๋„, ๋๊นŒ์ง€ ์ˆ˜๊ฒฝ๋‹˜์˜ ์ผ์„ ํ•ด์น˜์›Œ๋‚˜๊ฐ€์‹  ๋ชจ์Šต์ด ์ง„์งœ์ง„์งœ ๋ฉ‹์ ธ์š”!!
ํ† ์š”์ผ ๋ฆฌํ”„๋ ˆ์‰ฌํ•˜์‹œ๊ณ  ๋‹ค์‹œ ์—๋„ˆ์ œํ‹ฑํ•œ ๋ชจ์Šต์œผ๋กœ ๋งŒ๋‚ฉ์‹œ๋‹นโ™ฅโ™ฅ
์ฝ˜์„œํŠธ๋„ ์ž˜ ๋‹ค๋…€์˜ค์‹œ๊ตฌ์š”!!

๋‹ต๊ธ€ ๋‹ฌ๊ธฐ