AJAX(Asynchronous JavaScript and XML)는
웹 애플리케이션에서 서버와 비동기적으로 데이터를 주고받기 위한 기술이다.
웹 페이지를 새로고침하지 않고도 서버와 데이터를 주고받을 수 있게 해주는 특징이 있다.
동기 통신 (Synchronous Communication)
동기 통신은 요청과 응답이 순차적으로 이루어지는 방식이다. 클라이언트가 요청을 보내면
그 요청에 대한 응답이 올 때까지 다른 작업을 하지 않고 기다린다. 응답이 오면 그때서야 다음 작업을 수행한다.
특징:
- 차단(Blocking): 요청을 보낸 후 응답을 받을 때까지 프로그램이 차단된다. 이 동안 다른 작업은 수행되지 않는다.
- 순차적 처리: 요청과 응답이 순차적으로 처리되기 때문에 로직이 단순해지고, 디버깅이 상대적으로 쉽다.
- 성능: 응답을 기다리는 동안 애플리케이션이 다른 작업을 하지 못하기 때문에 사용자 경험이 저하될 수 있다.
// 동기적인 HTTP 요청을 위해 XMLHttpRequest 사용
const xhr = new XMLHttpRequest(); // XMLHttpRequest 객체를 const로 선언
xhr.open("GET", "https://api.example.com/data", false); // false는 동기 호출을 의미
xhr.send(); // 요청 전송
if (xhr.status === 200) {
console.log(xhr.responseText); // 성공적인 응답 처리
} else {
console.error("Request failed with status:", xhr.status); // 실패한 요청 처리
}
비동기 통신 (Asynchronous Communication)
비동기 통신은 요청을 보내고, 그 응답을 기다리지 않고 다른 작업을 계속 진행할 수 있는 방식이다.
요청을 보낸 후 응답이 도착하면, 지정한 콜백 함수나 프로미스 처리기에서 응답을 처리한다.
특징:
- 비차단(Non-Blocking): 요청을 보낸 후 응답을 기다리는 동안 다른 작업을 계속할 수 있다.
- 이로 인해 애플리케이션의 응답성이 향상된다.
- 이벤트 기반: 응답이 도착했을 때 호출되는 콜백 함수나 프로미스를 사용하여 응답을 처리한다.
- 성능: 비동기 처리로 인해 더 나은 사용자 경험을 제공할 수 있으며, 서버와의 통신이 지연되더라도 애플리케이션이 계속 동작할 수 있다.
// 비동기적인 HTTP 요청을 위해 XMLHttpRequest 사용
const xhr = new XMLHttpRequest(); // XMLHttpRequest 객체를 const로 선언
xhr.open("GET", "https://api.example.com/data", true); // true는 비동기 호출을 의미
xhr.onload = function() {
if (xhr.status >= 200 && xhr.status < 300) {
console.log(xhr.responseText); // 성공적인 응답 처리
} else {
console.error("Request failed with status:", xhr.status); // 실패한 요청 처리
}
};
xhr.send(); // 요청 전송
XMLHttpRequest (XHR)
AJAX에서는 웹 브라우저에서 비동기적으로 데이터를 요청하고 받아오는 데 XMLHttpRequest (XHR)를 사용했다.
서버와 비동기적으로 데이터를 교환할 수 있는 오래된 API로, XMLHttpRequest의 문제점을 보완하여 나온 것이 FetchApi이다.
1. 복잡한 콜백 처리
XMLHttpRequest는 콜백 기반으로 작동한다. 이는 비동기 요청이 완료되면 호출될 콜백 함수를 설정하는 방식이다.
하지만 콜백을 사용하는 방식은 다음과 같은 문제를 야기할 수 있다
- 콜백 지옥: 여러 개의 비동기 호출이 중첩될 때, 콜백 함수가 서로 중첩되어 코드가 복잡해지고 가독성이 떨어진다.
- 에러 처리: 각 콜백 함수 내에서 에러를 처리해야 하며, 에러가 발생할 경우 복잡한 로직이 필요하다.
const xhr = new XMLHttpRequest();
xhr.open("GET", "https://api.example.com/data", true);
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
// 첫 번째 비동기 요청 성공 시 처리
const data = JSON.parse(xhr.responseText);
const xhr2 = new XMLHttpRequest();
xhr2.open("POST", "https://api.example.com/submit", true);
xhr2.onreadystatechange = function() {
if (xhr2.readyState === 4) {
if (xhr2.status === 200) {
// 두 번째 비동기 요청 성공 시 처리
console.log("Second request succeeded.");
} else {
// 두 번째 요청 오류 처리
console.error("Second request failed with status:", xhr2.status);
}
}
};
xhr2.send(JSON.stringify(data));
} else {
// 첫 번째 요청 오류 처리
console.error("First request failed with status:", xhr.status);
}
}
};
xhr.send();
2. 프로미스 지원 부족
XMLHttpRequest는 프로미스를 지원하지 않으므로 비동기 처리 시 프로미스 기반의 접근을 사용할 수 없다.
이는 비동기 코드를 작성할 때 비효율적이며, JavaScript 비동기 처리 패턴(async/await)과의 통합이 어렵다.
3. 응답 데이터 처리의 복잡성
XMLHttpRequest는 응답 데이터를 처리할 때 여러 번의 변환 작업이 필요하다.
예를 들어, JSON 응답을 처리하려면 responseText를 파싱해야 한다.
const xhr = new XMLHttpRequest(); // XMLHttpRequest 객체를 const로 선언
const url = "https://api.example.com/data"; // 요청 URL을 const로 선언
xhr.open("GET", url, true); // 비동기 GET 요청 설정
xhr.onload = function() {
if (xhr.status >= 200 && xhr.status < 300) {
const data = JSON.parse(xhr.responseText); // 응답 데이터를 const로 선언
console.log(data);
} else {
console.error("Request failed with status:", xhr.status);
}
};
xhr.onerror = function() {
console.error("Request failed due to a network error.");
};
xhr.send(); // 요청 전송
4. HTTP 상태 코드와 에러 처리
XMLHttpRequest는 HTTP 상태 코드를 직접 처리해야 하며, 네트워크 오류를 처리하기 위해 추가적인 코드가 필요하다.
상태 코드가 실패를 나타내는 경우에도 onreadystatechange 이벤트에서 수동으로 처리해야 한다.
5. 동기 호출의 문제
XMLHttpRequest는 동기 모드를 지원하지만, 이는 브라우저의 UI 스레드를 차단해
사용자가 요청이 완료될 때까지 기다려야 한다.
6. 제한된 기능과 설정
XMLHttpRequest는 캐시 제어, 요청 타임아웃 등과 같은 일부 기능을 설정하는 데 제한이 있다.
7. 호이스팅과 스코프 문제
XMLHttpRequest의 상태를 관리하는 데 필요한 콜백 함수와 이벤트 핸들러는 this 키워드와 같은
스코프 관련 문제를 동반한다.
XMLHttpRequest의 복잡성과 한계를 극복하기 위해 Fetch API가 도입되었다.
Fetch API는 다음과 같은 개선된 기능을 제공한다
Fetch API
- 프로미스 기반: fetch() 함수는 프로미스를 반환하여, async/await와 함께 사용할 수 있음으로 콜백 문제를 해결했다
- 단순한 문법: fetch()는 간단한 문법으로 HTTP 요청을 수행하고, 응답을 처리한다.
- 응답 객체의 메서드: 응답 객체에서 다양한 메서드를 사용하여 JSON, 텍스트, Blob 등으로 변환한다.
- 에러 처리: 네트워크 오류를 프로미스의 catch 블록에서 처리하고,
- HTTP 상태 코드로 응답 성공 여부를 확인할 수 있다.
// 서버에서 데이터를 비동기적으로 가져오기
fetch("https://api.example.com/data")
.then(response => {
if (!response.ok) {
throw new Error('Network response was not ok');
}
return response.json(); // JSON 형식으로 응답 데이터 파싱
})
.then(data => {
console.log(data); // 데이터 처리
})
.catch(error => {
console.error('There was a problem with the fetch operation:', error); // 오류 처리
});
'CS > JAVASCRIPT' 카테고리의 다른 글
REACT 함수형 클래스와 컴포넌트 (0) | 2024.08.15 |
---|---|
React와 ReactDOM (0) | 2024.08.14 |
REST API (0) | 2024.07.18 |
JSON (0) | 2024.06.28 |
var, let, const (0) | 2024.06.28 |