AJAX 처리
Function Guide
AJAX 처리 함수들
클라이언트(브라우저)와 서버 간의 AJAX 통신을 처리하는 함수들입니다.
푸시 구독 관리, 알림 설정, VAPID 키 조회 등을 JSON 형태로 처리합니다.
handle_push_subscription()
브라우저에서 푸시 구독 등록 요청을 AJAX로 처리합니다. JSON 응답을 반환하고 함수 실행을 종료합니다.
function handle_push_subscription()
요청 형식
HTTP Method
요청 형식
HTTP Method
GET 또는 POST 메서드 모두 지원합니다. 추가 파라미터는 필요하지 않습니다.
응답 형식
성공 시 (200 OK)
{
"success": true,
"message": "성공",
"data": {
"vapid_public_key": "BGtFqB7V9OZFKv7yZj8r5z6KcGqKh..."
}
}
"success": true,
"message": "성공",
"data": {
"vapid_public_key": "BGtFqB7V9OZFKv7yZj8r5z6KcGqKh..."
}
}
실패 시 (404)
{
"success": false,
"message": "VAPID 공개키가 설정되지 않았습니다."
}
"success": false,
"message": "VAPID 공개키가 설정되지 않았습니다."
}
JavaScript 사용 예시
// VAPID 공개키 조회 후 푸시 구독
async function initializePushSubscription() {
// 1. VAPID 공개키 가져오기
const response = await fetch('/ajax/get_vapid_key.php');
const result = await response.json();
if (!result.success) {
console.error('VAPID 키 조회 실패:', result.message);
return;
}
// 2. VAPID 키로 푸시 구독
const vapidKey = result.data.vapid_public_key;
const registration = await navigator.serviceWorker.ready;
const subscription = await registration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: urlBase64ToUint8Array(vapidKey)
});
console.log('푸시 구독 완료', subscription);
}
// VAPID 키 형식 변환 함수
function urlBase64ToUint8Array(base64String) {
const padding = '='.repeat((4 - base64String.length % 4) % 4);
const base64 = (base64String + padding)
.replace(/-/g, '+')
.replace(/_/g, '/');
const rawData = window.atob(base64);
return new Uint8Array([...rawData].map(char => char.charCodeAt(0)));
}
async function initializePushSubscription() {
// 1. VAPID 공개키 가져오기
const response = await fetch('/ajax/get_vapid_key.php');
const result = await response.json();
if (!result.success) {
console.error('VAPID 키 조회 실패:', result.message);
return;
}
// 2. VAPID 키로 푸시 구독
const vapidKey = result.data.vapid_public_key;
const registration = await navigator.serviceWorker.ready;
const subscription = await registration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: urlBase64ToUint8Array(vapidKey)
});
console.log('푸시 구독 완료', subscription);
}
// VAPID 키 형식 변환 함수
function urlBase64ToUint8Array(base64String) {
const padding = '='.repeat((4 - base64String.length % 4) % 4);
const base64 = (base64String + padding)
.replace(/-/g, '+')
.replace(/_/g, '/');
const rawData = window.atob(base64);
return new Uint8Array([...rawData].map(char => char.charCodeAt(0)));
}
사용자 설정 AJAX 함수들
사용자의 알림 설정과 기기 관리를 위한 AJAX 처리 함수들입니다.
handle_save_notification_settings()
사용자의 알림 설정과 기기별 설정을 저장합니다.
요청 본문 예시
{
"message_notification": 1,
"comment_notification": 1,
"inquiry_notification": 0,
"devices": [
{"id": 1, "enabled": 1},
{"id": 2, "enabled": 0}
]
}
"message_notification": 1,
"comment_notification": 1,
"inquiry_notification": 0,
"devices": [
{"id": 1, "enabled": 1},
{"id": 2, "enabled": 0}
]
}
handle_get_notification_settings()
현재 사용자의 알림 설정과 등록된 기기 목록을 조회합니다.
응답 예시
{
"success": true,
"message": "성공",
"data": {
"settings": {
"message_notification": 1,
"comment_notification": 1,
"inquiry_notification": 1
},
"devices": [
{
"id": 1,
"device_name": "Chrome on Windows",
"device_icon": "????",
"is_active": 1,
"created_at": "2024-01-15 10:30:00"
}
]
}
}
"success": true,
"message": "성공",
"data": {
"settings": {
"message_notification": 1,
"comment_notification": 1,
"inquiry_notification": 1
},
"devices": [
{
"id": 1,
"device_name": "Chrome on Windows",
"device_icon": "????",
"is_active": 1,
"created_at": "2024-01-15 10:30:00"
}
]
}
}
handle_toggle_device_notification()
특정 기기의 알림을 활성화/비활성화합니다.
요청 본문 예시
{
"device_id": 1,
"is_active": 0
}
"device_id": 1,
"is_active": 0
}
공통 응답 처리
모든 AJAX 함수는
send_json_response()
함수를 사용하여 일관된 JSON 형태로 응답합니다.
send_json_response()
function send_json_response($success, $message, $data = null, $http_code = 200)
표준 응답 구조
모든 AJAX 응답은 다음 구조를 따릅니다.
- •
success
(Boolean) - 처리 성공 여부 - •
message
(String) - 처리 결과 메시지 - •
data
(Mixed) - 추가 데이터 (선택사항)
공통 에러 코드
HTTP 코드 | 의미 | 발생 상황 |
---|---|---|
200 | 성공 | 정상 처리 완료 |
400 | 잘못된 요청 | 필수 데이터 누락, 잘못된 형식 |
404 | 리소스 없음 | VAPID 키 미설정, 데이터 없음 |
405 | 메서드 불허용 | GET 요청이 필요한 곳에 POST 요청 |
500 | 서버 오류 | 데이터베이스 오류, 내부 처리 실패 |
실제 구현 예시
완전한 푸시 알림 시스템 구축
// 1. 페이지 로드 시 초기화
document.addEventListener('DOMContentLoaded', async function() {
if ('serviceWorker' in navigator && 'PushManager' in window) {
await initializePushSystem();
}
});
async function initializePushSystem() {
// Service Worker 등록
await navigator.serviceWorker.register('/sw.js');
// 현재 구독 상태 확인
const registration = await navigator.serviceWorker.ready;
const subscription = await registration.pushManager.getSubscription();
if (subscription) {
// 이미 구독된 상태라면 서버에 등록
await registerSubscriptionToServer(subscription);
} else {
// 구독되지 않은 상태라면 구독 버튼 표시
showSubscribeButton();
}
}
async function subscribeUser() {
// VAPID 키 조회
const vapidResponse = await fetch('/ajax/get_vapid_key.php');
const vapidResult = await vapidResponse.json();
if (!vapidResult.success) {
alert('푸시 서비스 설정이 완료되지 않았습니다.');
return;
}
// 푸시 구독
const registration = await navigator.serviceWorker.ready;
const subscription = await registration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: urlBase64ToUint8Array(vapidResult.data.vapid_public_key)
});
// 서버에 구독 정보 등록
await registerSubscriptionToServer(subscription);
}
async function registerSubscriptionToServer(subscription) {
const response = await fetch('/ajax/subscribe_push.php', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ subscription: subscription.toJSON() })
});
const result = await response.json();
if (result.success) {
console.log('푸시 알림 구독 완료');
updateUIForSubscribed();
} else {
console.error('구독 등록 실패:', result.message);
}
}
document.addEventListener('DOMContentLoaded', async function() {
if ('serviceWorker' in navigator && 'PushManager' in window) {
await initializePushSystem();
}
});
async function initializePushSystem() {
// Service Worker 등록
await navigator.serviceWorker.register('/sw.js');
// 현재 구독 상태 확인
const registration = await navigator.serviceWorker.ready;
const subscription = await registration.pushManager.getSubscription();
if (subscription) {
// 이미 구독된 상태라면 서버에 등록
await registerSubscriptionToServer(subscription);
} else {
// 구독되지 않은 상태라면 구독 버튼 표시
showSubscribeButton();
}
}
async function subscribeUser() {
// VAPID 키 조회
const vapidResponse = await fetch('/ajax/get_vapid_key.php');
const vapidResult = await vapidResponse.json();
if (!vapidResult.success) {
alert('푸시 서비스 설정이 완료되지 않았습니다.');
return;
}
// 푸시 구독
const registration = await navigator.serviceWorker.ready;
const subscription = await registration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: urlBase64ToUint8Array(vapidResult.data.vapid_public_key)
});
// 서버에 구독 정보 등록
await registerSubscriptionToServer(subscription);
}
async function registerSubscriptionToServer(subscription) {
const response = await fetch('/ajax/subscribe_push.php', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ subscription: subscription.toJSON() })
});
const result = await response.json();
if (result.success) {
console.log('푸시 알림 구독 완료');
updateUIForSubscribed();
} else {
console.error('구독 등록 실패:', result.message);
}
}
주의사항
함수 종료: 모든 AJAX 함수는 응답 후 exit()로 종료됩니다
Content-Type: JSON 응답 시 자동으로 application/json 헤더 설정
에러 처리: 클라이언트에서 HTTP 상태코드와 success 필드 모두 확인 필요
보안: 사용자 인증이 필요한 경우 세션 또는 토큰 검증 추가 필요
Content-Type: JSON 응답 시 자동으로 application/json 헤더 설정
에러 처리: 클라이언트에서 HTTP 상태코드와 success 필드 모두 확인 필요
보안: 사용자 인증이 필요한 경우 세션 또는 토큰 검증 추가 필요
관련 함수
Content-Type
application/json
형태의 JSON 데이터를 받습니다.
요청 본문
브라우저의 푸시 구독 정보를 담은 JSON 객체입니다.
{
"subscription": {
"endpoint": "https://fcm.googleapis.com/fcm/send/...",
"keys": {
"p256dh": "BGtFqB7V9OZF...",
"auth": "rF3dm4Ux..."
}
}
}
"subscription": {
"endpoint": "https://fcm.googleapis.com/fcm/send/...",
"keys": {
"p256dh": "BGtFqB7V9OZF...",
"auth": "rF3dm4Ux..."
}
}
}
응답 형식
성공 시 (200 OK)
{
"success": true,
"message": "구독이 등록되었습니다."
}
"success": true,
"message": "구독이 등록되었습니다."
}
실패 시 (400/500)
{
"success": false,
"message": "구독 정보가 올바르지 않습니다."
}
"success": false,
"message": "구독 정보가 올바르지 않습니다."
}
JavaScript 사용 예시
// Service Worker에서 푸시 구독 후 서버에 등록
async function subscribeToPush() {
const registration = await navigator.serviceWorker.ready;
const subscription = await registration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: vapidPublicKey
});
// 서버에 구독 정보 등록
const response = await fetch('/ajax/subscribe_push.php', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
subscription: subscription.toJSON()
})
});
const result = await response.json();
if (result.success) {
console.log('푸시 구독 등록 성공');
} else {
console.error('구독 등록 실패:', result.message);
}
}
async function subscribeToPush() {
const registration = await navigator.serviceWorker.ready;
const subscription = await registration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: vapidPublicKey
});
// 서버에 구독 정보 등록
const response = await fetch('/ajax/subscribe_push.php', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
subscription: subscription.toJSON()
})
});
const result = await response.json();
if (result.success) {
console.log('푸시 구독 등록 성공');
} else {
console.error('구독 등록 실패:', result.message);
}
}
handle_push_unsubscription()
브라우저에서 푸시 구독 해제 요청을 AJAX로 처리합니다.
function handle_push_unsubscription()
요청 형식
{
"endpoint": "https://fcm.googleapis.com/fcm/send/cJhJBNJGqA..."
}
"endpoint": "https://fcm.googleapis.com/fcm/send/cJhJBNJGqA..."
}
JavaScript 사용 예시
// 푸시 구독 해제
async function unsubscribeFromPush() {
const registration = await navigator.serviceWorker.ready;
const subscription = await registration.pushManager.getSubscription();
if (subscription) {
// 브라우저에서 구독 해제
await subscription.unsubscribe();
// 서버에 해제 알림
const response = await fetch('/ajax/unsubscribe_push.php', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
endpoint: subscription.endpoint
})
});
const result = await response.json();
console.log(result.message);
}
}
async function unsubscribeFromPush() {
const registration = await navigator.serviceWorker.ready;
const subscription = await registration.pushManager.getSubscription();
if (subscription) {
// 브라우저에서 구독 해제
await subscription.unsubscribe();
// 서버에 해제 알림
const response = await fetch('/ajax/unsubscribe_push.php', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
endpoint: subscription.endpoint
})
});
const result = await response.json();
console.log(result.message);
}
}
get_vapid_public_key()
클라이언트에서 푸시 구독 시 필요한 VAPID 공개키를 AJAX로 조회합니다.
function get_vapid_public_key()