본문 바로가기
프로그램 (PHP,Python)

콜백은 잊어라! jQuery AJAX의 Promise 기반 진화한 비동기 표준 처리

by 날으는물고기 2025. 10. 22.

콜백은 잊어라! jQuery AJAX의 Promise 기반 진화한 비동기 표준 처리

728x90

한눈에 보는 핵심 변화(요약)

  1. 콜백 메서드 제거 → Promise 체인 정착
  • jqXHR.success() / error() / complete()jQuery 3.0에서 제거되었습니다. 이제 jqXHR.done() / fail() / always() 같은 Promise 인터페이스(jQuery Deferred 기반)를 사용합니다.
  1. jqXHR = Promise 인터페이스 제공
  • $.ajax()가 반환하는 jqXHRPromise 메서드(.done/.fail/.always/.then)를 지원합니다. 콜백을 여러 개 등록하거나 요청 후에도 등록할 수 있습니다.
  1. async:false(동기 요청) 사용 지양
  • 기본값은 계속 비동기(async:true)이고, 동기 요청은 경고 및 비권장입니다(UX 저하, 메인 스레드 블로킹).
  1. JSONP
  • dataType: "jsonp"여전히 지원되지만(스크립트 삽입 기반), 보안상 권장되지 않습니다. 크로스 도메인은 가급적 CORS로 전환하세요.
  1. 업그레이드 가이드 & Migrate 플러그인
  • 1.12 → 3.x 업그레이드시 공식 Upgrade GuidejQuery Migrate로 브레이킹 체인지 탐지/수정이 안전합니다.
300x250

현대식 jQuery AJAX 작성 패턴

1. 가장 기본 형태 (Promise 체인)

$.ajax({
  url: '/api/items',
  method: 'GET',           // or type: 'GET'
  dataType: 'json',        // 서버 응답이 JSON일 때
})
  .done(function (data, textStatus, jqXHR) {
    console.log('OK', data);
  })
  .fail(function (jqXHR, textStatus, errorThrown) {
    console.error('FAIL', textStatus, errorThrown);
  })
  .always(function () {
    console.log('ALWAYS');
  });
  • jqXHR가 Promise 인터페이스를 제공하므로 .done/.fail/.always 사용이 표준입니다.

2. 간단 호출(헬퍼)도 jqXHR 반환

$.get('/api/ping')        // $.post, $.getJSON 등도 동일
  .done(function (data) { console.log(data); })
  .fail(function () { console.error('error'); });
  • $.get / $.post / $.getJSONjqXHR를 반환하므로 동일한 체인을 사용할 수 있습니다.

3. JSON POST (가장 많이 쓰는 패턴)

$.ajax({
  url: '/api/users',
  method: 'POST',
  data: JSON.stringify({ name: 'Alice' }),
  contentType: 'application/json; charset=UTF-8',
  dataType: 'json'
}).done(function (res) {
  console.log('created:', res);
});
  • 보내는 본문contentType으로 JSON 명시
  • 받는 응답dataType:'json'으로 파싱 힌트

4. FormData(파일 업로드 등)

const fd = new FormData();
fd.append('avatar', fileInput.files[0]);
fd.append('nickname', 'alice');

$.ajax({
  url: '/api/profile',
  method: 'POST',
  data: fd,
  processData: false,          // FormData 그대로 전송
  contentType: false           // 브라우저가 적절한 boundary 설정
}).done(/* ... */);

5. 공통 헤더/공통 옵션 중앙관리

$.ajaxSetup({
  timeout: 10000,
  headers: { 'X-Requested-With': 'XMLHttpRequest' }
});

// 또는 요청별로
$.ajax({
  beforeSend: function (xhr) {
    xhr.setRequestHeader('Authorization', 'Bearer ' + token);
  }
});
  • beforeSend 등 콜백/옵션은 공식 API에서 확인 가능합니다.

1.12 → 3.x 마이그레이션 체크리스트

1. 코드 변경(필수)

  • jqXHR.success/error/complete 모두 제거.done/.fail/.always로 교체
  • - $.ajax(...).success(fn).error(fn).complete(fn); + $.ajax(...).done(fn).fail(fn).always(fn);
  • async:false 사용 제거(가능한 전량 리팩토링)
    • 동기 요청은 브라우저/UX에 악영향. 기본은 async:true를 유지하세요.
  • JSONP(dataType:'jsonp') 사용 재검토
    • 가능하면 CORS 기반 표준 AJAX로 전환. 보안/정책 측면에서 더 안전하고 현대적입니다.

2. 업그레이드 절차(안전모드)

  1. jQuery 3.x + jQuery Migrate를 먼저 적용해 경고/호환 이슈 로그를 수집
  2. 콘솔 경고를 기준으로 .success()류/구식 패턴을 점진 교체
  3. 모든 경고가 사라지면 Migrate 제거 → 3.x 순정으로 전환
  • 공식 Upgrade Guide를 참조하며 진행하면 안정적입니다.

실무에서 자주 겪는 옵션/오해 정리

  • dataType vs contentType 차이
    • contentType: 보내는 본문의 MIME 타입(예: JSON 전송 시 application/json)
    • dataType : 응답을 어떻게 해석할지 힌트(예: JSON 응답이면 json)
    • 공식 문서 설명 참조.
  • 기본은 비동기(async:true)
    • 동기 요청을 원하면 async:false지만, 강력 비권장(경고/성능 저하).
  • 헬퍼 메서드($.get, $.post, $.getJSON)
    • 예전부터 있던 간편 래퍼입니다. 최신 jQuery에서도 계속 사용 가능하며 jqXHR 반환으로 Promise 체인을 연결할 수 있습니다.
  • JSONP는 “지원은 되지만 비권장”
    • jQuery API에 dataType:'jsonp'가 여전히 명시되어 있고 동작합니다. 다만 보안상 취약하고 현대 표준은 CORS입니다.

보안 가이드(체크포인트)

1. 크로스 도메인(CORS) 정책

  • 원칙: JSONP 대신 CORS 사용
  • 서버가 Access-Control-Allow-Origin(필요 시 -Methods, -Headers, -Credentials)을 올바르게 설정해야 합니다. 프리플라이트(OPTIONS) 동작을 고려해 서버 라우팅/보안장비 예외를 준비하세요.

2. 인증/인가

  • 토큰 전송: Authorization: Bearer <token> 헤더를 beforeSendheaders 옵션으로 부여
  • 자격증명: 쿠키 인증이라면 서버의 CORS에서 Access-Control-Allow-Credentials: truewithCredentials(환경에 따라) 고려

3. 입력/출력 검증

  • 서버 응답 검증: dataType:'json'을 사용하고, 서버는 올바른 Content-Type: application/json을 반환
  • DOM 삽입 시 XSS 주의: 응답 문자열을 그대로 innerHTML에 넣지 말고, 텍스트 노드로 다루거나 템플릿 엔진의 이스케이프 사용

4. 오류/예외 처리 표준화

  • 실패 분류(네트워크/타임아웃/권한/서버오류) 후 공통 핸들러에서 사용자 메시지/재시도/로그 수집 일원화
$(document).ajaxError(function (event, jqXHR) {
  const status = jqXHR.status;
  if (status === 401) { /* re-login flow */ }
  else if (status >= 500) { /* server error banner */ }
  // 공통 로깅/알림
});
  • timeout 옵션(예: 10초)으로 무한 대기 방지.

5. 민감정보

  • URL 쿼리에 토큰/개인정보 금지
  • HTTPS 강제, 중간자 공격 대비
  • 응답 데이터 마스킹(로그/브라우저 저장소)

“옛 코드 → 최신 스타일” 리팩토링 예시

(A) success/error/complete 제거

- $.ajax({ url:'/api', type:'GET',
-   success: onOk, error: onErr, complete: onAny
- });

+ $.ajax({ url:'/api', method:'GET' })
+   .done(onOk)
+   .fail(onErr)
+   .always(onAny);
  • 제거 사유 및 대체 메서드는 공식 문서에 명시되어 있습니다.

(B) 동기 요청 제거

- $.ajax({ url:'/api/slow', async: false });
+ $.ajax({ url:'/api/slow', timeout: 15000 })
+   .done(/* ... */)
+   .fail(/* 타임아웃/오류 처리 ... */);
  • UX/성능 위해 반드시 비동기로 전환하세요.

(C) JSONP → CORS 전환

- $.ajax({ url:'https://other.com/data?callback=?', dataType:'jsonp' });
+ $.ajax({ url:'https://other.com/data',
+          method:'GET',
+          xhrFields: { withCredentials: true }, // 필요한 경우
+          // 서버는 CORS 헤더를 올바르게 설정
+        });
  • CORS 원리와 헤더는 MDN 정리를 참고하세요.

운영 팁(스케일/유지보수)

  1. 중앙 에러/로깅 훅: $(document).ajaxError, $.ajaxSetup({timeout, headers})로 공통화
  2. 재시도/백오프: .fail()에서 상태코드별로 지수백오프 재시도(429/503 등)
  3. 취소/중복 방지: 동일 요청 중복 시 이전 jqXHR.abort()
  4. 성능: 목록 조회에 서버 페이지네이션/필터/정렬 적용
  5. 전환 전략: 신규 화면은 네이티브 fetch로, 기존 화면은 jQuery 유지 등 혼합 전략도 현실적

미니 레시피

1. 공통 JSON 클라이언트

function getJSON(url, params) {
  return $.ajax({
    url,
    method: 'GET',
    data: params,
    dataType: 'json',
    timeout: 10000
  });
}

function postJSON(url, body) {
  return $.ajax({
    url,
    method: 'POST',
    data: JSON.stringify(body),
    contentType: 'application/json; charset=UTF-8',
    dataType: 'json',
    timeout: 10000
  });
}

2. 토큰 자동 첨부

$.ajaxSetup({
  beforeSend: function (xhr) {
    const token = localStorage.getItem('access_token');
    if (token) xhr.setRequestHeader('Authorization', 'Bearer ' + token);
  }
});

3. 전역 에러 배너

$(document).ajaxError(function (e, jqXHR) {
  if (jqXHR.status >= 500) {
    $('#error-banner').text('서버 오류가 발생했습니다. 잠시 후 다시 시도해주세요.').show();
  }
});

참고

  • jQuery.ajax 공식 문서(jqXHR의 Promise 메서드, success/error/complete 제거, async 기본값 등)
  • jQuery 3.0 Upgrade Guide & Migrate(브레이킹 체인지 대응)
  • MDN CORS 가이드(JSONP 대신 CORS로의 전환 원칙/헤더)
728x90
그리드형(광고전용)

댓글