JavaScript

6. AJAX 프로그래밍 기법(Asynchronous JavaScript and XML)

문정훈 2022. 1. 18. 20:02

1.  기존의 node와 client의 동작 방식

node로 구현된 서버와 localhost로 구성된 웹브라우저가 있다.

기본적인 동작 방식을 설명하면 client 측에서 url의 변경을 통해 node로 url을 전송하게 된다. 

이때 전송 방식으로는 크게 get방식과 post 방식을 알면되는데 

get 방식은 url에 쿼리로 데이터를 담아 서버로 전송하는 것이고 post 방식은 데이터(payload)를 일종의 바구니(?)에 담아 서버로 전송하는 방식이다. 

 

서버와 클라이언트의 동작 방식을 도식도로 보면 url을 변경함으로써 해당 url을 서버에서 catch하고 그 처리 결과로 웹 파일을 다시 client로 전송하게 된다. 

그럼 client 측에서는 전송 받은 웹 파일을 다시 랜더링하게 된다. 

이러한 방식의 단점으로는 매번 서버로 데이터를 요청할 때 마다 url을 변경해야하고 그 에 해당하는 웹 파일을 매번 새로 랜더링해야하는데 이때 기존에 웹 파일에서 변경되는 부분이 아주 작은 일부분이라고 완전 새로운 웹 파일로 랜더링을 다시하기 때문에 웹 브라우저를 랜더링하는데 있어 화면 깜박거림 현상 또는 지연 현상이 없을 수가 없다. 

 

 

2.  ajax를 사용하면?

ajax라는 프로그래밍 기법을 사용하면 client에서는 url을 변경하지 않고 서버로 데이터를 요청할 수 있다.

실제 웹 브라우저의 갱신 없이 single page로 서버에게 각기 다른 url을 통해 요청을 보낼 수 있고 서버는 그에 응답으로 query, Json 데이터를 client로 보낼 수 있게 된다. 

그럼 client 측에서는 전달 받은 데이터를 catch하여 웹 브라우저의 DOM요소를 갱신하는데 사용한다면

결과적으로 웹 브라우저의 변경(url 변경) 없이 서버로 데이터를 요청하고 요청 받은 데이터로 웹 브라우저를 갱신할 수 있게 된다. 

 

3.  ajax를 예시1 - 검색 엔진

검색 엔진에 키워드를 입력하면 매번 입력마다 연관 검색 결과들이 화면에 보여지게 된다.

이것은 ajax를 통해 구현 될 수 있는 것으로

사용자가 키보드를 입력할 때마다 입력된 값을 서버로 ajax를 사용해 전송하게 되고 서버에서는 전달받은 키워드에 해당되는 연관 검색 결과(payload)를 다시 client로 보내게 된다. 

그럼 client 측에서는 전달 받은 데이터를 랜더링함으로써 검색 엔진이 구현 될 수 있다. 

 

 

4.  ajax를 예시2 - 크롤링

client 웹브라우저 코드 

<!doctype html>
<html>
<head>
  <title>코로나 알리미</title>
  <meta charset="utf-8">
  
</head>
<body>
  <h1><a id = "Home">코로나 확진자 알리미</a></h1>
  <input id ="Seoul" type="button" value="Seoul">
  <input id = 'Gyeonggi' type="button" value = "Gyeonggi">
  <input id = 'Incheon' type="button" value = "Incheon">
  
  <h2 id='contentTitle'></h2>
  <p id = 'content'></p>
</body>

<script>

document.querySelector('#Home').addEventListener('click', function(event) {
    console.log('request of crawling');
    const xhr = new XMLHttpRequest();
    const heroku = 'https://moonjeonghunapp1.herokuapp.com/';
    const crolURL = 'https://m.search.naver.com/search.naver?where=m&sm=top_hty&fbm=1&ie=utf8&query=%EB%B6%80%EC%82%B0+%EC%BD%94%EB%A1%9C%EB%82%98';

    xhr.open('get', heroku+crolURL);
    xhr.responseType = "document";
    xhr.send();

    xhr.onload = function() {
      console.log(xhr.responseXML);
      var CoronaData1 = xhr.responseXML.getElementsByClassName('info_01');
      var CoronaData2 = xhr.responseXML.getElementsByClassName('info_02');
      var CoronaData3 = xhr.responseXML.getElementsByClassName('info_03');
      var CoronaData4 = xhr.responseXML.getElementsByClassName('info_04');
      var content = document.querySelector('#content');

      document.querySelector('#contentTitle').innerText = "전국 발생 현황"
     
      while(content.hasChildNodes()) {content.removeChild(content.firstChild)} //태그 내용 초기화
      content.insertAdjacentHTML('beforeend', `
      <p>크롤링한 정보(전국 확진자 수) : ${CoronaData1[0].childNodes[3].innerText}</p>
      <p>크롤링한 정보(전국 재원 위중증 수) : ${CoronaData2[0].childNodes[3].innerText}</p>
      <p>크롤링한 정보(전국 신규 인원 수) : ${CoronaData3[0].childNodes[3].innerText}</p>
      <p>크롤링한 정보(전국 일일 사망 수) : ${CoronaData4[0].childNodes[3].innerText}</p>
      `);
    }
  })

  
  document.querySelector('#Seoul').addEventListener('click', function(event) {
    console.log('request of crawling');
    const xhr = new XMLHttpRequest();
    const heroku = 'https://moonjeonghunapp1.herokuapp.com/';
    const crolURL = 'https://www.seoul.go.kr/coronaV/coronaStatus.do';

    xhr.open('get', heroku+crolURL);
    xhr.responseType = "document";
    xhr.send();

    xhr.onload = function() {
      console.log(xhr.responseXML);
      var CoronaData1 = xhr.responseXML.getElementsByClassName('num num10');
      var CoronaData2 = xhr.responseXML.getElementsByClassName('num num1');
      var CoronaData3 = xhr.responseXML.getElementsByClassName('num num9');
      var content = document.querySelector('#content');

      document.querySelector('#contentTitle').innerText = "서울 코로나 현황"

      while(content.hasChildNodes()) {content.removeChild(content.firstChild)} //태그 내용 초기화
      content.insertAdjacentHTML('beforeend', `
      <p>크롤링한 정보(서울 신규 확진자 수) : ${CoronaData1[0].firstElementChild.innerText}</p>
      <p>크롤링한 정보(서울 누적 확진자 수) : ${CoronaData2[0].firstElementChild.innerText}</p>
      <p>크롤링한 정보(사망 수) : ${CoronaData3[0].firstElementChild.innerText}</p>
      `);
    }
  })

  document.querySelector('#Gyeonggi').addEventListener('click', function(event) {
    
  })

  document.querySelector('#Incheon').addEventListener('click', function(event) {
   
  })
</script>
</html>

 

node로 만든 서버

var http = require('http');
var url = require('url');
var fs = require('fs');
var qs = require('querystring');
var port = 8100;

var app = http.createServer(function(request, response) {
  var _url = request.url;
  var queryData = url.parse(_url, true).query;
  var pathName = url.parse(_url, true).pathname;

  if(pathName == '/') {
    fs.readFile('./index.html', 'utf-8', function(err, description) {
      response.writeHead(200);
      response.end(description);
    })
  }
});

app.listen(port);

 

 

 

크롤링을 통해 웹사이트의 코로나와 관련된 정보를 가져오는 예시이다. 

코로나 정보가 있는 웹 서버의 DOM 요소를 ajax를 통해서 요청할 수 있고 서버로부터 전송된 DOM 데이터를 client 측에서 load() 이벤트로 catch하여 내부에서 웹 브라우저를 갱신하는데 사용할 수 있다.