[Ajax] Ajax와 비동기 통신

dondonee·2024년 1월 10일
0
post-thumbnail
post-custom-banner

Ajax와 비동기 통신

Ajax 이해

Ajax(Asynchronous JavaScript and XML)는 동적인 웹 페이지를 만들기 위한 개발 기법이다. 그 자체로 새로운 언어는 아니고 HTML, CSS, 자바스크립트, DOM, XML 등 기존에 사용되던 여러 기술을 함께 사용한다.

Ajax는 웹 페이지 전체를 다시 로딩하지 않고도 웹 페이지의 일부분만을 갱신할 수 있다. 이 때 Ajax는 서버와 JSON, XML, HTML, 텍스트 파일 등 다양한 형식의 데이터를 주고받을 수 있는데 최근에는 주로 JSON을 사용한다.


장점

  1. 웹 페이지 전체를 다시 로딩하지 않고도 웹 페이지의 일부분만을 갱신할 수 있다.
  2. 웹 페이지가 로드된 후에 서버로 데이터 요청을 보낼 수 있다.
  3. 웹 페이지가 로드된 후에 서버로부터 데이터를 받을 수 있다.
  4. 백그라운드 영역에서 서버로 데이터를 보낼 수 있다.

한계

  1. Ajax는 클라이언트가 서버에 데이터를 요청하는 클라이언트 풀링 방식을 사용하므로, 서버 푸시 방식의 실시간 서비스는 만들 수 없다.
  2. Ajax로는 바이너리 데이터를 보내거나 받을 수 없다.
  3. Ajax 스크립트가 포함된 서버가 아닌 다른 서버로 Ajax 요청을 보낼 수는 없다.
  4. 클라이언트의 PC로 Ajax 요청을 보낼 수는 없다.


Ajax 동작

구성요소

  • 웹 페이지의 표현을 위한 HTMLCSS
  • 데이터에 접근하거나 화면 구성을 동적으로 조작하기 위해 사용되는 DOM 모델
  • 데이터의 교환을 위한 JSON이나 XML (최근에는 주로 JSON을 사용)
  • 웹 서버와의 비동기식 통신을 위한 XMLHttpRequest 객체
  • 위에서 언급한 모든 기술을 결합하여 사용자의 작업 흐름을 제어하는 데 사용되는 자바스크립트

동작 과정

Ajax를 사용하지 않고 클라이언트 요청에 대해 뷰를 반환하는 기존의 방식은 매 HttpRequest 요청마다 전체 페이지가 갱신되어야 한다. 따라서 웹 애플리케이션이 다양한 기능을 제공하기 위해서는 여러 개의 웹 페이지가 필요하다.

반면 Ajax는 XMLHttpRequest 객체를 사용하여 요청하고 서버는 JSON으로 응답한다. 클라이언트는 이 응답을 받아 자바스크립트를 이용하여 DOM을 조작하여 웹 페이지의 일부분만을 다시 로딩한다. 때문에 기존 방식과 달리 웹 애플리케이션은 하나의 페이지만으로도 여러 가지 기능을 제공할 수 있다.


DOM

DOM(Document Object Model, 문서 객체 모델)은 HTML 문서나 XML 문서에 접근하기 위한 일종의 인터페이스이며, 노드(node)라고 불리는 계층적 단위에 정보를 저장하고 있다.

Ajax는 자바스크립트를 이용해 노드를 삭제하거나 추가하는 등 조작함으로써 웹 페이지의 일부를 변경할 수 있다.



비동기 통신

웹 애플리케이션이 사용자에게 두 가지 기능을 제공하는 상황을 가정해 보자 :

  1. 서버로부터 데이터를 받아 서울특별시 지도를 보여준다.
  2. 서버로부터 데이터를 받아 서울에서 별점 4.0 이상의 맛집 리스트를 보여준다.

동기식 처리방법

Ajax를 사용하지 않는 기존의 방식에서 다음 두 가지 일을 하나의 페이지에서 동시에 처리할 수 있을까?

결론부터 말하자면 불가능하다. 기존 방식에서 두 가지 기능을 제공하려면 다음과 같은 식으로 구현해야 할 것이다 :

  1. 첫 번째로 클라이언트가 지도를 요청하면 서버로부터 데이터를 받아 사용자에게 지도 페이지(예. map.jsp)를 보여준다.
  2. 그 다음에 클라이언트가 맛집 리스트를 요청하면 서버로부터 데이터를 받아 맛집 리스트를 보여주기 위해서 다른 페이지(예. list.jsp)로 이동한다.

이런 방식을 동기식 처리 방법이라고 한다. 각 응답에 대한 별도의 뷰가 필요하며, 첫 번째 일이 끝난 후에야 그 다음 일이 처리될 수 있다. 만약 지도를 로딩하는 것이 시간이 오래 걸리는 일이라면, 맛집 리스트를 보고 싶은 사용자는 지도 로딩이 끝날 때까지 기다려야만 한다.


비동기식 처리방법

Ajax 비동기 처리를 이용하면 하나의 뷰에서 두 개의 요청을 동시에 처리할 수 있다.

Ajax를 사용하는 경우 하나의 페이지(예. main.jsp)에서 첫 번째로 지도 데이터를 요청하고, 첫 번째 요청이 완료되지 않아도 두 번째 요청으로 맛집 리스트를 요청할 수 있다.

첫 번째 요청과 두 번째 요청은 서로의 동작에 관여하지 않으므로 비동기 방식이라고 한다.


콜백 함수

비동기 통신에서 첫 번째 요청 이후 다른 요청을 하기 위해 콜백 함수를 사용한다. 자바스크립트에서 콜백이란 전달인자로 함수를 받는 함수를 말하는데, Ajax에서는 클라이언트가 서버로 요청 후 서버에서 응답한 데이터를 클라이언트에서 받아 처리하는 함수라고도 말할 수 있다.



Ajax 사용하기

XMLHttpRequest

XMLHttpRequest 객체는 Ajax에서 웹 브라우저가 서버와 데이터를 교환할 때 사용된다. 웹 브라우저가 백그라운드에서 계속해서 서버와 통신할 수 있는 것은 이 객체 덕분이다.

XMLHttpRequest 객체를 생성하는 방법은 두 가지가 있다 :

  1. XMLHttpRequest 객체를 이용한 방법
  2. ActiveXObject 객체를 이용한 방법

비동기식 통신 방식인 XMLHttp는 가장 처음으로 익스플로러 5 버전에서 ActiveXObject라는 객체를 사용하여 구현되었고, 그 후에 모질라와 사파리에서 XMLHttpRequest라는 이름으로 도입하여 널리 사용되기 시작했다.

초기에는 XMLHttpRequest 객체가 W3C 표준이 아니었기 때문에 웹 브라우저마다 구현상의 차이가 존재했으나, 현재는 XMLHttpRequest 객체가 W3C 표준으로도 제정되었고 모든 브라우저가 기본적으로 지원하고 있다.

따라서 이제는 브라우저와 관계 없이 다음과 같이 XMLHttpRequest를 생성하면 된다:

var httpRequest = new XMLHttpRequest();

요청

XMLHttpRequest 인스턴스의 메서드를 통해 요청을 보낼 수 있다. 다음은 GET과 POST 요청의 예시이다 :

// GET 방식으로 요청을 보내면서 데이터를 동시에 전달함.

httpRequest.open("GET", "/examples/media/request_ajax.php?city=Seoul&zipcode=06141", true);

httpRequest.send();
// POST 방식의 요청은 데이터를 Http 헤더에 포함시켜 전송함.

httpRequest.open("POST", "/examples/media/request_ajax.php", true);

httpRequest.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");

httpRequest.send("city=Seoul&zipcode=06141");

서버에 비동기식 요청을 보내기 위해서는 open() 메소드의 세 번째 인수로 true를 전달하면 된다. false를 전달하는 경우 동기식 요청이 되어 자바스크립트는 서버로부터 응답이 도착할 때까지 대기하게 된다.


응답

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

이 함수는 서버에서 응답이 도착할 때까지 readyState 프로퍼티 값의 변화에 따라 총 5번 호출된다. 이 프로퍼티를 이용하면 서버에 요청한 데이터가 존재하고, 서버로부터 응답이 도착하는 순간을 특정할 수 있다.

  • UNSET, OPENED, HEADERS_RECIEVED, LOADING, DONE

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

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

    document.getElementById("text").innerHTML = httpRequest.responseText;

}

요청에 대한 응답이 완료(DONE)되고 정상 응답(200)인 경우 응답으로 받은 데이터를 문자열로 idtext인 엘리먼트에 HTML에 삽입한다.


JQuery Ajax

Ajax를 이용하여 개발을 손쉽게 할 수 있도록 미리 여러 가지 기능을 포함해 놓은 개발 환경을 Ajax 프레임워크라고 한다. 제이쿼리는 많이 사용되는 Ajax 프레임워크 중 하나이다.

제이쿼리는 Ajax와 관련된 다양하고도 편리한 메소드를 많이 제공하고 있는데, 그 중 가장 핵심적인 메서드는 $.ajax() 이다.

$.ajax([옵션])
$.ajax(
type : “post” or “get,
url : “요청할 URL,
data : { 서버로 전송할 데이터},
dataType : “서버에서 전송받을 데이터형식”,
success : function(서버로부터 데이터 받기){
// 정상 요청, 응답시 처리
},
error : function(오류정보){
// 오류 발생시 처리
}
);


예시

Ajax를 사용하면 위와 같이 페이지 전체를 다시 로딩하지 않고도 화면을 전환할 수도 있고 서버에 요청을 보내 응답을 받아 처리할 수도 있다.


글 목록 요청

<script type="text/javascript">
        $(document).ready(function () {
            loadList();
        });

        function loadList() {
            //서버와 통신 : 게시판 리스트 가져오기
            $.ajax({
                url: "boardList.do",
                type: "get",
                dataType: "json",
                success: makeView,
                error: function () {
                    alert("error");
                }
            });
        }
</script>

사용자가 처음 사이트에 접속하면 main.jsp로 이동한다. 페이지가 로딩되면 loadList() 함수가 호출되어 제이쿼리 $.ajax()를 통해 서버에게 게시글 목록을 요청한다(@GetMapping boardList.do). 요청이 성공적으로 처리되는 경우(success) makeView 함수가 호출된다.


function makeView(data) { //콜백 함수 : 서버에서 응답으로 받은 데이터(data)를 처리하는 함수
    var listHtml = "<table class='table table-bordered'>"
    listHtml += "<tr>";
    listHtml += "<td>번호</td>";
    listHtml += "<td>제목</td>";
    listHtml += "<td>작성자</td>";
    listHtml += "<td>작성일</td>";
    listHtml += "<td>조회수</td>";
    listHtml += "</tr>";

    $.each(data, function (index, obj) {
        //...
    });

    listHtml += "<tr>";
    listHtml += "<td colspan='5'>";
    listHtml += "<button class='btn btn-primary btn-sm' onclick='goForm()'>글쓰기</button>";
    listHtml += "</td>";
    listHtml += "</tr>";

    listHtml += "</table>";
    $("#view").html(listHtml);  //view라는 id를 가진 div에 listHTML을 출력
}

makeView(data) 함수는 서버로부터 응답받은 데이터(data)를 받아 게시글 목록을 표시하는 HTML을 작성해 listHTML에 저장한다. 그리고 view라는 이름을 가진 엘리먼트에 이 HTML을 삽입한다.

이러한 동작을 통해 사용자가 처음 페이지(/controller)에 접속하면 게시글 목록을 볼 수 있게 되는 것이다.


뷰 - 두 개의 body

<div class="panel-body" id="view">Panel Content</div>
<div class="panel-body" id="wform" style="display: none">
    <form action="boardInsert.do" method="post"></form>
</div>

게시글 목록 뿐 아니라 게시글 등록 폼도 표시하기 위해서 main.jsp는 두 개의 HTML body를 가지고 있다.

하나는 처음 페이지가 로딩되었을 때 게시글 목록을 보여주는 view이다. 다른 하나는 게시글 입력 폼을 가지고 있는 wform이다. wform은 처음에 display: none 스타일을 가지고 있어서 표시되지 않는다.


function goForm() {
    $("#view").css("display", "none");    //숨기기
    $("#wform").css("display", "block");  //보이기
}
function goList() {
    $("#view").css("display", "block");   //보이기
    $("#wform").css("display", "none");   //숨기기
}

그러나 사용자가 글쓰기 버튼을 클릭하면 onclick='goForm()'이 동작하여 view 바디가 숨겨지고 wform 바디가 표시되게 된다. 반대로 글쓰기 폼에서 리스트 버튼을 클릭하면 wform 바디를 숨기고 view를 표시하는 goList() 함수가 호출되게 된다.


이러한 과정을 통해 한 페이지에서 글쓰기 목록과 글쓰기 화면을 전환할 수 있게 되었다.




🔗 References

post-custom-banner

0개의 댓글