jQuery를 사용하는 가장 큰 이유 중 하나가 바로 AJAX 기능이다. AJAX를 통해 페이지를 새로고침하지 않고도 서버와 통신할 수 있기 때문에, 사용자 경험을 크게 향상시킬 수 있다. 다만 AJAX는 비동기 통신이기 때문에 실행 순서, 에러 처리, 타이밍 등 신경 써야 할 부분이 많다.
이번 글에서는 jQuery AJAX의 기본부터 시작해서, 실무에서 자주 사용되는 GET/POST/JSON 처리, 그리고 흔히 마주치는 문제들과 해결 방법을 정리해서 소개하겠다.
1. $.ajax() - 가장 기본적인 방법
$.ajax({
url: 'server.php', // 요청할 서버 URL
type: 'GET', // 요청 방식 (GET, POST, PUT, DELETE)
dataType: 'json', // 응답 데이터 타입 (json, html, text, xml)
data: { // 전송할 데이터
id: 123,
name: 'test'
},
success: function(response) { // 성공 시 실행
console.log(response);
},
error: function(xhr, status, error) { // 에러 시 실행
console.log('ERROR: ' + error);
},
complete: function() { // 성공/실패 상관없이 항상 실행
console.log('요청 완료');
},
timeout: 5000 // 타임아웃 5초 설정
});
2. GET 요청
// 기본 GET 요청
$.get('server.php', function(response) {
console.log(response);
});
// 데이터와 함께 GET 요청
$.get('server.php', {id: 123, name: 'test'}, function(response) {
console.log(response);
});
// 응답 타입 명시
$.get('server.php', {id: 123}, function(response) {
console.log(response);
}, 'json'); // JSON 응답 기대
3. POST 요청
// 기본 POST 요청
$.post('server.php', {
username: 'user123',
password: 'pass123'
}, function(response) {
console.log(response);
});
// 응답 타입 명시
$.post('server.php', {
id: 123,
action: 'update'
}, function(response) {
console.log(response);
}, 'json');
4. JSON 요청/응답
$.ajax({
url: 'api.php',
type: 'POST',
dataType: 'json',
contentType: 'application/json', // 전송 데이터 형식
data: JSON.stringify({ // 객체를 JSON 문자열로 변환
userId: 123,
action: 'update'
}),
success: function(response) {
// response는 자동으로 JSON 객체로 파싱됨
console.log(response.message);
console.log(response.data);
}
});
1. 사용자 정보 조회
$(document).ready(function(){
$('#searchBtn').click(function(){
var userId = $('#userId').val();
$.ajax({
url: 'user.php',
type: 'GET',
data: {id: userId},
dataType: 'json',
beforeSend: function() {
$('#result').html('로딩 중...');
},
success: function(response) {
if(response.success) {
$('#result').html(
'<p>이름: ' + response.data.name + '</p>' +
'<p>이메일: ' + response.data.email + '</p>'
);
} else {
$('#result').html('사용자를 찾을 수 없습니다');
}
},
error: function() {
$('#result').html('오류가 발생했습니다');
}
});
});
});
2. 폼 제출 (AJAX)
$(document).ready(function(){
$('#myForm').submit(function(e){
e.preventDefault(); // 기본 폼 제출 방지
var formData = $(this).serialize(); // 폼 데이터를 문자열로 변환
$.post('process.php', formData, function(response) {
if(response.success) {
alert('저장되었습니다');
$('#myForm')[0].reset(); // 폼 초기화
} else {
alert('저장 실패: ' + response.message);
}
}, 'json');
});
});
3. 파일 업로드 (FormData 사용)
$(document).ready(function(){
$('#uploadForm').submit(function(e){
e.preventDefault();
var formData = new FormData(this); // 파일 포함한 폼 데이터
$.ajax({
url: 'upload.php',
type: 'POST',
data: formData,
processData: false, // jQuery가 데이터를 처리하지 않게
contentType: false, // Content-Type을 자동 설정하게
success: function(response) {
console.log('업로드 완료: ' + response.filename);
},
error: function() {
alert('업로드 실패');
}
});
});
});
1. 에러 타입 구분하기
$.ajax({
url: 'server.php',
type: 'GET',
error: function(xhr, status, error) {
// xhr.status : HTTP 상태 코드 (200, 404, 500 등)
// status : 에러 타입 (error, timeout, parsererror, abort)
// error : 에러 메시지
if(status === 'timeout') {
alert('요청 시간 초과');
} else if(xhr.status === 404) {
alert('페이지를 찾을 수 없습니다');
} else if(xhr.status === 500) {
alert('서버 오류 발생');
} else if(xhr.status === 403) {
alert('접근 권한이 없습니다');
} else {
alert('알 수 없는 오류: ' + error);
}
}
});
2. 진행 상황 표시 (진행바)
$.ajax({
url: 'download.php',
type: 'GET',
xhrFields: {
onprogress: function(e) {
if(e.lengthComputable) {
var percentComplete = (e.loaded / e.total) * 100;
$('#progressBar').css('width', percentComplete + '%');
}
}
},
success: function(response) {
console.log('완료');
}
});
클라이언트의 AJAX 요청을 처리하는 서버 코드도 중요하다.
<?php
// server.php
header('Content-Type: application/json; charset=utf-8');
$response = array();
try {
$id = isset($_GET['id']) ? $_GET['id'] : '';
if(empty($id)) {
throw new Exception('ID가 필요합니다');
}
// 데이터베이스에서 조회 (예제)
$mysqli = new mysqli('localhost', 'user', 'pass', 'database');
$result = $mysqli->query("SELECT * FROM users WHERE id = {$id}");
if($result->num_rows > 0) {
$user = $result->fetch_assoc();
$response['success'] = true;
$response['data'] = $user;
} else {
$response['success'] = false;
$response['message'] = '사용자를 찾을 수 없습니다';
}
} catch(Exception $e) {
$response['success'] = false;
$response['message'] = $e->getMessage();
}
echo json_encode($response); // JSON 형식으로 응답
?>
1. "Uncaught SyntaxError: Unexpected token <"
원인: PHP 파일에 HTML이 섞여 있거나, 문법 에러로 HTML 에러 페이지가 반환됨
$.ajax({
url: 'server.php',
dataType: 'json',
error: function(xhr) {
// 실제 응답 확인
console.log(xhr.responseText);
}
});
2. CORS 에러 (Cross-Origin Request Blocked)
원인: 다른 도메인의 서버로 요청할 때 발생
// server.php - 서버에서 CORS 헤더 추가
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type');
header('Content-Type: application/json');
3. AJAX로 전송된 데이터를 서버에서 받지 못함
// jQuery에서 전송 (data 키 주의)
$.post('server.php', {
username: 'test',
email: 'test@example.com'
}, function(response) {
console.log(response);
});
// 서버에서 수신
// echo $_POST['username'];
// echo $_POST['email'];
- 요청 중복 방지 : 빠른 클릭으로 같은 AJAX가 여러 번 실행되지 않도록 플래그 사용
- 캐싱 : $.ajax의 cache 옵션으로 캐싱 활용
- 타임아웃 설정 : 무한 대기를 방지하기 위해 타임아웃 설정
- 로딩 표시 : 사용자 경험을 위해 로딩 중 표시
jQuery AJAX는 실무에서 매우 자주 사용되는 기능이다. 기본 원리를 이해하고 에러 처리를 제대로 하면, 안정적인 비동기 통신이 가능해진다. 다음 편에서는 jQuery의 이벤트 처리와 플러그인 개발, 그리고 성능 최적화에 대해 다룰 예정이니 계속해서 따라와주길 바란다.