Notice
Recent Posts
Recent Comments
Link
«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
Archives
Today
Total
관리 메뉴

heyday2024 님의 블로그

Web APIs , DOM, 로컬 스토리지, 이벤트 처리 방식 본문

프론트엔드 부트캠프

Web APIs , DOM, 로컬 스토리지, 이벤트 처리 방식

heyday2024 2024. 10. 18. 20:51
  • API
    • Application Programming Interfaces 약자
    • 서로 다른 시스템이 서로 소통할 수 있는 방법 또는 창구
    • 일종의 메뉴판 역할. ex) 손님(client)이 키오스크를 통해서 메뉴를 주문(요청)하면 식당(server)이 주문한 메뉴를 조리해서 손님에게 가져옵니다(응답).
  • DOM
    • Document Object Model 의 약자
    • 웹 페이지 문서를 구성하는 요소들을 트리(Tree) 구조로 표현한 객체
    • 브라우저에서 HTML 문서를 자바스크립트로 제어할 수 있게 해주는 인터페이스
  • BOM
    • Browser Object Model 의 약자
    • 문서 이외의 모든 것을 제어하기 위해 제공하는 추가 객체
  • Event
    • 브라우저에서 사용자가 웹 페이지와 상호작용할 때 발생하는 사건
    • 다양한 종류의 Event가 있음 ex) click, scroll, submit, keydown 등

Web APIs (fetch API)

  • 브라우저가 웹 애플리케이션이 다양한 작업을 수행할 수 있도록 제공하는 모든 API를 포괄하는 용어
  • 다양한 종류
    • DOM APIs (웹페이지 요소조작)
      • querySelector, getElementById, **innerHTML**등
    • Network APIs (서버와의 통신)
      • fetch, WebSocket, WebRTC 등
    • Storage APIs (브라우저 내 데이터 저장 및 관리)
      • localStorage, sessionStorage 등
    • File APIs (파일 읽기,쓰기)
      • FileReader, Blob
    • Graphics APIs (웹상에서 그래픽 처리)
      • Canvas, WebGL
    • Audio/Video APIs (웹상의 오디오,비디오 제어)
      • HTML5 Audio/Video API: <audio>, <video>
    • Device APIs (기기 상태에 접근)
      • 온라인/오프라인 여부 등 device 의 상태 정보 조회
    로컬스토리지 (localStorage)
    • 로컬스토리지 3가지 특징
    1. 문자열 형식으로 데이터가 저장됩니다. (로컬스토리지에서는 언제나 string임.)
    2. → 배열, 객체의 경우 반드시 JSON 문자열화해서 저장해야 합니다.
    3. 영구적 저장소로 사용자가 삭제하지 않는 새로고침해도 유지됩니다.
    4. 브라우저 내에 저장되는 것으로 서버요청없이 데이터 사용이 가능합니다.
    주요 메서드:
    1. localStorage.setItem(key, value): 데이터를 저장할 때 사용.
    2. localStorage.getItem(key): 저장된 데이터를 불러올 때 사용.
    3. localStorage.removeItem(key): 특정 데이터를 삭제할 때 사용.
    4. localStorage.clear(): 저장된 모든 데이터를 삭제할 때 사용.
  • : 브라우저(client)에 영구적으로 데이터를 저장할 수 있는 저장소 중 하나

실습 문제 : 데이터 타입별로 로컬스토리지 CRUD

// 이 문제는 브라우저상에서 실습을 진행합니다.
// 1. key 를 "test-num" 으로 하고 숫자 10 을 로컬스토리지에 저장해 보세요.
// 2. 저장했던 test-num 데이터를 가져와서 타입이 number 인지 확인해 보세요.
// 3. 아래 영화 데이터를 movies 라는 key 로 로컬스토리지에 저장해 보세요.
// [{id: 1, title: "어벤져스1"},{id: 2, title: "어벤져스2"}]
// 4. movies 데이터를 가져와서 배열 타입으로 movies 라는 변수에 할당해 보세요.

 

도메인 마다 로컬 스토리지가 있어 다른 도메인에서 접근 안됨. 개발자도구에서 application에서 볼 수 있음.

 

10으로 저장해도 로컬 스토리지에서는 스트링으로 저장되기 떄문에 false가 나옴.

 

스트링을 넘버로 바꾸는 법 세가지

 

이런식으로 저장하면 안됨!!!! 왜냐하면 스트링으로 바꿔주고 넣어주어야하기 때문

 

 

그러면 ""로 string을 만들면되지 않을까??? 놉!!!!!!! ----> Json 형식의 문자열이어야지만, 객체나 배열은 해동이됨(parse)가됨

 

문자열 바꿔서 저장.

 

이렇게 보임.

 

parse해서 다시 정보 가져오기


 

document가 브라우저 상에 보여지는 그 화면 임.

 

BOM: url창을 제어할 수 있는 것 =  location---> location 안에 여러 메서드있음.

 

f는 function을 의미
location으로 url 통제

 

브라우저 핵심 구조: window라는 전역객체의 자식 객체들 (DOM, BOM, Javascript)


DOM

 

DOM 구조

 

  1. DOM Tree 에서 각각의 DOM 요소를 노드(Node) 라고 부름. → HTML 문서를 트리 구조로 구조화한 브라우저가 제공하는 객체
  2. DOM 으로 무엇을 할 수 있나요? → 자바스크립트가 DOM API를 통해 페이지 요소를 조작 (CRUD) 가능.
  3. DOM 은 언제 생성되나요? → 브라우저가 html 문서를 읽고 나면 생성됨.

코드를 다 parsing해야 dom 구조 생성됨.

 

html 태그를 js 객체로 객체화 시킨 것과 다름없음. $0을 가지고

 

이렇게 사용할 수 있음

getElementID 보다 쿼리 셀렉터가 최근거임.

 

nodeList는 array 와 다름. 배열 메소드 못씀. nodeList는 forEach 밖에 못씀.

 

<속성>

html: attribute

js: property


DOM API

문서 탐색, 선택 메서드

 

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body
    style="
      display: flex;
      justify-content: center;
      align-items: center;
      flex-direction: column;
      height: 100vh;
    "
  >
    <picture>
      <img
        src="https://i.namu.wiki/i/SzWIT97QJSXiojeFDWs0IF6ggzfowjrrxBjrccTq1e4IwPJDqD5dcqS7L7n57mbigJSayWQS6Y-TA6Jxw5QwRJiDublckdHxwyclzHVkecZpcMjUyjQJtSery1OXAqo2DliKt_egwI5cUuPBcHk9TQ.svg"
        alt="Javascript"
        style="display: block; margin-bottom: 20px; width: 100px; height: 100px"
      />
    </picture>
    <div>
      <img
        src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSLPLQGezkpT1ntM2T0k3TR0yY75wevMpjLKA&s"
        alt="React"
        style="display: block; margin-bottom: 20px; width: 100px; height: 100px"
      />
    </div>
    <section>
      <img
        src="https://i.namu.wiki/i/ni7tOjXGL82aDoXFV7ufKaAJtdOXYvRo7BS6sGrqADJy5E9mhGFkazeQ6Ssuf9mrpV3N3p4APXUSBv0DjfOFk-uQBosaNQ8kl4KaBlOiX5X3VGTip4WDXG-sLcN1P06YDkbZjf1U51sNKtwhbgMW2A.svg"
        alt="Next.js"
        style="display: block; margin-bottom: 20px; height: 50px"
      />
    </section>

    <script>
      // alt가 React인 img 태그 선택
      const reactImg = document.querySelector('img[alt="React"]');
      console.log("React 이미지 선택:", reactImg); // 선택된 img 태그 출력

      // TODO: querySelector로 div 의 자식인 img 태그를 선택해 보세요.
      const img = document.querySelector("div img");
      console.log("이미지 선택", img);
    </script>
  </body>
</html>

- querySelector 로 요소 선택하기

 

요소 생성 및 조작 메서드

 

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Element Generation Practice</title>
  </head>
  <body>
    <div id="parent">
      <p>기존 문단입니다.</p>
    </div>
    <button id="addElementButton">부모의 마지막 자식요소로 추가</button>
    <button id="insertBeforeButton">두 번째 자식 요소 앞에 추가</button>

    <script>
      const parent = document.getElementById("parent");
      const addElementButton = document.getElementById("addElementButton");

      addElementButton.addEventListener("click", () => {
        // 새로운 요소 생성
        const newElement = document.createElement("p");
        newElement.textContent = "appendChild로 추가된 문단입니다.";

        parent.appendChild(newElement);

        // TODO: 새로운 요소를 parent의 마지막 자식요소로 추가해 보세요

      });

      insertBeforeButton.addEventListener("click", () => {
        const newElement = document.createElement("p");
        newElement.textContent = "insertBefore로 추가된 문단입니다.";
				// TODO: 새로운 요소를 parent의 두 번째 요소로 추가해 보세요.
				// 힌트: parent.children 은 [ <p>, <p>, ... ] 형식
          
          parent.insertBefore(newElement, parent.children[2]);
      });
    </script>
  </body>
</html>

- 새로운 요소 추가함

 

속성 조작

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Toggle Card Visibility</title>
    <style>
      .card {
        width: 200px;
        height: 100px;
        background-color: lightblue;
        display: flex;
        justify-content: center;
        align-items: center;
        margin-bottom: 20px;
      }
      .hidden {
        display: none;
      }
    </style>
  </head>
  <body>
    <div class="card" id="card">This is a card</div>
    <button id="toggleButton">카드 보이기/숨기기</button>

    <script>
      // TODO: "카드 보이기/숨기기" 버튼을 클릭했을 때 
      //      카드가 보이는 상태면 숨기고, 안보이는 상태면 보이게 해보세요

      const card = document.querySelector('.card');
      const btn = document.getElementById('toggleButton');

      btn.addEventListener("click", function(){
        card.classList.toggle('hidden');
      })

    </script>
  </body>
</html>

- 카드 보이기/숨기기 토글링

 

 

스타일 조작

 

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Style Manipulation Example</title>
  </head>
  <body>
    <div
      id="box"
      style="width: 100px; height: 100px; background-color: lightcoral"
    ></div>
    <button id="changeStyleButton">스타일 변경</button>

    <script>
      const box = document.getElementById("box");
      const changeStyleButton = document.getElementById("changeStyleButton");

      changeStyleButton.addEventListener("click", () => {
	      // 스타일 변경 버튼 클릭 시
	      // width 를 200px, height 를 200px,
	      // backgroundColor 는 "lightgreen" 으로 변경해 보세요.
        box.style.width = '200px'
        box.style.height = '200px'
        box.style.backgroundColor = 'lightgreen';
      });
    </script>
  </body>
</html>

- style 사용해서 스타일 조작

 

이벤트 처리

 

 

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Event Handler Example</title>
  </head>
  <body>
    <div
      id="box"
      style="width: 100px; height: 100px; background-color: lightcoral"
    ></div>
    <button>스타일 변경</button>

    <script>
      function changeStyle() {
        const box = document.getElementById("box");
        box.style.width = "200px";
        box.style.height = "200px";
        box.style.backgroundColor = "lightgreen";
      }

      // TODO-1: 스타일 변경 버튼의 이벤트 핸들러 어트리뷰트 방식을
      // 이벤트 리스너 방식으로 리팩터링 해보세요.
      const button = document.querySelector("button");

      button.addEventListener("click", function(){
        changeStyle();
      })
      // TODO-2: 스타일 변경 버튼 우클릭 시 
      //        "우클릭 했습니다."를 alert 처리 해보세요.
      // 힌트: 우클릭에 대한 이벤트는 contextmenu

      button.addEventListener("contextmenu", function(){
        alert("우클릭했습니다.")
      }

      )
    </script>
  </body>
</html>

- 이벤트 헨들러 어트리뷰트 방식 -> 이벤트 리스너로 변경

 

다양한 이벤트 종류

<form id="myForm">
  <input type="text" placeholder="username" />
  <input type="password" placeholder="password" />
  <button type="submit">Submit</button>
  <button type="reset">Reset</button>
</form>

<script>
  document
    .getElementById("myForm")
    .addEventListener("submit", function (event) {
      event.preventDefault(); // 기본 제출 동작 방지
      console.log("Form submitted!");
    });

  document.getElementById("myForm").addEventListener("reset", function () {
    console.log("Form reset!");
  });
</script>

- 폼 요소 이벤트---> submit: 폼 제출 시 

 

 

예시

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>DOMContentLoaded와 Load 이벤트 예시</title>
  </head>
  <body>
    <h1>DOMContentLoaded와 load 이벤트 시점을 확인해보세요.</h1>
    <img
      src="https://cdn.bootcampkorea.com/bootcamp/NB%20Camp.png"
      alt="내일배움캠프 이미지"
    />

    <script>
      window.addEventListener("load", () => {
        console.log("load 이벤트 발생: 모든 리소스가 로드되었습니다.");
      });

      document.addEventListener("DOMContentLoaded", () => {
        console.log(
          "DOMContentLoaded 이벤트 발생: DOM이 완전히 로드되었습니다.",
        );
      });
    </script>
  </body>
</html>

 

 

 

 

 

https://github.com/rjc1704/event-bubbling-code

 

GitHub - rjc1704/event-bubbling-code

Contribute to rjc1704/event-bubbling-code development by creating an account on GitHub.

github.com

 

 

이벤트 위임

 


<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Event Delegation Example</title>
    <style>
      #itemList li {
        display: inline;
        cursor: pointer;
      }
    </style>
  </head>
  <body>
    <ul id="itemList">
      <li>아이템 1</li>
      <li>아이템 2</li>
      <li>아이템 3</li>
      <li>아이템 4</li>
    </ul>

    <script>
      const items = document.querySelectorAll("#itemList li");

      items.forEach((item) => {
        item.addEventListener("click", () => {
          alert(`${item.textContent} 클릭됨`);
        });
      });

      // TODO: 위 JS코드를 삭제하고 이벤트 위임으로 리팩터링
      const ul = document.querySelector('#itemList');

      ul.addEventListener("click", (event) =>{
        if(event.target === event.currentTarget) return; //내가 클릭한게 ul 이면 아무것도 하지마... ul은 범위가 너무 커서
        alert(`${event.target.textContent} 클릭됨`)
      })
    </script>
  </body>
</html>

- 예시 코드

 

 

<추가적인 내용>

Element.classList.add(class-name) : 요소의 클래스명 추가하기 위해 나온 최신 문법.

 

이벤트리스너는 다른 함수와 달리 호출후에고 계속 살아있음.

 

예를 들어, 첫번째 페이지에 쓰인 addEventerListener를 더이상 안쓰는데. 이떄 

removeEventListener로 지워주지 않으면 addeventlistener는 다음 페이지로 넘어가도 계속 살아있기 때문에

메모리 누수 문제 생김.

 

onclick은 관리하기 어려움으로 안 쓰는 게 좋음. 헷갈릴 수 있음. 왠만하면 html과 js를 구분해서 쓰는 것이 좋음.

 

이벤트 헨들러 어트리뷰트방식은 지양해야하는 패턴 중 하나--> 하지만, 리액트에서는 상관 없음.

 

이벤트 헨들러 프로퍼티 방식도 지양.

 

 

addeventlistener는 여러가지 이벤트를 달 수 있음.(큰 장점)

 

 

 

  • scroll  vs wheel
  • scroll 은 스크롤이 있을 떄만 적용
  • wheel은 스크롤이 없어도 wheel 돌리면 적용됨

 

 

form 태그로 submit 사용을 권장. 

예전에는 제출 시 새로고침이 되었는데, 이를 방지하기 위해 preventDefault() 생김.

 

연속적으로 되는냐, 혹은 한번만 작동되느냐 차이

 

DomContentLoaded와 Load의 속도 차이 전자가 먼저 실행됨