객체 · DOM 조작 · 이벤트 · 비동기 프로그래밍
객체 리터럴, 점/대괄호 표기법, 메서드와 this, 객체 배열 패턴, 구조분해할당, 전개 연산자, 그리고 JSON 직렬화를 익힙니다. DOM 요소를 선택(getElementById/querySelector), 변경(textContent vs innerHTML), 동적 추가/삭제(createElement, appendChild), classList 토글, data-* 속성을 익힙니다. addEventListener로 이벤트 등록, 자주 쓰는 이벤트(click/input/submit/keydown 등), event 객체의 target·key·preventDefault, 버블링, 그리고 이벤트 위임 패턴을 익힙니다. 동기 vs 비동기, setTimeout/setInterval, Promise의 then/catch, async/await로 비동기 코드를 동기처럼, fetch API로 외부 데이터 가져오기, 그리고 try/catch 에러 처리를 익힙니다.
이 강의에서 배우는 것
- 1객체 리터럴로 데이터를 구조화한다
- 2점/대괄호 표기법으로 속성에 접근한다
- 3메서드와 this를 이해한다
- 4구조분해와 전개로 깔끔한 코드를 쓴다
- 5JSON.stringify / JSON.parse로 직렬화한다
- 6getElementById/querySelector/querySelectorAll로 요소를 선택한다
- 7textContent와 innerHTML의 보안 차이를 안다
- 8createElement → appendChild로 요소를 동적으로 만든다
- 9classList의 add/remove/toggle/contains를 사용한다
- 10data-* 속성과 dataset으로 데이터를 저장·읽는다
- 11addEventListener / removeEventListener로 이벤트를 등록·해제한다
- 12click·input·submit·keydown·change 같은 자주 쓰는 이벤트를 안다
- 13event.target / event.key / preventDefault를 활용한다
- 14버블링을 이해하고 stopPropagation으로 막는다
- 15이벤트 위임 패턴으로 효율적인 핸들러를 작성한다
- 16동기와 비동기의 실행 순서 차이를 설명한다
- 17Promise를 만들고 then/catch/finally로 처리한다
- 18async/await으로 가독성 좋은 비동기 코드를 작성한다
- 19fetch + response.json()으로 외부 데이터를 가져온다
- 20try/catch + throw로 에러를 안전하게 처리한다
객체
객체 리터럴, 점/대괄호 표기법, 메서드와 this, 객체 배열 패턴, 구조분해할당, 전개 연산자, 그리고 JSON 직렬화를 익힙니다.
1. 객체 리터럴
const person = {
name: "홍길동",
age: 25,
city: "서울",
isStudent: false,
};2. 속성 접근
// 점 표기법
console.log(person.name);
person.email = "h@a.com"; // 추가
person.age = 26; // 수정
delete person.isStudent; // 삭제
// 대괄호 표기법 (동적 키)
const key = "name";
console.log(person[key]);
const obj = { "first name": "길동" };
console.log(obj["first name"]);3. 메서드와 this
const person = {
name: "홍길동",
age: 25,
greet: function() {
return `안녕하세요, ${this.name}입니다!`;
},
// 단축 메서드 (ES6+)
getInfo() {
return `${this.name} (${this.age}세)`;
},
};
console.log(person.greet());
console.log(person.getInfo());화살표 함수는 자신만의 this를 갖지 않으므로 메서드에는 일반 함수를 사용합니다.
4. 객체 배열
const students = [
{ id: 1, name: "김철수", grade: "A", score: 95 },
{ id: 2, name: "이영희", grade: "B", score: 82 },
{ id: 3, name: "박민준", grade: "A", score: 91 },
];
const student = students.find(s => s.id === 2);
const aStudents = students.filter(s => s.grade === "A");
const avg = students.reduce((sum, s) => sum + s.score, 0) / students.length;5. 구조분해할당
const person = { name: "홍길동", age: 25, city: "서울" };
const { name, age, city } = person;
// 변수명 변경
const { name: userName, age: userAge } = person;
// 기본값
const { email = "없음" } = person;
// 함수 매개변수
function greet({ name, age }) {
return `${name}님은 ${age}세입니다.`;
}6. 전개 연산자
const original = { name: "홍길동", age: 25 };
// 복사 (얕은)
const copy = { ...original };
// 합치기 (뒤가 우선)
const merged = { ...original, ...{ city: "서울", age: 30 } };
// 속성 추가/수정
const updated = { ...original, email: "h@a.com", age: 26 };7. JSON
const person = { name: "홍길동", age: 25 };
// 객체 → JSON 문자열
const json = JSON.stringify(person);
// JSON 문자열 → 객체
const parsed = JSON.parse(json);
// 들여쓰기
console.log(JSON.stringify(person, null, 2));DOM 조작
DOM 요소를 선택(getElementById/querySelector), 변경(textContent vs innerHTML), 동적 추가/삭제(createElement, appendChild), classList 토글, data-* 속성을 익힙니다.
1. 요소 선택
// ID로 단일 (가장 빠름)
const title = document.getElementById('title');
// CSS 선택자로 첫 번째
const btn = document.querySelector('.btn');
const input = document.querySelector('input[type="text"]');
// CSS 선택자로 모두 (NodeList)
const allItems = document.querySelectorAll('.item');
allItems.forEach(item => console.log(item.textContent));2. textContent vs innerHTML
const div = document.querySelector('#content');
// textContent: 텍스트만 (HTML 무시, 안전)
div.textContent = '<b>굵게</b>'; // "<b>굵게</b>" 그대로 표시
// innerHTML: HTML 해석
div.innerHTML = '<b>굵게</b>'; // 굵게 표시innerHTML에 사용자 입력값을 직접 넣으면 XSS 공격 위험. 사용자 입력은 textContent를 사용하거나 별도 이스케이프 처리.
3. 요소 생성/추가/삭제
// 생성
const newDiv = document.createElement('div');
newDiv.textContent = '새 요소';
newDiv.className = 'card';
// 추가
const container = document.querySelector('#container');
container.appendChild(newDiv); // 끝
container.prepend(newDiv); // 앞
container.insertBefore(newDiv, container.firstChild);
// 삭제
container.removeChild(newDiv);
newDiv.remove(); // 모던 방식
// 부모 참조
const parent = newDiv.parentElement;4. classList
const box = document.querySelector('.box');
box.classList.add('active');
box.classList.add('highlight', 'large'); // 여러 개
box.classList.remove('active');
box.classList.toggle('dark-mode'); // 있으면 제거, 없으면 추가
if (box.classList.contains('active')) {
console.log('active!');
}5. dataset
<button data-id="42" data-user-name="홍길동" data-is-admin="true">
클릭
</button>const btn = document.querySelector('button');
// kebab-case → camelCase 자동 변환
console.log(btn.dataset.id); // "42"
console.log(btn.dataset.userName); // "홍길동"
console.log(btn.dataset.isAdmin); // "true" ← 항상 문자열
// 쓰기
btn.dataset.count = 0;
btn.dataset.lastClicked = Date.now();이벤트
addEventListener로 이벤트 등록, 자주 쓰는 이벤트(click/input/submit/keydown 등), event 객체의 target·key·preventDefault, 버블링, 그리고 이벤트 위임 패턴을 익힙니다.
1. addEventListener
const btn = document.querySelector('#myBtn');
btn.addEventListener('click', (event) => {
console.log('클릭됨!', event.target);
});
// 이벤트 제거
function handleClick() { console.log('클릭'); }
btn.addEventListener('click', handleClick);
btn.removeEventListener('click', handleClick);2. 자주 쓰는 이벤트
| 이벤트 | 발생 시점 | 대상 |
|---|---|---|
| click | 마우스 클릭 | 버튼·링크·카드 |
| input | 값 변경 (실시간) | input·textarea |
| change | 값 변경 후 포커스 이탈 | select·checkbox |
| submit | 폼 제출 | form |
| keydown | 키 누름 | input·document |
| keyup | 키 뗌 | input |
| mouseover/mouseout | 마우스 진입/이탈 | 모든 요소 |
| focus / blur | 포커스 받음/잃음 | input |
| DOMContentLoaded | DOM 준비 완료 | document |
3. event 객체
document.addEventListener('keydown', (event) => {
console.log(event.key); // "Enter", "a", "ArrowUp"
console.log(event.code); // "KeyA", "Enter", "Space"
console.log(event.ctrlKey); // true/false
console.log(event.shiftKey);
});
// 폼 기본 동작 막기
document.querySelector('form').addEventListener('submit', (event) => {
event.preventDefault();
console.log('폼 처리');
});
btn.addEventListener('click', (event) => {
console.log(event.target); // 실제 클릭된 요소
console.log(event.currentTarget); // 이벤트가 등록된 요소
console.log(event.clientX, event.clientY); // 마우스 좌표
});4. 이벤트 버블링
<div id="outer">
<div id="inner">
<button id="btn">클릭</button>
</div>
</div>document.getElementById('btn').addEventListener('click', () => console.log('버튼'));
document.getElementById('inner').addEventListener('click', () => console.log('inner'));
document.getElementById('outer').addEventListener('click', () => console.log('outer'));
// 버튼 클릭 시: "버튼" → "inner" → "outer"
// 버블링 중단
document.getElementById('btn').addEventListener('click', (e) => {
e.stopPropagation();
});5. 이벤트 위임
부모 요소에 이벤트를 등록해 자식 요소들을 한꺼번에 처리. 동적으로 추가된 요소에도 자동 적용.
// 비효율: 각 버튼마다 등록
document.querySelectorAll('.item-btn').forEach(btn => {
btn.addEventListener('click', handleClick);
});
// 효율: 부모에 위임
document.querySelector('#list').addEventListener('click', (event) => {
if (event.target.classList.contains('item-btn')) {
const itemId = event.target.dataset.id;
console.log(`아이템 ${itemId} 클릭`);
}
if (event.target.classList.contains('delete-btn')) {
event.target.closest('.item').remove();
}
});비동기 프로그래밍
동기 vs 비동기, setTimeout/setInterval, Promise의 then/catch, async/await로 비동기 코드를 동기처럼, fetch API로 외부 데이터 가져오기, 그리고 try/catch 에러 처리를 익힙니다.
1. 동기 vs 비동기
// 동기: 순서대로
console.log("1번");
console.log("2번");
console.log("3번");
// 1번 → 2번 → 3번
// 비동기: 완료 안 기다리고 다음으로
console.log("1번");
setTimeout(() => console.log("2번 (1초 후)"), 1000);
console.log("3번");
// 1번 → 3번 → 2번 (1초 후)2. setTimeout / setInterval
// 한 번 실행
const timerId = setTimeout(() => {
console.log("3초 후");
}, 3000);
clearTimeout(timerId);
// 반복 실행
const intervalId = setInterval(() => {
console.log("1초마다");
}, 1000);
setTimeout(() => {
clearInterval(intervalId);
}, 5000);3. Promise
const myPromise = new Promise((resolve, reject) => {
const success = true;
if (success) {
resolve("성공!");
} else {
reject("실패!");
}
});
myPromise
.then(result => {
console.log(result);
return result + " 처리 완료";
})
.then(result => console.log(result))
.catch(error => console.error(error))
.finally(() => console.log("항상 실행"));4. async / await
Promise를 더 간결하게 작성하는 문법입니다.
function delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function main() {
console.log("시작");
await delay(1000);
console.log("1초 후");
await delay(1000);
console.log("2초 후");
}
main();5. fetch API
Promise 방식
fetch('https://api.example.com/data')
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error(error));async/await 방식 (권장)
async function loadData() {
try {
const response = await fetch('https://api.example.com/data');
if (!response.ok) {
throw new Error(`HTTP 오류: ${response.status}`);
}
const data = await response.json();
console.log(data);
} catch (error) {
console.error("실패:", error.message);
}
}6. JSON.parse / stringify
const user = { name: "홍길동", age: 25 };
const json = JSON.stringify(user);
const parsed = JSON.parse(json);
// localStorage와 자주 사용
localStorage.setItem('user', JSON.stringify(user));
const saved = JSON.parse(localStorage.getItem('user'));7. try / catch 에러 처리
async function risky() {
try {
const response = await fetch('https://invalid-url.xyz');
if (!response.ok) throw new Error(`서버 오류: ${response.status}`);
const data = await response.json();
return data;
} catch (error) {
console.error("오류:", error.message);
return null;
} finally {
console.log("작업 종료 (성공/실패 무관)");
}
}댓글 0
아직 댓글이 없습니다. 첫 댓글을 남겨 주세요.
댓글은 회원만 쓸 수 있습니다.
광고·욕설·비방·개인정보·불법 내용이 담긴 댓글은 숨기거나 지웁니다. 댓글은 닉네임과 함께 공개됩니다. 개인정보처리방침