출처 : http://www.ibm.com/developerworks/kr/series/web/index.html
아래 내용은 위 출처의 기사의 일부를 복사 후 편집/수정한 것입니다.
단순히 개인적으로 알고자하는 내용만을 남긴 것이니, 자세한 정보는 위의 출처를 참조하세요.

* HTTP 준비 상태
* HTTP 상태 코드
* 요청 유형들

HTTP 준비 상태
* 0: (open()을 호출하기 전에는) 요청이 초기화 되지 않는다.
* 1: (send()를 호출하기 전에는) 요청은 설정은 되지만 보내지지 않는다.
* 2: 요청이 보내지고 처리 중에 있다. (이 시점에서 응답에서 콘텐트 헤더를 얻을 수 있다.)
* 3: 요청이 처리 중에 있다. 부분적인 데이터를 응답에서 사용할 수 있지만 서버는 이 응답으로는 종료되지 않는다.
* 4: 응답이 완료된다. 서버의 응답을 받고 이를 사용한다.

readyState 0 (readyState == 0)으로 표시되는 첫 번째 준비 상태는 초기화 되지 않은 요청을 나타낸다. 요청 객체에 대해 open()을 호출하면 속성은 1로 설정된다. 대부분 요청을 초기화 하면서 open()을 호출하기 때문에 readyState == 0을 보는 일은 드물다. 더욱이 초기화 되지 않은 준비 상태는 실제 애플리케이션에서는 쓸모 없다.

 function getSalesData() {
   // Create a request object
   createRequest();        
   alert("Ready state is: " + request.readyState);

   // Setup (initialize) the request
   var url = "/boards/servlet/UpdateBoardSales";
   request.open("GET", url, true);
   request.onreadystatechange = updatePage;
   request.send(null);
}
open()이 호출되기 전에 준비 상태를 체크
요청 객체가 새로운 요청을 만들기 전에 초기화 되지 않은 상태(readyState == 0)에 있다는 것을 확인

0이 4와 같을 때
다중 JavaScript 함수들이 같은 요청 객체를 사용하는 경우, 그 요청 객체가 사용되고 있지 않다는 것을 확인하기 위해 준비 상태 0을 확인하면 문제가 많아질 수 있다. readyState == 4는 완료된 요청을 나타내기 때문에, 4로 설정된 준비 상태인 채로 사용되지 않은 요청 객체를 종종 보게 된다. abort()이라고 하는 요청 객체를 리셋하는 함수가 있지만 이는 여기에 사용하는 것이 아니다. 다중 함수들을 사용해야 한다면 다중 함수에 객체를 공유하는 것 보다 각 함수용 요청 객체를 생성 및 사용하는 것이 낫다.

브라우저 차이
Firefox 1.5
    * 1
    * 2
    * 3
    * 4

Safari 2.0.1
    * 2
    * 3
    * 4
Safari는 첫 번째 준비 상태를 배제하고 그 이유에 대해서는 자세히 나와있지 않다. 바로 이것이 Safari 방식이다. 또한 중요한 포인트이기도 하다. 서버에서 데이터를 사용하기 전에 요청의 준비 상태가 4라는 것을 확인하는 것은 좋은 생각인 반면 일시적인 준비 상태에 의존하는 코드를 작성하는 것은 다른 브라우저 마다 다른 결과를 얻을 수 있는 확실한 방법이다.

Opera 8.5를 사용할 때 상황은 더 악화된다.
    * 3
    * 4

Internet Explorer
    * 1
    * 2
    * 3
    * 4

responseText
준비 상태 2에서 responseText 속성은 정의되지 않는다
준비 상태 3에서, 서버는 responseText 속성에 값을 배치한다

준비 상태 3의 응답은 스크립트 마다, 서버 마다, 브라우저 마다 다르다. 애플리케이션을 디버깅 하는데 매우 유용하다.
모든 문서와 스팩들에서는 준비 상태가 4가 되어야지만 데이터를 안전하게 사용할 수 있다고 나와있다. 나를 믿으라. 준비 상태가 3일 때에도 responseText 속성에서 데이터를 얻을 수 있다. 하지만 여러분의 애플리케이션에서 이것에 의존하는 것은 좋지 않은 생각이다. 준비 상태 3에서 완전한 데이터에 의존하는 코드를 작성하는 것은 데이터가 불완전하다는 증거이다.

준비 상태가 변할 때 마다 폼이나 페이지에 대한 필드를 업데이트 할 수 있다. 예를 들어, 프로그레스 인디케이터의 넓이를 준비 상태 1에 25 퍼센트, 준비 상태 2에 50 퍼센트, 준비 상태 3에 75 퍼센트, 준비 상태 4에 100 퍼센트를 설정한다. 물론 알다시피, 이 방식은 좋기는 하지만, 브라우저에 의존적이다. Opera에서는 첫 번째 두 개의 준비 상태를 결코 얻지 못하고 Safari는 처음 1 상태를 누락시킨다.

HTTP 상태 코드

* 401: Unauthorized
* 403: Forbidden
* 404: Not Found
* 200: Everything is OK

리다이렉션과 재 라우팅
에러에 대해 이야기 하기 전에 Ajax를 사용할 때 걱정하지 않아도 될 부분에 대해 말해두겠다. 바로 리다이렉션이다. HTTP 상태 코드에서, 이것은 300 대의 상태 코드이다.
* 301: Moved permanently
* 302: Found (요청이 또 다른 URL/URI로 리다이렉션 된다.)
* 305: Use Proxy (요청은 프록시를 사용하여 요청 받은 리소스에 액세스 해야 한다.)

Ajax 프로그래머가 리다이렉션에 대해 염려 할 필요가 없는 이유가 두 가지 있다.
* Ajax 애플리케이션들은 특정 서버측 스크립트, 서블릿, 애플리케이션을 위해 작성된다. 그 컴포넌트를 없애거나 다른 곳으로 이동하기 위함이다. 리소스는 변경되었다는 것을 (이미 이동했기 때문에)알고, 요청에서 URL을 변경하고 이러한 종류의 결과를 절대 만나지 않게 된다.
* 보다 관련성 있는 이유가 있다. Ajax 애플리케이션과 요청들은 샌드박스화 되어있다. Ajax 요청을 만드는 웹 페이지를 공급하는 도메인은 그러한 요청에 응답해야 하는 도메인이다. 따라서 ebay.com에서 공급 받은 웹 페이지는 Ajax 스타일의 요청을 amazon.com에서 실행되는 스크립트에 할 수 없다. ibm.com 상의 Ajax 애플리케이션은 netbeans.org에서 실행되는 서블릿으로 요청할 수 없다.

결국, 요청은 보안 에러를 만들지 않고서는 또 따른 서버로 리다이렉션 될 수 없다. 그러한 경우에, 상태 코드를 전혀 얻을 수 없다. 디버그 콘솔에 JavaScript 에러를 갖게 된다. 따라서 많은 상태 코드에 대해 생각하는 동안 리다이렉션 코드 정도는 무시할 수 있는 것이다.

HTTP 상태코드 처리
 function updatePage() {
  if (request.readyState == 4) {
     if (request.status == 200) {
        var response = request.responseText.split("|");
        document.getElementById("order").value = response[0];
        document.getElementById("address").innerHTML =
         response[1].replace(/\n/g, "<br />");
     } else if (request.status == 404) {
        alert ("Requested URL is not found.");
     } else if (request.status == 403) {
        alert("Access denied.");
     } else
        alert("status is " + request.status);
  }
}

추가 요청 유형
향상된 에러 핸들링과 정보 수집을 위해 HEAD 요청에 대해 배워야 한다.
 function getSalesData() {
    createRequest();
    var url = "/boards/servlet/UpdateBoardSales";
    request.open("HEAD", url, true);
    request.onreadystatechange = updatePage;
    request.send(null);
}

function updatePage() {
   if (request.readyState == 4) {
      alert(request.getAllResponseHeaders());
   }
}

이러한 헤더들을 개별적으로 사용하여 Ajax 애플리케이션에서 추가 정보나 기능을 제공할 수 있다.

유용한 HEAD 요청
HEAD 요청이 유용한 한 가지 부분은 콘텐트 길이나 콘텐트 유형을 검사할 때이다. 요청을 처리하기 위해 많은 양의 데이터를 보낼 것인지, 서버가 HTML, 텍스트, XML 대신 바이너리 데이터를 리턴해야 할지를 결정할 수 있다. (이 세 가지 모두 바이너리 데이터 보다 JavaScript에서 처리하는 것이 더 쉽다.)

이 경우, 적절한 헤더 이름을 사용하고 이를 XMLHttpRequest 객체의 getResponseHeader() 메소드로 보낸다. 따라서 응답의 길이를 알려면 request.getResponseHeader("Content-Length");를 호출한다. 콘텐트 유형을 알려면 request.getResponseHeader("Content-Type");를 사용한다.

많 은 애플리케이션에서 HEAD 요청을 하면 어떤 기능도 추가하지 않고 요청의 속도를 늦출 수 있다. (HEAD 요청을 실행하여 응답에 대한 데이터를 얻고 후속 GET 또는 POST 요청을 통해 응답을 실제로 받는다.) 하지만 스크립트나 서버측 컴포넌트에 대해 확실하지 않은 경우 HEAD 요청으로 기본적인 데이터를 받을 수 있다.


결론

Ajax 와 웹 프로그래머에게 이 글은 다소 어려울 것이다. HEAD 요청을 하는 것의 가치는 무엇인가? JavaScript에서 리다이렉션 상태 코드를 핸들해야 하는 때는 언제인가? 이 모두 좋은 질문이다. 간단한 애플리케이션의 경우, 이 모든 것은 가치가 별로 없다.

하지만 웹이 단순한 애플리케이션만 수용하는 것은 아니다. 사용자는 점점 고급화 되고 고객들도 강력한 에러 리포팅을 원한다. 관리자 역시 애플리케이션이 조금만 느려져도 해고를 당하게 된다.

간단한 애플리케이션을 넘어 XMLHttpRequest에 대한 이해를 높여야 할 때이다.

    * 다양한 준비 상태를 이해하고 이들이 브라우저 마다 어떻게 다른지를 이해하면 애플리케이션을 빠르게 디버깅 할 수 있다. 준비 상태에 기반하여 창조적인 기능을 만들고 요청자의 상태에 대해 사용자와 고객에게 보고할 수 있다.
    * 상태 코드를 핸들했다면 스크립트 에러, 예기치 못한 응답들, 엣지 케이스들을 다룰 수 있다. 결국, 애플리케이션은 언제나 잘 작동될 것이다.
    * 여기에 더하여 HEAD 요청을 만들고, URL의 존재를 검사하고 파일이 언제 수정되었는지를 파악하고 사용자가 유효 페이지를 얻었는지를 확인할 수 있다면 언제나 최신의 정보와 강력한 기능으로 사용자들을 만족시킬 수 있을 것이다.


사실 HEAD 요청은 뭐에 필요한지 잘 모르겠음.
리다이렉션 상태 코드는 핸들하지 않아도 상관없어 보임.
결론에서도 보듯이 핸들하면 좋다...는 정도일려나?