https://www.notion.so/d64a4eeb40b14ba69e8d12313ca2ffe5?pvs=4
https://www.notion.so/JS-Promise-abb52b3c0437467d99011bbcc7986649?pvs=4
https://www.notion.so/JS-async-await-1efb1935768145cd9bd5e546a08bebb7?pvs=4
1. 동기, 비동기에 대한 개념
2. 그리고 콜백 함수와 콜백 지옥
3. JS fetch 및 Promise 객체
4. async function ~ await 함수
에 대해서 모두 배워봤는데
의문이 드는 점은,
fetch 를 이용해서 객체를 가져오고, 다음 함수를 Callback 하거나 Promise 를 이용해도 되는데
왜 async function ~ await 를 쓰는 것이 왜 더 좋은가 ?? 였다.
내가 볼땐 두 기능 모두 잘 작동하고, 크게 달라보이지 않아서 였다.
실제로 제가 사이드 프로젝트를 하면서 작성한
두 코드의 예시로 설명드리도록 하겠습니다.
첫번째
// index.js
console.log("index.js 가 잘 로딩 되었습니다.")
fetch("./navbar.html").then(response => {
return response.text()
})
.then(data => {
document.querySelector("header").innerHTML = data;
// 1. header 라는 속성에 innerHTML 에 먼저 navbar.html 코드(데이터)를 담아주고
buttonBlockAndHide();
// 2. 아래의 buttonBlockAndHide 함수를 순차적으로 실행한다.
})
const buttonBlockAndHide = () => {
// 페이로드를 로컬스토리지에 저장하고, 페이로드에 있는 사용자 정보를 가져옴
const payload = localStorage.getItem("payload");
const payload_parse = JSON.parse(payload);
const intro = document.getElementById("intro")
if (payload) {
intro.innerText = `${payload_parse.username}님 안녕하세요!`
// 1. 로그인 성공 시, 로그인 버튼을 숨기고
// 2. 로그아웃 버튼을 생성한다.
// 3.
console.log("로그인 버튼 Hide")
let loginButton = document.getElementById("login-button")
loginButton.style.display = "none";
// 로그아웃 버튼을 ul 안에 li 로 생성
let navberULRight = document.getElementById("navbar-right")
let newLi = document.createElement("li")
newLi.setAttribute("class", 'nav-item')
let logOutBtn = document.createElement("button")
logOutBtn.setAttribute("class", 'navbar-link btn')
logOutBtn.setAttribute("id", "logout-button")
logOutBtn.innerText = "로그아웃"
logOutBtn.setAttribute("onclick", "handleLogout()")
newLi.appendChild(logOutBtn)
navberULRight.appendChild(newLi)
// let logoutButton = document.getElementById("")
} else {
console.log("로그인 버튼 Block")
}
}
fetch 로 navbar.html 을 넣어주는 것과 로그인 버튼을 숨기는 함수를
굳이 따로따로 작성해서 콜백함수로 들고온 것을 볼 수 있다.
두번째
async function injectNavbar() {
let navbarHtml = await fetch("./navbar.html")
let data = await navbarHtml.text()
document.querySelector("header").innerHTML = data
const payload = localStorage.getItem("payload");
if (payload) {
const payload_parse = JSON.parse(payload);
const intro = document.getElementById("intro")
intro.innerText = `${payload_parse.username}님 안녕하세요!`
// 1. 로그인 성공 시, 로그인 버튼을 숨기고 로그아웃 버튼을 생성한다.
// 2. 로그인 X, 로그인 버튼을 유지하고 굳이 로그아웃 버튼이 생성되지 않는다
console.log("로그인 버튼 Hide")
let loginButton = document.getElementById("login-button")
loginButton.style.display = "none";
// 로그아웃 버튼을 ul 안에 li 로 생성
let navberULRight = document.getElementById("navbar-right")
let newLi = document.createElement("li")
newLi.setAttribute("class", 'nav-item')
let logOutBtn = document.createElement("button")
logOutBtn.setAttribute("class", 'navbar-link btn')
logOutBtn.setAttribute("id", "logout-button")
logOutBtn.innerText = "로그아웃"
logOutBtn.setAttribute("onclick", "handleLogout()")
newLi.appendChild(logOutBtn)
navberULRight.appendChild(newLi)
// let logoutButton = document.getElementById("")
} else {
console.log("로그인 버튼 Block")
}
}
injectNavbar();
fetch 로 navbar 를 가져오는 등의 코드가 3줄로 요약되었고
async function ~ await 함수로 인해, injectNavbar 라는 이름을 가진 함수명은
한눈에 알아보기 쉬운 함수명을 가졌으며
1. 함수명을 가졌다는 것 자체
에 대한 의미가 있다고 생각을 했다.
변수명, 함수명, 클래스명 -- 정의를 하는 것 자체가 주는 "의미"가 있는 것이다.
관리하는 측면에서 (유지보수)
코드를 읽어내야하는 피로도면에서
2. 동기적이냐 비동기적이냐에 대한 고민을 줄여준다.
콜백함수를 쓴다는 것 자체가, 지금
동기적이지 않아서 생기는 "문제"가 발생했다는 것이다.. (필자도 에러가 발생..)
내가 겪은 문제는, navbar.html 이 순서대로 읽혀지지 않고 비동기적으로 불러와져서
id 값이 null 로 불러와졌다.
3. api.js 및 index.js loader.js 등등 동시에 많은 JS 함수들이
하나의 html 에 불러와지기 때문에
1번 코드와 같이, 굉장히 많은 함수들에 대해서
콜백함수로 한땀 한땀 순서를 정하는 것은
굉장히 피곤한 일이 된다.
4. Error 처리 및 로직 구현의 용이성
async function logTodoTitle() {
try {
var user = await fetchUser();
if (user.id === 1) {
var todo = await fetchTodo();
console.log(todo.title);// delectus aut autem}
} catch (error) {
console.log(error);
}
}
다음과 같이 try catch 문법으로 예외 처리가 가능하다.
const condition = true;
const promise = new Promise((resolve, reject) => {
if (condition) {
resolve('resolved');
} else {
reject('rejected');
}
});
promise
.then((res) => {
console.log(res);
})
.catch((error) => {
console.error(error);
});
callback 이나 Promise 를 이용하면 then catch 문법으로 체이닝 및 로직 구현이 가능하지만
동기 / 비동기 로직에 대한 순서에 대한 고민도 많이 해야하고
유지 보수가 어려울 수도 있다는 생각을 했다.
promise 는 에러 핸들링이 다소 편해보이지만,
async await 도 try catch 를 통해 에러처리가 가능해서
크게 차이점이라곤 생각이 들지 않았다.
" 도대체 왜일까 ??? "
async function ~ await 를 쓰는 이유가 무엇인지
편의성을 위해 Callback, Promise 이후에 생겨난 이유가 무엇인지
배운지 약 1주일이 지나고난 후에 내린 결론은 이거지만
추후에 동기/비동기에 대한 깨달음이 주어진다면, |
블로그에 더 기록하겠읍니다....!
감사합니다
'Coding > JAVA_SCRIPT' 카테고리의 다른 글
console.log 사용을 멈춰주세요! 대신에 이것을 사용해보는 건 어떨까요 ? (1) | 2023.12.26 |
---|---|
[JS] 동기/비동기 , Callback 및 Promise 개념과 Promise chaining이해하기. (0) | 2023.09.15 |
JS window.onload() 에서 TypeError로 로그인/로그아웃시 로그인 버튼의 유무 적용 (1) | 2023.09.12 |