업데이트:

태그: , , ,

카테고리:



AJAX란

API를 fetch할때, 이걸 왜 get으로 가져와야하는지, 왜 post로 가져와야하고, 어떻게 동작하는지 알기위해선 Ajax에 대해 먼저 알아야한다.

빠르게 동작하는 웹페이지 개발 기법 중 하나이다.

웹 페이지 전체를 리로딩하지 않고, 웹 페이지의 일부분만을 갱신할 수 있다.

AJAX를 사용하면 웹 페이지의 로드 이후 백그라운드 영역(사용자가 인식하지 못하는 영역)에서 서버와 통신해 필요한 데이터를 주고받을 수 있다.

데이터를 받아올때, 부드럽게 새로운 데이터를 받아와서 사용자에게 보여주는 건 이 Ajax 덕분이라고 볼 수 있다.

페이스북, 인스타그램 등등의 사이트들은 수없이 많은 Ajax기술로 이루어져있다.

Ajax는 데이터를 주고받을 때, HTML, XML, 그리고 JSON과 같은 형태의 데이터를 주고받을 수 있다.

한계

이런 AJAX는 클라이언트 풀링 방식을 사용한다.
클라이언트 풀링 방식이란 클라이언트가 서버에 데이터를 요청하는 방식을 의미한다.
구글 검색엔진이 이런 원리이다.
글자를 하나씩 입력할때마다 브라우저와 서버가 통신하면서 사용자의 입력에 맞는 데이터를 서버가 보내준다.

이 방식의 한계는 서버 푸시 방식의 실시간 서비스를 만들 수 없다는 것이다.
클라이언트의 요청에 의해 데이터를 주고받기 때문에, 서버가 알아서 자동으로 특정 정보를 제공하는 서버 푸시 방식은 사용할 수 없다.

그리고 AJAX로는 (바이너리 데이터)[https://ko.wikipedia.org/wiki/%EC%9D%B4%EC%A7%84_%ED%8C%8C%EC%9D%BC]를 주고 받을 수 없다는 것이다.

동작원리

위에서 봤듯, 클라이언트 풀링 방식이므로 동작의 시작은 사용자이다.

  1. 사용자에 의한 이벤트 발생
  2. 이벤트 핸들러가 JS호출
  3. XMLHttpRequest객체 생성, 요청
  4. 웹 서버의 Ajax 요청 처리
  5. 서버가 DB에서 알맞는 데이터로 응답을 생성
  6. Html, Json, XML같은 데이터 형태로 전달
  7. 브라우저가 웹 페이지의 일부분만을 갱신하는 자바스크립트 호출
  8. 일부분만 로딩

XMLHttpRequest

브라우저와 서버가 데이터를 교환할 때 사용되는 객체이다.

대부분의 웹 브라우저가 이 객체를 내장하고 있다.

const Name = new XMLHttpRequest();로 객체를 생성할 수 있다.

이 인스턴스를 생성한 이후, 서버에 요청을 보내기 위해선 2가지를 정해야한다.

open() 메서드

open()메서드는 서버로 보낼 Ajax 요청의 형식을 설정한다.

open(전달방식, 데이터를 요청할 서버의 URL주소, 동기여부);
  • 전달방식 : GET or POST
  • URL주소 : 요청을 처리할 서버의 파일 주소를 전달
  • 동기여부 : 동기적, 비동기적 처리 여부

send() 메서드

send()메서드는 Ajax 요청을 서버로 전달한다.
이 메서드는 전달 방식에 따라 인수를 가질수도, 안가질수도 있는데,

send(); //GET
send(문자열); //POST

보통 GET 방식은 브라우저의 주소에 data를 추가해 전달하는데(쿼리URL), 이때 브라우저에 캐시상태로 저장된다. 그래서 보안상 취약점이 존재한다.

요즘에는 대부분 POST 방식을 사용한다고 한다. POST방식의 HttpRequest는 브라우저에 캐시되지 않고, 브라우저의 히스토리에도 남지않는다. 쿼리 URL 처럼 전송되지 않아 데이터 길이에 제한도 없고 GET 방식보다 보안성이 높다.

요청하기

GET

httpRequest.open("GET", "URL주소", true);
httpRequest.send();

URL주소를 쿼리 URL 형태로 보내면 밑의 코드로 XMLHttpRequest 객체의 현재 상태와 서버 상의 문서 존재 유무를 알 수 있다.

if (httpRequest.readyState == XMLHttpRequest.DONE && httpRequest.status == 200 ) {
    ...
}

readyState 프로퍼티와 status 프로퍼티는 뒤에서 다룬다.

POST

httpRequest.open("POST", "URL주소", true);
httpRequest.setRequestHeader(~,~);
httpRequest.send("전송할 데이터");

POST 방식에서는 .send 메서드로 전송할 데이터를 쿼리 URL형식으로 보낸다.

비동기 요청

비동기 요청은 Javascript의 작동원리를 알면 쉽게 이해할 수 있다.

자바스크립트는 비동기적으로 동작하는 코드들과 동기적으로 동작하는 코드들을 구분해 실행한다.

자바스크립트에는 변수, 비동기식 코드, 동기식 코드 이렇게 3가지로 구분된다.

Heap, Queue, Stack 이렇게 3가지 공간이 있는데, 작성된 파일이 실행되면, 이 공간들을 활용해 JS파일이 실행된다.

코드들이 실행되는 공간인 Stack은 필요한 변수들을 Heap 공간에서 찾아와서 사용한다.
Stack은 비동기식 처리가 필요한 Ajax 요청코드, 이벤트핸들러, setTimeOut과 같은 코드들을 빼고 동기식 코드들을 먼저 처리한다.

자바스크립트는 비동기식 코드들의 처리를 해야하는 요청이 오더라도 동기식 처리를 하는 코드들의 처리가 끝나 Stack이 비어있어야만 비동기식 코드들을 처리할 수 있다.

그 이유는 비동기식 코드들은 요청이 오면 Queue 라는 공간을 한 번 거쳐가는데, Queue에서 빠져나가 Stack으로 가서 실행되기 위해선 Stack이 비어있어야한다는 규칙이 있기 때문이다.

느린 웹브라우저, 최적화가 안된 웹 브라우저에서 아무런 버튼을 누르지 못하고 이것저것 누르고 있다가 로딩이 끝나니까 그동안 누른 모든 버튼이 실행됬던 경험이 모두 있었을 텐데, 이 원리 때문이다.

서버로부터의 응답

브라우저가 Ajax 요청을 보냈을때, 서버가 응답했는지 확인하기 위해서 사용하는 프로퍼티로는

  • readyState
  • status
  • onreadystatechange

가 있다.

readyState 프로퍼티

XMLHttpRequest 객체의 현재 상태를 나타낸다.

객체의 현재 상태에 따라 숫자 0~4까지로 나뉜다

  1. UNSENT : XMLHttpRequest 객체 생성됨
  2. OPENED : open() 메서드 실행완료
  3. HEADERS_RECEIVED : 모든 요청에 대한 응답 도착
  4. LOADING : 데이터 처리중
  5. DONE : 요청한 데이터의 처리가 완료되어 응답할 준비 완료

status 프로퍼티

서버의 문서 상태를 의미

  • 200 : 서버에 존재함
  • 404 : 서버에 존재하지 않음

onreadystatechange 프로퍼티

XMLHttpRequest 객체의 readyState 값이 변할때마다 자동으로 호출되는 함수를 설정

서버에서 응답이 도착할때마다 총 5번(0~4까지) 호출된다.

switch (httpRequest.readyState) {
  case XMLHttpRequest.UNSET:
    currentState += "현재 XMLHttpRequest 객체의 상태는 UNSET 입니다.<br>";

    break;

  case XMLHttpRequest.OPENED:
    currentState += "현재 XMLHttpRequest 객체의 상태는 OPENED 입니다.<br>";

    break;

  case XMLHttpRequest.HEADERS_RECIEVED:
    currentState +=
      "현재 XMLHttpRequest 객체의 상태는 HEADERS_RECEIVED 입니다.<br>";

    break;

  case XMLHttpRequest.LOADING:
    currentState += "현재 XMLHttpRequest 객체의 상태는 LOADING 입니다.<br>";

    break;

  case XMLHttpRequest.DONE:
    currentState += "현재 XMLHttpRequest 객체의 상태는 DONE 입니다.<br>";

    break;
}

document.getElementById("status").innerHTML = currentState;

if (
  httpRequest.readyState == XMLHttpRequest.DONE &&
  httpRequest.status == 200
) {
  document.getElementById("text").innerHTML = httpRequest.responseText;
}

예제

위의 코드들을 모아서 예제를 만들어보자.

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

<script>
(function() {
  var httpRequest;
  document.getElementById("ajaxButton").addEventListener('click', makeRequest);

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

    if(!httpRequest) {
      alert('XMLHTTP 인스턴스를 만들 수가 없어요 ㅠㅠ');
      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 {
        alert('request에 뭔가 문제가 있어요.');
      }
    }
  }
})();
</script>

fetch API

위의 방식은 코드가 길고 복잡해서 요즘에는 사용하지 않는다고 한다.
그래서 Ajax의 최신기술로 fetch API가 등장했다.

fetch("데이터를 요청할 서버의 URL주소")
  .then((response) => {
    if (!response.ok) {
      throw new Error("400 or 500 에러");
    }
    return response.json();
  })
  .then((json) => {
    console.log(json);
  })
  .catch(() => {
    console.log("에러");
  });

외부 라이브러리 방식

자바스크립트는 외부 라이브러리 방식으로 JQuery를 사용하고, 리액트나 뷰는 axios를 사용해 간편하게 ajax를 사용한다.

댓글남기기