상세 컨텐츠

본문 제목

jQuery #2 : jQuery & Ajax (XMLHttpRequest)

PROGRAMMING/Web

by koharin 2021. 2. 21. 23:30

본문

728x90
반응형

Ajax(Asynchronous JavaScript ans XML)


  • JavaScript를 이용한 비동기적(asynchronous)으로 서버와 브라우저가 데이터를 교환하는 통신 방식
  • 서버로부터 갱신이 필요한 웹페이지 일부만 로드하여 갱신한다.
  • 서버는 Ajax에 JSON 데이터 형식을 반환한다.

 

동기식 처리 모델 vs 비동기식 처리 모델


동기식 처리 모델

  • 직렬 방식
  • 순차적으로 작업이 진행되어 하나의 작업이 진행 중이면 끝날 때까지 대기하게 되어 다른 작업은 하지 못한다.

비동기식 처리 모델

  • 병렬 방식
  • 하나의 작업이 끝나지 않아도 대기하지 않고 다른 작업을 수행할 수 있다.

 

Ajax: 요청과 응답 처리


브라우저는 XMLHttpRequest 객체를 이용해서 Ajax 요청을 생성한다.

서버가 브라우저 요청에 대한 응답 반환 시 동일한 XMLHttpRequest 객체가 결과를 처리한다.

Ajax 요청 처리 예

// 1. XMLHttpRequest 객체 생성 -> Ajax 요청 생성
var request = new XMLHttpRequest();

// 비동기 방식으로 Request 오픈
request.open('GET', 'data/test.json', true);

//XMLHttpRequest.send()를 통해 서버에 Request 전송 => 서버는 Response를 반환
request.send();

 

Ajax 응답 처리 예

// XMLHttpRequest.readyState 프로퍼티가 변경(이벤트 발생)될 때마다 XMLHttpRequest.onreadystatechange라는 콜백함수(이벤트 핸들러) 호출.
// Response가 클라이언트에 도달 시 호출된다.
request.onreadystatechange = function(e){
    // readyStates는 XMLHttpRequest의 상태(state) 반환
    // readyState == 4 : DONE(서버 응답 완료)
    if(request.readyState === XMLHttpRequest.DONE){
        // status는 response 상태 코드 반환
        // 200 : 정상응답
        if(request.status == 200){
            console.log(request.responseText);
        }else{
            console.log("Error!");
        }
    }
};

XMLHttpRequest.send()로 서버에 Request를 보내면, 서버는 Response를 반환한다.

XMLHttpRequest.onreadystatechange

  • 언제 Response가 클라이언트에 도달할지 알 수 없으므로, Response가 클라이언트에 도달하여 발생된 이벤트를 감지하고, 콜백함수(이벤트 핸들러)를 실행해준다.
  • 이벤트는 Request에 변화가 발생한 경우, 즉 XMLHttpRequest.readyState 프로퍼티가 변경된 경우 발생한다.
  • XMLHttpRequest.onreadystatechange는 XMLHttpRequest.readyState 프로퍼티가 변경될 때마다 호출되는 이벤트 핸들러이다.

XMLHttpRequest.responseText

  • 서버가 전송한 데이터

 

JSON


  • Ajax 요청에 대한 서버 응답으로 가장 일반적인 데이터 형식은 JSON이다.
  • key는 반드시 큰따옴표로 둘러싸야 한다.
  • JSON.stringfy(): 객체를 JSON 형식 문자열로 변환
  • JSON.parse(): JSON 데이터를 가진 문자열을 객체로 변환

 

Web Server


  • 클라이언트(브라우저 등)로부터 HTTP 요청 받고 HTML 문서 등의 웹 페이지를 반환하는 프로그램
  • Ajax는 웹서버와 통신이 필요하므로, 웹서버 설치가 필요하다.
  • Node.js의 웹 애플리케이션 프레임워크인 Express이나 MAMP, Mongoose등의 웹서버를 사용한다.
$ git clone https://github.com/ungmo2/webserver-express.git
$ cd webserver-express
$ npm i // install dependencies
$ mkdir public // working directory (root directory)
$ cd public

위의 과정으로 express 웹서버 세팅을 했고, public이라는 디렉터리가 작업 디렉터리로, 여기에서 파일을 생성한다.

webserver-express 디렉터리에서 

$ npm start

위의 명령어를 입력하면 웹서버를 실행하면 3000번 포트에서 포트를 열어서 서버가 listening을 하고 있다.

<!DOCTYPE html>
<html>
    <head>
        <meta charset='utf-8'>
        <title>Example document</title>
    </head>
    <body>
        <h1>Hello world!</h1>
    </body>
</html>

http://localhost:3000/exam.html 으로 접속 시 페이지가 정상적으로 로드되어 실행되는 것을 확인할 수 있다.

 

Ajax


1. Load HTML

<!-- public/loadhtml.html -->
<!DOCTYPE html>
<html>
    <head>
        <meta charset='utf-8'>
        <link rel="stylesheet" href="http://poiemaweb.com/assets/css/ajax.css">
    </head>
    <body>
        <div id="content"></div>
        <script>
            // XMLHttpRequest 객체 생성 - Ajax 요청 생성
            var request = new XMLHttpRequest(); 
            // Request 오픈 (비동기 방식)
            request.open('GET', 'data/data.html', true)
            // Request를 서버에게 전송
            request.send();

            request.onreadystatechange = function(e){
                // 서버 응답이 완료됐고,
                if(request.readyState === XMLHttpRequest.DONE){
                    // 정상 응답이면
                    if(request.status == 200){
                        console.log(request.responseText);
                        document.getElementById('content').innerHTML = request.reseponseText;
                    }else{
                        console.log('[' + request.status + ']: ' + request.statusText);
                    }
                }
            };
        </script>
    </body>
</html>
<!-- public/data/data.html -->
<div id="tours">
    <h1>Guided Tours</h1>
    <ul>
      <li class="usa tour">
        <h2>New York, USA</h2>
        <span class="details">$1,899 for 7 nights</span>
        <button class="book">Book Now</button>
      </li>
      <li class="europe tour">
        <h2>Paris, France</h2>
        <span class="details">$2,299 for 7 nights</span>
        <button class="book">Book Now</button>
      </li>
      <li class="asia tour">
        <h2>Tokyo, Japan</h2>
        <span class="details">$3,799 for 7 nights</span>
        <button class="book">Book Now</button>
      </li>
    </ul>
  </div>

 

2. Load JSON

서버에서 브라우저로 전송된 JSON 데이터 == 문자열

역직렬화(Deserializing)

  • 문자열인 JSON 데이터를 객체화하는 것 (String -> Object)
  • JSON.parse() : 내장 객체 JSON의 static 메소드로, 역직렬화에 사용
<-- public/loadjson.html -->
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <link rel="stylesheet" href="http://poiemaweb.com/assets/css/ajax.css">
  </head>
  <body>
    <div id="content"></div>

    <script>
      // XMLHttpRequest 객체의 생성
      var req = new XMLHttpRequest();

      // 비동기 방식으로 Request를 오픈한다
      req.open('GET', 'data/data.json', true);
      // Request를 전송한다
      req.send();

      req.onreadystatechange = function () {
        // 서버 응답 완료 && 정상 응답
        if (req.readyState === XMLHttpRequest.DONE) {
          if (req.status == 200) {
            console.log(req.responseText);

            // Deserializing (String → Object)
            responseObject = JSON.parse(req.responseText);

            // JSON → HTML String
            var newContent = '';
            newContent += '<div id="tours">';
            newContent += '<h1>Guided Tours</h1>';
            newContent += '<ul>';
            for (var i = 0; i < responseObject.tours.length; i++) {
              newContent += '<li class="' + responseObject.tours[i].region + ' tour">';
              newContent += '<h2>' + responseObject.tours[i].location + '</h2>';
              newContent += '<span class="details">' + responseObject.tours[i].details + '</span>';
              newContent += '<button class="book">Book Now</button>';
              newContent += '</li>';
            }
            newContent += '</ul></div>';

            document.getElementById('content').innerHTML = newContent;

            // document.getElementById('content').insertAdjacentHTML('beforeend', newContent);

          } else {
            console.log('[' + req.status + ']: ' + req.statusText);
          }
        }
      };
    </script>
  </body>
</html>
// public/data/data.json
{
  "tours": [
    {
      "region": "usa",
      "location": "New York, USA",
      "details": "$1,899 for 7 nights"
    },
    {
      "region": "europe",
      "location": "Paris, France",
      "details": "$2,299 for 7 nights"
    },
    {
      "region": "asia",
      "location": "Tokyo, Japan",
      "details": "$3,799 for 7 nights"
    }
  ]
}

loadjson.html 에서 data.json 파일을 열어서, String인 JSON 데이터를 JSON,parse()를 통해 responseObject라는 Object로 역직렬화했다.

이후 이 responseObject 객체를 통해 tours 내 각 region 키에서 value를 가져와 <li> 태그의 클래스 이름을 순차적으로 usa tour, europe tour, asia tour로 만드는 등 HTML String으로 구조화한다.

document.getElementById('content').innerHTML = newContent; 로 만든 HTML String을 content라는 아이디 가진 태그 내의 innerHTML으로 넣는다.

 

 

3. Load JSONP

동일출처원칙(Same-origin policy)

  • 요청에 의해 웹페이지가 전달된 서버와 동일한 도메인의 서버로부터 전달된 데이터는 문제없이 처리되지만, 다른 도메인으로부터 요청(크로스 도메인 요청)은 제한된다.
  • http와 https, 포트 다르면 다른 도메인으로 간주한다.
  • 동일출처원칙 우회
    • 프록시
    • JSONP 스크립트 태그의 원본 주소에 대한 제약이 없는 것을 이용해서 다른 도메인의 서버에서 데이터를 수집한다.
    • Cross-Origin Resource Sharing HTTP 헤더에 정보를 추가해 브라우저와 서버가 서로 통신한다는 사실을 알게 해준다. 최신 브라우저에서만 동작하고, 서버에서 HTTP 헤더를 설정해야 한다.
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <link rel="stylesheet" href="http://poiemaweb.com/assets/css/ajax.css">
  </head>
  <body>
    <div id='content'></div>

    <script>
    function showTours(data) {
      console.log(data); // data: object

      // JSON → HTML String
      var newContent = '';
      newContent += '<div id="tours">';
      newContent += '<h1>Guided Tours</h1>';
      newContent += '<ul>';
      for (var i = 0; i < data.tours.length; i++) {
        newContent += '<li class="' + data.tours[i].region + ' tour">';
        newContent += '<h2>' + data.tours[i].location + '</h2>';
        newContent += '<span class="details">' + data.tours[i].details + '</span>';
        newContent += '<button class="book">Book Now</button>';
        newContent += '</li>';
      }
      newContent += '</ul></div>';

      document.getElementById('content').innerHTML = newContent;
    }
    </script>
    <script src='http://poiemaweb.com/assets/data/data-jsonp.js'></script>
  </body>
</html>
https://poiemaweb.com/assets/data/data-jsonp.js
showTours({
  "tours": [
    {
      "region": "usa",
      "location": "New York, USA",
      "details": "$1,899 for 7 nights"
    },
    {
      "region": "europe",
      "location": "Paris, France",
      "details": "$2,299 for 7 nights"
    },
    {
      "region": "asia",
      "location": "Tokyo, Japan",
      "details": "$3,799 for 7 nights"
    }
  ]
});
  • 스크립트로 로드되는 링크를 확인해보면, data-jsonp.js라는 자바스크립트 스크립트임을 확인할 수 있다.
  • tours는 객체로, function showTours(data){ ... }가 있고, showTours({ ~ });는 JavaScript 내에서 함수를 호출한 것과 동일하다.
  • 따라서 data는 tours 객체가 들어가고, 이 tours 객체의 key와 value를 사용해서 HTML을 생성 후 id가 content인 태그에 HTML String을 넣어준 것을 확인할 수 있다.

 

Ajax with jQuery


1. Low-level Interface

jQuery.ajax( url [, settings ] )  // Returns: jqXHR
jQuery.ajax( [settings ] )        // Returns: jqXHR

settings : Ajax 요청 설정 정보, key/value 쌍으로 이루어진 객체. 옵션으로 사용한다.

1-1. Load HTML

<!DOCTYPE html>
<html>
    <head>
        <meta charset='utf-8'>
        <link rel="stylesheet" href="http://poiemaweb.com/assets/css/ajax.css">
    </head>
    <body>
        <div id='content'></div>
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
        <script>
            $.ajax({
                url: "data/data.html",
                cache: false
            })
            .done(function(data, textStatus, jqXHR){
                $("#content").html(data); 
            })
            .fail(function(jqXHR, textStatus, errorThrown){
                console.log("fail: ", jqXHR);
            })
            .always(function(data, textStatus, jqXHR){
                console.log("always: ", data);
            })
        </script>
    </body>
</html>
  • .done : 데이터 로드 완료 시 content라는 아이디 가지는 요소에 data를 넣는다. 만약 해당 요소에 내용이 있으면 기존 내용을 지우고 새로운 data 내용을 넣는다. html() 은 요소의 데이터를 가져온다.
  • $.ajax() : 비동기 방식으로 AJAX 요청을 수행한다.

1-2. Load JSON

<!DOCTYPE html>
<html>
    <head>
        <meta charset='utf-8'>
        <link rel="stylesheet" href="http://poiemaweb.com/assets/css/ajax.css">
    </head>
    <body>
        <div id='content'></div>
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
        <script>
            $.ajax({
                url: "data/data.json",
                dataType: "json"
            })

            .done(function(data){
                var newContent = '';
                newContent += '<div id="tours">';
                newContent += '<h1>Guided Tours</h1>';
                newContent += '<ul>';
                for(var i = 0; i < data.tours.length; i++){
                    newContent += '<li class="' + data.tours[i].region + ' tour">';
                    newContent += '<h2>' + data.tours[i].location + '</h2>';
                    newContent += '<span class="details">' + data.tours[i].details + '</span>';
                    newContent += '<button class="book">Book Now</button>';
                    newContent += '</li>';
                }
                newContent += '</ul>';
                newContent += '</div>';

                $("#content").html(newContent);
            })

            .fail(function(jqXHR, textStatus, errorThrown){
                console.log("fail: ", jqXHR);
            })

            .always(function(data, textStatus, jqXHR){
                console.log("always: ", data);
            })
        </script>
    </body>
</html>

1-3. Load JSONP

<!DOCTYPE html>
<html>
    <head>
        <meta charset='utf-8'>
        <link rel="stylesheet" href="http://poiemaweb.com/assets/css/ajax.css">
    </head>
    <body>
        <div id="content"></div>
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
        <script>
            $.ajax({
                url: "http://poiemaweb.com/assets/data/data-jsonp.js",
                dataType: "jsonp",
                jsonpCallback: "showTours"
            })
            .done(function(data, textStatus, jqXHR){
                console.log("done: ", data);

                var newContent = '';
                newContent += '<div id="tours">';
                newContent += '<h1>Guided Tours</h1>';
                newContent += '<ul>';
                for (var i = 0; i < data.tours.length; i++) {
                    newContent += '<li class="' + data.tours[i].region + ' tour">';
                    newContent += '<h2>' + data.tours[i].location + '</h2>';
                    newContent += '<span class="details">' + data.tours[i].details + '</span>';
                    newContent += '<button class="book">Book Now</button>';
                    newContent += '</li>';
                }
                newContent += '</ul></div>';
                $('#content').html(newContent);
            })
            .fail(function(jqXHR, textStatus, errorThrown){
                console.log("fail: ", jqXHR);
            })
            .always(function(data, textStatus, jqXHR){
                console.log("always: ", data);
            })
        </script>
    </body>
</html>

 

2. Method

2-1. jQuery.get()

jQuery.get( url [, data ] [, success ] [, dataType ] ) // Returns: jqXHR

HTTP GET 요청으로 서버로부터 데이터 로드한다.

<!DOCTYPE html>
<html>
    <head>
        <meta charset='utf-8'>
        <link rel="stylesheet" href="http://poiemaweb.com/assets/css/ajax.css">
    </head>
    <body>
        <div id="content"></div>
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
        <script>
            $.get("data/data.html", function(data){
                $('#content').html(data);
            });
        </script>
    </body>
</html>

2-2. jQuery.getJSON()

jQuery.getJSON( url [, data ] [, success ] ) // Returns: jqXHR

HTTP GET 요청을 통해 서버로부터 JSON encoded 데이터를 로드한다.

<!DOCTYPE html>
<html>
    <head>
        <meta charset='utf-8'>
        <link rel="stylesheet" href="http://poiemaweb.com/assets/css/ajax.css">
    </head>
    <body>
        <div id="content"></div>
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
        <script>
            $.getJSON("data/data.json", function(data){
                var content = '';
                content += '<div id="tours">';
                content += '<h1>Guided Tours</h1>';
                content += '<ul>';
                for (var i = 0; i < data.tours.length; i++) {

                    content += '<li class="' + data.tours[i].region + ' tour">';
                    content += '<h2>' + data.tours[i].location + '</h2>';
                    content += '<span class="details">' + data.tours[i].details + '</span>';
                    content += '<button class="book">Book Now</button>';
                    content += '</li>';
                }
                content += '</ul></div>';
                $('#content').html(content);
            });
        </script>
    </body>
</html>

2-3. jQuery.getScript()

jQuery.getScript( url [, success ] ) // Returns: jqXHR

HTTP GET 요청을 통해 서버로부터 JavaScript 파일을 로드한 후 실행한다.

 

2-4. JQuery.post()

jQuery.post( url [, data ] [, success ] [, dataType ] ) // Returns: jqXHR

서버로부터 데이터를 로드한다.

 

2-5. load()

.load( url [, data ] [, complete ] ) // Returns: jQuery

서버로부터 HTML 데이터 로드 후 Matched set에 적용한다.

<!DOCTYPE html>
<html>
    <head>
        <meta charset='utf-8'>
        <link rel="stylesheet" href="http://poiemaweb.com/assets/css/ajax.css">
    </head>
    <body>
        <div id="content"></div>
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
        <script>
            $('#content').load("data/data.html", function(){
                console.log("Load performed.");
            })
        </script>
    </body>
</html>

Reference


poiemaweb:jQuery Ajax & JSON

728x90
반응형

'PROGRAMMING > Web' 카테고리의 다른 글

Fetch API 통한 Ajax 구현 #2  (0) 2021.02.24
Fetch API 통한 Ajax 구현 #1  (0) 2021.02.24
[Web 개발] Day and Night Mode #2 (jQuery, Bootstrap)  (0) 2021.02.19
jQuery #1  (0) 2021.02.18
[Web 개발] Day and Night Mode #1 (jQuery, Bootstrap)  (0) 2021.02.02

관련글 더보기