jQuery의 비동기 처리 및 dom 조작
기본 개념 설명
- 함수: 함수는 어떤 작업을 수행하는 코드 블록입니다.
- 즉시 실행 함수 표현식(IIFE): 함수가 정의되자마자 바로 실행되는 특별한 함수입니다.
- 매개변수: 함수가 실행될 때 외부에서 값을 받아오는 변수입니다.
예시 코드
(function($, window) {
// 여기에 코드를 작성합니다.
})(jQuery, window);
이 코드의 목적
이 코드는 특별한 함수(즉시 실행 함수)를 사용하여 작성되었습니다. 이 함수는 바로 실행되며, 두 개의 매개변수 $와 window를 받습니다.
매개변수 설명
- $:
- $는 보통 jQuery라는 라이브러리를 의미합니다.
- jQuery는 웹 페이지를 쉽게 조작할 수 있도록 도와주는 도구입니다.
- 보통 jQuery라고 쓰는 대신 $라고 쓰면 더 간단하고 코드가 짧아집니다.
- window:
- window는 브라우저의 전역 객체를 의미합니다.
- 브라우저에서 전역적으로 사용할 수 있는 모든 변수와 함수들을 포함하고 있습니다.
- 예를 들어, 현재 페이지의 URL을 가져오고 싶다면 window.location.href를 사용할 수 있습니다
코드가 동작하는 방식
- 함수 정의와 즉시 실행:
- (function($, window) { ... })(jQuery, window);는 함수를 정의하고 바로 실행합니다.
- 함수가 정의되면 바로 (jQuery, window)를 통해 매개변수를 전달하고 실행합니다.
- 매개변수 전달:
- jQuery 라이브러리와 window 객체를 함수의 매개변수로 전달합니다.
- 함수 내부에서 jQuery를 $로, window를 window로 사용하게 됩니다.
JavaScript의 비동기 동작과 Fetch API
JavaScript에서 비동기 동작은 페이지가 응답을 기다리지 않고 다른 작업을 계속 수행할 수 있게 합니다. fetch API는 비동기적으로 네트워크 요청을 보내고 응답을 받기 위해 자주 사용됩니다.
fetch('https://api.example.com/data')
.then(response => {
if (!response.ok) {
throw new Error('Network response was not ok');
}
return response.json();
})
.then(data => {
console.log(data); // 여기서 응답 데이터를 처리
})
.catch(error => {
console.error('Fetch error:', error);
});
위 코드에서 fetch는 네트워크 요청을 보내고, 서버에서 응답을 받을 때까지 기다리지 않고 즉시 다음 줄로 넘어갑니다. then 블록은 응답이 도착했을 때 실행됩니다.
비동기 동작의 이점
- 사용자 경험 향상: 페이지가 응답을 기다리느라 멈추지 않기 때문에 사용자 경험이 좋아집니다.
- 효율적 리소스 사용: 네트워크 요청이 진행되는 동안 브라우저가 다른 작업을 수행할 수 있습니다.
DOM 조작
fetch를 사용해 데이터를 가져오는 것만으로는 화면에 변화가 일어나지 않습니다. 데이터를 가져온 후, 이 데이터를 사용해 DOM을 조작해야 합니다.
fetch('https://api.example.com/data')
.then(response => response.json())
.then(data => {
// 데이터로 DOM을 업데이트
const contentDiv = document.getElementById('content');
contentDiv.innerHTML = '';
data.items.forEach(item => {
const p = document.createElement('p');
p.textContent = item.name;
contentDiv.appendChild(p);
});
})
.catch(error => console.error('Fetch error:', error));
위 코드에서는 fetch로 데이터를 가져온 후, data.items 배열을 사용해 새로운 HTML 요소를 생성하고 DOM에 추가합니다.
왜 Fetch로는 HTML 코드가 변하지 않는 것처럼 보일까?
- 비동기 특성: fetch 요청은 비동기적으로 동작하기 때문에 요청을 보낸 직후에는 HTML이 변하지 않은 것처럼 보일 수 있습니다. 응답이 도착하고 데이터를 처리할 때까지 시간이 걸리기 때문입니다.
- DOM 조작의 필요성: fetch는 단순히 데이터를 가져오는 역할만 합니다. 이 데이터를 가지고 DOM을 조작하는 작업을 별도로 해줘야 화면에 변화가 생깁니다.
- 타이밍 문제: 비동기 코드가 언제 실행되는지에 대한 이해가 부족하면, 요청이 완료되기 전에 화면을 확인하게 되어 변화가 없는 것처럼 보일 수 있습니다.
비동기 동작을 시각적으로 확인하기
네트워크 요청과 응답을 기다리는 동안 로딩 메시지를 표시하는 예제입니다:
// 로딩 메시지를 표시
const contentDiv = document.getElementById('content');
contentDiv.textContent = 'Loading...';
fetch('https://api.example.com/data')
.then(response => response.json())
.then(data => {
// 로딩 메시지를 지우고 데이터로 DOM을 업데이트
contentDiv.innerHTML = '';
data.items.forEach(item => {
const p = document.createElement('p');
p.textContent = item.name;
contentDiv.appendChild(p);
});
})
.catch(error => {
contentDiv.textContent = 'Error loading data';
console.error('Fetch error:', error);
});
이 예제는 fetch 요청을 보내고 응답을 기다리는 동안 "Loading..." 메시지를 표시합니다. 응답을 받아서 데이터를 처리할 때 이 메시지를 지우고, 새로운 데이터를 DOM에 추가합니다.
JavaScript Promise
Promise 객체는 자바스크립트에서 비동기 작업을 처리하기 위해 도입된 객체입니다. Promise는 미래에 완료될 작업(또는 실패할 작업)을 나타내며, 이를 통해 비동기 작업의 결과를 처리할 수 있습니다. Promise는 비동기 작업이 성공했을 때와 실패했을 때의 콜백을 등록할 수 있게 합니다.
Promise의 상태
Promise 객체는 세 가지 상태를 가집니다:
- Pending(대기): 초기 상태로, 작업이 아직 완료되지 않은 상태입니다.
- Fulfilled(이행): 작업이 성공적으로 완료된 상태입니다.
- Rejected(거부): 작업이 실패한 상태입니다.
Promise의 기본 문법
let promise = new Promise(function(resolve, reject) {
// 비동기 작업을 수행합니다.
// 작업이 성공하면 resolve(value)를 호출합니다.
// 작업이 실패하면 reject(error)를 호출합니다.
});
예시: Promise 생성 및 사용
1. Promise 객체 생성
// 1. Promise 객체 생성
let myPromise = new Promise(function(resolve, reject) {
// 비동기 작업 (예: 네트워크 요청)
setTimeout(() => {
let success = true; // 이 조건은 예시입니다.
if (success) {
resolve("작업이 성공했습니다!"); // 작업이 성공하면 resolve 호출
} else {
reject("작업이 실패했습니다."); // 작업이 실패하면 reject 호출
}
}, 1000); // 1초 후에 비동기 작업을 완료합니다.
});
2. Promise 사용
myPromise
.then(function(result) {
console.log(result); // "작업이 성공했습니다!" 출력
})
.catch(function(error) {
console.error(error); // "작업이 실패했습니다." 출력
});
Promise 메서드
- then(onFulfilled, onRejected): Promise가 이행되었을 때 호출할 콜백과 거부되었을 때 호출할 콜백을 설정합니다.
- catch(onRejected): Promise가 거부되었을 때 호출할 콜백을 설정합니다.
- finally(onFinally): Promise가 이행되었든 거부되었든 상관없이 항상 호출할 콜백을 설정합니다.
- all(promises): 모든 Promise가 이행될 때까지 기다립니다. 하나라도 거부되면 전체가 거부됩니다.
- race(promises): 가장 먼저 이행되거나 거부된 Promise의 결과를 반환합니다.
예시: Promise.all
let promise1 = Promise.resolve(3);
let promise2 = new Promise((resolve, reject) => setTimeout(resolve, 100, 'foo'));
let promise3 = 42;
Promise.all([promise1, promise2, promise3])
.then(values => {
console.log(values); // [3, 'foo', 42]
})
.catch(error => {
console.error(error);
});
예시: Promise.race
let promise1 = new Promise((resolve, reject) => {
setTimeout(resolve, 500, 'one');
});
let promise2 = new Promise((resolve, reject) => {
setTimeout(resolve, 100, 'two');
});
Promise.race([promise1, promise2])
.then(value => {
console.log(value); // 'two' (promise2가 먼저 완료됩니다)
})
.catch(error => {
console.error(error);
});
예시: async/await와 Promise
function delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function asyncFunction() {
console.log("작업 시작");
await delay(1000); // 1초 기다림
console.log("1초 후 작업 완료");
}
asyncFunction();
결론
Promise는 비동기 작업을 관리하고, 그 결과를 처리하는 강력한 도구입니다. 이를 사용하여 복잡한 비동기 작업을 보다 직관적이고 가독성 있게 작성할 수 있습니다. Promise를 활용하면 콜백 헬(callback hell)을 피하고, 비동기 코드의 가독성을 높일 수 있습니다.