[JavaScript] AJAX 통신 정리[JavaScript] AJAX 통신 정리

Posted at 2019. 11. 17. 22:35 | Posted in JavaScript & jQuery/JavaScript




참고① : 하루 10분씩 핵심만 골라 마스터하는 Ajax 핸드북

참고② : Ajax 시작하기 





전통적인 방식의 사이트들을 이용할 때에는 텍스트와 그림, 데이터 입력 폼(Form) 등이 하나의 페이지 단위로 처리되었다.


각각의 페이지들도 다른 페이지로 이동하기 전에는 페이지 전체가 하나의 독립된 페이지로 처리되었다.



예를 들면, 폼의 데이터 입력 필드에 값을 기록하고 또 수정하는 등의 작업을 하더라도 우리가 전송 버튼을 누르기 전에는


어떠한 내용도 서버에 보내지 않는다.



입력된 폼을 전송하거나 링크를 통해서 다른 곳으로 이동할 때,


사용자는 반드시 새로운 페이지가 서버로부터 전송되어 화면에 업데이트될 때까지 기다려야 한다.







■ AJAX에 대하여




사용자 경험을 위해서 기존의 페이지 방식의  디자인에서 몇 가지 기능을 추가해야 한다.


그것은 사용자의 행동에 따라 변화된 내용으로 응답이 이루어져야 하고,


화면이 지워지고 페이지가 다시 로드되는 등의 방해 없이 업데이트가 이루어져야 한다.


이를 위해서, Ajax는 웹 페이지와 서버 간에 별도의 처리 단계를 둔다.





이 층(Layer)을 Ajax 엔진이나, Ajax 프레임워크라고 하는데,


사용자의 요청을 가로채서, 서버와의 통신을 뒤에서 비동기적(Asynchronously)으로 조용하고 묵묵히 처리한다.


이는 서버 요청과 응답이 더 이상 사용자의 특정한 요청에 의해서 동시에 일어나는 것이 아니라,


사용자나 어플리케이션에 알맞은 시간에 어느 때나  일어날 수 있다는 말이다.


브라우저는 마지막 요청에 대한 응답을 무작정 멈춰서 기다리지 않고,


사용자가 스크롤하거나, 마우스로 클릭하거나 글을 입력하는 등의 일을 하도록 한다.




새로 변경된 정보를 받아서 페이지의 일부를 수정하는 일도 AJAX를 거쳐 이루어진다.


물론 이 일을 하는 중에도 페이지는 여전히 사용 가능하다.









■ AJAX의 동작 원리




새로운 AJAX 어플리케이션을 개발한다거나 기존 웹 어플리케이션에 AJAX를 추가한다고 가정해보면


먼저 어떤 페이지 이벤트와 사용자 입력을 비동기 HTTP 요청을 통해 처리할 것인지를 결정할 필요가 있다.


예를 들어, 어떤 그림의 onMouseOver 이벤트가 발생했을 때,


서버로 그 그림에 대한 자세한 정보를 요청할 수도 있다.


예를 들어, 어떤 그림의 onMouseOver 이벤트가 발생했을 경우,


서버로 그 그림에 대한 자세한 정보를 요청할 수도 있다.


또는 버튼의 onClick 이벤트가 발생했을 때, 폼의 어떤 필드를 확장할 것인지에 대한 정보를 서버에 요청할 수도 있다.



앞으로 작성할 AJAX 어플리케이션에서는 이러한 이벤트 핸들러들이 비동기 HTTP 요청을 생성하고


XMLHTTPRequest를 통해서 보내는 일을 하도록 해야 한다.



요청(Request)을 보냈다면, 그 요청의 진행 상태를 감시하기 위한 루틴을 작성해야 하고,


서버로부터 요청이 성공적으로 처리되었다는 것을 확인해야 한다.







마지막으로 서버로부터 처리된 응답을 받으면, 그 응답을 받아서 정보를 처리하는 루틴을 작성하고,


어플리케이션에 반영하는 일을 해야 한다.


예를 들면, 새로받은 데이터를 웹 페이지의 본문 내용을 업데이트하는 데 사용하거나,


팝업창을 나타내거나, 폼의 필드를 추가하는 등의 일이 그것이다.








■ XMLHTTPRequest 객체



하이퍼링크를 클릭하거나 폼의 전송 버튼을 누를 때, 브라우저는 서버에게 HTTP 요청(Request)을 보낸다.


그러면 서버는 새로운 페이지나 수정된 페이지를 사용자에게 다시 보낸다.


그러나 비동기적으로 동작하는 웹 어플리케이션에서는 서버에게 화면을 새롭게 갱신하지 않는 성질의 요청을 보낼 필요가 있다.



이를 위해서 XMLHTTPRequest 객체를 이용해야 한다.


이 자바스크립트 객체는 서버에 연결하고 HTTP 요청을 새로운 페이지 로드 없이 보낼 수 있게 한다.



Tip.


  보안을 위해 XMLHTTPRequest 객체는 일반적으로 페이지와 같은 도메인에 있는 URL로만 명령을 내릴 수 있고,

  외부 서버로의 직접 호출은 할 수 없다.

       



XMLHTTPRequest 객체는 실질적으로 현재 사용되는 모든 웹 브라우저에서 지원된다.


인터넷 익스플로러 5.0이상 버전과 모질라 파이어폭스, 구글 크롬, 오페라, 사파리등이 모두 지원한다.


또안 MS 윈도우즈는 물론이고, UNIX / Linux, Mac OS X 등의 플랫폼에서 위에서 나열한 브라우저들을 이용해서 사용할 수 있다.



XMLHTTPRequest 객체의 목적은 자바스크립트가 HTTP 요청을 생성하고 서버로 전송하는 것이다.


전통적인 웹 어플리케이션은 이러한 요청을 동기적으로 수행했다.


이는 사용자가 클릭하거나 폼을 전송하면, 그에 따라서 새로운 페이지가 브라우저로 전송되는 방식이다.



XMLHTTPRequest 객체를 이용하면 이러한 서버 호출을 배후에서 비동기적으로 수행할 수 있다.


이는 웹 페이지 전체가 새롭게 로드되는 등의 방해없이 계속 사용할 수 있을을 의미한다.



이러한 기능은 모든 Ajax 어플리케이션에서 기초가 되는 개념이고,


XMLHTTPRequest가 Ajax 프로그래밍의 핵심인 이유이다.





#01. XMLHTTPRequest 객체의 속성


속성(Properties)

내   

 onreadystatechange

 · 객체의 readyState 속성이 변경될 때 어떤 이벤트 처릴르 호출할지를 결정한다.

 readyState

 · 요청(Request)에 대한 상태를 나타내는 정수값

   0 = 초기화되지 않음

   1 = 로드 중( Loading )

   2 = 로드 됨( Loaded )

   3 = 상호작용( Interactive )

   4 = 완료됨( Completed )

 responseText

 · 서버로부터 리턴된 데이터(문자형식)

 responseXML

 · 서버로부터 리턴된 문서 객체 형식의 XML 데이터

 status

 · 서버가 리턴한 HTTP 상태 코드

 statusText

 · 서버가 리턴한 HTTP 상태 설명



#02. XMLHTTPRequest 메소드


메소드(Methods)

설   명 

 abort( )

 · 현재 요청을 취소함

 getAllResponseHeaders( )

 · 모든 헤더 정보를 문자열로 얻어냄

 getResponseHeader( × )

 · 헤더 ×의 내용을 문자열로 얻어냄

 open( "method", "URL", "A" )

 · HTTP 명령(GET, POST 등)과 그 대상 URL을 통해서 HTTP 요청을 비동기적으로 처리할지를 나타냄

  ( A에 true(기본값)를 넣으면 비동기적으로 동작하고, false는 동기적으로 동작한다. )

 send( CONTENT )

 · 요청을 보냄 POST의 내장 데이터도 필요할 경우 보낼 수 있음

 setRequestHeader( "x", "y" )

 · 요청을 보낼 때 추가적인 파라미터를 지정하기 위한 메소드.

 · x=y 쌍으로 된 파라미터를 헤더에 추가하는 기능을 한다.




① open( ) 메소드


open( ) 메소드를 이용해서 XMLHTTPRequest 객체가 서버와 통신하기 위한 준비과정을 진행한다.


최소한 2개의 인자는 필수적으로 넘겨야 한다.


 -. 첫째. 어떤 HTTP 명령을 사용할 것인지 여부인데, GET 또는 POST를 많이 사용할 것이다.


 -. 둘째. 요청을 보낼 대상 URL이다.

    GET 쵸엉을 보낸다면, URL에 파라미터에 대한 내용이 인ㅌ코딩되어 URL에 포함된 상태여야 한다.



보안상의 이유로 XMLHTTPRequest 객체는 같은 도메인 내에서만 통신할 수 있다.


외부의 도메인에 접근하고자 할 때는 권한이 없다는 에러 메시지인 "permission denied"를 받게 된다.


 -. 셋째. open( ) 요청에 세번째 인자는 Bool-ean 값으로, 보내는 요청이 비동기적으로 이루어질 것인지를 나타낸다.

    false로 설정하면, 서버로 보내는 요청은 동기적으로 처리도리 것이기 때문에 응아답이 올 때까지 화면은 응답하지 않는 잠김 상태가 된다.

    기본값인 true를 넣거나 인자를 생략하면, 요청은 비동기적으로 처리된다.




②  send( ) 메소드


open( ) 메소드를 이용해서 XMLHTTPRequest를 준비한 후에, 실제 요청을 보내기 위해서 send( ) 메소드를 사용한다.


send( ) 함수는 한 개의 인자를 받는다.



보낼 요청이 GET 형식이라면, 요청 정보가 URL 안에 인코딩된 값이 포함되므로, 인자는 null 인자를 넣어서 호출하면 된다.


GET방식

 objectname.send( null );



그러나 POST 형식의 경우는 요청 내용을 인코딩한 후 이 메소드의 인자로 넘겨야 한다.



POST방식

 objectname.setRequestHeader("Content-Type", "application/x-www-from-urlencoded");

 objectname.send(var1=value1&var2=value2);




이 경우는 setRequestHeader 메소드를 호출해서 요청 내용이 어떤 종류의 데이터를 가지고 있는지를


HTTP 요청 헤더에 기록하게 된다.

 









■ AJAX를 이용하여 XML 데이터 출력하기




# 소스코드 - XML 데이터 생성

 tell_time_xml.php

<?php

header("Content-Type:text/xml");

echo "<?xml version='1.0'?>";

echo "<clock>";

echo "<timeNow>";

echo date("Y-m-d H:i:s");

echo "</timeNow>";

echo "</clock>";

?>




# 소스코드 - AJAX 호출 영역

 ajax_application.html

<html>

<head>

<meta charset="UTF-8">

<title>:: Ajax Demonstration ::</title>

<style type="text/css">

body { text-align:center; }

#showTime {

display:inline-block;

width:250px;

background-color:#FFFFFF;

border:2px solid #000000;

padding:10px;

font:24px normal verdana, helvetic, arial, sans-serif;

}

</style>

<script language="JavaScript" type="text/javascript">

document.addEventListener("DOMContentLoaded", function() {

// HTML 실행이 완료되었을 경우 getServerTime( ) 함수를 실행한다.

getServerTime();

});

function getXMLHTTPRequest() {

let request = false;

// 브라우저(FireFox, Chrome)에 맞는 생성자를 이용해서 객체의 인스턴스를 생성

try {

request = new XMLHttpRequest();

}

// 객체가 존재하지 않는경우 MS방식의 브라우저 이므로 ActiveX객체를 검사하고 생성하는 작업을 수행한다.

catch(err01) {

try {

request = new ActiveXObject("Msxml2.XMLHTTP"); // some versions IE

}

catch(err02) {

try {

request = new ActiveXObject("Microsoft.XMLHTTP"); // some versions IE

}

catch(err03) {

request = false;

}

}

}

return request;

}

// XMLHTTPRequest 객체를 생성하여 http라는 전역 변수에 담아 필요할때 바로 사용한다.

let http = getXMLHTTPRequest();

function getServerTime() {

// xml 형태의 시간정를 가지고 있는 URL 정보

let xmlUrl = "tell_time_xml.php";

// XMLHTTPRequest 객체가 서버와 통신하기 위한 준비과정을 진행한다.

                // true : 비동기, false : 동기

http.open("GET", xmlUrl, true);


                // onreadystatechange 메소드는 useHttpResponse( ) 함수를 호출한다.

                // 해당 함수를 수행하는 것이 아니라 단순하게 어떤 함수가 불릴 것인지만 지정한다.

                // 단순하게 그 함수를 지정하는 것이므로 그 함수로 어떠한 변수도 전달하지 않는다. ( 괄호사용× )

                // 또한 단순하게 함수를 연결하면 되기 때문에 함수 본체를 기입해도 된다.

http.onreadystatechangeuseHttpResponse;

// .open( ); 메소드를 이용해서 XMLHTTPRequest를 준비된 내용을 가지고,

// 서버에 실제 요청을 보내기위해 .send( ); 메소드를 사용한다. 

http.send(null);

}

function useHttpResponse() {

// readyState값이 4인경우 완료됨을 의미한다.

if(http.readyState == 4) {

// HTTP 응답이 "OK"인 경우

if(http.status == 200) {

var timeValue = http.responseXML.getElementsByTagName("timeNow")[0];

document.getElementById("showTime").innerHTML = timeValue.childNodes[0].nodeValue;

}

else {

// 서버가 리턴한 http 상태를 설명한다.

        // statusText 의 기본값은 'OK' 이다. 

alert("An error has occurred : " + http.statusText);

}

}

// 완료되지 않은경우 버퍼링 이미지를 노출한다.

else {

document.getElementById("showTime").innerHTML = "<img src='http://gph.is/1XRTmuh' style='width:100%;'>";

}

}

</script>

</head>

<body style="background-color:#CCCCCC">

<h1>Ajax Domonstration</h1>

<h2>Getting the server time without page refresh</h2>

<form>

<input type="button" value="Get Server Time" onClick="getServerTime();"/>

</form>

<div id="showTime"></div>

</body>

</html>



# 출력결과









■ AJAX를 이용한 JSON 데이터 전송 및 출력




위와같이 자바스크립트를 통한 Ajax 통신방법을 알아 보았다.


그렇지만 현업에서는 jQuery의 Ajax를 실제로 더 많이 사용하게 되고.


필자또한 jQuery의 Ajax기능을 안쓰고 비동기 이벤트를 구현한다는것은 거의 상상하기도 힘들었다.


jQuery를 안쓰는 추세라곤 하지만, 필자의 생각은 역시 완전히 jQuery가 사라지기에는


적어도 필자의 개발을 하는 가운데서는 아마도 이루어지 지지 않을것이라고 생각한다.


그런데도 위와같이 자바스크립트를 통한 Ajax 통신 방법을 따로 정리하는 이유는


jQuery가 앞도하던 시장에서 Vue.js React.js Angular.js 등이 각광받고 있지만.


결국 JavaScript로 구현 가능하다면,


기초와 기본에 충실하게 사용할 수 있어 프론트개발자의 길에 흠들림의 여파를 줄이고 싶었기 때문이기도 하다.




# 소스코드 - JSON 데이터 전송 받고 JSON 형태로 내보내기

 tell_time_json.php

<?php

$RetVal = array("ret"=>"fail", "error"=>"", "error_msg"=>"", "message"=>"");

$backUrl = $_SERVER['HTTP_REFERER'];


// php://input은 내용의 유형에 관계없이 요청 HTTP 헤더 뒤에 모든 원시 데이터를 반환한다.

$data = json_decode(file_get_contents("php://input"), true);


switch($data['mode']) {


    case "timeIs" :


        $timestamp = mktime(

          $data['hour'] // 시간

        , $data['minute'] // 분

        , $data['second'] // 초

        , $data['month'] // 월

        , $data['day'] // 일

        , $data['year'] // 년도

        );

        

$RetVal['data']['date'] = date('Y-m-d H:i:s', $timestamp);

        $RetVal['ret'] = "success";


        print json_encode($RetVal);

        return;


    break;


    default :

   

    $RetVal['message'] = "데이터 조회 실패";

   

    print json_encode($RetVal);

        return;

        

    break;

}


header("location:".$backUrl);

?>



# 소스코드 - AJAX 호출(JSON 데이터 전송 및 파싱)

 ajax_application_post.html

<html>

<head>

<meta charset="UTF-8">

<title>:: Ajax Demonstration ::</title>

<style type="text/css">

body { text-align:center; }

#showTime {

display:inline-block;

width:250px;

background-color:#FFFFFF;

border:2px solid #000000;

padding:10px;

font:24px normal verdana, helvetic, arial, sans-serif;

}

</style>

<script language="JavaScript" type="text/javascript">

document.addEventListener("DOMContentLoaded", function() {

// HTML 실행이 완료되었을 경우 getServerTime 함수를 실행한다.

getServerTime('timeIs');

});

function getXMLHTTPRequest() {

let request = false;

try { request = new XMLHttpRequest(); }

catch(err01) {

try { request = new ActiveXObject("Msxml2.XMLHTTP"); }

catch(err02) { 

try { request = new ActiveXObject("Microsoft.XMLHTTP"); }

catch(err03) { request = false; }

}

}

return request;

}

const ajax = getXMLHTTPRequest();

function getServerTime(mode) {

// 서버로 전송할 데이터 생성

const toTime = new Date(); 

const arrData =  {

  "mode" : mode                                           // 실행조건

, "year" : toTime.getFullYear().toString()               // 년

, "minute" : (toTime.getMonth() + 1).toString()      // 월

, "day" : toTime.getDate().toString()                    // 일

, "hour" : toTime.getHours().toString()                 // 시

              , "minute" : toTime.getMinutes().toString()           // 분

, "second" :  toTime.getSeconds().toString()          // 초

};

// XMLHTTPRequest 객체가 서버와 통신하기 위한 준비과정을 진행한다.

ajax.open("POST", "/tell_time_json.php", true);

// send() 함수를이용해 POST 형식의 데이터를 넘기는 경우는

// setRequestHeader() 함수를 이용해 인코딩한 후 이 메소드의 인자로 넘겨야 한다.

ajax.setRequestHeader("Content-Type", "application/json;charset=UTF-8;");

// json 타입으로 변경하여 데이터를 전송한다.

ajax.sendJSON.stringify(arrData) );

ajax.onreadystatechange = function() {

if(ajax.readyState == 4) {

if(ajax.status == 200) {

// responseText 속성은 서버가 리턴한 정보를 텍스트 형식으로 가져온다.

const json = JSON.parse(ajax.responseText);

if(json.ret == "success") {

document.getElementById("showTime").innerHTML = json.data.date;

} else {

console.log(json.message);

}

}

else {

alert("An error has occurred : " + ajax.statusText);

}

} else {

document.getElementById("showTime").innerHTML = "<img src='http://gph.is/1XRTmuh' style='width:100%;'>";

}

};

}

</script>

</head>

<body style="background-color:#CCCCCC">

<h1>Ajax Domonstration</h1>

<h2>Getting the server time without page refresh</h2>

<form>

<input type="button" value="Get Server Time" onClick="getServerTime();"/>

</form>

<div id="showTime"></div>

</body>

</html>




# 출력결과




위의 GET 전송방식의 예제와 같은 결과 화면이 나오는 것을 확인 할 수 있다.









Name __

Password __

Link (Your Website)

Comment

SECRET | 비밀글로 남기기