웹브라우저 JavaScript

Ajax

Ajax

웹브라우저는 대단히 정적인 시스템이었다. 내용이 바뀌면 페이지 새로고침을 해서 내용을 새롭게 변경해야 했다. 이것은 웹이 전자 문서를 염두에 두고 고안된 시스템이기 때문에 당연하게 생각 되었다. 

그러다 Ajax 개념이 도입되면서 모든 것이 바뀌었다. Ajax는 웹브라우저와 웹서버가 내부적으로 데이터 통신을 하게 된다. 그리고 변경된 결과를 웹페이지에 프로그래밍적으로 반영함으로써 웹페이지의 로딩 없이 서비스를 사용할 수 있게 한다. 

Ajax는 Asynchronous JavaScript and XML의 약자다. 한국어로는 비동기적 자바스크립트와 XML 정도로 직역할 수 있는데 자바스크립트를 이용해서 비동기적으로 서버와 브라우저가 데이터를 주고 받는 방식을 의미한다. 이 때 사용하는 API가 XMLHttpRequest이다. 그렇다고 꼭 XML을 사용해서 통신해야 하는 것은 아니다. 사실 XML 보다는 JSON을 더 많이 사용한다.

IE5,6 에서는 XMLHttpRequest 객체 대신 ActiveXObject("Msxml2.XMLHTTP.6.0")을 사용해야 한다. 여기서는 다루지 않는다.

XMLHttpRequest

이 때 사용하는 API가 XMLHttpRequest이다. 다음 예제를 보자.

본 예제를 실행하기 위해서는 서버 환경이 구축 되어 있어야 한다. 서버 구축에 대한 설명은 우리 수업의 범위를 넘어서기 때문에 여기서는 언급하지 않는다. 하지만 학습하는데는 큰 문제가 없다. 중요한 주제이기 때문에 꼭 학습하기 바란다.

time.php

아래 코드는 현재 시간을 출력한다.

<?php
$d1 = new DateTime;
$d1->setTimezone(new DateTimezone("asia/seoul"));
echo $d1->format('H:i:s');
?>

demo1.html

아래 코드는 time.php에 접속해서 현재 시간은 페이지에 표시한다.

<p>time : <span id="time"></span></p>
<input type="button" id="execute" value="execute" />
<script>
document.querySelector('input').addEventListener('click', function(event){
	var xhr = new XMLHttpRequest();
	xhr.open('GET', './time.php');
	xhr.onreadystatechange = function(){
		if(xhr.readyState === 4 && xhr.status === 200){
			document.querySelector('#time').innerHTML = xhr.responseText;
		}
	}
	xhr.send();	
});	
</script>	

코드를 분석해보자.

var xhr = new XMLHttpRequest();

XMLHttpRequest 객체를 생성한다.

xhr.open('GET', './time.php');

접속하려는 대상을 지정한다. 첫번째 인자는 form 태그의 method에 대응하는 것으로 GET/POST 방식을 주로 사용한다. 두번째 인자는 접속하고자 하는 서버쪽 리소스의 주소로 form 태그의 action에 해당한다.

xhr.onreadystatechange = function(){
    if(xhr.readyState === 4 && xhr.status === 200){
    	document.querySelector('#time').innerHTML = xhr.responseText;
    }
}

onreadystatechange 이벤트는 서버와의 통신이 끝났을 때 호출되는 이벤트이다. readyState는 통신의 현재 상태를 알려준다. 4는 통신이 완료되었음을 의미한다. status는 HTTP 통신의 결과를 의미하는데 200은 통신이 성공했음을 의미한다. responseText 프로퍼티는 서버에서 전송한 데이터를 담고 있다. 이것을 id가 time 엘리먼트의 하위로 삽입한다. 이를 통해서 현재 서버에서 가져온 현재시간을 페이지 리로딩 없이 가져올 수 있다.

POST 방식

post 방식으로 데이터를 전송하는 방법을 알아보자.

GET과 POST 방식에 대한 자세한 내용은 생활코딩 HTML 수업을 참고하자.

demo2.html

아래 예제는 시간대와 시간의 출력 형식을 지정하는 예제다. 

<p>time : <span id="time"></span></p>
<select id="timezone">
	<option value="Asia/Seoul">asia/seoul</option>
	<option value="America/New_York">America/New_York</option>
</select>
<select id="format">
	<option value="Y-m-d H:i:s">Y-m-d H:i:s</option>
	<option value="Y-m-d">Y-m-d</option>
</select>
<input type="button" id="execute" value="execute" />
<script>
document.querySelector('input').addEventListener('click', function(event){
	var xhr = new XMLHttpRequest();
	xhr.open('POST', './time2.php');
	xhr.onreadystatechange = function(){
		document.querySelector('#time').innerHTML = xhr.responseText;
	}
	xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
    var data = '';
	data += 'timezone='+document.getElementById('timezone').value;
	data += '&format='+document.getElementById('format').value;
	xhr.send(data);	
});
</script>	

중요한 부분을 살펴보자. 데이터 전송방법을 GET에서 POST로 변경했다. 

xhr.open('POST', './time2.php');

서버로 전송할 데이터 타입의 형식(MIME)을 지정한다. 

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

서버로 전송할 데이터를 형식에 맞게 만든다. 이름=값&이름=값... 의 형식을 지켜야 한다. 

var data = '';
data += 'timezone='+document.getElementById('timezone').value;
data += '&format='+document.getElementById('format').value;

send 메소드의 인자로 전송할 데이터를 전달한다.

xhr.send(data);	

time2.php

아래는 Ajax를 이용해서 전송한 데이터를 받아서 현재 시간을 출력해주는 서버쪽 구현이다. 

<?php
$d1 = new DateTime;
$d1->setTimezone(new DateTimezone($_POST['timezone']));
echo $d1->format($_POST['format']);
?>

댓글

댓글 본문
  1. labis98
    20210915 좋은 강의 감사합니다.
  2. 드림보이
    수강완료했습니다...
  3. psmqdt
    서버구축이라는 것이 자신의 컴퓨터에 Bitnami 를 설치하면 되는 것이고, 앞의 강의들에서 이미 이를 설치한 상태인데, 아마 Bitnami 설치 이전에 하신 강의 같습니다.
  4. 박병진
    2020.12.12 오늘은 여기까지 하겠습니다. 주말 잘보내세요 이고잉 프로그래머 선생님
  5. 싸알
    완료,,
  6. 정승옥
    완료
  7. 한강
    말로만 들어본 Ajax ,감사합니다~~^^!
    200716
  8. 굼벵이
    완료
  9. HTML 수업의 GET/POST에 대한 링크입니닷.

    https://opentutorials.org....../14
    대화보기
    • JuicyFresh
      감사합니다.
      HTML 수업 링크는 없어졌네요 ㅠ.ㅠ
    • 태우
      감사합니다!
    • ㅎㅎ
      감사합니당~~
    • 박인호
      1-3
      수강완료.
    • Byungsoo Kim
      감사합니다.
    • kkuk,kkouk
      감사합니다.^^
    • 브라우저 보안정책상 원칙적으로는 안되게 되어있으나 CORS라는 것을 찾아보시면 방법이 있다고 합니다.
      대화보기
      • toxic
        위 예제는 다른 도메인에서는 사용 불가능 한가요?

        예를 들어 외부서버로 요청하여
        localhost로 데이터를 받으려 하는데 이 경우 적용되는지 궁금합니다~
      • illliilllliillliii
        혹시 이 수업처럼 PHP가 아니라 Python, NodeJS를 통해서 AJAX, JSON 네트워크를 할 수 있는 건 어떻게 검색해야 하는지 아는 분 계실까요 ㅠㅠ
        저는 Python web AJAX, Python network 등등 으로 검색했는데 원하는 걸 찾지 못하겠어요 ㅠㅠ
        만약 아는 분 계시다면 검색어 제안이라도 부탁드립니다 ㅠㅠ
      • crable
        감사합니다.
      • 삐리빠라뽕
        function(event)에 들어오는 이벤트는 click 이벤트에 바인드 되어 있는 함수에서 받는 이벤트 이며,
        time.php에서 리턴하는 echo $d1->format('H:i:s'); 데이터는
        XMLHttpRequest 객체인 xhr에 바인드 되어 있는 onreadystatechange 이벤트 발생 시에
        xhr.responseText; 로 받게 되어 있는것 같습니다.
        대화보기
        • 베리스트롱
          Ajax (2/3)
          강의에 대한 질문이 있습니다 ^ ^

          function(event)

          함수에 들어오는 event인자가

          1. time.php에서 출력한
          echo $d1->format('H:i:s');

          값을 넘겨 받는 것 인가요?

          아니면
          2. 'click'
          이벤트를 받아서 함수를 실행하라는 명령이 들어 오는 거라고 보면 되나요?

          항상 모르는게 있으면 돌아 돌아 생활코딩으로 돌아오게 되네요 ㅎ
          감사드립니다 ^ ^
        • 감사합니다
          대화보기
          • 항가
            time.php 에서 'setTimezone' 오류 나오시는분들은
            asia/seoul -> Asia/Seoul 로 바꿔보시기 바랍니다.
            (PHP 에서 대소문자를 구분하더군요..)
          • 신입1
            감사합니다
          • chobo
            저는 위의 코드 그대로 따라했는데, time.php 하고 time2.php 파일을 크롬으로 열어보니, 그 내부의 코드가 출력되고 시간이 출력이 안되네요? 어떻게 해야하나요?
          • Zone이 아닌 zone입니다
            대화보기
            • HelloJS
              많이 늦었지만, 그래서 이미 해결을 하셨을 수도 있지만 ^^; 저도 같은 에러 메시지가 출력이 되어서, 다시 코드를 보니, data += 'timezone' + 에 'timezome' 이라고 오타를 냈더군요. 그래서 오타를 수정하고 나니 정상적으로 작동이 됩니다. ㅎㅎ 만약 다른 분들도 해당 메시지가 출력이 되면 오타는 없는지 다시 한 번 살펴보세요~
              대화보기
              • ckocko
                나중에 다시 와야겠습니다 어렵네요ㅠㅠ
              • 독병아리
                상세한 설명 감사드립니다. ^^
              • 카구카구
                == 는 일반적인 equal 연산자입니다. (true, false 가 결과)
                ===는 엄밀한 의미로 equal을 연산하는 연산자 입니다. (같은 기능이지만 좀 강한 느낌)
                대화보기
                • ddddss
                  Fatal error: Uncaught exception 'Exception' with message 'DateTimeZone::__construct(): Unknown or bad timezone ()' in C:\Bitnami\wampstack-5.6.27-0\apache2\htdocs\time2.php:4 Stack trace: #0 C:\Bitnami\wampstack-5.6.27-0\apache2\htdocs\time2.php(4): DateTimeZone->__construct('') #1 {main} thrown in C:\Bitnami\wampstack-5.6.27-0\apache2\htdocs\time2.php on line 4

                  서버안에서 실행시켜 보니 php가 말썽이네요.. 위에는 에러 내용입니다.. 어떻게 해야할까요 구글링해도 만족할 만한 답을 못찾겠어서 댓글 달았습니다.
                • JustStudy
                  2016.07.16 토
                  고맙습니다 3.
                • https://opentutorials.org......722

                  이 강의를 참고해주세요~
                  대화보기
                  • 이수현
                    질문있습니다!! ===은 무엇인가요? ==와 같은건가요?
                  • JustStudy
                    2016.07.03 일
                    고맙습니다 2.
                  • xhr.status === 200에서 실행이 안되는데 무슨 이유들이 있을까요?
                  • 온달장군
                    강좌 잘보고 갑니다. 감사합니다.
                  • 이주환
                    2016. 04. 28
                    중요한 Ajax내용 잘보고갑니다.
                  • JustStudy
                    고맙습니다
                  • delayjang
                    지금 POST 돌아가는 상황이 이런게 맞나요?
                    1. var xhr = new XMLHttpRequest() -> 객체 생성
                    2. xhr.open('POST', './time2.php') -> 접속할 URI 기입
                    3. xhr.send(data) -> 요청할 데이터 내 웹서버로 전달
                    4. xhr.responseText -> time2.php에서 요청받은 데이터 전송
                    그러면 이제 화면에 뿌려지는거 같은데...
                    왜 send가 먼저 실행되는데 코드 기입할때 가장 마지막에 쓰는건가요???
                    post 찾아보니깐 다들 send를 나중에 쓰더라구요.....실행은 먼저 되는거 같은데....
                    이유가 있나요???
                  • nkbak@naver.com
                    server 설치했더니
                    신통하게 되네
                  • SK Kim
                    잠시 난이도 급상승, 개념만 이해하고 넘어갑니다.
                  • Harryki007
                    php time1.php 랑 time2.php안되시는 분들은 <?php 다음줄에 date_default_timezone_set('UTC'); 넣고 해보세요!
                  • WayneKing
                    GO~GO~
                  • 씨뽈뽈
                    저랑 똑같네요 저희같이 직업이 아닌이상 그건 힘들것 같구요 규모가 있는게 결국 혼자만드는게아니라 협업으로 하는거니까요 저두 VBA로 시작해서 사무자동화에 뿌듯함을 느끼고 C++및 윈도우프로그래밍쪽으로 했었죠
                    지금은 C++로 vba엑셀 다루듯 엑셀 제어도 하고 vb스크립트도하면서 잘 갖고 놀고있고 실무에서도 말씀하셨듯이 말그대로 맹활약이고 다들 신기해 하죠. C언어로 만들었다고하니까 무슨 호박씨로 엑셀을 하냐고 그러고 엑셀로 브라우저 띄우면 무슨 이상한 짓이냐면서 정말 궁금해들 하더군요 ㅎㅎ 문과생 일반인 사이에서 저희 같은 사람들은 반쯤 영웅이죠 ㅋㅋ 그 맛에 사실하기도 하구요(물론 실제로는 아마추어도 안되겠지만 ㅋㅋ)
                    저희같이 먹고살게 아니라 취미로 할거면 자바스크립트, VBA, python은 탁월한 선택이신거 같습니다. java는 협동용 먹고살기용이라...취직할거아니면 굳이... 프로그램 규모에 집착할 필요가 있을까요.
                    다른싸이트를 참고하시기보단 그냥 혼자 블로그질 하며 만족하며 알고리즘이나, 모듈같은게 생각 날때마다 외로운 포스팅을 하는게 좋다고 봅니다. 코딩이란게 취미와 취업의 경로가 나름 명확하다고 생각합니다 저는..
                    보통 취업위주로 다루다보니 취미인분들도 거기에 같이 휩쓸려서 엉뚱한 삽질하고 있는 경우도 많죠.
                    엄격한 프로토콜과 나름 규칙이있는(협업해야하므로, 취업할거아니면 그규칙에 크게 목멜 필요가 없잔아요?)
                    컴파일java나 c++같은 언어 보다는 취미로 할거면 좀 자유분방한 스크립트 언어 파이썬 자바스크립트 같은게 좋다고 생각합니다.
                    그런 의미에서 생활코딩은 딱저희같은 사람들이 오기에 찮은곳인거 같습니다. 효도코딩과 같이 꼭 직업이 아니더라도 사람들을 이롭게 할수 있는데 말이죠 ㅋㅋ 굳이 더 급하시다면 유투브에서 영어로된거 수두룩합니다. 코딩을 자발적으로 하실 정도로 나이가먹고 머리가 굵어지다보면 영어공포증 그런것도 없습니다. 어차피여기서 한번 듣고 내용을 아는 상태에서 듣는거니까요. 님이 가려운 부분을 긁어주는 그런 강의들이 꽤나 많습니다.
                    대화보기
                    • egoing
                      캠타시아라는 스크린캐스트 도구의 드로잉 기능입니다.
                      epic pen이라는 도구도 찾아보시면 도움이 될 것 같습니다.
                      대화보기
                      • 조조
                        좋은 강의 항상 감사합니다.

                        강의 중 사용하시는 "펜, 도형 등" 툴 이름이 무엇인지 궁금합니다~
                      • 2015-11-13 금요일
                        2번째 동영상 6분정도에 나온 내용 중에서요.

                        xhr.open('GET', './time.php');

                        주소를 나타낼때 ./를 적어야 하나요? 다른 디렉토리에 있으면 ../로 밖으로 나가서 찾아가는것은 아는데...
                        같은 디렉토리에 있으면 바로 파일명 적으면 되지 않나요?
                      • 코딩!
                        감사합니다. 반복해서 봐야할 것 같습니다 ㅎㅎ
                      • 행인
                        해당 함수는 콜백함수이므로 리턴해서 받을 수는 없습니다. 따라서 리턴할것이 아니라 외부에 변수를 선언해서 받으셔야 할 것입니다.
                        단, respTxt를 사용하는 곳에서는 반드시 콜백이 호출된 이후에 사용되어야 합니다.
                        var respTxt;
                        xhr.onreadystatechange = function(){
                        if(xhr.readyState === 4 && xhr.status === 200){
                        respTxt = xhr.responseText;
                        }
                        }
                        대화보기
                        버전 관리
                        egoing
                        현재 버전
                        선택 버전
                        graphittie 자세히 보기