[JS] 09. 이벤트와 JSON, 렌더링

블랑·2023년 3월 14일
0

[FE] - HTML/CSS/JavaScript

목록 보기
13/14

EVENT

이벤트(event)는 브라우저에서 발생하는 다양한 상황을 의미한다.
예를 들어, 버튼을 클릭하거나 마우스를 움직이는 등의 동작, 웹 페이지의 로딩 완료, 입력 필드에서 값이 변경될 때 등 다양한 상황이 이벤트로 간주될 수 있다.

이벤트가 발생하면, 이를 처리하는 이벤트 핸들러(event handler)를 등록하여 원하는 동작을 수행할 수 있다.

이벤트는 일반적으로 함수와 연결된다.
이 함수는 이벤트가 발생되기 전에는 실행되지 않다가 이벤트가 발생할 경우 실행된다.

마우스 이벤트, 키보드 이벤트, 프레임 이벤트, 폼 이벤트

각각 이후의 실습에 적용해보도록 하겠다.
대표적인 메서드들은 다음과 같다.

  1. 마우스 이벤트
  • click: 요소를 클릭할 때 발생
  • mousedown: 마우스 버튼을 누르는 순간 발생
  • mouseup: 마우스 버튼을 눌렀다 놓을 때 발생
  • mousemove: 마우스를 움직일 때 발생
  • mouseover: 요소 위로 마우스 커서가 올라갈 때 발생
  • mouseout: 요소에서 마우스 커서가 벗어날 때 발생
  1. 키보드 이벤트
  • keydown: 키보드의 버튼이 눌리는 순간 발생
  • keyup: 키보드의 버튼이 떼어지는 순간 발생
  • keypress: 키보드의 버튼이 눌리는 순간과 떼어지는 순간 사이에 발생
  1. 프레임 이벤트
  • load: 프레임이 로드되었을 때 발생
  • unload: 프레임이 언로드되었을 때 발생
  • beforeunload: 프레임이 언로드되기 전에 발생
  • resize: 프레임의 크기가 변경될 때 발생
  1. 폼 이벤트
  • submit: 폼이 제출될 때 발생
  • reset: 폼이 초기화될 때 발생
  • focus: 요소에 포커스가 들어갈 때 발생
  • blur: 요소에서 포커스가 벗어날 때 발생

인라인 이벤트 핸들러

이벤트 핸들러를 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('버튼이 클릭되었습니다!');
}
  1. 위의 코드에서 document.querySelector 메서드로 버튼 요소를 선택했다.
  2. 이렇게 선택한 요소의 onclick 프로퍼티에 이벤트 핸들러 함수를 할당한다.
  3. 이벤트가 발생하면 할당된 이벤트 핸들러 함수가 실행되어 이벤트를 처리한다.

이벤트 핸들러 프로퍼티 방식은 코드의 가독성이 좋고 유지보수가 용이하지만,
하나의 이벤트에 하나의 이벤트 핸들러만 할당할 수 있기 때문에 여러 개의 이벤트 핸들러를 할당해야 하는 경우에는 다른 방식을 사용해야 한다.

이벤트 핸들러 할당 제한 예시 : 

/* 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 메서드를 사용하면 하나의 이벤트에 여러 개의 이벤트 핸들러를 할당할 수 있다.

AddEventLinstener

JavaScript에서 addEventListener 메서드는 이벤트를 처리하는 함수를 등록하는 방식이다.
이벤트가 발생했을 때, 등록된 함수가 자동으로 호출된다.

addEventListener 메서드는 DOM 요소에 대해서 호출할 수 있으며, 다음과 같은 방식으로 사용된다.

element.addEventListener(event, function, useCapture);
  1. element는 이벤트를 등록할 DOM 요소이다.
  2. event는 이벤트의 종류를 나타내는 문자열이다. 예를 들어, "click", "mouseover", "keydown" 등이 있다.
  3. function은 이벤트가 발생했을 때 실행할 함수이다.
  4. useCapture는 이벤트 캡처링을 사용할지 여부를 나타내는 boolean 값이다.
    기본값은 false이며, 이벤트 버블링을 사용한다.
var element = document.getElementById("myButton");

function myFunction() {
  alert("Button clicked!"); //대화 상자 출력
}

element.addEventListener("click", myFunction);

3가지 이벤트 방식 정리

<!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 요소에서 발생한 이벤트가 상위 요소로 전파되는 방식을 뜻한다.

버블링(Bubbling)

하위 요소에서 이벤트가 발생하면 상위 요소로 이벤트가 전파되는 방식이다.
즉, 하위 요소에서 발생한 이벤트부터 상위 요소까지 차례대로 이벤트가 전파된다.

예를 들어, button 태그를 클릭하면 버튼에서 발생한 클릭 이벤트가 button → form → body → html 순으로 전파된다.

캡쳐링(Capturing)

상위 요소에서 이벤트가 발생하면 하위 요소로 이벤트가 전파되는 방식.
즉, 상위 요소에서 발생한 이벤트부터 하위 요소까지 차례대로 이벤트가 전파된다.

예를 들어, html 태그를 클릭하면 클릭 이벤트가 html → body → form → button 순으로 전파된다.

함수의 세 번째 인자 값이 true면 캡쳐링, false면 버블링이 일어난다.

일반적으로 자바스크립트에서 이벤트가 발생한 요소에서부터 버블링이 일어나며, addEventListener 메서드의 세 번째 인자로 capture 옵션을 true로 설정하면 캡쳐링을 사용할 수 있다. 기본값은 false로 버블링을 사용한다.

JSON

JSON(JavaScript Object Notation)은 사람이 읽을 수 있는 텍스트 기반의 데이터 교환 표준이다.

  1. 경량: XML과 같은 다른 데이터 교환 형식에 비해 용량이 작다.
  2. 텍스트 형식: 사람과 기계 모두 이해하기 쉽게 텍스트 형식으로 구성되어 있다.
  3. JavaScript 객체의 문법을 따르고 있으며, 다양한 프로그래밍 언어에서 사용할 수 있다.
JSON에서 지원하는 데이터 타입의 예시 : 
{
  "name": "John",
  "age": 30,
  "isMarried": true,
  "hobbies": ["reading", "writing", "swimming"],
  "address": {
    "city": "Seoul",
    "state": "Seoul"
  },
  "car": null
}

JSON과 XML의 차이

  1. JSON은 종료 태그가 없다.
  2. XML에 비해 상대적으로 구문이 짧다.
  3. JSON 데이터가 XML 데이터보다 빨리 읽고 쓸 수 있다.
  4. XML 데이터는 배열 사용이 불가능하나, JSON은 가능
  5. XML은 XML파서가 있어야 하나, JSON은 자바스크립트 함수로 변환하여 사용 가능
  6. XML은 문서의 DOM을 이용하여 접근하지만, JSON은 문자열로 전송받은 후 바로 파싱하기 때문에 XML보다 처리 속도가 빠름.

자바스크립트에서의 JSON 사용 관련 메소드

아래에서는 자바스크립트에서의 JSON 사용 관련 메소드에 대한 정의와 예시를 설명한다.

JSON.stringify(JSON 객체)

  • 직렬화
  • argument로 전달받은 자바스크립트의 객체를 문자열로 변환한다.

자바스크립트 객체나 배열을 JSON 문자열로 변환하는 메서드로, 자바스크립트 객체나 배열을 문자열 형태로 전송하거나 저장할 수 있다.

const myObj = { name: "John", age: 30 };
const jsonString = JSON.stringify(myObj);
console.log(jsonString); // 출력 결과: {"name":"John","age":30}

JSON.parse(JSON형식의 문자열)

  • 1의 반대로 역직렬화 (전달받은 문자열을 자바스크립트의 객체로 변환)
  • argument로 받은 text는 반드시 JSON 형식에 일치해야 한다.
//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 객체로 변환하여 사용할 수 있다.

toJSON()

  • 자바스크립트의 Date 객체의 데이터를 JSON 형식의 문자열로 변환
  • Date.prototype 객체에서만 사용가능

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 형식의 문자열로 직렬화하는 등의 작업이 가능하다.

브라우저 렌더링

SSR (Server Side Rendering)

CSR (Client Side Rendering)

Web Storage

profile
안녕하세요.

0개의 댓글