heyday2024 님의 블로그
Web APIs , DOM, 로컬 스토리지, 이벤트 처리 방식 본문
- 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 의 상태 정보 조회
- 로컬스토리지 3가지 특징
- 문자열 형식으로 데이터가 저장됩니다. (로컬스토리지에서는 언제나 string임.)
- → 배열, 객체의 경우 반드시 JSON 문자열화해서 저장해야 합니다.
- 영구적 저장소로 사용자가 삭제하지 않는 새로고침해도 유지됩니다.
- 브라우저 내에 저장되는 것으로 서버요청없이 데이터 사용이 가능합니다.
- localStorage.setItem(key, value): 데이터를 저장할 때 사용.
- localStorage.getItem(key): 저장된 데이터를 불러올 때 사용.
- localStorage.removeItem(key): 특정 데이터를 삭제할 때 사용.
- localStorage.clear(): 저장된 모든 데이터를 삭제할 때 사용.
- DOM APIs (웹페이지 요소조작)
- : 브라우저(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에서 볼 수 있음.
parse해서 다시 정보 가져오기
BOM: url창을 제어할 수 있는 것 = location---> location 안에 여러 메서드있음.
DOM
- DOM Tree 에서 각각의 DOM 요소를 노드(Node) 라고 부름. → HTML 문서를 트리 구조로 구조화한 브라우저가 제공하는 객체
- DOM 으로 무엇을 할 수 있나요? → 자바스크립트가 DOM API를 통해 페이지 요소를 조작 (CRUD) 가능.
- DOM 은 언제 생성되나요? → 브라우저가 html 문서를 읽고 나면 생성됨.
코드를 다 parsing해야 dom 구조 생성됨.
getElementID 보다 쿼리 셀렉터가 최근거임.
<속성>
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
<!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 사용을 권장.
'프론트엔드 부트캠프' 카테고리의 다른 글
[3주차 과제] 객체 복사, this 이해 (4) | 2024.10.20 |
---|---|
[JS 기초 문법 3주차(3)] 실행 컨텍스트의 세번째 요소, ThisBindings (0) | 2024.10.20 |
[Github 특강] Github 이용해서 협업 과정 + 팁(dev) (2) | 2024.10.17 |
[JS 강의 2회차] 객체&배열 의 데이터 저장, 수정, 삭제, 복사 정리 (2) | 2024.10.17 |
[JS 기초 문법 3주차(2)] 실행 컨텍스트 (스코프, 변수, 객체, 호이스팅) (4) | 2024.10.17 |