이벤트(event)는 브라우저에서 발생하는 다양한 상황을 의미한다.
예를 들어, 버튼을 클릭하거나 마우스를 움직이는 등의 동작, 웹 페이지의 로딩 완료, 입력 필드에서 값이 변경될 때 등 다양한 상황이 이벤트로 간주될 수 있다.
이벤트가 발생하면, 이를 처리하는 이벤트 핸들러(event handler)를 등록하여 원하는 동작을 수행할 수 있다.
이벤트는 일반적으로 함수와 연결된다.
이 함수는 이벤트가 발생되기 전에는 실행되지 않다가 이벤트가 발생할 경우 실행된다.
각각 이후의 실습에 적용해보도록 하겠다.
대표적인 메서드들은 다음과 같다.
이벤트 핸들러를 HTML 요소에 직접 작성하는 방식을 의미한다.
즉, HTML 요소의 속성값으로 JavaScript 코드를 포함하는 이벤트 핸들러를 지정하는 방식이다.
ex) 버튼 클릭 시 메시지를 띄우는 이벤트 핸들러
<button onclick="alert('버튼이 클릭되었습니다!')">클릭</button>
인라인 이벤트 핸들러 방식은 코드가 직관적이고 간단하게 작성할 수 있어서 초보자들이 사용하기 쉬운 방식이다.
하지만 코드의 가독성이 나쁘고, JavaScript 코드와 HTML 요소가 섞여 있어서 유지보수가 어려워지는 문제가 있다.
따라서 대부분의 개발자들은 이벤트 핸들러를 JavaScript 코드로 작성하고, HTML 요소와 JavaScript 코드를 분리하는 방식으로 작성하는 것을 권장한다.
최근 관심 받고 있는 CBD (Component Based Development) 방식의 Angular / React / Vue.js와 같은 framework / library에서는 인라인 방식으로 이벤트를 처리한다.
(CBD는 html, css, js를 view의 구성 요소로만 보기 때문)
JavaScript 코드로 이벤트를 작성하는 방식이다.
앞서 설명한 인라인 이벤트 핸들러와 달리, 달리 JavaScript 코드와 HTML 요소를 분리하여 작성할 수 있어서 유지보수가 용이하다는 장점이 있다.
이벤트 핸들러 프로퍼티 방식으로 이벤트 핸들러를 작성하기 위해서는 코드 할당이 필요하다.
이벤트가 발생할 HTML 요소를 선택하고, 해당 요소의 이벤트 핸들러 프로퍼티에 JavaScript 코드를 할당하면 된다. 다음 예시를 살펴보자.
/* HTML */
<button id="myButton">클릭</button>
/* JavaScript */
const button = document.querySelector('#myButton');
button.onclick = function() {
alert('버튼이 클릭되었습니다!');
}
이벤트 핸들러 프로퍼티 방식은 코드의 가독성이 좋고 유지보수가 용이하지만,
하나의 이벤트에 하나의 이벤트 핸들러만 할당할 수 있기 때문에 여러 개의 이벤트 핸들러를 할당해야 하는 경우에는 다른 방식을 사용해야 한다.
이벤트 핸들러 할당 제한 예시 :
/* HTML */
<button id="myButton">클릭</button>
/* JavaScript */
const button = document.querySelector('#myButton');
function handleClick() {
console.log('첫 번째 핸들러');
}
function handleClick2() {
console.log('두 번째 핸들러');
}
button.onclick = handleClick;
button.onclick = handleClick2;
위의 코드를 실행하면 버튼을 클릭할 때 handleClick2 함수만 실행되고 handleClick 함수는 실행되지 않는다.
이는 해당 방식이 하나의 이벤트에 하나의 이벤트 핸들러만 할당할 수 있다는 제한이 있기 때문이다.
따라서 하나의 이벤트에 여러 개의 이벤트 핸들러를 할당하려면, 다른 방식을 사용해야 한다.
예를 들어, addEventListener 메서드를 사용하면 하나의 이벤트에 여러 개의 이벤트 핸들러를 할당할 수 있다.
JavaScript에서 addEventListener 메서드는 이벤트를 처리하는 함수를 등록하는 방식이다.
이벤트가 발생했을 때, 등록된 함수가 자동으로 호출된다.
addEventListener 메서드는 DOM 요소에 대해서 호출할 수 있으며, 다음과 같은 방식으로 사용된다.
element.addEventListener(event, function, useCapture);
var element = document.getElementById("myButton");
function myFunction() {
alert("Button clicked!"); //대화 상자 출력
}
element.addEventListener("click", myFunction);
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.btn__area,
#list {
border: 1px solid #345;
}
</style>
</head>
<body>
<div class="btn__area">
<button id="btn1" onclick="doAction1()">Click1</button> <!--함수 호출 인라인 방식-->
<button id="btn2">Click2</button> <!-- 프로퍼티 사용-->
<button id="btn3">Click3</button> <!-- addEventListener-->
</div>
<div id="list"></div>
<script>
function doAction1() { //1. 인라인 방식
alert('doAction - 1');
}
let btn2 = document.getElementById("btn2"); //2. 프로퍼티 사용
btn2.onclick = function () {
alert('doAction - 2');
};
btn2.onclick = function () { //해당 방식은 이벤트를 여러개 등록할 수 없다. 프로퍼티의 바인딩은 한 개만 가능하다.
alert('doAction - 2222'); //이 구문은 의미 없는 구문이다. 여러 개를 등록하고자 한다면 이벤트리스너를 사용하자.
};
let btn3 = document.getElementById('btn3'); //3. 이벤트리스너 사용
btn3.addEventListener('click', function (e) { //e에 이벤트를 발생한 이벤트 객체를 받을 수 있다.
console.dir(e);
console.dir(e.target); // 이벤트가 발생한 대상 객체
console.log(e.target.innerHTML); // 이벤트가 발생한 대상 객체
e.target.innerText = '클릭3';
});
</script>
</body>
</html>
버블링(Bubbling)과 캡쳐링(Capturing)은 이벤트 전파(Event Propagation)에 관한 개념으로, HTML 요소에서 발생한 이벤트가 상위 요소로 전파되는 방식을 뜻한다.
하위 요소에서 이벤트가 발생하면 상위 요소로 이벤트가 전파되는 방식이다.
즉, 하위 요소에서 발생한 이벤트부터 상위 요소까지 차례대로 이벤트가 전파된다.
예를 들어, button 태그를 클릭하면 버튼에서 발생한 클릭 이벤트가 button → form → body → html 순으로 전파된다.
상위 요소에서 이벤트가 발생하면 하위 요소로 이벤트가 전파되는 방식.
즉, 상위 요소에서 발생한 이벤트부터 하위 요소까지 차례대로 이벤트가 전파된다.
예를 들어, html 태그를 클릭하면 클릭 이벤트가 html → body → form → button 순으로 전파된다.
함수의 세 번째 인자 값이 true면 캡쳐링, false면 버블링이 일어난다.
일반적으로 자바스크립트에서 이벤트가 발생한 요소에서부터 버블링이 일어나며, addEventListener 메서드의 세 번째 인자로 capture 옵션을 true로 설정하면 캡쳐링을 사용할 수 있다. 기본값은 false로 버블링을 사용한다.
JSON(JavaScript Object Notation)은 사람이 읽을 수 있는 텍스트 기반의 데이터 교환 표준이다.
JSON에서 지원하는 데이터 타입의 예시 :
{
"name": "John",
"age": 30,
"isMarried": true,
"hobbies": ["reading", "writing", "swimming"],
"address": {
"city": "Seoul",
"state": "Seoul"
},
"car": null
}
아래에서는 자바스크립트에서의 JSON 사용 관련 메소드에 대한 정의와 예시를 설명한다.
자바스크립트 객체나 배열을 JSON 문자열로 변환하는 메서드로, 자바스크립트 객체나 배열을 문자열 형태로 전송하거나 저장할 수 있다.
const myObj = { name: "John", age: 30 };
const jsonString = JSON.stringify(myObj);
console.log(jsonString); // 출력 결과: {"name":"John","age":30}
//JSON 문자열
const jsonStr = '{"name": "John", "age": 30, "city": "New York"}';
const jsonObj = JSON.parse(jsonStr);
console.log(jsonObj);
// 출력 결과: { name: 'John', age: 30, city: 'New York' }
JSON.parse() 메소드는 JSON 형식의 문자열을 파싱하여 JavaScript 객체로 변환한다.
이때 JSON 형식의 문자열은 반드시 큰따옴표("")로 묶인 문자열이어야 하며,
객체의 키는 큰따옴표("")로 묶인 문자열이어야 한다.
JSON 형식의 문자열에는 객체, 배열, 문자열, 숫자, true, false, null 등의 값이 포함될 수 있다.
JSON.parse() 메소드를 사용하면, 서버에서 전송된 JSON 형식의 데이터를 JavaScript 객체로 변환하여 사용할 수 있다.
JSON.stringify() 메소드를 호출하여 JavaScript 객체를 JSON 형식의 문자열로 직렬화할 때, 객체의 toJSON() 메소드를 사용하여 직렬화할 수 있다.
이때, toJSON() 메소드는 JSON.stringify() 메소드 내부에서 호출되는 메소드입니다.
const obj = {
name: "John",
age: 30,
toJSON: function () {
return {
person: {
name: this.name,
age: this.age
}
};
}
};
이 객체의 toJSON() 메소드에서는,
name과 age 프로퍼티를 가진 객체를 person 프로퍼티로 감싸서 반환하도록 구현되어 있다.
이를 JSON.stringify() 메소드를 사용하여 직렬화하면,
toJSON() 메소드에서 반환한 값이 JSON 형식의 문자열로 직렬화된다.
const jsonString = JSON.stringify(obj);
console.log(jsonString);
// 출력 결과: {"person":{"name":"John","age":30}}
위 예시에서는 toJSON() 메소드를 사용하여 객체를 JSON 형식의 문자열로 직렬화하는 방법을 나타냈다.
toJSON() 메소드를 사용하면, 객체의 특정 프로퍼티만을 JSON 형식의 문자열로 직렬화하거나,
객체의 값을 변환하여 JSON 형식의 문자열로 직렬화하는 등의 작업이 가능하다.