클론코딩

[인프런] 맛집지도 만들기 (8)

cmkoi1 2023. 1. 31. 22:00

비전공자를 위한 풀스택 맛집지도 만들기 프로젝트!: Front, Back-end 그리고 배포까지

 

비전공자를 위한 풀스택 맛집지도 만들기 프로젝트!: Front, Back-end 그리고 배포까지 - 인프런 | 강

내가 좋아하는 유튜버의 맛집지도를 만들면서 프론트엔드, 백엔드, 카카오맵 API 사용법, 배포까지 한번에 배울 수 있는 풀스택 맛집지도 강의입니다., - 강의 소개 | 인프런...

www.inflearn.com

※ 해당 링크 강의 내용을 바탕으로 작성된 포스팅입니다.

 

 

 

JS DOM과 비동기처리

JS로 HTML과 CSS를 컨트롤하는 방법

JS에서 HTML 요소 선택 방법

 

메서드 설명
document.querySelector(선택자) 해당 선택자로 선택되는 요소 선택.
document.querySelectorAll(선택자) 해당 선택자로 선택되는 요소 모두 선택(배열).
document.getElementsByTagName(태그이름) 해당 태그 이름의 요소 모두 선택(배열).
document.getElementById(아이디) 해당 아이디 요소 선택.
document.getElementsByClassName(클래스이름) 해당 클래스에 속한 요소 모두 선택(배열).

 

html

<!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>
</head>
<body>
    <div></div>
    <div id="hi"></div>
    <div class="welcome"></div>
    <script src="dom.js"></script>
</body>
</html>

 

js

// 엘리먼트 선택 예제
console.log(document.querySelector("div.welcome"));
console.log(document.querySelectorAll("div"));
console.log(document.getElementsByTagName("div"));
console.log(document.getElementById("hi"));
console.log(document.getElementsByClassName("welcome"));

 

 

 

HTMLCollection(동적)과 NodeList(정적)의 차이

 

HTMLCollection vs NodeList - 한현상 블로그

DOM을 조작할 때 접하게 되는 유사배열들이다. getElementsByClassName()과 querySelectorAll()이 거의 같은 것이라 인식하고 있는 사람들이 있을 것이다. 결정적으로 다른 부분이 있다. 바로 그 결과가 각각 H

tillog.netlify.app

 

 

 

JS에서 HTML 요소 Read, Update를 위한 속성

 

이름 설명
innerText = "content" 요소 내부 컨텐츠 조회, 수정. 들어온 값을 Text로 인식.
innerHTML = "html" 요소 내부 엘리먼트 전체 조회, 수정. 들어온 값을 HTML로 인식.
style.property = "css property value" 요소 스타일 조회, 수정

 

divTag.innerText = "<h1>안녕하세요.</h1>"

 

 

 

divTag.innerHTML = "<h1>안녕하세요.</h1>"

 

 

 

 

html

<!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>
</head>
<body>
    <div>안녕</div>
    <script src="dom.js"></script>
</body>
</html>

 

js

// <div> 가져오기
const divTag = document.querySelector("div");

console.log(divTag);

// color에 접근해 색을 red로 바꾼다.
divTag.style.color = "red";

 

 

 

 

JS에서 중첩된 태그 선택

관계를 기반으로 요소 선택.

 

이름 설명
parentElement 부모 태그
children 자식 태그 리스트
nextElementSibling 인접 형제 태그

 

html

<!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>
</head>
<body>
    <div class="container">
        <div class="inner first">
            <div class="item">1</div>
            <div class="item">2</div>
            <div class="item">3</div>
        </div>
        <div class="inner second">
            <div class="item">1</div>
            <div class="item">2</div>
            <div class="item">3</div>
        </div>
    </div>
    <script src="dom.js"></script>
</body>
</html>

 

js

const container = document.querySelector(".container");
console.log(container);

// 부모 태그
console.log(container.parentElement);

// 자식 태그
console.log(container.children);

// 형제 태그
console.log(container.nextElementSibling);

 

 

 

 

JS에서 태그 추가

  • document.createElement() : 태그 만들기
  • document.createTextNode(): text 노드 만들기
  • element.appendChild(): 자식 노드 추가하기
  • element.setAttribute(attribute, value): 요소에 속성 추가하기

정석적인 방법

 

html

<!DOCTYPE html>
<html lang="ko">
    <head>
        <meta charset="UTF-8" />
        <title>Document</title>
    </head>
    <body>
        <div id="container">
            <div class="inner"></div>
        </div>
        <script src="dom.js"></script>
    </body>
</html>

 

js

// div.inner를 선택
let inner = document.querySelector(".inner");

// <div>태그 생성
let element = document.createElement("div");

// text 노드 hello 생성
let hello = document.createTextNode("hello");

// <div>hello</div>로 만들기
element.appendChild(hello);

// div.inner에 element 추가
inner.appendChild(element);

 

 

 

간편한 방법(ES6 템플릿 리터널)

문자열 안에 변수, 표현식 등을 넣어 사용 가능. 백틱(``)과 $와 중괄호(${})를 사용.

 

비어있는 div 태그 생성.

 

html

<!DOCTYPE html>
<html lang="ko">
    <head>
        <meta charset="UTF-8" />
        <title>Document</title>
    </head>
    <body>
        <div id="app"></div>
        <script src="dom.js"></script>
    </body>
</html>

 

네트워크 요청을 통해 서버에서 상품 정보를 받아왔다고 가정.

div#app 태그에 div.item을 넣는다.

 

js

const prouductData = { title: "감자칩", weight: 300 };
 
// div#app 태그 선택
const app = document.querySelector("div#app"); 

// 템플릿 리터럴과 innerHTML 속성을 사용
app.innerHTML = `<div class="item">상품명 : ${productsData.title}, 무게 ${productsData.weight}g</div>`;

 

 

 

 

JS Event 처리

이벤트는 웹 브라우저가 인식하는 사건으로, 키보드를 누르거나, 마우스를 클릭하는 것이 예시.

 

이벤트 타입

발생한 이벤트의 종류를 나타내는 문자열.

 

이름 설명
load 웹 브라우저 상에서 HTML, CSS가 모두 로드 완료되었을 때 발생
keydown, keyup 키를 누를 때, 키에서 손을 뗐을 때 발생
change 변동이 있을 때 발생(input)
click 클릭했을 때 발생
focus 커서 포커스를 얻을 때 발생(input)

 

 

 

이벤트 등록 방법

1. 프로퍼티로 등록하는 방법(잘 사용하지 않음)

 

html

<!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>
</head>
<body>
    <p onclick="alert('문자열을 클릭했어요!')">이 문자열을 클릭해 보세요!</p>
    <script src="event.js"></script>
</body>
</html>

 

 

2. 메소드에 이벤트 리스너를 전달하는 방법

 

html

<!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>
</head>
<body>
    <button id="btn">클릭</button>
    <p id="text"></p>
    <script src="event.js"></script>
</body>
</html>

 

js

const showBtn = document.getElementById("btn"); // 아이디가 "btn"인 요소를 선택함.

//element.addEventListener(이벤트 타입, 이벤트 핸들러, 이벤트 전파방식)
showBtn.addEventListener("click", function () {
    document.getElementById("text").innerHTML = "짜잔~!! 텍스트가 나타났어요!!";
}); // 선택한 요소에 click 이벤트 리스너를 등록함.

 

const showBtn = document.getElementById("btn");

showBtn.addEventListener("click", eventHandler); //eventHandler()로 쓰면 함수가 바로 실행된다.

function eventHandler() {
    document.getElementById("text").innerHTML = "짜잔~!! 텍스트가 나타났어요!!";
} //이렇게 사용해도 됨

 

 

 

이벤트 객체

이벤트가 일어났을 때의 정보를 자세하게 저장.

 

js

function eventHandler(event) { //이벤트 객체가 전달됨
    console.log(event);
}

 

event 객체 정보

 

target, type이 주로 쓰임

 

 

 

JS 헬구간! 비동기 처리

동기/비동기

  • 동기(synchronous): 한 번에 한 가지 일만 처리. 실행이 끝난 후 다음 코드로 넘어간다.
  • 비동기(asynchronous): 동시에 여러 가지 일 처리. 완료 여부와 관계없이 다름 코드로 넘어간다.

실행이 오래 걸리는 코드가 있을 경우 비동기로 실행하는 것이 효율적.

동기/비동기

 

 

 

비동기 동작 예시

setTimeout(callback, ms)

 

setTimeout(() => {
    console.log(1);
}, 2000) //2초 뒤에 전달된 함수를 실행.

 

console.log('1등!');

setTimeout(function() {
	console.log('2등!');
}, 2000); // 2초 후 등장

setTimeout(function() {
	console.log('3등!');
}, 2000); // 2초 후 등장

 

이와 같이 네트워크 요청(API)도 비동기적으로 이루어진다.

 

실행 순서가 중요한 상황이면 문제가 발생할 수 있다.

코드의 실행 순서를 보장받아야만 하는 상황에서는 비동기적으로 처리되는 함수를 동기적으로 바꿔 준다(동기화 시킨다, 비동기 처리).

 

 

 

JS 비동기 처리

  • 콜백 함수
  • promise 객체
  • async await

콜백 함수 내부에 넣기

함수가 많아지면 콜백 지옥... 코드가 읽기 어려워질 수 있다.

 

console.log('1등!');

setTimeout(function() {
	console.log('2등!');
    setTimeout(function() {
        console.log('3등!');
    }, 2000); //콜백함수 안에 넣어 준다
}, 2000);

 

 

 

 

promise 객체

ES6부터 등장.

promise는 3가지의 상태값이 존재.

  1. 대기(pending): promise 객체를 새로 생성한 상태. 대기.
  2. 이행(fulfiled): resolove 가 실행된 상태. 비동기 로직이 완료된 상태.
  3. 거부(rejected): reject가 실행된 상태. 비동기 로직에서 에러가 난 경우.

 

// const 변수명 = new Promise((resolve, reject) => {
//     resolve("good"); //then 호출
//     reject("fail"); //catch 호출
// });
  
// 변수명.then((res) => console.log(res)).catch((err) => console.log(err));

 

resolve가 호출 된다 → 이행상태 → promise 객체의 then() 메서드 호출

reject가 호출된다 → 거부 상태 → promise 객체의 catch() 메서드 호출

 

 

 

const helloPromise = new Promise((resolve, reject) => {
    // 생성 자체는 pending
    let isSuccess = true;
  
    if (!isSuccess) {
        reject(false); // catch 호출
        return;
    }
  
    console.log("1등");
    setTimeout(() => {
        resolve(); // then 호출
    }, 2000);
});
  
helloPromise
    .then((res) => {
        console.log("2등");
        return new Promise((resolve, reject) => {
            setTimeout(() => resolve(), 2000); //아래 then 호출
        });
    })
    .then((res) => {
        console.log("3등");
    })
    .catch((err) => { //에러 처리
        console.log(err);
    });

 

 

 

 

async await

promise를 기반으로 동작. promise에서 resolve로 넘어온 값이 await 구문에 반환. 사람이 읽기 쉽다.

 

// async fuction 함수명(){
// 	await 비동기처리함수();
// }

 

async function asyncFunction() {
    console.log(1);
    const result = await getResult(); //getResult를 비동기 처리
    console.log(result);
}
  
function getResult() { //Promise 반환
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(2); //2가 result에 전달.
        }, 2000); //2초 뒤에 resolve 실행.
    });
}
  
asyncFunction();

 

async function asyncFunction() { //메인
    console.log("1등"); //실행 1
    await second(); //Promise를 반환하는 함수
    await third(); //Promise를 반환하는 함수
}
  
function second() { //실행 2
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            console.log("2등");
            resolve(); //await가 작업을 끝냈다고 인식. 다음 코드로 넘어감.
        }, 2000);
    });
}
  
function third() { //실행 3
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            console.log("3등");
            resolve();
        }, 2000);
    });
}
  
asyncFunction();

 

클라이언트 - 서버 통신간에서 비동기 처리 기법이 중요.

 

 

 

try-catch

async/await 구문 에러를 처리하기 위해서는 try-catch 이해가 필요.

try-catch는 비동기 처리 이외에도 일반적인 에러까지도 잡아낸다.

 

try {
    소스코드; //에러가 나면
} catch (err) { //여기로 넘어감
    console.log(err);
}

 

 

 

async function asyncFunction() {
    try {
        console.log(1);
        const result = await getResult();
        console.log(result);
        console.log(3);
    } catch (err) { //에러 발생 시 여기로
        console.log(err);
    }
}
  
function getResult() {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            reject(new Error("에러발생 예시")); //일부로 에러 발생
        }, 500);
    });
}
  
asyncFunction();

 

 

728x90