웹브라우저 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. 카구카구
    == 는 일반적인 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;
            }
            }
            대화보기
            • will
              으음.. 여태까지중 가장 어렵네요
            • quki
              이고잉님 안녕하세요~
              질문이 있습니다.
              1.
              POST방식에서는 GET방식과는 다르게
              xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); 와 같이
              데이터 타입형식을 지정해주지않습니까.
              이는 POST방식의 특성상 많은양(?)의 데이터를 효과적으로 처리하기위해 일련의 규약이 있다고 보면되는지요?
              HTML의 form방식 '처럼' 이라는 말이 이해가 잘 되질않네요ㅠ

              2.
              그리고 1번 질문에서 언급했듯이xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); 가 HTML의 form과 같이 전송하는 것이라고 하셨는데
              form element는 내부 정보를 서버에 전송한다고 이전 강의에서 배웠습니다.
              이렇게 Ajax를 사용하는 것과 HTML form의 event로 처리하는 것의 차이는 서버와 통신하는 과정이 페이지가 리로드되고 안되고의 차이가 맞나요?
              php문법중에 header('Location : http://....');과 같이 Redirection의 과정이 Ajax에서는 필요가 없다는 말이 맞나요?

              form태그의 개념이 다소 모호해서 질문이 많이 번잡한것같아 죄송합니다.

              생활코딩을 통해 코딩뿐 만 아니라 여러가지를 얻어가는 것 같아 항상 너무 감사합니다.
              이고잉님 좋은하루되세요^^
            • Soori
              안녕하세요, 처음 인사 드리네요. 이렇게 좋은 강의를 올려주셔서 언제나 감사합니다. 저는 개발자는 아니구요, 취미로 코딩을 공부하고 있습니다. 개인적으로 동영상 강의 보다는 책을 보며 공부하는 것을 좋아하는데 이고잉님의 강의는 책을 뛰어 넘는 명강의이십니다. 웹 부분은 양도 많고 잡다한 것이 많아서 어디서 부터 봐야 할지 감이 잡히지 않았는데 이렇게 핵심을 콕콕 집어 주셔서 공부하는데 수월하였습니다. 개인적으로 공부하려 했다가 사실 포기했었거든요... (제가 외우는 걸 못해서 HTML 태그들만 보면 머리가 혼수상태가 되는 바람에...ㅠㅠ) 자바스크립트 공부하면서 태그에도 익숙해지고, 이제 마음 놓고 CSS 공부도 하고 PHP도 공부해서 저만의 웹페이지를 만들고 싶습니다.ㅎ 이 부분 부터는 갑자기 어려워져서ㅠㅠ PHP공부하고 나중에 올게요.ㅠ
              아, 그리고 질문이 있는데요.. 제가 JAVA, Python, VBA 기본적인 책 한권씩은 보았는데, (정말) 간단한 프로그램만 만들줄 알고 큰 프로그램 (안에 보면 많은 파일들이 유기적으로 엮여 있는)은 어떻게 만들어야 할지 모르겠습니다. exe는 또 어떻게 만드는 거며...ㅠㅠ 근처에 있는 소스 코드 보려고 해도 다 깨지고.. 일부러 그런건지...ㅠㅠ 결국 가장 만만한 VBA만 맹활약 중입니다..(직장생활에 깨알같이 필요하더군요.) 중간 규모의 프로그램은 어떻게 만드는 건가요? 그걸 알려면 어떤 책을 보아야 할지,, 어디 사이트를 참고해야 할지... 알려 주시면 너무너무 감사할 것 같습니다!
            • 서당개
              이고잉님 안녕하세요. 좋은 강의 무료로 너무 잘 듣고 있습니다.
              한가지 질문이 있는데요. 위의 demo1.html 예제에서 9번째 줄의 xhr.responseText를 함수의 리턴 값으로 해서 바깥으로 빼낼 수 없는지요? 다시 말해 이것을 객체로 반환한 후에 프로그램의 다른 곳에서도 쓰고자 함 입니다. 아래와 비슷하게 변경해 보니까 안되더라구요. 감사합니다.

              xhr.onreadystatechange = function(){
              if(xhr.readyState === 4 && xhr.status === 200){
              return xhr.responseText;
              }
              }
            • 이우연
              전 갠적으로 강의보고 책보는데 너무 좋네요
              강의만 보고 자바스크립트를 마스터 하신다는건 좀 무리이신듯 합니다.
              댓글중에 그런 댓글들이 많네요.
            • 자바로 설명해주시는건 없나요??
              Php는 모르는데... ㅜㅜ
            • egoing
              아래 부분은 서버와 통신이 성공했는지를 파악하는 부분입니다.
              이 부분이 없으면 성공 여부를 체크할 수 없습니다.
              하지만 일단 진도도 중요하니까 여기서 머물지 마시고 한바퀴 완주하세요~
              if(xhr.readyState === 4 && xhr.status === 200){
              대화보기
              • ShotgunBlues
                post예제를 get방식으로 보낼 때, 요렇게 하니까 성공 ㅜㅜ(3시간 해멨음 ㅜㅜ)
                document.querySelector('input').addEventListener('click', function(e) {
                var xhr = new XMLHttpRequest();
                var data = '';
                data += "?timezone=" + document.querySelector('#timezone').value;
                data += "&format=" + document.querySelector('#format').value;
                xhr.open('get', 'php/time3.php'+data); // 혹시나 하고 했는데 됐음 ㅜ.ㅜ 감동이...
                xhr.onreadystatechange = function(e) {
                //if(xhr.readyState === 4 && xhr.status === 200){
                document.querySelector('#time').innerHTML = xhr.responseText;
                }
                //}
                //xhr.setRequestHeader('content-type', 'application/x-www-form-urlencoded');
                xhr.send();
                });
                위에서 주석처리 된 코드는 없어도 잘 되더라구요. 근데 없어도 되는 건가요? 질문이 많아 죄송해요 ^^;
              • ShotgunBlues
                ajax과 form을 비교해야 하는군요. 빠른 답변 고맙습니다.^^
                대화보기
                • egoing
                  음 비교 대상을 바꿔야 합니다. ajax와 form을 비교하셔야 해요
                  대화보기
                  • ShotgunBlues
                    헷갈리는게 있는데요. php의 통신 방법과의 차이는 php는 form태그로만 통신하는 반면, js의 ajax를 이용하면 form태그를 쓰지 않고도 통신할 수 있다. 뭐 그런 차인가요?
                  • 나그네
                    잘 봤어요!
                    감사합니다^^
                  • 환글
                    좋은 강의 고맙습니다. Ajax 가 이런 거였군요^^
                  • egoing
                    맞습니다. 인자를 생략하는 경우는 true가 됩니다. 비동기방식은 사용하는 경우가 거의 없기 때문에 부러 수업에서는 제외시켰습니다.
                    대화보기
                    • somdari
                      좋은 수업 감사합니다..
                      한 가지 궁금한 점은 xhr.open할때 인자로 2개만 주셨는데.. 어떤 책에서 보니까 세번째 인자가 있고 이 인자가 true 이면 요청이 비동기화 되고 false 이면 동기화 된다고 되있던데요.. 세번째 인자는 생략 가능하고 생략 하면 디폴트 인자로 true가 설정되어 요청이 비동기화 되는 것인지요? 즉 아래와 같이 세번째 인자를 쓰지 않아도 되는건지요..
                      xhr.open('POST', './time2.php', true);
                    버전 관리
                    egoing
                    현재 버전
                    선택 버전
                    graphittie 자세히 보기