ํ‹ฐ์Šคํ† ๋ฆฌ ๋ทฐ

์ด๋ฒคํŠธ ๋“œ๋ฆฌ๋ธ ํ”„๋กœ๊ทธ๋ž˜๋ฐ

๋ธŒ๋ผ์šฐ์ €๋Š” ์ฒ˜๋ฆฌํ•ด์•ผ ํ•  ํŠน์ • ์‚ฌ๊ฑด(ํด๋ฆญ, ํ‚ค๋ณด๋“œ ์ž…๋ ฅ, ๋งˆ์šฐ์Šค ์ด๋™ ๋“ฑ)์ด ๋ฐœ์ƒํ•˜๋ฉด ์ด๋ฅผ ๊ฐ์ง€ํ•˜์—ฌ ์ด๋ฒคํŠธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚ต๋‹ˆ๋‹ค.

์ด๋•Œ, ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ํŠน์ • ํƒ€์ž…์˜ ์ด๋ฒคํŠธ์— ๋Œ€ํ•ด ๋ฐ˜์‘ํ•˜์—ฌ ์–ด๋–ค ์ผ์„ ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด ํ•ด๋‹นํ•˜๋Š” ํƒ€์ž…์˜ ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ–ˆ์„ ๋•Œ ํ˜ธ์ถœ๋  ํ•จ์ˆ˜๋ฅผ ๋ธŒ๋ผ์šฐ์ €์—๊ฒŒ ์•Œ๋ ค ํ˜ธ์ถœ์„ ์œ„์ž„ํ•ฉ๋‹ˆ๋‹ค.

  • ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ : ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ–ˆ์„ ๋•Œ ํ˜ธ์ถœ๋  ํ•จ์ˆ˜
  • ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ ๋“ฑ๋ก : ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ–ˆ์„ ๋•Œ ๋ธŒ๋ผ์šฐ์ €์—๊ฒŒ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ์˜ ํ˜ธ์ถœ์„ ์œ„์ž„ํ•˜๋Š” ๊ฒƒ
<!DOCTYPE html>
<html>
<body>
  <button>Click me!</button>
  <script>
    const $button = document.querySelector('button');

    // ์‚ฌ์šฉ์ž๊ฐ€ ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜๋ฉด ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๋„๋ก ์š”์ฒญ
    $button.onclick = () => { alert('button click'); };
  </script>
</body>
</html>

 

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


์ด๋ฒคํŠธ ํƒ€์ž…

์ด๋ฒคํŠธ ํƒ€์ž…์€ ์ด๋ฒคํŠธ์˜ ์ข…๋ฅ˜๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ๋ฌธ์ž์—ด์ž…๋‹ˆ๋‹ค. ์•ฝ 200์—ฌ ๊ฐ€์ง€๊ฐ€ ์žˆ๋Š” ์ด๋ฒคํŠธ ํƒ€์ž… ์ค‘ ์‚ฌ์šฉ ๋นˆ๋„๊ฐ€ ๋†’์€ ์ด๋ฒคํŠธ๋“ค์— ๋Œ€ํ•ด ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

 

๋งˆ์šฐ์Šค ์ด๋ฒคํŠธ

์ด๋ฒคํŠธ ํƒ€์ž… ์ด๋ฒคํŠธ ๋ฐœ์ƒ ์‹œ์ 
click ๋งˆ์šฐ์Šค ๋ฒ„ํŠผ์„ ํด๋ฆญํ–ˆ์„ ๋•Œ
dblclick ๋งˆ์šฐ์Šค ๋ฒ„ํŠผ์„ ๋”๋ธ” ํด๋ฆญํ–ˆ์„ ๋•Œ
mousedown ๋งˆ์šฐ์Šค ๋ฒ„ํŠผ์„ ๋ˆŒ๋ €์„ ๋•Œ
mouseup ๋ˆ„๋ฅด๊ณ  ์žˆ๋˜ ๋งˆ์šฐ์Šค ๋ฒ„ํŠผ์„ ๋†“์•˜์„ ๋•Œ
mousemove ๋งˆ์šฐ์Šค ์ปค์„œ๋ฅผ ์›€์ง์˜€์„ ๋•Œ
mouseenter ๋งˆ์šฐ์Šค ์ปค์„œ๋ฅผ HTML ์š”์†Œ ์•ˆ์œผ๋กœ ์ด๋™ํ–ˆ์„ ๋•Œ(๋ฒ„๋ธ”๋งX)
mouseover ๋งˆ์šฐ์Šค ์ปค์„œ๋ฅผ HTML ์š”์†Œ ์•ˆ์œผ๋กœ ์ด๋™ํ–ˆ์„ ๋•Œ(๋ฒ„๋ธ”๋งO)
mouseleave ๋งˆ์šฐ์Šค ์ปค์„œ๋ฅผ HTML ์š”์†Œ ๋ฐ–์œผ๋กœ ์ด๋™ํ–ˆ์„ ๋•Œ(๋ฒ„๋ธ”๋งX)
mosueout ๋งˆ์šฐ์Šค ์ปค์„œ๋ฅผ HTML ์š”์†Œ ๋ฐ•์œผ๋กœ ์ด๋™ํ–ˆ์„ ๋•Œ(๋ฒ„๋ธ”๋งO)

* ๋ฒ„๋ธ”๋ง : ํ•˜์œ„์š”์†Œ์—์„œ ์ƒ์œ„์š”์†Œ๋กœ์˜ ์ด๋ฒคํŠธ ์ „ํŒŒ ๋ฐฉ์‹์œผ๋กœ HTML ๊ตฌ์กฐ์ƒ ์ž์‹์š”์†Œ์— ๋ฐœ์ƒํ•œ ์ด๋ฒคํŠธ๊ฐ€ ์ƒ์œ„ ๋ถ€๋ชจ์š”์†Œ์—๊นŒ์ง€ ์˜ํ–ฅ์„ ๋ฏธ์น˜๋Š” ๊ฒƒ

 

ํ‚ค๋ณด๋“œ ์ด๋ฒคํŠธ

์ด๋ฒคํŠธ ํƒ€์ž… ์ด๋ฒคํŠธ ๋ฐœ์ƒ ์‹œ์ 
keydown ๋ชจ๋“  ํ‚ค๋ฅผ ๋ˆŒ๋ €์„ ๋•Œ ๋ฐœ์ƒ
keypress ๋ฌธ์ž ํ‚ค๋ฅผ ๋ˆŒ๋ €์„ ๋•Œ ์—ฐ์†์ ์œผ๋กœ ๋ฐœ์ƒ
keyup ๋ˆ„๋ฅด๊ณ  ์žˆ๋˜ ํ‚ค๋ฅผ ๋†“์•˜์„ ๋•Œ ํ•œ ๋ฒˆ๋งŒ ๋ฐœ์ƒ

 

ํฌ์ปค์Šค ์ด๋ฒคํŠธ

์ด๋ฒคํŠธ ํƒ€์ž… ์ด๋ฒคํŠธ ๋ฐœ์ƒ ์‹œ์ 
focus HTML ์š”์†Œ๊ฐ€ ํฌ๊ฑฐ์Šค๋ฅผ ๋ฐ›์•˜์„ ๋•Œ(๋ฒ„๋ธ”๋งX)
blur HTML ์š”์†Œ๊ฐ€ ํฌ๊ฑฐ์Šค๋ฅผ ์žƒ์—ˆ์„ ๋•Œ(๋ฒ„๋ธ”๋งX)
focusin HTML ์š”์†Œ๊ฐ€ ํฌ๊ฑฐ์Šค๋ฅผ ๋ฐ›์•˜์„ ๋•Œ(๋ฒ„๋ธ”๋งO)
focusout HTML ์š”์†Œ๊ฐ€ ํฌ๊ฑฐ์Šค๋ฅผ ์žƒ์—ˆ์„ ๋•Œ(๋ฒ„๋ธ”๋งX)

*focusin, focusout ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋Š” addEventLisner ๋ฉ”์„œ๋“œ ๋ฐฉ์‹์„ ์ด์šฉํ•ด ๋“ฑ๋กํ•ด์•ผ ํ•จ

 

ํผ ์ด๋ฒคํŠธ

์ด๋ฒคํŠธ ํƒ€์ž… ์ด๋ฒคํŠธ ๋ฐœ์ƒ ์‹œ์ 
submit form ์š”์†Œ ๋‚ด์˜ input, select ์ž…๋ ฅ ํ•„๋“œ(textarea ์ œ์™ธ)์—์„œ ์—”ํ„ฐ ํ‚ค๋ฅผ ๋ˆŒ๋ €์„ ๋•Œ
form ์š”์†Œ ๋‚ด์˜ submit ๋ฒ„ํŠผ์„ ํด๋ฆญํ–ˆ์„ ๋•Œ
reset form ์š”์†Œ ๋‚ด์˜ reset ๋ฒ„ํŠผ์„ ํด๋ฆญํ–ˆ์„ ๋•Œ(์ตœ๊ทผ์—” ์‚ฌ์šฉX)

 

๊ฐ’ ๋ณ€๊ฒฝ ์ด๋ฒคํŠธ

์ด๋ฒคํŠธ ํƒ€์ž… ์ด๋ฒคํŠธ ๋ฐœ์ƒ ์‹œ์ 
input input, select, textarea ์š”์†Œ์˜ ๊ฐ’์ด ์ž…๋ ฅ๋˜์—ˆ์„ ๋•Œ
change input, select,  teatarea ์š”์†Œ์˜ ๊ฐ’์ด ๋ณ€๊ฒฝ๋˜์—ˆ์„ ๋•Œ
readystatechange HTML ๋ฌธ์„œ์˜ ๋กœ๋“œ์™€ ํŒŒ์‹ฑ์ด ์ƒํƒœ๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” document.readyState ํ”„๋กœํผํ‹ฐ ๊ฐ’('loading',
'interactive', 'complete')์ด ๋ณ€๊ฒฝ๋  ๋•Œ 

 

DOM ๋ฎคํ…Œ์ด์…˜ ์ด๋ฒคํŠธ

์ด๋ฒคํŠธ ํƒ€์ž… ์ด๋ฒคํŠธ ๋ฐœ์ƒ ์‹œ์ 
DOMContentLoaded HTML ๋ฌธ์„œ์˜ ๋กœ๋“œ์™€ ํŒŒ์‹ฑ์ด ์™„๋ฃŒ๋˜์–ด DOM ์ƒ์„œ์ž‰ ์™„๋ฃŒ๋˜์—ˆ์„ ๋•Œ

 

๋ทฐ ์ด๋ฒคํŠธ

์ด๋ฒคํŠธ ํƒ€์ž… ์ด๋ฒคํŠธ ๋ฐœ์ƒ ์‹œ์ 
resize ๋ธŒ๋ผ์šฐ์ € ์œˆ๋„์šฐ์˜ ํฌ๊ธฐ๋ฅผ ๋ฆฌ์‚ฌ์ด์ฆˆํ•  ๋•Œ ์—ฐ์†์ ์œผ๋กœ ๋ฐœ์ƒ
scroll ์›นํŽ˜์ด์ง€(document) ๋˜๋Š” HTML ์š”์†Œ๋ฅผ ์Šคํฌ๋กคํ•  ๋•Œ ์—ฐ์†์ ์œผ๋กœ ๋ฐœ์ƒ

 

๋ฆฌ์†Œ์Šค ์ด๋ฒคํŠธ

์ด๋ฒคํŠธ ํƒ€์ž… ์ด๋ฒคํŠธ ๋ฐœ์ƒ ์‹œ์ 
load DOMContentLoaded ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•œ ํ›„, ๋ชจ๋“  ๋ฆฌ์†Œ์Šค์˜ ๋กœ๋”ฉ์ด ์™„๋ฃŒ๋˜์—ˆ์„ ๋•Œ
unload ๋ฆฌ์†Œ์Šค๊ฐ€ ์–ธ๋กœ๋“œ๋  ๋•Œ
abort ๋ฆฌ์†Œ์Šค ๋กœ๋”ฉ์ด ์ค‘๋‹จ๋˜์—ˆ์„ ๋•Œ
error ๋ฆฌ์†Œ์Šค ๋กœ๋”ฉ์ด ์‹คํŒจํ–ˆ์„ ๋•Œ

์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ ๋“ฑ๋ก

์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ–ˆ์„ ๋•Œ ๋ธŒ๋ผ์šฐ์ €์—๊ฒŒ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ์˜ ํ˜ธ์ถœ์„ ์œ„์ž„ํ•˜๋Š” ๊ฒƒ์„ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ ๋“ฑ๋ก์ด๋ผ ํ•˜๋ฉฐ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ๋“ฑ๋กํ•˜๋Š” ๋ฐฉ๋ฒ•์€ 3๊ฐ€์ง€๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

 

์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ ์–ดํŠธ๋ฆฌ๋ทฐํŠธ ๋ฐฉ์‹

HTML ์š”์†Œ์˜ ์–ดํŠธ๋ฆฌ๋ทฐํŠธ ์ค‘์—๋Š” ์ด๋ฒคํŠธ์— ๋Œ€์‘ํ•˜๋Š” ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ ์–ดํŠธ๋ฆฌ๋ทฐํŠธ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

  • ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ ์–ดํŠธ๋ฆฌ๋ทฐํŠธ์˜ ์ด๋ฆ„์€ on ์ ‘๋‘์‚ฌ์™€ ์ด๋ฒคํŠธ์˜ ์ข…๋ฅ˜๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ์ด๋ฒคํŠธ ํƒ€์ž…(onclick)์œผ๋กœ ์ด๋ฃจ์–ด์ ธ ์žˆ์Œ
  • ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ ์–ดํŠธ๋ฆฌ๋ทฐํŠธ์˜ ๊ฐ’์œผ๋กœ ํ•จ์ˆ˜ ํ˜ธ์ถœ๋ฌธ ๋“ฑ์˜ ๋ฌธ์„ ํ• ๋‹นํ•˜๋ฉด ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๊ฐ€ ๋“ฑ๋ก๋จ
<!DOCTYPE html>
<html>
<body>
  <button onclick="sayHi('Lee')">Click me!</button>
  <script>
    function sayHi(name) {
      console.log(`Hi! ${name}.`);
    }
  </script>
</body>
</html>

 

์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ ์–ดํŠธ๋ฆฌ๋ทฐํŠธ ๊ฐ’์œผ๋กœ ํ• ๋‹นํ•œ ๋ฌธ์ž์—ด์€ ์•”๋ฌต์ ์œผ๋กœ ์ƒ์„ฑ๋˜๋Š” ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ์˜ ํ•จ์ˆ˜ ๋ชธ์ฒด์ž…๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ํ•จ์ˆ˜ ์ฐธ์กฐ๊ฐ€ ์•„๋‹Œ ํ•จ์ˆ˜ ํ˜ธ์ถœ๋ฌธ ๋“ฑ์˜ ๋ฌธ์„ ํ• ๋‹นํ•˜์—ฌ๋„ ์•„๋ž˜์™€ ๊ฐ™์ด onclick="sayHi('Lee')" ์–ดํŠธ๋ฆฌ๋ทฐํŠธ๋Š” ํŒŒ์‹ฑ๋˜์–ด ํ•จ์ˆ˜๋ฅผ ์•”๋ฌต์ ์œผ๋กœ ์ƒ์„ฑํ•˜๊ณ  ์ด๋ฅผ onclick ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ ํ”„๋กœํผํ‹ฐ์— ํ• ๋‹นํ•ฉ๋‹ˆ๋‹ค. 

 

function onclick(event) {
  sayHi('Lee');
}

 

์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ ํ”„๋กœํผํ‹ฐ ๋ฐฉ์‹

window ๊ฐ์ฒด์™€ Document, HTMLElement ํƒ€์ž…์˜ DOM ๋…ธ๋“œ ๊ฐ์ฒด๋Š” ์ด๋ฒคํŠธ์— ๋Œ€์‘ํ•˜๋Š” ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ ํ”„๋กœํผํ‹ฐ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

  • ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ ํ”„๋กœํผํ‹ฐ ํ‚ค๋Š” on ์ ‘๋‘์‚ฌ์™€ ์ด๋ฒคํŠธ์˜ ์ข…๋ฅ˜๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ์ด๋ฒคํŠธ ํƒ€์ž…(onclick)์œผ๋กœ ์ด๋ฃจ์–ด์ ธ ์žˆ์Œ
  • ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ ํ”„๋กœํผํ‹ฐ์— ํ•จ์ˆ˜๋ฅผ ๋ฐ”์ธ๋”ฉํ•˜๋ฉด ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๊ฐ€ ๋“ฑ๋ก๋จ
<!DOCTYPE html>
<html>
<body>
  <button>Click me!</button>
  <script>
    const $button = document.querySelector('button');

    // ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ ํ”„๋กœํผํ‹ฐ์— ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ๋ฐ”์ธ๋”ฉ
    $button.onclick = function () {
      console.log('button click');
    };
  </script>
</body>
</html>

์ด์ฒ˜๋Ÿผ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ๋“ฑ๋กํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ์ด๋ฒคํŠธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚ฌ ๊ฐ์ฒด์ธ ์ด๋ฒคํŠธ ํƒ€๊นƒ๊ณผ ์ด๋ฒคํŠธ์˜ ์ข…๋ฅ˜๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ๋ฌธ์ž์—ด์ธ ์ด๋ฒคํŠธ ํƒ€์ž… ๊ทธ๋ฆฌ๊ณ  ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ์ง€์ •ํ•  ํ•„์š”๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. 

 

addEventListener ๋ฉ”์„œ๋“œ ๋ฐฉ์‹

DOM level2 ์—์„œ ๋„์ž…๋œ EventTarget.prototype.addEventListener ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•ด ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ๋“ฑ๋กํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • ์ฒซ ๋ฒˆ์งธ ๋งค๊ฐœ๋ณ€์ˆ˜ : ์ด๋ฒคํŠธ ์ข…๋ฅ˜๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ๋ฌธ์ž์—ด์„ ์ „๋‹ฌ(on ์ ‘๋‘์‚ฌ X)
  • ๋‘ ๋ฒˆ์งธ ๋งค๊ฐœ๋ณ€์ˆ˜ : ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ์ „๋‹ฌ
  • ๋งˆ์ง€๋ง‰ ๋งค๊ฐœ ๋ณ€์ˆ˜ : ์ด๋ฒคํŠธ๋ฅผ ์บ์น˜ํ•  ์ด๋ฒคํŠธ ์ „ํŒŒ ๋‹จ๊ณ„(์บก์ณ๋ง|๋ฒ„๋ธ”๋ง)๋ฅผ ์ง€์ •
<!DOCTYPE html>
<html>
<body>
  <button>Click me!</button>
  <script>
    const $button = document.querySelector('button');

    // addEventListener ๋ฉ”์„œ๋“œ๋Š” ๋™์ผํ•œ ์š”์†Œ์—์„œ ๋ฐœ์ƒํ•œ ๋™์ผํ•œ ์ด๋ฒคํŠธ์— ๋Œ€ํ•ด
    // ํ•˜๋‚˜ ์ด์ƒ์˜ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ๋“ฑ๋กํ•  ์ˆ˜ ์žˆ๋‹ค.
    $button.addEventListener('click', function () {
      console.log('[1]button click');
    });

    $button.addEventListener('click', function () {
      console.log('[2]button click');
    });

    const handleClick = () => console.log('button click');

    // ์ฐธ์กฐ๊ฐ€ ๋™์ผํ•œ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ์ค‘๋ณต ๋“ฑ๋กํ•˜๋ฉด ํ•˜๋‚˜์˜ ํ•ธ๋“ค๋Ÿฌ๋งŒ ๋“ฑ๋ก๋œ๋‹ค.
    $button.addEventListener('click', handleClick);
    $button.addEventListener('click', handleClick);
  </script>
</body>
</html>

 

์œ„ ์˜ˆ์ œ์ฒ˜๋Ÿผ ๋™์ผํ•œ HTML ์š”์†Œ์—์„œ ๋ฐœ์ƒํ•œ ๋™์ผํ•œ ์ด๋ฒคํŠธ์— ๋Œ€ํ•ด ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ ํ”„๋กœํผํ‹ฐ ๋ฐฉ์‹์€ ํ•˜๋‚˜์ด์ƒ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ๋“ฑ๋กํ•  ์ˆ˜ ์—†๋Š” ๋ฐ˜๋ฉด, addEventListener ๋ฉ”์„œ๋“œ๋Š” ํ•˜๋‚˜ ์ด์ƒ์˜ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ๋“ฑ๋ก ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ ๋“ฑ๋ก๋œ ์ˆœ์„œ๋Œ€๋กœ ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ, ์ฐธ์กฐ๊ฐ€ ๋™์ผํ•œ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋Š” ์ค‘๋ณต ๋“ฑ๋ก๋˜์ง€ ์•Š๊ณ  ํ•œ ๊ฐœ๋งŒ ๋“ฑ๋ก๋ฉ๋‹ˆ๋‹ค.


์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ ์ œ๊ฑฐ

addEventListener ๋ฉ”์„œ๋“œ๋กœ ๋“ฑ๋กํ•œ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ์ œ๊ฑฐํ•˜๋ ค๋ฉด EventTarget.prototype.removeEventListener ๋ฉ”์„œ๋“œ์— addEventListener์™€ ๋™์ผํ•œ ์ธ์ˆ˜๋ฅผ ์ „๋‹ฌํ•ด ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. (์ผ์น˜ํ•˜์ง€ ์•Š์œผ๋ฉด ์ œ๊ฑฐ X)

 

<!DOCTYPE html>
<html>
<body>
  <button>Click me!</button>
  <script>
    const $button = document.querySelector('button');

    const handleClick = () => console.log('button click');

    // ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ ๋“ฑ๋ก
    $button.addEventListener('click', handleClick);

    // ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ ์ œ๊ฑฐ
    // addEventListener ๋ฉ”์„œ๋“œ์— ์ „๋‹ฌํ•œ ์ธ์ˆ˜์™€ removeEventListener ๋ฉ”์„œ๋“œ์—
    // ์ „๋‹ฌํ•œ ์ธ์ˆ˜๊ฐ€ ์ผ์น˜ํ•˜์ง€ ์•Š์œผ๋ฉด ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๊ฐ€ ์ œ๊ฑฐ๋˜์ง€ ์•Š๋Š”๋‹ค.
    $button.removeEventListener('click', handleClick, true); // ์‹คํŒจ
    $button.removeEventListener('click', handleClick); // ์„ฑ๊ณต
  </script>
</body>
</html>

 

๋”ฐ๋ผ์„œ ๋ฌด๋ช… ํ•จ์ˆ˜๋ฅผ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋กœ ๋“ฑ๋กํ•œ ๊ฒฝ์šฐ ์ œ๊ฑฐํ•  ์ˆ˜ ์—†์œผ๋ฏ€๋กœ ๊ฐ€๊ธ‰์  ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ์˜ ์ฐธ์กฐ๋ฅผ ๋ณ€์ˆ˜๋‚˜ ์ž๋ฃŒ๊ตฌ์กฐ์— ์ €์žฅํ•˜์—ฌ ์ œ๊ฑฐํ•˜๋Š” ํŽธ์ด ์ข‹์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ, ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ ํ”„๋กœํผํ‹ฐ ๋ฐฉ์‹์œผ๋กœ ๋™๋กํ•œ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋Š” removeEventListener ๋ฉ”์„œ๋“œ๋กœ ์ œ๊ฑฐํ•  ์ˆ˜ ์—†์–ด ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ ํ”„๋กœํผํ‹ฐ์— null์„ ํ• ๋‹นํ•˜์—ฌ ์ œ๊ฑฐํ•ฉ๋‹ˆ๋‹ค.


์ด๋ฒคํŠธ ๊ฐ์ฒด

์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ์ด๋ฒคํŠธ์— ๊ด€๋ จํ•œ ๋‹ค์–‘ํ•œ ์ •๋ณด๋ฅผ ๋‹ด๊ณ  ์žˆ๋Š” ์ด๋ฒคํŠธ ๊ฐ์ฒด๊ฐ€ ๋™์ ์œผ๋กœ ์ƒ์„ฑ๋˜๋ฉฐ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ์˜ ์ฒซ ๋ฒˆ์งธ ์ธ์ˆ˜๋กœ ์ „๋‹ฌ๋ฉ๋‹ˆ๋‹ค.

 

<!DOCTYPE html>
<html>
<head>
  <style>
    html, body { height: 100%; }
  </style>
</head>
<!-- ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ ์–ดํŠธ๋ฆฌ๋ทฐํŠธ ๋ฐฉ์‹์˜ ๊ฒฝ์šฐ event๊ฐ€ ์•„๋‹Œ ๋‹ค๋ฅธ ์ด๋ฆ„์œผ๋กœ๋Š” ์ด๋ฒคํŠธ ๊ฐ์ฒด๋ฅผ
์ „๋‹ฌ๋ฐ›์ง€ ๋ชปํ•œ๋‹ค. -->
<body onclick="showCoords(event)">
  <p>ํด๋ฆญํ•˜์„ธ์š”. ํด๋ฆญํ•œ ๊ณณ์˜ ์ขŒํ‘œ๊ฐ€ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.</p>
  <em class="message"></em>
  <script>
    const $msg = document.querySelector('.message');

    // ํด๋ฆญ ์ด๋ฒคํŠธ์— ์˜ํ•ด ์ƒ์„ฑ๋œ ์ด๋ฒคํŠธ ๊ฐ์ฒด๋Š” ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ์˜ ์ฒซ ๋ฒˆ์งธ ์ธ์ˆ˜๋กœ ์ „๋‹ฌ๋œ๋‹ค.
    function showCoords(e) {
      $msg.textContent = `clientX: ${e.clientX}, clientY: ${e.clientY}`;
    }
  </script>
</body>
</html>

 

์ด์ฒ˜๋Ÿผ ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ํ˜ธ์ถœํ•  ๋•Œ ์ด๋ฒคํŠธ ๊ฐ์ฒด๋ฅผ ์ „๋‹ฌ๋ฐ›์œผ๋ ค๋ฉด ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ์ •์˜ํ•  ๋•Œ ์ด๋ฒคํŠธ ๊ฐ์ฒด๋ฅผ ์ „๋‹ฌ๋ฐ›์„ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ๋ช…์‹œ์ ์œผ๋กœ ์„ ์–ธํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋‹จ, ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ ์–ดํŠธ๋ฆฌ๋ทฐํŠธ ๋ฐฉ์‹์œผ๋กœ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ๋“ฑ๋กํ–ˆ๋‹ค๋ฉด ์ฒซ ๋ฒˆ์งธ ๋งค๊ฐœ๋ณ€์ˆ˜์˜ ์ด๋ฆ„์ด event๋กœ ์•”๋ฌต์ ์œผ๋กœ ๋ช…๋ช…๋˜๊ธฐ ๋•Œ๋ฌธ์— event๋ฅผ ํ†ตํ•ด ์ด๋ฒคํŠธ ๊ฐ์ฒด๋ฅผ ์ „๋‹ฌ๋ฐ›์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค.

 

์ด๋ฒคํŠธ ๊ฐ์ฒด์˜ ์ƒ์† ๊ตฌ์กฐ

์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ์ด๋ฒคํŠธ ํƒ€์ž…์— ๋”ฐ๋ผ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ƒ์† ๊ตฌ์กฐ๋ฅผ ๊ฐ–๋Š” ๋‹ค์–‘ํ•œ ํƒ€์ž…์˜ ์ด๋ฒคํŠธ ๊ฐ์ฒด๊ฐ€ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค.

 

 

์œ„ ๊ทธ๋ฆผ์˜ Event, UIEvent, MouseEvent ๋“ฑ ๋ชจ๋‘ ์ƒ์„ฑ์ž ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ƒ์„ฑ์ž ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ์ด๋ฒคํŠธ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

<!DOCTYPE html>
<html>
<body>
  <script>
    // Event ์ƒ์„ฑ์ž ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ foo ์ด๋ฒคํŠธ ํƒ€์ž…์˜ Event ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.
    let e = new Event('foo');
    console.log(e);
    // Event {isTrusted: false, type: "foo", target: null, ...}
    console.log(e.type); // "foo"
    console.log(e instanceof Event); // true
    console.log(e instanceof Object); // true

    // FocusEvent ์ƒ์„ฑ์ž ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ focus ์ด๋ฒคํŠธ ํƒ€์ž…์˜ FocusEvent ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.
    e = new FocusEvent('focus');
    console.log(e);
    // FocusEvent {isTrusted: false, relatedTarget: null, view: null, ...}

    // MouseEvent ์ƒ์„ฑ์ž ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ click ์ด๋ฒคํŠธ ํƒ€์ž…์˜ MouseEvent ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.
    e = new MouseEvent('click');
    console.log(e);
    // MouseEvent {isTrusted: false, screenX: 0, screenY: 0, clientX: 0, ... }

    // KeyboardEvent ์ƒ์„ฑ์ž ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ keyup ์ด๋ฒคํŠธ ํƒ€์ž…์˜ KeyboardEvent ๊ฐ์ฒด๋ฅผ
    // ์ƒ์„ฑํ•œ๋‹ค.
    e = new KeyboardEvent('keyup');
    console.log(e);
    // KeyboardEvent {isTrusted: false, key: "", code: "", ctrlKey: false, ...}

    // InputEvent ์ƒ์„ฑ์ž ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ change ์ด๋ฒคํŠธ ํƒ€์ž…์˜ InputEvent ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.
    e = new InputEvent('change');
    console.log(e);
    // InputEvent {isTrusted: false, data: null, inputType: "", ...}
  </script>
</body>
</html>

 

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

 

Event ์ธํ„ฐํŽ˜์ด์Šค

Event ์ธํ„ฐํŽ˜์ด์Šค๋Š” DOM ๋‚ด์—์„œ ๋ฐœ์ƒํ•œ ์ด๋ฒคํŠธ์— ์˜ํ•ด ์ƒ์„ฑ๋˜๊ณ  ์ด๋ฒคํŠธ ๊ฐ์ฒด๋กœ ๋ชจ๋“  ์ด๋ฒคํŠธ ๊ฐ์ฒด์˜ ๊ณตํ†ต ํ”„๋กœํผํ‹ฐ๊ฐ€ ์ •์˜๋˜์–ด ์žˆ๊ณ  FocuseEvent, MouseEvent, KeyboardEvent, WheelEvent ๊ฐ™์€ ํ•˜์œ„ ์ธํ…ŒํŽ˜์ด์Šค์—๋Š” ์ด๋ฒคํŠธ ํƒ€์ž…์— ๋”ฐ๋ผ ๊ณ ์œ ํ•œ ํ”„๋กœํผํ‹ฐ๊ฐ€ ์ •์˜๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ฆ‰, ์•„๋ž˜์™€ ๊ฐ™์ด ์ด๋ฒคํŠธ ๊ฐ์ฒด์˜ ํ”„๋กœํผํ‹ฐ๋Š” ๋ฐœ์ƒํ•œ ์ด๋ฒคํŠธ์˜ ํƒ€์ž…์— ๋”ฐ๋ผ ๋‹ฌ๋ผ์ง‘๋‹ˆ๋‹ค.

 

<!DOCTYPE html>
<html>
<body>
  <input type="text">
  <input type="checkbox">
  <button>Click me!</button>
  <script>
    const $input = document.querySelector('input[type=text]');
    const $checkbox = document.querySelector('input[type=checkbox]');
    const $button = document.querySelector('button');

    // load ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด Event ํƒ€์ž…์˜ ์ด๋ฒคํŠธ ๊ฐ์ฒด๊ฐ€ ์ƒ์„ฑ๋œ๋‹ค.
    window.onload = console.log;

    // change ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด Event ํƒ€์ž…์˜ ์ด๋ฒคํŠธ ๊ฐ์ฒด๊ฐ€ ์ƒ์„ฑ๋œ๋‹ค.
    $checkbox.onchange = console.log;

    // focus ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด FocusEvent ํƒ€์ž…์˜ ์ด๋ฒคํŠธ ๊ฐ์ฒด๊ฐ€ ์ƒ์„ฑ๋œ๋‹ค.
    $input.onfocus = console.log;

    // input ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด InputEvent ํƒ€์ž…์˜ ์ด๋ฒคํŠธ ๊ฐ์ฒด๊ฐ€ ์ƒ์„ฑ๋œ๋‹ค.
    $input.oninput = console.log;

    // keyup ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด KeyboardEvent ํƒ€์ž…์˜ ์ด๋ฒคํŠธ ๊ฐ์ฒด๊ฐ€ ์ƒ์„ฑ๋œ๋‹ค.
    $input.onkeyup = console.log;

    // click ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด MouseEvent ํƒ€์ž…์˜ ์ด๋ฒคํŠธ ๊ฐ์ฒด๊ฐ€ ์ƒ์„ฑ๋œ๋‹ค.
    $button.onclick = console.log;
  </script>
</body>
</html>

 

์ด๋ฒคํŠธ ๊ฐ์ฒด์˜ ๊ณตํ†ต ํ”„๋กœํผํ‹ฐ

Event ์ธํ„ฐํŽ˜์ด์Šค, ์ฆ‰ Event.prototype์— ์ •์˜๋˜์–ด ์žˆ๋Š” ์ด๋ฒคํŠธ ๊ด€๋ จ ํ”„๋กœํผํ‹ฐ๋Š” UIEvent, CustomEvent, MouseEvent ๋“ฑ ๋ชจ๋“  ํŒŒ์ƒ ์ด๋ฒคํŠธ ๊ฐ์ฒด์— ์ƒ์†๋ฉ๋‹ˆ๋‹ค. ๋ชจ๋“  ์ด๋ฒคํŠธ ๊ฐ์ฒด๊ฐ€ ์ƒ์†๋ฐ›๋Š” ๊ณตํ†ต ํ”„๋กœํผํ‹ฐ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

 

๊ณตํ†ต ํ”„๋กœํผํ‹ฐ ์„ค๋ช… ํƒ€์ž…
type ์ด๋ฒคํŠธ ํƒ€์ž… string
target ์ด๋ฒคํŠธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚จ DOM ์š”์†Œ DOM ์š”์†Œ ๋…ธ๋“œ
currentTarget ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๊ฐ€ ๋ฐ”์ธ๋”ฉ๋œ DOM ์š”์†Œ DOM ์š”์†Œ ๋…ธ๋“œ
eventPhase ์ด๋ฒคํŠธ ์ „ํŒŒ ๋‹จ๊ณ„(0: ์ด๋ฒคํŠธ ์—†์Œ, 1: ์บก์ณ๋ง ๋‹จ๊ณ„, 2: ํƒ€๊นƒ ๋‹จ๊ณ„, 3: ๋ฒ„๋ธ”๋ง ๋‹จ๊ณ„) number
bubbles ์ด๋ฒคํŠธ๋ฅผ ๋ฒ„๋ธ”๋ง์œผ๋กœ ์ „ํŒŒํ•˜๋Š”์ง€ ์—ฌ๋ถ€ boolean
cancelable preventDefault ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ์ด๋ฒคํŠธ์˜ ๊ธฐ๋ณธ ๋™์ž‘์„ ์ทจ์†Œํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ์—ฌ๋ถ€ boolean
defaultPrevented preventDefault ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ์ด๋ฒคํŠธ๋ฅผ ์ทจ์†Œํ–ˆ๋Š”์ง€ ์—ฌ๋ถ€ boolean
isTrusted ์‚ฌ์šฉ์ž์˜ ํ–‰์œ„์— ์˜ํ•ด ๋ฐœ์ƒํ•œ ์ด๋ฒคํŠธ์ธ์ง€ ์—ฌ๋ถ€ boolean
timeStamp ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•œ ์‹œ๊ฐ(1970/01/01/00:00:00๋ถ€ํ„ฐ ๊ฒฝ๊ณผํ•œ ๋ฐ€๋ฆฌ์ดˆ) number

 

๋งˆ์šฐ์Šค ์ •๋ณด ์ทจ๋“

MouseEvent ํƒ€์ž…์˜ ์ด๋ฒคํŠธ ๊ฐ์ฒด๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ณ ์œ  ํ”„๋กœํผํ‹ฐ๋ฅผ ๊ฐ€์ง‘๋‹ˆ๋‹ค.

  • ๋งˆ์šฐ์Šค ํฌ์ธํ„ฐ์˜ ์ขŒํ‘œ ์ •๋ณด๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ํ”„๋กœํผํ‹ฐ : screenX/screenY, clientX/clientY, pageX/pageY, offsetX, offsetY
  • ๋ฒ„ํŠผ ์ •๋ณด๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ํ”„๋กœํผํ‹ฐ : altKey, ctrlKey, shiftKey, button

 

ํ‚ค๋ณด๋“œ ์ •๋ณด ์ทจ๋“

KeyboardEvent ํƒ€์ž…์˜ ์ด๋ฒคํŠธ ๊ฐ์ฒด๋Š” altKey, ctrlKey, shiftKey, metaKey, key, keyCode ๊ฐ™์€ ๊ณ ์œ ์˜ ํ”„๋กœํผํ‹ฐ๋ฅผ ๊ฐ–์Šต๋‹ˆ๋‹ค.


์ด๋ฒคํŠธ ์ „ํŒŒ

์ด๋ฒคํŠธ ์ „ํŒŒ๋Š” DOM ํŠธ๋ฆฌ ์ƒ์— ์กด์žฌํ•˜๋Š” DOM ์š”์†Œ ๋…ธ๋“œ์—์„œ ๋ฐœ์ƒํ•œ ์ด๋ฒคํŠธ๊ฐ€ DOM ํŠธ๋ฆฌ๋ฅผ ํ†ตํ•ด ์ „ํŒŒ๋˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

 

์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ์ƒ์„ฑ๋œ ์ด๋ฒคํŠธ ๊ฐ์ฒด๊ฐ€ ์ด๋ฒคํŠธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚จ DOM ์š”์†Œ์˜ ์ด๋ฒคํŠธ ํƒ€๊นƒ์„ ์ค‘์‹ฌ์œผ๋กœ DOM ํŠธ๋ฆฌ๋ฅผ ํ†ตํ•ด ์ „ํŒŒ๋ฉ๋‹ˆ๋‹ค. ์ด๋•Œ, ์ด๋ฒคํŠธ ์ „ํŒŒ๋Š” ์ด๋ฒคํŠธ ๊ฐ์ฒด๊ฐ€ ์ „ํŒŒ๋˜๋Š” ๋ฐฉํ–ฅ์— ๋”ฐ๋ผ ๋‹ค์Œ๊ณผ ๊ฐ™์ด 3๋‹จ๊ณ„๋กœ ๊ตฌ๋ถ„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • ์บก์ณ๋ง ๋‹จ๊ณ„ : ์ด๋ฒคํŠธ๊ฐ€ ์ƒ์œ„ ์š”์†Œ์—์„œ ํ•˜์œ„ ์š”์†Œ ๋ฐฉํ–ฅ์œผ๋กœ ์ „ํŒŒ
  • ํƒ€๊นƒ ๋‹จ๊ณ„ : ์ด๋ฒคํŠธ๊ฐ€ ์ด๋ฒคํŠธ ํƒ€๊นƒ์— ๋„๋‹ฌ
  • ๋ฒ„๋ธ”๋ง ๋‹จ๊ณ„ : ์ด๋ฒคํŠธ๊ฐ€ ํ•˜์œ„ ์š”์†Œ์—์„œ ์ƒ์œ„ ์š”์†Œ ๋ฐฉํ–ฅ์œผ๋กœ ์ „ํŒŒ

์•„๋ž˜์˜ ์˜ˆ์ œ๋ฅผ ์‚ดํŽด๋ณด๋ฉด ์ด๋ฒคํŠธ ์ „ํŒŒ ๋‹จ๊ณ„๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

<!DOCTYPE html>
<html>
<body>
  <ul id="fruits">
    <li id="apple">Apple</li>
    <li id="banana">Banana</li>
    <li id="orange">Orange</li>
  </ul>
  <script>
    const $fruits = document.getElementById('fruits');
    const $banana = document.getElementById('banana');

    // #fruits ์š”์†Œ์˜ ํ•˜์œ„ ์š”์†Œ์ธ li ์š”์†Œ๋ฅผ ํด๋ฆญํ•œ ๊ฒฝ์šฐ
    // ์บก์ฒ˜๋ง ๋‹จ๊ณ„์˜ ์ด๋ฒคํŠธ๋ฅผ ์บ์น˜ํ•œ๋‹ค.
    $fruits.addEventListener('click', e => {
      console.log(`์ด๋ฒคํŠธ ๋‹จ๊ณ„: ${e.eventPhase}`); // 1: ์บก์ฒ˜๋ง ๋‹จ๊ณ„
      console.log(`์ด๋ฒคํŠธ ํƒ€๊นƒ: ${e.target}`); // [object HTMLLIElement]
      console.log(`์ปค๋ŸฐํŠธ ํƒ€๊นƒ: ${e.currentTarget}`); // [object HTMLUListElement]
    }, true);

    // ํƒ€๊นƒ ๋‹จ๊ณ„์˜ ์ด๋ฒคํŠธ๋ฅผ ์บ์น˜ํ•œ๋‹ค.
    $banana.addEventListener('click', e => {
      console.log(`์ด๋ฒคํŠธ ๋‹จ๊ณ„: ${e.eventPhase}`); // 2: ํƒ€๊นƒ ๋‹จ๊ณ„
      console.log(`์ด๋ฒคํŠธ ํƒ€๊นƒ: ${e.target}`); // [object HTMLLIElement]
      console.log(`์ปค๋ŸฐํŠธ ํƒ€๊นƒ: ${e.currentTarget}`); // [object HTMLLIElement]
    });

    // ๋ฒ„๋ธ”๋ง ๋‹จ๊ณ„์˜ ์ด๋ฒคํŠธ๋ฅผ ์บ์น˜ํ•œ๋‹ค.
    $fruits.addEventListener('click', e => {
      console.log(`์ด๋ฒคํŠธ ๋‹จ๊ณ„: ${e.eventPhase}`); // 3: ๋ฒ„๋ธ”๋ง ๋‹จ๊ณ„
      console.log(`์ด๋ฒคํŠธ ํƒ€๊นƒ: ${e.target}`); // [object HTMLLIElement]
      console.log(`์ปค๋ŸฐํŠธ ํƒ€๊นƒ: ${e.currentTarget}`); // [object HTMLUListElement]
    });
  </script>
</body>
</html>
  • ul ์š”์†Œ์— ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ๋ฐ”์ธ๋”ฉํ•˜๊ณ  ul ์š”์†Œ์˜ ํ•˜์œ„ ์š”์†Œ์ธ li ์š”์†Œ๋ฅผ ํด๋ฆญํ•˜์—ฌ ์ด๋ฒคํŠธ๋ฅผ ๋ฐœ์ƒํ•˜๋ฉด ํด๋ฆญ ์ด๋ฒคํŠธ ๊ฐ์ฒด๊ฐ€ ์ƒ์„ฑ๋˜๊ณ  ํด๋ฆญ๋œ li ์š”์†Œ๊ฐ€ ์ด๋ฒคํŠธ ํƒ€๊นƒ์ด๋จ
    1. ์บก์ณ๋ง ๋‹จ๊ณ„ : ํด๋ฆญ ์ด๋ฒคํŠธ๋Š” window์—์„œ ์‹œ์ž‘ํ•ด์„œ ์ด๋ฒคํŠธ ํƒ€๊นƒ ๋ฐฉํ–ฅ์œผ๋กœ ์ „ํŒŒ
    2. ํƒ€๊นƒ ๋‹จ๊ณ„ : ์ด๋ฒคํŠธ ๊ฐ์ฒด๋Š” ์ด๋ฒคํŠธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚จ ์ด๋ฒคํŠธ ํƒ€๊นƒ์— ๋„๋‹ฌ
    3. ๋ฒ„๋ธ”๋ง ๋‹จ๊ณ„ : ์ด๋ฒคํŠธ ๊ฐ์ฒด๋Š” ์ด๋ฒคํŠธ ํƒ€๊นƒ์—์„œ ์‹œ์ž‘ํ•ด์„œ window ๋ฐฉํ–ฅ์œผ๋กœ ์ „ํŒŒ
  • ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ ์–ดํŠธ๋ฆฌ๋ทฐํŠธ/ํ”„๋กœํผํ‹ฐ ๋ฐฉ์‹์œผ๋กœ ๋“ฑ๋กํ•œ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋Š” ํƒ€๊นƒ ๋‹จ๊ณ„์™€ ๋ฒ„๋ธ”๋ง ๋‹จ๊ณ„์˜ ์ด๋ฒคํŠธ๋งŒ ์บ์น˜ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, addEventListener ๋ฉ”์„œ๋“œ ๋ฐฉ์‹์œผ๋กœ ๋“ฑ๋กํ•œ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋Š” ๋ฉ”์„œ๋“œ์˜ 3๋ฒˆ์งธ ์ธ์ˆ˜๋กœ true๋ฅผ ์ „๋‹ฌํ•˜๋ฉด ์บก์ฒ˜๋ง ๋‹จ๊ณ„์˜ ์ด๋ฒคํŠธ๋„ ์„ ๋ณ„์ ์œผ๋กœ ์บ์น˜ํ•  ์ˆ˜ ์žˆ์Œ

 

์ด์ฒ˜๋Ÿผ ์ด๋ฒคํŠธ๋Š” ์ด๋ฒคํŠธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚จ ์ด๋ฒคํŠธ ํƒ€๊นƒ์€ ๋ฌผ๋ก  ์ƒ์œ„ DOM ์š”์†Œ์—์„œ๋„ ์บ์น˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ฆ‰, DOM ํŠธ๋ฆฌ๋ฅผ ํ†ตํ•ด ์ „ํŒŒ๋˜๋Š” ์ด๋ฒคํŠธ๋Š” ์ด๋ฒคํŠธ ํŒจ์Šค(๊ฒฝ๋กœ)์— ์œ„์น˜ํ•œ ๋ชจ๋“  DOM ์š”์†Œ์—์„œ ์บ์น˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

๋Œ€๋ถ€๋ถ„์˜ ์ด๋ฒคํŠธ๋Š” ์บก์ฒ˜๋ž‘๊ณผ ๋ฒ„๋ธ”๋ง์„ ํ†ตํ•ด ์ „ํŒŒ๋˜์ง€๋งŒ, ํฌ์ปค์Šค ์ด๋ฒคํŠธ focus/blur, ๋ฆฌ์†Œ์Šค ์ด๋ฒคํŠธ load/unload/abort/error, ๋งˆ์šฐ์Šค ์ด๋ฒคํŠธ mouseenter/mouseleave๋Š” event.bubbles์˜ ๊ฐ’์ด ๋ชจ๋‘ false๋ผ ๋ฒ„๋ธ”๋ง์„ ํ†ตํ•ด ์ „ํŒŒ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์ƒ์œ„ ์š”์†Œ์—์„œ ์บ์น˜ํ•ด์•ผ ํ•œ๋‹ค๋ฉด ๋‹ค๋ฅธ ์ด๋ฒคํŠธ๋กœ ๋Œ€์ฒดํ•˜์—ฌ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.


์ด๋ฒคํŠธ ์œ„์ž„

์ด๋ฒคํŠธ ์œ„์ž„(event delegation)์€ ์—ฌ๋Ÿฌ ๊ฐœ์˜ ํ•˜์œ„ DOM ์š”์†Œ์— ๊ฐ๊ฐ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ๋“ฑ๋กํ•˜๋Š” ๋Œ€์‹  ํ•˜๋‚˜์˜ ์ƒ์œ„ DOM ์š”์†Œ์— ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ๋“ฑ๋กํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋งํ•ฉ๋‹ˆ๋‹ค.

 

<!DOCTYPE html>
<html>
<head>
  <style>
    #fruits {
      display: flex;
      list-style-type: none;
      padding: 0;
    }

    #fruits li {
      width: 100px;
      cursor: pointer;
    }

    #fruits .active {
      color: red;
      text-decoration: underline;
    }
  </style>
</head>
<body>
  <nav>
    <ul id="fruits">
      <li id="apple" class="active">Apple</li>
      <li id="banana">Banana</li>
      <li id="orange">Orange</li>
    </ul>
  </nav>
  <div>์„ ํƒ๋œ ๋‚ด๋น„๊ฒŒ์ด์…˜ ์•„์ดํ…œ: <em class="msg">apple</em></div>
  <script>
    const $fruits = document.getElementById('fruits');
    const $msg = document.querySelector('.msg');

    // ์‚ฌ์šฉ์ž ํด๋ฆญ์— ์˜ํ•ด ์„ ํƒ๋œ ๋‚ด๋น„๊ฒŒ์ด์…˜ ์•„์ดํ…œ(li ์š”์†Œ)์— active ํด๋ž˜์Šค๋ฅผ ์ถ”๊ฐ€ํ•˜๊ณ 
    // ๊ทธ ์™ธ์˜ ๋ชจ๋“  ๋‚ด๋น„๊ฒŒ์ด์…˜ ์•„์ดํ…œ์˜ active ํด๋ž˜์Šค๋ฅผ ์ œ๊ฑฐํ•œ๋‹ค.
    function activate({ target }) {
      // ์ด๋ฒคํŠธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚จ ์š”์†Œ(target)๊ฐ€ ul#fruits์˜ ์ž์‹ ์š”์†Œ๊ฐ€ ์•„๋‹ˆ๋ผ๋ฉด ๋ฌด์‹œํ•œ๋‹ค.
      if (!target.matches('#fruits > li')) return;

      [...$fruits.children].forEach($fruit => {
        $fruit.classList.toggle('active', $fruit === target);
        $msg.textContent = target.id;
      });
    }

    // ์ด๋ฒคํŠธ ์œ„์ž„: ์ƒ์œ„ ์š”์†Œ(ul#fruits)๋Š” ํ•˜์œ„ ์š”์†Œ์˜ ์ด๋ฒคํŠธ๋ฅผ ์บ์น˜ํ•  ์ˆ˜ ์žˆ๋‹ค.
    $fruits.onclick = activate;
  </script>
</body>
</html>

 

์ด์ฒ˜๋Ÿผ ์ด๋ฒคํŠธ ์œ„์ž„์„ ํ†ตํ•ด ํ•˜์œ„ DOM ์š”์†Œ์—์„œ ๋ฐœ์ƒํ•  ์ด๋ฒคํŠธ๋ฅผ ์ฒ˜๋ฆฌํ•  ๋•Œ ์ƒ์œ„ ์š”์†Œ์— ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ๋“ฑ๋กํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ด๋ฒคํŠธ ํƒ€๊นƒ์„ ๊ฒ€์‚ฌํ•˜์ง€ ์•Š์œผ๋ฉด ๊ฐœ๋ฐœ์ž๊ฐ€ ๊ธฐ๋Œ€ํ•œ DOM ์š”์†Œ๊ฐ€ ์•„๋‹Œ ๋‹ค๋ฅธ ๊ณณ์—์„œ ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒ๋  ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์„ ์ฃผ์˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.


DOM ์š”์†Œ์˜ ๊ธฐ๋ณธ ๋™์ž‘ ์กฐ๊ฑด

DOM ์š”์†Œ๋Š” ์ €๋งˆ๋‹ค ๊ธฐ๋ณธ ๋™์ž‘์„ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, a ์š”์†Œ๋ฅผ ํด๋ฆญํ•˜๋ฉด href ์–ดํŠธ๋ฆฌ๋ทฐํŠธ์— ์ง€์ •๋œ ๋งํฌ๋กœ ์ด๋™ํ•˜๊ณ , checkbox/radio ์š”์†Œ๋ฅผ ํด๋ฆญํ•˜๋ฉด ์ฒดํฌ/ํ•ด์ œ ๋ฉ๋‹ˆ๋‹ค.

 

DOM ์š”์†Œ์˜ ๊ธฐ๋ณธ ๋™์ž‘ ์ค‘๋‹จ

์ด๋ฒคํŠธ ๊ฐ์ฒด์˜ preventDefault ๋ฉ”์„œ๋“œ๋Š” DOM ์š”์†Œ์˜ ๊ธฐ๋ณธ ๋™์ž‘์„ ์ค‘๋‹จ์‹œํ‚ต๋‹ˆ๋‹ค.

 

<!DOCTYPE html>
<html>
<body>
  <a href="https://www.google.com">go</a>
  <input type="checkbox">
  <script>
    document.querySelector('a').onclick = e => {
      // a ์š”์†Œ์˜ ๊ธฐ๋ณธ ๋™์ž‘์„ ์ค‘๋‹จํ•œ๋‹ค.
      e.preventDefault();
    };

    document.querySelector('input[type=checkbox]').onclick = e => {
      // checkbox ์š”์†Œ์˜ ๊ธฐ๋ณธ ๋™์ž‘์„ ์ค‘๋‹จํ•œ๋‹ค.
      e.preventDefault();
    };
  </script>
</body>
</html>

 

์ด๋ฒคํŠธ ์ „ํŒŒ ๋ฐฉ์ง€

์ด๋ฒคํŠธ ๊ฐ์ฒด์˜ stopPropagation ๋ฉ”์„œ๋“œ๋Š” ์ด๋ฒคํŠธ ์ „ํŒŒ๋ฅผ ์ค‘์ง€์‹œํ‚ต๋‹ˆ๋‹ค.

 

<!DOCTYPE html>
<html>
<body>
  <div class="container">
    <button class="btn1">Button 1</button>
    <button class="btn2">Button 2</button>
    <button class="btn3">Button 3</button>
  </div>
  <script>
    // ์ด๋ฒคํŠธ ์œ„์ž„. ํด๋ฆญ๋œ ํ•˜์œ„ ๋ฒ„ํŠผ ์š”์†Œ์˜ color๋ฅผ ๋ณ€๊ฒฝํ•œ๋‹ค.
    document.querySelector('.container').onclick = ({ target }) => {
      if (!target.matches('.container > button')) return;
      target.style.color = 'red';
    };

    // .btn2 ์š”์†Œ๋Š” ์ด๋ฒคํŠธ๋ฅผ ์ „ํŒŒํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ ์ƒ์œ„ ์š”์†Œ์—์„œ ์ด๋ฒคํŠธ๋ฅผ ์บ์น˜ํ•  ์ˆ˜ ์—†๋‹ค.
    document.querySelector('.btn2').onclick = e => {
      e.stopPropagation(); // ์ด๋ฒคํŠธ ์ „ํŒŒ ์ค‘๋‹จ
      e.target.style.color = 'blue';
    };
  </script>
</body>
</html>
  • ํ•˜์œ„ DOM ์š”์†Œ์—์„œ ๋ฐœ์ƒํ•œ ํด๋ฆญ ์ด๋ฒคํŠธ๋ฅผ ์ƒ์œ„ DOM ์š”์†Œ์ธ container ์š”์†Œ๊ฐ€ ์บ์น˜ํ•˜์—ฌ ์ด๋ฒคํŠธ๋ฅผ ์ฒ˜๋ฆฌ
  • ํ•˜์œ„ ์š”์†Œ ์ค‘์—์„œ btn2 ์š”์†Œ๋Š” ์ด๋ฒคํŠธ ์ „ํŒŒ๊ฐ€ ์ค‘๋‹จ๋˜์–ด ์ž์ฒด์ ์œผ๋กœ ์ด๋ฒคํŠธ๋ฅผ ์ฒ˜๋ฆฌ

์ด์ฒ˜๋Ÿผ stopPropagation ๋ฉ”์„œ๋“œ๋Š” ํ•˜์œ„ DOM ์š”์†Œ์˜ ์ด๋ฒคํŠธ๋ฅผ ๊ฐœ๋ณ„์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด ์ด๋ฒคํŠธ ์ „ํŒŒ๋ฅผ ์ค‘๋‹จ์‹œํ‚ต๋‹ˆ๋‹ค.


์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ ๋‚ด๋ถ€์˜ this

์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ ์–ดํŠธ๋ฆฌ๋ทฐํŠธ ๋ฐฉ์‹

์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ ์–ดํŠธ๋ฆฌ๋ทฐํŠธ์˜ ๊ฐ’์œผ๋กœ ์ง€์ •ํ•œ ๋ฌธ์ž์—ด์€ ์‚ฌ์‹ค ์•”๋ฌต์ ์œผ๋กœ ์ƒ์„ฑ๋˜๋Š” ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ์˜ ๋ฌธ์ด๊ธฐ ๋•Œ๋ฌธ์— ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ์— ์˜ํ•ด ์ผ๋ฐ˜ ํ•จ์ˆ˜๋กœ ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ํ•จ์ˆ˜ ๋‚ด๋ถ€์˜ this๋Š” ์ „์—ญ ๊ฐ์ฒด์ธ window๋ฅผ ๊ฐ€๋ฆฌํ‚ต๋‹ˆ๋‹ค. ๋‹จ, ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ํ˜ธ์ถœํ•  ๋•Œ ์ธ์ˆ˜๋กœ ์ „๋‹ฌํ•œ this๋Š” ์ด๋ฒคํŠธ๋ฅผ ๋ฐ”์ธ๋”ฉํ•œ DOM ์š”์†Œ๋ฅผ ๊ฐ€๋ฆฌํ‚ต๋‹ˆ๋‹ค.

 

<!DOCTYPE html>
<html>
<body>
  <button onclick="handleClick(this)">Click me</button>
  <script>
    function handleClick(button) {
      console.log(button); // ์ด๋ฒคํŠธ๋ฅผ ๋ฐ”์ธ๋”ฉํ•œ button ์š”์†Œ
      console.log(this);   // window
    }
  </script>
</body>
</html>

 

 

์ด์ฒ˜๋Ÿผ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ ์–ดํŠธ๋ฆฌ๋ทฐํŠธ ๋ฐฉ์‹์— ์˜ํ•ด ์•”๋ฌต์ ์œผ๋กœ ์ƒ์„ฑ๋œ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ ๋‚ด๋ถ€์˜ this๋Š” ์ด๋ฒคํŠธ๋ฅผ ๋ฐ”์ธ๋”ฉํ•œ DOM ์š”์†Œ๋ฅผ ๊ฐ€๋ฅดํ‚ค๋ฉฐ ์ด๋Š” ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ ํ”„๋กœํผํ‹ฐ ๋ฐฉ์‹๊ณผ ๋™์ผํ•ฉ๋‹ˆ๋‹ค.

 

 

์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ ํ”„๋กœํผํ‹ฐ ๋ฐฉ์‹๊ณผ addEventListener ๋ฉ”์„œ๋“œ ๋ฐฉ์‹

๋‘ ๋ฐฉ์‹ ๋ชจ๋‘ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ ๋‚ด๋ถ€์˜ this๋Š” ์ด๋ฒคํŠธ๋ฅผ ๋ฐ”์ธ๋”ฉํ•œ DOM ์š”์†Œ๋ฅผ ๊ฐ€๋ฅดํ‚ต๋‹ˆ๋‹ค. ์ฆ‰, ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ ๋‚ด๋ถ€์˜ this๋Š” ์ด๋ฒคํŠธ ๊ฐ์ฒด์˜ currentTarget ํ”„๋กœํผํ‹ฐ์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค. 

 

<!DOCTYPE html>
<html>
<body>
  <button class="btn1">0</button>
  <button class="btn2">0</button>
  <script>
    const $button1 = document.querySelector('.btn1');
    const $button2 = document.querySelector('.btn2');

    // ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ ํ”„๋กœํผํ‹ฐ ๋ฐฉ์‹
    $button1.onclick = function (e) {
      // this๋Š” ์ด๋ฒคํŠธ๋ฅผ ๋ฐ”์ธ๋”ฉํ•œ DOM ์š”์†Œ๋ฅผ ๊ฐ€๋ฆฌํ‚จ๋‹ค.
      console.log(this); // $button1
      console.log(e.currentTarget); // $button1
      console.log(this === e.currentTarget); // true

      // $button1์˜ textContent๋ฅผ 1 ์ฆ๊ฐ€์‹œํ‚จ๋‹ค.
      ++this.textContent;
    };

    // addEventListener ๋ฉ”์„œ๋“œ ๋ฐฉ์‹
    $button2.addEventListener('click', function (e) {
      // this๋Š” ์ด๋ฒคํŠธ๋ฅผ ๋ฐ”์ธ๋”ฉํ•œ DOM ์š”์†Œ๋ฅผ ๊ฐ€๋ฆฌํ‚จ๋‹ค.
      console.log(this); // $button2
      console.log(e.currentTarget); // $button2
      console.log(this === e.currentTarget); // true

      // $button2์˜ textContent๋ฅผ 1 ์ฆ๊ฐ€์‹œํ‚จ๋‹ค.
      ++this.textContent;
    });
  </script>
</body>
</html>

์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ์— ์ธ์ˆ˜ ์ „๋‹ฌ

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

  • ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ ๋‚ด๋ถ€์—์„œ ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด์„œ ์ธ์ˆ˜๋ฅผ ์ „๋‹ฌ
<!DOCTYPE html>
<html>
<body>
  <label>User name <input type='text'></label>
  <em class="message"></em>
  <script>
    const MIN_USER_NAME_LENGTH = 5; // ์ด๋ฆ„ ์ตœ์†Œ ๊ธธ์ด
    const $input = document.querySelector('input[type=text]');
    const $msg = document.querySelector('.message');

    const checkUserNameLength = min => {
      $msg.textContent
        = $input.value.length < min ? `์ด๋ฆ„์€ ${min}์ž ์ด์ƒ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”` : '';
    };

    // ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ ๋‚ด๋ถ€์—์„œ ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด์„œ ์ธ์ˆ˜๋ฅผ ์ „๋‹ฌํ•œ๋‹ค.
    $input.onblur = () => {
      checkUserNameLength(MIN_USER_NAME_LENGTH);
    };
  </script>
</body>
</html>

 

  • ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด์„œ ์ธ์ˆ˜๋ฅผ ์ „๋‹ฌ
<!DOCTYPE html>
<html>
<body>
  <label>User name <input type='text'></label>
  <em class="message"></em>
  <script>
    const MIN_USER_NAME_LENGTH = 5; // ์ด๋ฆ„ ์ตœ์†Œ ๊ธธ์ด
    const $input = document.querySelector('input[type=text]');
    const $msg = document.querySelector('.message');

    // ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜
    const checkUserNameLength = min => e => {
      $msg.textContent
        = $input.value.length < min ? `์ด๋ฆ„์€ ${min}์ž ์ด์ƒ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”` : '';
    };

    // ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด์„œ ์ธ์ˆ˜๋ฅผ ์ „๋‹ฌํ•œ๋‹ค.
    $input.onblur = checkUserNameLength(MIN_USER_NAME_LENGTH);
  </script>
</body>
</html>

์ปค์Šคํ…€ ์ด๋ฒคํŠธ

์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ์•”๋ฌต์ ์œผ๋กœ ์ƒ์„ฑ๋˜๋Š” ์ด๋ฒคํŠธ ๊ฐ์ฒด๋Š” ๋ฐœ์ƒํ•œ ์ด๋ฒคํŠธ์˜ ์ข…๋ฅ˜์— ๋”ฐ๋ผ ์ด๋ฒคํŠธ ํƒ€์ž…์ด ๊ฒฐ์ •๋˜์ง€๋งŒ Event, UIEvent, MouseEvent ๊ฐ™์€ ์ด๋ฒคํŠธ ์ƒ์„ฑ์ž ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ๋ช…์‹œ์ ์œผ๋กœ ์ƒ์„ฑํ•œ ์ด๋ฒคํŠธ ๊ฐ์ฒด๋Š” ์ž„์˜์˜ ์ด๋ฒคํŠธ ํƒ€์ž…์„ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด์ฒ˜๋Ÿผ ๊ฐœ๋ฐœ์ž์˜ ์˜๋„๋กœ ์ƒ์„ฑ๋œ ์ด๋ฒคํŠธ๋ฅผ ์ปค์Šคํ…€ ์ด๋ฒคํŠธ๋ผ ํ•ฉ๋‹ˆ๋‹ค.

 

์ปค์Šคํ…€ ์ด๋ฒคํŠธ ์ƒ์„ฑ

์ด๋ฒคํŠธ ์ƒ์„ฑ์ž ํ•จ์ˆ˜๋Š” ์ฒซ ๋ฒˆ์งธ ์ธ์ˆ˜๋กœ ์ด๋ฒคํŠธ ํƒ€์ž…์„ ๋‚˜ํƒ€๋‚ด๋Š” ๋ฌธ์ž์—ด์„ ์ „๋‹ฌ๋ฐ›์Šต๋‹ˆ๋‹ค. ์ด๋•Œ ๊ธฐ์กด ์ด๋ฒคํŠธ ํƒ€์ž…์ด ์•„๋‹Œ ์ž„์˜์˜ ๋ฌธ์ž์—ด์„ ์‚ฌ์šฉํ•ด ์ƒˆ๋กœ์šด ์ด๋ฒคํŠธ ํƒ€์ž…์„ ์ง€์ •ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

 

์ผ๋ฐ˜์ ์œผ๋กœ ์•„๋ž˜์™€ ๊ฐ™์ด CustomEvent ์ด๋ฒคํŠธ ์ƒ์„ฑ์ž ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•ด ์ปค์Šคํ…€ ์ด๋ฒคํŠธ๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

 

// KeyboardEvent ์ƒ์„ฑ์ž ํ•จ์ˆ˜๋กœ keyup ์ด๋ฒคํŠธ ํƒ€์ž…์˜ ์ปค์Šคํ…€ ์ด๋ฒคํŠธ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑ
const keyboardEvent = new KeyboardEvent('keyup');
console.log(keyboardEvent.type); // keyup

// CustomEvent ์ƒ์„ฑ์ž ํ•จ์ˆ˜๋กœ foo ์ด๋ฒคํŠธ ํƒ€์ž…์˜ ์ปค์Šคํ…€ ์ด๋ฒคํŠธ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑ
const customEvent = new CustomEvent('foo');
console.log(customEvent.type); // foo

// MouseEvent ์ƒ์„ฑ์ž ํ•จ์ˆ˜๋กœ click ์ด๋ฒคํŠธ ํƒ€์ž…์˜ ์ปค์Šคํ…€ ์ด๋ฒคํŠธ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑ
const customEvent = new MouseEvent('click');
console.log(customEvent.type); // click
console.log(customEvent.bubbles); // false
console.log(customEvent.cancelable); // false

// MouseEvent ์ƒ์„ฑ์ž ํ•จ์ˆ˜๋กœ click ์ด๋ฒคํŠธ ํƒ€์ž…์˜ ์ปค์Šคํ…€ ์ด๋ฒคํŠธ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑ
const customEvent = new MouseEvent('click', {
  bubbles: true,
  cancelable: true
});

console.log(customEvent.bubbles); // true
console.log(customEvent.cancelable); // true

// MouseEvent ์ƒ์„ฑ์ž ํ•จ์ˆ˜๋กœ click ์ด๋ฒคํŠธ ํƒ€์ž…์˜ ์ปค์Šคํ…€ ์ด๋ฒคํŠธ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑ
const mouseEvent = new MouseEvent('click', {
  bubbles: true,
  cancelable: true,
  clientX: 50,
  clientY: 100
});

console.log(mouseEvent.clientX); // 50
console.log(mouseEvent.clientY); // 100

// KeyboardEvent ์ƒ์„ฑ์ž ํ•จ์ˆ˜๋กœ keyup ์ด๋ฒคํŠธ ํƒ€์ž…์˜ ์ปค์Šคํ…€ ์ด๋ฒคํŠธ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑ
const keyboardEvent = new KeyboardEvent('keyup', { key: 'Enter' });

console.log(keyboardEvent.key); // Enter

// InputEvent ์ƒ์„ฑ์ž ํ•จ์ˆ˜๋กœ foo ์ด๋ฒคํŠธ ํƒ€์ž…์˜ ์ปค์Šคํ…€ ์ด๋ฒคํŠธ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑ
const customEvent = new InputEvent('foo');
console.log(customEvent.isTrusted); // false
  • ๋ฒ„๋ธ”๋ง๋˜์ง€ ์•Š์œผ๋ฉฐ, preventDefault ๋ฉ”์„œ๋“œ๋กœ ์ทจ์†Œํ•  ์ˆ˜๋„ ์—†์Œ (bubbles์™€ cancelable์ด false)
  • ์ปค์Šคํ…€ ์ด๋ฒคํŠธ ๊ฐ์ฒด์˜ bubbles/cancelable ํ”„๋กœํผํ‹ฐ๋ฅผ true๋กœ ์„ค์ •ํ•˜๋ ค๋ฉด ์ด๋ฒคํŠธ ์ƒ์„ฑ์ž ํ•จ์ˆ˜์˜ ๋‘ ๋ฒˆ์งธ ์ธ์ˆ˜๋กœ bubbles/cancelable ํ”„๋กœํผํ‹ฐ๋ฅผ ๊ฐ–๋Š” ๊ฐ์ฒด๋ฅผ ์ „๋‹ฌํ•ด์•ผ ํ•จ
  • ์ด๋ฒคํŠธ ํƒ€์ž…์— ๋”ฐ๋ผ ๊ฐ€์ง€๋Š” ์ด๋ฒคํŠธ ๊ณ ์œ ์˜ ํ”„๋กœํผํ‹ฐ ๊ฐ’์„ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์Œ
  • ์ด๋ฒคํŠธ ์ƒ์„ฑ์ž ํ•จ์ˆ˜๋กœ ์ƒ์„ฑํ•œ ์ปค์Šคํ…€ ์ด๋ฒคํŠธ๋Š” isTrusted ํ”„๋กœํผํ‹ฐ์˜ ๊ฐ’์ด ์–ธ์ œ๋‚˜ false

 

์ปค์Šคํ…€ ์ด๋ฒคํŠธ ๋””์ŠคํŒจ์น˜

์ƒ์„ฑ๋œ ์ปค์Šคํ…€ ์ด๋ฒคํŠธ๋Š” dispatchEvent ๋ฉ”์„œ๋“œ๋กœ ๋””์ŠคํŒจ์น˜(์ด๋ฒคํŠธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚ค๋Š” ํ–‰์œ„)ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. dispatchEvent ๋ฉ”์„œ๋“œ์— ์ด๋ฒคํŠธ ๊ฐ์ฒด๋ฅผ ์ธ์ˆ˜๋กœ ์ „๋‹ฌํ•˜๋ฉด์„œ ํ˜ธ์ถœํ•˜๋ฉด ์ธ์ˆ˜๋กœ ์ „๋‹ฌํ•œ ์ด๋ฒคํŠธ ํƒ€์ž…์˜ ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

 

<!DOCTYPE html>
<html>
<body>
  <button class="btn">Click me</button>
  <script>
    const $button = document.querySelector('.btn');

    // ๋ฒ„ํŠผ ์š”์†Œ์— click ์ปค์Šคํ…€ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ๋“ฑ๋ก
    // ์ปค์Šคํ…€ ์ด๋ฒคํŠธ๋ฅผ ๋””์ŠคํŒจ์น˜ํ•˜๊ธฐ ์ด์ „์— ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ๋“ฑ๋กํ•ด์•ผ ํ•œ๋‹ค.
    $button.addEventListener('click', e => {
      console.log(e); // MouseEvent {isTrusted: false, screenX: 0, ...}
      alert(`${e} Clicked!`);
    });

    // ์ปค์Šคํ…€ ์ด๋ฒคํŠธ ์ƒ์„ฑ
    const customEvent = new MouseEvent('click');

    // ์ปค์Šคํ…€ ์ด๋ฒคํŠธ ๋””์ŠคํŒจ์น˜(๋™๊ธฐ ์ฒ˜๋ฆฌ). click ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.
    $button.dispatchEvent(customEvent);
  </script>
</body>
</html>

 

dispatchEvent ๋ฉ”์„œ๋“œ๋Š” ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ๋™๊ธฐ ์ฒ˜๋ฆฌ ๋ฐฉ์‹์œผ๋กœ ํ˜ธ์ถœํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋””์ŠคํŒจ์น˜ ํ•˜๊ธฐ ์ด์ „์— ์ปค์Šคํ…€ ์ด๋ฒคํŠธ๋ฅผ ์ฒ˜๋ฆฌํ•  ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ๋“ฑ๋กํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ๊ธฐ์กด ์ด๋ฒคํŠธ ํƒ€์ž…์ด ์•„๋‹Œ ์ž„์˜์˜ ์ด๋ฒคํŠธ ํƒ€์ž…์„ ์ง€์ •ํ•˜์—ฌ ์ปค์Šคํ…€ ์ด๋ฒคํŠธ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•œ ๊ฒฝ์šฐ ๋ฐ˜๋“œ์‹œ addEventListener ๋ฉ”์„œ๋“œ ๋ฐฉ์‹์œผ๋กœ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ๋“ฑ๋กํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

 

<!DOCTYPE html>
<html>
<body>
  <button class="btn">Click me</button>
  <script>
    const $button = document.querySelector('.btn');

    // ๋ฒ„ํŠผ ์š”์†Œ์— foo ์ปค์Šคํ…€ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ๋“ฑ๋ก
    // ์ปค์Šคํ…€ ์ด๋ฒคํŠธ๋ฅผ ๋””์ŠคํŒจ์น˜ํ•˜๊ธฐ ์ด์ „์— ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ๋“ฑ๋กํ•ด์•ผ ํ•œ๋‹ค.
    $button.addEventListener('foo', e => {
      // e.detail์—๋Š” CustomEvent ํ•จ์ˆ˜์˜ ๋‘ ๋ฒˆ์งธ ์ธ์ˆ˜๋กœ ์ „๋‹ฌํ•œ ์ •๋ณด๊ฐ€ ๋‹ด๊ฒจ ์žˆ๋‹ค.
      alert(e.detail.message);
    });

    // CustomEvent ์ƒ์„ฑ์ž ํ•จ์ˆ˜๋กœ foo ์ด๋ฒคํŠธ ํƒ€์ž…์˜ ์ปค์Šคํ…€ ์ด๋ฒคํŠธ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑ
    const customEvent = new CustomEvent('foo', {
      detail: { message: 'Hello' } // ์ด๋ฒคํŠธ์™€ ํ•จ๊ป˜ ์ „๋‹ฌํ•˜๊ณ  ์‹ถ์€ ์ •๋ณด
    });

    // ์ปค์Šคํ…€ ์ด๋ฒคํŠธ ๋””์ŠคํŒจ์น˜
    $button.dispatchEvent(customEvent);
  </script>
</body>
</html>

[์ถœ์ฒ˜] ๋ชจ๋˜ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ Deep Dive

https://wikibook.co.kr/mjs/

 

๋ชจ๋˜ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ Deep Dive: ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์˜ ๊ธฐ๋ณธ ๊ฐœ๋…๊ณผ ๋™์ž‘ ์›๋ฆฌ

269๊ฐœ์˜ ๊ทธ๋ฆผ๊ณผ ์›๋ฆฌ๋ฅผ ํŒŒํ—ค์น˜๋Š” ์„ค๋ช…์œผ๋กœ ‘์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์˜ ๊ธฐ๋ณธ ๊ฐœ๋…๊ณผ ๋™์ž‘ ์›๋ฆฌ’๋ฅผ ์ดํ•ดํ•˜์ž! ์›นํŽ˜์ด์ง€์˜ ๋‹จ์ˆœํ•œ ๋ณด์กฐ ๊ธฐ๋Šฅ์„ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•œ ์ œํ•œ์ ์ธ ์šฉ๋„๋กœ ํƒœ์–ด๋‚œ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋Š” ๊ณผ๋„

wikibook.co.kr

https://frontsom.tistory.com/12

 

์ด๋ฒคํŠธ ๋ฒ„๋ธ”๋ง(Bubbling)๊ณผ ์บก์ณ๋ง(Capturing)

์ด๋ฒˆ์—๋Š” ๊ฝค ๊ธฐ์ดˆ์ ์ด์ง€๋งŒ ์ค‘์š”ํ•œ JavaScript๋กœ ๊ตฌํ˜„ํ•œ ์ด๋ฒคํŠธ๋ฅผ ๋ธŒ๋ผ์šฐ์ €์—์„œ ํ™”๋ฉด ๊ตฌ์„ฑ์š”์†Œ๊ฐ€ ์–ด๋–ป๊ฒŒ ๊ฐ์ง€ํ•˜๊ณ , ๊ทธ ์ด๋ฒคํŠธ๊ฐ€ ๋‹ค๋ฅธ ํ™”๋ฉด ์š”์†Œ์— ์ „ํŒŒ๋˜๋Š”์ง€์— ๋Œ€ํ•œ ํฌ์ŠคํŒ… ๊ธ€์„ ์ž‘์„ฑํ•˜๋ ค๊ณ  ํ•œ๋‹ค.

frontsom.tistory.com