2019년 4월 17일 수요일

AJAX와 CORS

AJAX (Asynchronous JavaScript And XML)


AJAX는 서버와 통신하기 위해 XMLHttpRequest 객체를 사용하는 것을 의미한다. 이 객체를 이용해 XML, JSON, HTML 그리고 일반 텍스트 형식 등을 포함한 다양한 포맷을 주고 받을 수 있다. 페이지 전체를 리프레쉬하지 않고서도 수행되는 "비동기성"은 AJAX의 가장 큰 특징으로 페이지의 일부분만을 업데이트 할 수 있게 해준다.

AJAX와 함께 자주 거론되는 개념이 있는데 그건 바로 CORS다. CORS의 도입 배경은 다음과 같다. HTTP 요청은 기본적으로 A 도메인에서 B 도메인으로 향하는 cross-site HTTP 요청이 가능하지만 <script></script>로 둘러싸인 스크립트에서 생성된 cross-site HTTP 요청은 보안상 이유로 호출이 제한된다. XMLHttpRequest도 same-origin 정책을 따르는데 XMLHttpRequest에 대해서도 cross-site HTTP 요청이 가능해야 한다는 요구가 생겨 W3C에 의해 CORS 권고안이 나오게 되었다.



CORS (Cross-Origin Resource Sharing)


CORS는 origin 도메인에서 실행중인 웹 애플리케이션이 추가 HTTP 헤더를 사용해 브라우저가 다른 출처 서버의 자원에 액세스할 수 있는 권한을 가지도록 하는 메커니즘이다.
→ CORS를 쓰면 AJAX로도 다른 도메인의 자원을 쓸 수 있다.

1. CORS 스펙에선 서버 데이터에 side-effects를 일으킬 수 있는 요청 메서드(특정 MIME 유형의 POST 등)에 대해 브라우저가 요청할 내용을 OPTIONS 메서드를 이용해 사전 전달(preflight) 하도록 하는데, 이는 서버로부터 지원 중인 메서드(GET, POST, ...) 목록을 내려 받은 뒤 승인(approval) 시에 실제 HTTP 요청을 전송하는 것을 말한다.
→ 사용자가 요청 프로세스를 직접 다루는 것이 아니라 브라우저가 알아서 처리한다.
2. 서버는 클라이언트에게 요청과 함께 자격 증명(credential)을 보내야하는지 여부를 알릴 수도 있다.


AJAX 요청의 흐름.

기본적으로 비동기이므로 요청 전에 서버로 보낸 요청에 대한 응답을 받았을 때 처리할 함수를 미리 지정해주어야 한다.
onreadystatechange property에 지정하면 된다.
그리고 나서 open()과 send()를 차례대로 요청하면 된다.


httpRequest.onreadystatechange = function () {
  // ...
};

// 쓸 일은 없겠으나 open의 셋째 파라미터를 false로 지정하면 동기적으로 동작한다.
// 이 경우엔 onreadystatechange는 필요하지 않다.
httpRequest.open('GET', 'http://www.example.org/some.file', true); 

// send()의 파라미터가 null인 까닭은 'GET' 방식의 호출이기 때문이다. 'POST'인 경우엔 서버로 보낼 데이터를 send() 파라미터에 지정하면 된다.
// 다만 서버가 데이터의 형식을 알 필요가 있기 때문에 request에 MIME type을 먼저 설정해야 한다.
httpRequest.send(null);
httpRequest.setRequestHEader('Content-Type', 'application/x-www-form-urlencoded');

위와 같이 서버 응답에 대한 처리는 onreadystatechange에 지정한 함수에서 이루어진다.
일반적으로 httpRequest.readyState의 값이 XMLHttpRequest.DONE(4) 이면서 httpRequest.status의 값이 200 OK인 경우 호출-응답의 프로세스가 성공한 것이다.

받은 데이터는 responseText 또는 responseXML property로 읽어오면 된다. responseXML의 경우 서버의 응답을 XMLDocument 객체로 반환하며 DOM API를 통해 이 객체를 다룰 수 있을 것이다.

기본적인 예제는 아래를 참고하자.

<button id="ajaxButton" type="button">Make a request</button>

<script>
(function() {
  var httpRequest; // httpRequest 변수는 지역 변수로 선언해야 한다. 
                   // 전역으로 사용되면 여러 요청에 의한 경쟁 상태(race condition)이 발생할 수 있다.
  document.getElementById("ajaxButton").addEventListener('click', makeRequest);

  function makeRequest() {
    httpRequest = new XMLHttpRequest();

    if(!httpRequest) {
      // Can not create instance.
      return false;
    }
    httpRequest.onreadystatechange = alertContents;
    httpRequest.open('GET', 'test.html');
    httpRequest.send();
  }

  function alertContents() {
    if (httpRequest.readyState === XMLHttpRequest.DONE) {
      if (httpRequest.status === 200) {
        alert(httpRequest.responseText);
      } else {
        // Error
      }
    }
  }
})();
</script>

https://developer.mozilla.org/ko/docs/Web/Guide/AJAX/Getting_Started
https://developer.mozilla.org/ko/docs/Web/HTTP/Access_control_CORS#%EA%B0%9C%EC%9A%94

댓글 없음:

댓글 쓰기