250904 [ Day 43 ] - JavaScript (4)

TaeHyun·2025년 9월 4일

TIL

목록 보기
45/182

시작하며

오늘은 JavaScript를 배우면서 가장 어려운 개념들을 배운 것 같다. 정규 과정이 아니라 짧은 시간 안에 HTML, CSS, JavaScript, React를 간단하게나마 배우고 있다 보니 수업 진도가 매우 빠른 템포로 진행된다. 그런데 내용 자체도 복잡한 내용이다 보니 더 어렵게 느껴진 것 같다.

CSS 지정

const list = document.querySelectorAll(".fruit");
console.log("list", list);
  • 인덱스로 접근하여 스타일 지정
  • JavaScript에서는 카멜 케이스로 작성
list[0].style.backgroundColor = "purple";
list[1].style.fontSize = "30px";

  • 반복문 활용
for (const li of list) {
    li.style.backgroundColor = "lightskyblue";
    li.style.fontSize = "25px";
    li.style.fontWeight = "bold";
}

classList

const h1 = document.querySelector("h1");
  • 클래스 추가
h1.classList.add("title");

  • 클래스 여부 확인
console.log(h1.classList.contains("title"));

  • 클래스 삭제
h1.classList.remove("title");

  • 클래스가 있으면 제거 없으면 추가
h1.classList.toggle("title");

요소 찾기

const fruits = document.querySelector("#fruits");
  • 자식 요소 찾기
console.log("자식 요소 조회", fruits.children);
console.log("자식 요소 조회", fruits.children[0]);

  • 형제 요소 찾기
const apple = document.querySelector("#apple");

console.log("형제 요소 조회", apple.nextElementSibling);
console.log("다음 형제 요소 조회", apple.nextElementSibling.nextElementSibling);

새로운 요소 생성, 추가, 삭제

const container = document.querySelector(".container");
  • 새로운 요소 생성
const p = document.createElement("p");

p.textContent = "새로운 요소";
p.style.color = "purple";
p.style.fontSize = "30px";
console.log("새로운 요소", p);

  • 요소를 화면에 추가
container.appendChild(p);

  • 자식 요소 삭제
const firstChild = document.querySelector(".container > p");
container.removeChild(firstChild);

  • 자기 자신 삭제
container.remove();

DOM Event

  • addEventListener : 이벤트를 감지해서 함수를 실행
const btn1 = document.querySelector("#btn1");
const btn2 = document.querySelector("#btn2");
const btn3 = document.querySelector("#btn3");
const btn4 = document.querySelector("#btn4");

btn1.addEventListener("click", () => alert("버튼1 클릭"));
btn2.addEventListener("mouseover", () => console.log("버튼2 마우스 오버"));
btn3.addEventListener("click", () => (btn3.style.color = "red"));
btn4.addEventListener("click", changeDivColor);

// 함수 선언식 호이스팅
function changeDivColor() {
    const divs = document.querySelectorAll(".container > div");
    for (const div of divs) {
        div.style.backgroundColor = "black";
        div.style.color = "white";
    }
}

  • 이벤트 객체 : 브라우저에서 발생한 이벤트에 대한 정보를 담은 객체
const btn5 = document.querySelector("button");
const input = document.querySelector("input");

btn5.addEventListener("click", (e) => console.log("Event", e));
input.addEventListener("keydown", (e) => {
    console.log("value", e.target.value);
    if (e.code === "ArrowUp") {
        console.log("code", e.code);
    }
});

  • 폼 이벤트
const testForm = document.querySelector("#test-form");
testForm.addEventListener("submit", (e) => {
    e.preventDefault(); // 새로고침 발생 방지
    console.log("submit");
});

  • onclick 함수
  • HTML
<body>
    <h1 onclick="handleH1Click()">JS Event</h1>

  • JS
  • 함수만 사용시 type="module" 제거 필요
const h1 = document.querySelector("h1");
h1.onclick = function handleH1Click() {
    h1.style.backgroundColor = "red";
};

구조 분해 할당

배열의 구조 분해 할당

const arr1 = [10, 20, 30, 40, 50];
const [ten, twenty, thirty, fourty, fifty] = arr1;
  • 기본값 지정
const arr2 = ["치킨", "피자"];
const [a, b, c = "콜라"] = arr2;

객체의 구조 분해 할당

  • 키를 기준으로 할당
const obj = {
    name: "name1",
    age: 27,
    city: "Seoul",
};

const { name, age, city, hobby = "독서" } = obj;
console.log("객체 구조분해할당", name, age, city, hobby);
// 객체 구조분해할당 name1 27 Seoul 독서

전개연산자 ... (Spread Syntax)

배열의 전개

const arr3 = [1, 2, 3];
const arr4 = [4, 5, 6];

const spread = [...arr3, ...arr4];
console.log("spread", spread);
// spread (6) [1, 2, 3, 4, 5, 6]

문자열의 전개

const spread2 = [..."HELLO"];
console.log("spread2", spread2);
// spread2 (5) ['H', 'E', 'L', 'L', 'O']

객체의 전개

const chip = {
    base: "포카칩",
    company: "오리온",
};

const potatoChip = {
    ...chip,
    flavor: "Onion",
};

console.log("객체 전개", potatoChip);
// 객체 전개 {base: '포카칩', company: '오리온', flavor: 'Onion'}

rest 파라미터

  • 순서대로 받고, 나머지는 rest에 넣기
const values = ["가", "나", "다", "라", "미"];

function myFunc(a, b, c, ...rest) {
    console.log(a, b, c);
    console.log("rest", rest);
}

myFunc(...values);
// 가 나 다
// rest (2) ['라', '미']
const icecream = {
    company: "빙그레",
    flavor: "초코",
    price: 2000,
};

const { flavor, ...rest } = icecream;
console.log(flavor);
console.log("rest", rest);
// 초코
// rest {company: '빙그레', price: 2000}

Callback

  • JavaScript = 동기적 (코드를 위에서 아래로 순서대로 실행함)
  • Callback 함수 : 함수의 실행이 끝난 후 이어서 실행되는 함수

setTimeout

  • 일정시간(ms)이 지난후 함수를 실행하게 해줌
  • Web API : 웹에서만 실행 가능
console.log(1);
setTimeout(() => console.log(2), 1000);
console.log(3);
// 1
// 3
// 2

Callback Hell

lass UserStorage {
    loginUser(id, password, onSuccess, onError) {
        setTimeout(() => {
            if (id === "taehyun" && password === "1234") {
                onSuccess(id);
            } else {
                onError(new Error("존재하지 않는 계정입니다"));
            }
        }, 1000);
    }

    getRoles(user, onSuccess, onError) {
        setTimeout(() => {
            if (user === "taehyun") {
                onSuccess({ name: "taehyun", role: "crew" });
            } else {
                onError(new Error("권한이 없습니다."));
            }
        }, 1000);
    }
}

  • UserStorage 인스턴스 생성
const userStorage = new UserStorage();

const id = prompt("ID를 입력해주세요");
const password = prompt("PW를 입력해주세요");

userStorage.loginUser(
    id,
    password,
    (id) => {
        userStorage.getRoles(
            id,
            (userWithRole) => {
                alert(
                    `Hello ${userWithRole.name}, 당신은 ${userWithRole.role}입니다.`
                );
            },
            (error) => console.log(error)
        );
    },
    (error) => console.log(error)
);

Promise

  • 비동기 수행을 위한 객체
  • 상태 : Pending(대기) -> Fulfilled(이행) or Rejected(거부)

Producer

  • excuter 함수 : 실행함수 -> Promise 생성시 자동 실행
  • resolve : 성공시 호출
  • reject : 실패시 호출
const promise = new Promise((resolve, reject) => {
    console.log("프로미스 실행...");
    setTimeout(() => {
        // 성공시 호출
        resolve("taehyun");
        // 실패시 호출
        reject(new Error("네트워크 에러"));
    }, 2000);
});

Consumer

  • then : resolve되었을 때 실행
  • catch : reject되었을 때 실행
  • finally : 모든 실행이 끝나고 최종적으로 실행 -> 성공 실패 여부에 상관없이 마지막에 호출
promise //
    .then((value) => console.log("Consumer", value))
    .catch((error) => console.log(error))
    .finally(() => console.log("마지막에 실행"));

Promise Chaining

const fetchNumber = new Promise((resolve, reject) => {
    setTimeout(() => resolve(1), 1000);
});

fetchNumber //
    .then((num) => num * 2)
    .then((num) => num * 3)
    .then((num) => {
        return new Promise((resolve, reject) => {
            setTimeout(() => resolve(num + 10), 1000);
        });
    })
    .then((num) => console.log("Promise Chaining", num));

  • Promise로 UserStorage 리팩토링
class UserStorage {
    loginUser(id, password) {
        return new Promise((resolve, reject) => {
            setTimeout(() => {
                if (id === "taehyun" && password === "1234") {
                    resolve(id);
                } else {
                    reject(new Error("존재하지 않는 계정입니다"));
                }
            }, 1000);
        });
    }

    getRoles(user) {
        return new Promise((resolve, reject) => {
            setTimeout(() => {
                if (user === "taehyun") {
                    resolve({ name: "taehyun", role: "crew" });
                } else {
                    reject(new Error("권한이 없습니다."));
                }
            }, 1000);
        });
    }
}

const userStorage = new UserStorage();

const id = prompt("ID를 입력해주세요");
const password = prompt("PW를 입력해주세요");

userStorage //
    .loginUser(id, password)
    .then((id) => userStorage.getRoles(id))
    .then((user) => alert(`Hello ${user.name}, 당신은 ${user.role}입니다.`));

Async, Await

  • Promise를 동기적인 형태로 작성할 수 있도록 도와주는 문법
    • syntatic sugar : 편의를 제공하는 문법

async

  • 함수 코드블럭을 자동으로 프로미스로 변환
async function fetchUser() {
    return "taehyun";
}

const user = fetchUser();
console.log(user);
// Promise {<fulfilled>: 'taehyun'}
user.then(console.log);
// taehyun

await

  • async 안에서 사용가능
  • Promise를 동기적으로 쓸 수 있게 해주는 키워드
function delay(ms) {
    return new Promise((resolve) => setTimeout(resolve, ms));
}

async function getApple() {
    await delay(1000);
    return "Apple";
}

async function getBanana() {
    await delay(1000);
    return "Banana";
}

async function pickFruits() {
    const apple = await getApple();
    const banana = await getBanana();
    return `${apple}, ${banana}`;
}

pickFruits().then(console.log);

마치며

드디어 JavaScript 파트가 끝났다. 처음에는 웹의 기능을 구현하는 언어라고 해서 CSS처럼 기능 위주의 언어라고 생각했는데, 그런 생각과는 차원이 달랐던 것 같다. 그래서 기능적인 부분을 많이 기대했었는데, 기대와는 다른 점이 다소 아쉽기도 했다.
JavaScript가 끝나고 React에 대한 소개를 간단히 듣고 끝났다. React도 다른 언어들처럼 하나의 프로그래밍 언어인 줄 알았는데, 라이브러리인 것을 알고 꽤 충격을 받은 수업의 마무리였다.

NOTION

MY NOTION (JavaScript. 06)
MY NOTION (JavaScript. 07)
MY NOTION (JavaScript. 08)

profile
Hello I'm TaeHyunAn, Currently Studying Data Analysis

0개의 댓글