Skip to content

Commit 85ec10e

Browse files
committed
✏️ 이벤트 추가, 수정 필요
1 parent f90772f commit 85ec10e

File tree

3 files changed

+225
-0
lines changed

3 files changed

+225
-0
lines changed

Browser/event.md

Lines changed: 205 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,205 @@
1+
브라우저는 처리해야 할 사건이 발생하면 이를 감지해서 이벤트를 발생 시킵니다. 이러한 이벤트와 대응하는 함수를 통해 프로그래밍을 제어할 수 있죠. 이벤트에 대해 자세히 알아봅시다.
2+
3+
<br>
4+
5+
## 이벤트 드리븐 프로그래밍
6+
> 이벤트가 발생했을 때 호출되는 함수를 이벤트 핸들러(Event Handler), 이벤트 발생 시 브라우저에 이벤트 핸들러 호출을 위임하는 것을 이벤트 **핸들러 등록**이라고 합니다.
7+
8+
사용자가 버튼을 클릭했을 때 특정 함수를 호출하고 싶다 가정해볼까요? 문제는 `언제 호출이 되는가`입니다. 사용자가 언제 버튼을 클릭할 수 없으니까요. 다행히 브라우저는 사용자의 버튼 클릭을 **감지**할 수 있으며, 클릭 이벤트를 **발생**시킬 수도 있죠. 클릭 이벤트가 발생하면 특정 함수(이벤트 핸들러)를 호출하도록 브라우저에게 **위임**할 수도 있습니다.
9+
10+
이렇게 이벤트와 이벤트 핸들러를 통해 사용자와 애플리케이션은 **상호작용(Interfaction)** 할 수 있는데, 결국 프로그램의 흐름이 이벤트 중심으로 제어됩니다. 이러한 프로그래밍 방식을 `이벤트 드리븐 프로그래밍(Event-driven Programming)`이라 합니다.
11+
12+
<br>
13+
14+
## 이벤트 타입
15+
> 이벤트 타입(Event Type)은 이벤트 종류를 나타내는 문자열입니다.
16+
17+
이벤트 타입은 약 200여 가지가 있는데, 상세 목록은 [여기](https://developer.mozilla.org/ko/docs/Web/Events)에서 확인해주세요. 큰 맥락의 이벤트 종류는 아래와 같습니다.
18+
- 마우스(Mouse) 이벤트
19+
- 키보드(Keyboard) 이벤트
20+
- 포커스(Focus) 이벤트
21+
- 폼(Form) 이벤트
22+
- 값 변경(Change Value) 이벤트
23+
- DOM 뮤테이션(Mutation) 이벤트
24+
- 뷰(View) 이벤트
25+
- 리소스(Resources) 이벤트
26+
27+
<br>
28+
29+
## 이벤트 핸들러 등록
30+
> 이벤트 핸들러(Event Handler 또는 Event Listener)는 이벤트가 발생했을 때 브라우저에 호출을 위임한 함수입니다.
31+
32+
이벤트가 발생하면 브라우저에 의해 호출될 함수가 이벤트 핸들러이며, 이를 등록하는 방법은 3가지가 있습니다.
33+
34+
<br>
35+
36+
### 이벤트 핸들러 어트리뷰트
37+
> 이벤트 핸들러 어트리뷰트 값으로 함수 호출문 등의 문(Statement)을 할당하면 이벤트 핸들러가 등록됩니다.
38+
39+
HTML 요소 중에는 이벤트에 대응하는 이벤트 핸들러 어트리뷰트가 있는데, on 접두사와 이벤트의 종류를 나타내는 이벤트 타입으로 이루어져 있습니다. `onclick`, `onchange`, `onfocus`처럼 말이죠. 이벤트 등록 방법은 아래와 같습니다.
40+
```html
41+
<!DOCTYPE html>
42+
<html lang="en">
43+
44+
<head>
45+
<meta charset="UTF-8">
46+
<meta http-equiv="X-UA-Compatible" content="IE=edge">
47+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
48+
<title>Document</title>
49+
</head>
50+
51+
<body>
52+
<button onclick="displayAlert('Hi!')">Click to Hi</button>
53+
<script>
54+
function displayAlert(greeting) {
55+
return alert(greeting);
56+
}
57+
</script>
58+
</body>
59+
60+
</html>
61+
```
62+
- 함수 참조가 아닌 함수 호출문 등의 ****을 할당합니다.
63+
- 콜백 함수와 마찬가지로 함수 참조를 등록해야 브라우저가 이벤트 핸들러를 호출할 수 있습니다.
64+
- 만약 함수 호출문을 등록하면 그 평가 결과가 이벤트 핸들러로 등록되므로, 고차 함수 호출문이라면 문제가 없지만 함수가 아닌 값을 반환하는 함수 호출문의 경우 브라우저가 이벤트 핸들러를 호출할 수 없습니다.
65+
- **이벤트 핸들러 어트리뷰트 값은 암묵적으로 생성될 이벤트 핸들러의 함수 몸체를 의미**합니다.
66+
```js
67+
// onclick="displayAlert('Hi!')" 어트리뷰트는
68+
// 자바스크립트 엔진에 의해 파싱되어 암묵적으로 함수를 생성합니다.
69+
function onclick(event){
70+
displayAlert('Hi');
71+
}
72+
// 그 후 onclick 이벤트 핸들러 프로퍼티에 할당합니다.
73+
```
74+
75+
이처럼 동작하는 이유는 이벤트 핸들러에 인수를 전달하기 위해서입니다. 함수 참조를 할당한다면 이벤트 핸들러에 인수를 전달하기 곤란해지거든요.
76+
```html
77+
// 너무 곤란해요.
78+
<button onclick="displayAlert">
79+
Click to Hi
80+
</button>
81+
```
82+
83+
따라서 이벤트 핸들러 어트리뷰트 값으로 여러 문을 할당할 수 있습니다.
84+
```html
85+
<button onclick="console.log('Hi'); alert('Hi!');">
86+
Click to Hi
87+
</button>
88+
```
89+
90+
기본적으로 HTML과 자바스크립트는 관심사가 다르므로 분리하는 것이 좋습니다. 그러나 모던 자바스크립트의 CBD(Component Based Development)의 경우 HTML, CSS, 자바스크립트를 관심사가 분리되어있지 않고 View를 구성하는 요소로 판단하므로 혼재하여 사용합니다.
91+
```html
92+
<!-- Angular.js -->
93+
<button (click)="handleClick($event)">
94+
Click
95+
</button>
96+
<!-- React.js -->
97+
<button onClick={handleClick}>
98+
Click
99+
</button>
100+
<!-- Vue.js -->
101+
<button on:click={handleClick}>
102+
Click
103+
</button>
104+
<!-- Svelte.js -->
105+
<button v-on:click="handleClick($event)">
106+
Click
107+
</button>
108+
```
109+
110+
<br>
111+
112+
### 이벤트 핸들러 프로퍼티
113+
> window 객체, Document와 HTMLElement 타입의 DOM Node 객체는 이벤트에 대응하는 이벤트 핸들러 프로퍼티를 가지며, 함수를 등록하면 해당 이벤트 핸들러 프로퍼티에 바인딩됩니다.
114+
115+
이벤트 핸들러 프로퍼티 키는 이벤트 핸들러 어트리뷰트와 마찬가지로 on 접두사와 이벤트 종류를 나타내는 이벤트 타입으로 이루어져 있습니다.
116+
```html
117+
<!DOCTYPE html>
118+
<html lang="en">
119+
120+
<head>
121+
<meta charset="UTF-8">
122+
<meta http-equiv="X-UA-Compatible" content="IE=edge">
123+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
124+
<title>Document</title>
125+
</head>
126+
127+
<body>
128+
<button>Click</button>
129+
<script>
130+
const $button = document.querySelector('button');
131+
$button.onclick = function () {
132+
console.log('button click');
133+
}
134+
</script>
135+
</body>
136+
137+
</html>
138+
```
139+
140+
이벤트 핸들러를 등록하기 위해 이벤트를 발생시킬 객체인 이벤트 타겟(Event Target)과 이벤트 종류를 나타내는 문자열인 이벤트 타입(Event Type)이 필요합니다. 위의 경우 이벤트 타겟은 **버튼 요소**, 이벤트 타입은 **'click'**, 이벤트 핸들러는 **익명 함수**입니다.
141+
142+
대부분 이벤트를 발생시킬 이벤트 타겟에 바인딩하여 이벤트 핸들러를 등록하지만, 반드시 그런 것은 아닙니다. 이벤트 핸들러는 `이벤트 타겟 또는 전파된 이벤트를 캐치할 DOM 노드 객체에 바인딩` 되기 때문이죠.
143+
144+
이벤트 핸들러 어트리뷰트도 결국 DOM Node 객체의 이벤트 핸들러 프로퍼티로 변환되기 때문에 결과적으로는 동일하게 등록하는 방식이나, 가장 큰 차이점은 `HTML과 자바스크립트의 분리`입니다. 그런데, 큰 문제가 있습니다. 객체의 프로퍼티는 중첩되지 않으므로 이벤트 핸들러 프로퍼티는 단 하나만 등록할 수 있는 것이죠. 이를 해결하기 위해 DOM 표준에 추가된 메서드가 있습니다.
145+
146+
<br>
147+
148+
### `addEventListener` 메서드
149+
> DOM Level 2에 도입되었으며 `EventTarget.prototype.addEventListener` 메서드를 사용해 이벤트 핸들러를 등록할 수 있습니다.
150+
151+
<br>
152+
153+
<div align='center'>
154+
155+
<img src='./img/event/addEventListener.jpg' width='900'/>
156+
157+
</div>
158+
159+
<br>
160+
161+
- 첫 번째 매개변수는 문자열인 이벤트 타입을 전달하는데 이벤트 핸들러 프로퍼티 방식과 달리 on 접두사를 붙이지 않습니다.
162+
- 두 번째 매개변수에는 이벤트 핸들러를 전달합니다.
163+
- 세 번째 매개변수로는 이벤트 전파 단계(캡처링 또는 버블링)를 지정할 수 있습니다.
164+
165+
```html
166+
<!DOCTYPE html>
167+
<html lang="en">
168+
169+
<head>
170+
<meta charset="UTF-8">
171+
<meta http-equiv="X-UA-Compatible" content="IE=edge">
172+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
173+
<title>Document</title>
174+
</head>
175+
176+
<body>
177+
<button>Click</button>
178+
<script>
179+
const $button = document.querySelector('button');
180+
$button.addEventListener('click', function () {
181+
console.log('button click');
182+
});
183+
</script>
184+
</body>
185+
186+
</html>
187+
```
188+
- addEventListener 메서드 방식은 이벤트 핸들러 프로퍼티에 바인딩된 이벤트 핸들러에 아무런 영향을 주지 않습니다.
189+
- 이벤트 핸들러 프로퍼티에 이벤트 핸들러를 바인딩하지 않고 이벤트 핸들러를 `인수로 전달`하기 때문이죠.
190+
- addEventListener 메서드는 하나 이상의 이벤트를 등록할 수 있으며, 이벤트 핸들러는 등록된 순서대로 호출됩니다.
191+
- 단, 참조가 동일한 이벤트 핸들러를 중복 등록하면 하나의 이벤트 핸들러만 등록됩니다.
192+
```html
193+
<script>
194+
const $button = document.querySelector('button');
195+
196+
const handleClick = function () {
197+
console.log('button click');
198+
}
199+
// 하나만 등록됩니다.
200+
$button.addEventListener('click', handleClick);
201+
$button.addEventListener('click', handleClick);
202+
</script>
203+
```
204+
205+
<br>
105 KB
Loading

Browser/index.html

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
4+
<head>
5+
<meta charset="UTF-8">
6+
<meta http-equiv="X-UA-Compatible" content="IE=edge">
7+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
8+
<title>Document</title>
9+
</head>
10+
11+
<body>
12+
<button onclick="displayAlert('Hi!')">Click to Hi</button>
13+
<script>
14+
function displayAlert(greeting) {
15+
return alert(greeting);
16+
}
17+
</script>
18+
</body>
19+
20+
</html>

0 commit comments

Comments
 (0)