Skip to content

11. HTML5 API


1. 키워드

  • Geolocation
  • Drag and Drop
  • Web Storage
  • Application Cache
  • Web Worker
  • Server Sent Events


2. Geolocation

  • Geolocation API는 사용자의 현재 위치 정보를 가져올 때 사용하는 자바스크립트 API이다.
  • 사용자의 위도 및 경도에 관한 정보는 자바스크립트를 이용해 웹 서버로 전송된다.


  • 이것을 이용하면 사용자의 위치를 지도에 표시하거나, 사용자 근처의 상점을 찾아주는 등의 위치기반 서비스를 할 수 있다.
  • 하지만 이러한 정보는 사용자의 사생활을 침해할 가능성이 높으므로, 사용자의 동의 없이는 사용할 수 없도록 하고 있다.


Note

  • 크롬 50.0 버전부터는 https와 같은 보안 프로토콜에서만 Geolocation API가 동작하도록 허용하고 있다.


1) getCurrentPosition() 메서드

  • getCurrentPosition() 메서드를 이용하면 사용자의 위치에 대한 위도와 경도값을 얻을 수 있다.
  • 이 메서드의 첫 번째 인수로는 가져온 사용자의 위치 정보를 출력하는 함수가 들어간다.


function findLocation() {
  if (navigator.geolocation) {
    navigator.geolocation.getCurrentPosition(showYourLocation);
  } else {
    loc.innerHTML =
      "이 문장은 사용자의 웹 브라우저가 Geolocation API를 지원하지 않을 때 나타납니다!";
  }
}


  • 이 메서드의 두 번째 인수로는 위치 정보에 관한 오류를 처리하는 함수가 들어간다.


function showErrorMsg(error) {
  switch (error.code) {
    case error.PERMISSION_DENIED:
      loc.innerHTML =
        "이 문장은 사용자가 Geolocation API의 사용 요청을 거부했을 때 나타납니다!";
      break;
    case error.POSITION_UNAVAILABLE:
      loc.innerHTML =
        "이 문장은 가져온 위치 정보를 사용할 수 없을 때 나타납니다!";
      break;
    case error.TIMEOUT:
      loc.innerHTML =
        "이 문장은 위치 정보를 가져오기 위한 요청이 허용 시간을 초과했을 때 나타납니다!";
      break;
    case error.UNKNOWN_ERROR:
      loc.innerHTML = "이 문장은 알 수 없는 오류가 발생했을 때 나타납니다!";
      break;
  }
}


  • 이처럼 가져온 사용자의 위치 정보를 구글 맵을 통해 표시할 수 있다.


function showYourLocation(position) {
  var userLat = position.coords.latitude;
  var userLng = position.coords.longitude;
  var imgUrl =
    "http://maps.googleapis.com/maps/api/staticmap?center=" +
    userLat +
    "," +
    userLng +
    "&zoom=15&size=500x400&sensor=false";

  document.getElementById("mapLocation").innerHTML =
    "<img src='" + imgUrl + "'>";
}


  • 위의 예제처럼 단순한 이미지로 표시하는 것이 아닌 구글 맵 스크립트를 이용한 연동도 가능하다.


function showYourLocation(position) {
  var userLat = position.coords.latitude;
  var userLng = position.coords.longitude;
  var userLocation = new google.maps.LatLng(userLat, userLng);

  loc = document.getElementById("mapLocation");
  loc.style.width = "500px";
  loc.style.height = "400px";

  var mapOptions = {
    center: userLocation,
    zoom: 15,
    mapTypeId: google.maps.MapTypeId.ROADMAP,
    mapTypeControl: false,
    navigationControlOptions: {
      style: google.maps.NavigationControlStyle.SMALL,
    },
  };
  var map = new google.maps.Map(loc, mapOptions);
  var marker = new google.maps.Marker({
    position: userLocation,
    map: map,
    title: "여기가 현재 위치입니다!",
  });
}


2) Geolocation API 메서드

메서드 설명
getCurrentPosition() 사용자의 현재 위치를 가져옴.
watchPosition() 사용자의 현재 위치를 가져오고 나서, 사용자의 움직임에 따라 지속적으로 위치 정보를 갱신함.
clearWatch() watchPosition() 메서드의 실행을 중지함.


3) getCurrentPosition() 메서드의 반환값

속성 반환값
coords.latitude 소수로 표현된 위도 값
coords.longitude 소수로 표현된 경도 값
coords.accuracy 위도 값과 경도 값의 정확도
coords.altitude 평균 해수면을 기준으로 하는 고도 값(해발)
coords.altitudeAccuracy 고도 값의 정확도
coords.heading 북쪽을 기준으로 현재 진행 방향에 대한 시계방향으로의 각도 값(˚)
coords.speed 초당 이동한 미터 수를 나타내는 속도 값(초속)
timestamp 위치 정보를 가져온 시간을 나타냄.


3. Drag and Drop

  • 드래그 앤 드롭 API는 웹 페이지 내의 요소를 사용자가 자유롭게 드래그할 수 있도록 설정해준다.
  • HTML5 이전에 이와 같은 기능을 구현하기 위해서는 엄청나게 많고 복잡한 스크립트를 작성해야 했다.
  • 하지만 HTML5에서는 드래그 앤 드롭 기능이 표준 권고안에 포함되어 간단하게 사용할 수 있게 되었다.
  • 현재 주요 웹 브라우저들은 모두 이 기능을 지원하며, 따라서 웹 페이지 내의 모든 요소는 드래그될 수 있다.


1) 드래그 앤 드롭 이벤트

  • 마우스로 객체(Object)를 드래그해서 놓을 때까지 여러 단계의 이벤트가 순차적으로 발생하게 된다.


  • 다음 표는 드래그 앤 드롭시 일어나는 이벤트를 순서대로 보여준다.


이벤트 설명
dragstart 사용자가 객체(Object)를 드래그하려고 시작할 때 발생함.
dragenter 마우스가 대상 객체의 위로 처음 진입할 때 발생함.
dragover 드래그하면서 마우스가 대상 객체의 위에 자리 잡고 있을 때 발생함.
drag 대상 객체를 드래그하면서 마우스를 움직일 때 발생함.
drop 드래그가 끝나서 드래그하던 객체를 놓는 장소에 위치한 객체에서 발생함.
dragleave 드래그가 끝나서 마우스가 대상 객체의 위에서 벗어날 때 발생함.
dragend 대상 객체를 드래그하다가 마우스 버튼을 놓는 순간 발생함.


2) DataTransfer 객체

  • 드래그 앤 드롭 이벤트를 위한 모든 이벤트 리스너 메서드(Event Listener Method)는 DataTransfer 객체를 반환합니다.
  • 이렇게 반환된 DataTransfer 객체는 드래그 앤 드롭 동작에 관한 정보를 가지고 있게 된다.


3) draggable 속성

  • 웹 페이지 내의 모든 요소는 draggable 속성을 사용하여 드래그될 수 있는 객체(Draggable Object)로 변환될 수 있다.


4) ondragstart 속성

  • 드래그될 수 있는 객체로 만든 후에는 ondragstart 속성을 통해 DataTransfer 객체의 setData() 메서드를 호출한다.
  • setData() 메서드는 드래그되는 대상 객체의 데이터(Data)와 타입(Data Type)을 설정한다.


5) ondragover 속성

  • ondragover 속성은 드래그되는 대상 객체가 어느 요소 위에 놓일 수 있는지를 설정한다.
  • 기본적으로 HTML 요소는 다른 요소의 위에 위치할 수 없다.
  • 따라서 다른 요소 위에 위치할 수 있도록 만들기 위해서는 놓일 장소에 있는 요소의 기본 동작을 막아야만 한다.
  • 이 작업을 event.preventDefault() 메서드를 호출하는 것만으로 간단히 설정할 수 있다.


6) ondrop 속성

  • 드래그하던 객체를 놓으면 drop 이벤트가 발생한다.
  • ondrop 속성을 이용하여 drop 이벤트에 대한 동작을 설정할 수 있다.


function dragEnter(ev) {
  ev.preventDefault();
}

function drag(ev) {
  ev.dataTransfer.setData("text", ev.target.id);
}

function drop(ev) {
  ev.preventDefault();
  var data = ev.dataTransfer.getData("text");
  ev.target.appendChild(document.getElementById(data));
}


4. Web Storage

  • 웹 스토리지 API는 기존 쿠키(Cookie)의 문제점을 극복하기 위해 웹 브라우저가 직접 데이터를 저장할 수 있게 해준다.


  • HTML5 이전에는 응용 프로그램이 데이터를 서버에게 요청할 때마다 매번 쿠키라는 곳에 그 정보를 저장한다.
  • 하지만 웹 스토리지는 사용자 측에서 좀 더 많은 양의 정보를 안전하게 저장할 수 있도록 해준다.
  • 웹 스토리지는 최소 5MB 이상의 많은 공간을 가지고 있으며, 이 정보는 절대 서버로 전송되지 않는다.


  • 이러한 웹 스토리지는 오리진(Origin)마다 단 하나씩만 존재한다.
  • 오리진이란 도메인(Domain)과 프로토콜(Protocol)의 한 쌍으로 이루어진 식별자이다.
  • 따라서 하나의 오리진에 속하는 모든 웹 페이지는 같은 데이터를 저장하며 또한 같은 데이터에 접근할 수 있다.


1) 웹 스토리지 지원 여부 확인

  • 웹 스토리지를 사용하기 전에, 우선 사용자의 웹 브라우저가 이를 지원하는지 안 하는지 확인해야 한다.


2) 웹 스토리지 객체

  • 웹 스토리지 API는 사용자가 데이터를 저장할 수 있도록 두 가지 객체를 제공한다.


1] sessionStorage 객체: 하나의 세션(Session)만을 위한 데이터를 저장하는 객체

2] localStorage 객체: 보관 기한이 없는 데이터를 저장할 수 있는 객체


(1) sessionStorage 객체

  • sessionStorage 객체는 하나의 세션만을 위한 데이터를 저장한다.
  • 따라서 사용자가 브라우저 탭이나 창을 닫으면 이 객체에 저장된 데이터는 사라진다.


function clickCounter() {
  if (typeof Storage !== "undefined") {
    if (sessionStorage.clickcount) {
      sessionStorage.clickcount = Number(sessionStorage.clickcount) + 1;
    } else {
      sessionStorage.clickcount = 1;
    }

    document.getElementById("counter").innerHTML =
      "카운터의 현재 횟수는 " + sessionStorage.clickcount + "입니다!";
  }
}


(2) localStorage 객체

  • localStorage 객체는 보관 기한이 없는 데이터를 저장한다.
  • 따라서 브라우저 탭이나 창이 닫히거나, 컴퓨터를 재부팅 해도 저장된 데이터는 없어지지 않는다.


function clickCounter() {
  if (typeof Storage !== "undefined") {
    if (localStorage.clickcount) {
      localStorage.clickcount = Number(localStorage.clickcount) + 1;
    } else {
      localStorage.clickcount = 1;
    }

    document.getElementById("counter").innerHTML =
      "카운터의 현재 횟수는 " + localStorage.clickcount + "입니다!";
  }
}


5. Application Cache

  • Application Cache API는 웹 응용 프로그램을 캐시(Cache)하여, 인터넷 접속 없이 사용자가 접근할 수 있게 해준다.
  • 따라서 Application Cache를 사용하면 웹 응용 프로그램의 오프라인 버전을 쉽게 만들 수 있다.


  • Application Cache를 사용해서 생기는 장점은 다음과 같다.


1] 오프라인 접속: 사용자가 웹 응용 프로그램을 오프라인(Off-line)으로도 사용할 수 있다.

2] 속도: 캐시된 자원은 빠르게 로드(Load)할 수 있다.

3] 서버의 부하 감소: 웹 브라우저는 서버의 자원에 변동이 있을 때만 자원을 갱신하면 된다.


1) Cache Mainfest 파일

  • Application Cache를 사용하기 위해서는 먼저 Cache Mainfest 파일을 작성해야 한다.
  • Cache Mainfest 파일은 웹 브라우저에 캐시해야 할 파일과 캐시하지 말아야 할 파일을 알려준다.


  • 이러한 Cache Mainfest 파일은 다음과 같이 세 개의 세션(Session)으로 이루어진다.


1] CACHE MAINFEST: 처음 다운로드한 이후에 계속 캐시할 파일들을 기록한다.

2] NETWORK: 서버와의 접속이 필요한 파일들을 기록하며, 이 파일들은 절대로 캐시되지 않는다.

3] FALLBACK: 파일에 접속할 수 없을 때에 대체할 파일들을 기록한다.


2) 캐시(Cache)의 갱신

  • 웹 브라우저는 다음과 같은 경우가 발생하면 캐시의 정보를 갱신하게 된다.


1] 사용자가 웹 브라우저의 캐시를 강제로 지웠을 경우

2] Application Cache가 프로그램 때문에 갱신됐을 경우

3] Cache Mainfest 파일이 수정됐을 경우


CACHE MAINFEST
# 2016-03-22 v1.0.1
test.html
test.css
test.js

NETWORK:
test.jpg

FALLBACK:
/ offline.html


  • 한 번 캐시되면 서버상의 파일을 수정해도, 웹 브라우저는 사용자 측에 캐시 되어 있는 버전의 파일만을 보여준다.
  • 따라서 서버상의 파일을 수정한 후에는 반드시 웹 브라우저가 캐시를 갱신하도록 만들어야 한다.


  • 이때 가장 많이 사용되는 방법이 Cache Mainfest 파일 내의 주석 부분을 수정하는 것이다.
  • 일반적으로 갱신 날짜 및 버전 정보를 주석으로 표시하고, 이 부분을 수정하여 웹 브라우저가 캐시를 갱신하도록 유도한다.


6. Web Worker

  • 웹 페이지에서 스크립트가 실행되면, 해당 웹 페이지는 실행 중인 스크립트가 종료될 때까지 응답 불가 상태가 된다.
  • Web Worker는 스크립트가 웹 페이지의 성능에 영향을 미치지 않도록 백그라운드에서 동작하게 해주는 자바스크립트이다.


  • 즉, Web Worker는 스크립트의 다중 스레드(Multi-thread)를 지원한다.
  • 따라서 사용자가 웹 페이지를 이용하면서도, 동시에 시간이 오래 걸리는 자바스크립트 작업도 병행할 수 있도록 해준다.


1) Web Worker 지원 여부 확인

  • Web Worker를 사용하기 전에, 우선 사용자의 웹 브라우저가 이를 지원하는지 안 하는지 확인해야 한다.


if (typeof(Worker) !== "undefined") {
    // web worker를 위한 코드 부분 }
else {
    // web worker를 지원하지 않는 브라우저를 위한 안내 부분
}


2) Web Worker 파일 생성

  • Web Worker의 동작을 확인하기 위해 소수를 찾는 외부 자바스크립트 파일을 만든다.


var n = 1;

search: while (true) {
  n += 1;

  for (var i = 2; i <= Math.sqrt(n); i += 1) if (n % i == 0) continue search;

  postMessage(n);
}


  • 위의 예제에서 postMessage() 메서드는 HTML 문서에 결과를 전달하기 위해 사용한다.


3) Web Worker 객체 생성

  • 위에서 만든 Web Worker 파일을 불러올 HTML 파일을 만든다.


if (typeof webworker == "undefined") {
  webworker = new Worker("/examples/web_worker.js");
}


  • 위의 예제는 Web Worker 파일이 존재하지 않으면, 새로운 Web Worker 객체를 만들어 준다.


4) Worker 객체와의 연결

  • onmessage 이벤트 리스너(Event Listener)를 통해 Web Worker 파일과 메시지를 주고받을 수 있다.


webworker.onmessage = function (event) {
  document.getElementById("result").innerHTML = event.data;
};


  • 위의 예제에서 Web Worker 파일이 메시지를 보내면 해당 이벤트 리스너가 실행된다.
  • 이 때 Web Worker 파일이 보낸 정보는 event.data에 저장된다.


5) Web Worker 객체의 실행 종료

  • Web Worker 객체는 생성되고 나서 종료될 때까지 계속해서 메시지를 받을 준비를 한다.
  • 따라서 웹 브라우저나 컴퓨터의 자원을 돌려주기 위해서는 terminate() 메서드를 사용하여 Web Worker를 반드시 종료해줘야 한다.


6) Web Worker 객체의 재사용

  • Web Worker 객체가 종료된 후에는 Web Worker의 값을 undefined로 설정해야만 Web Worker 객체를 재사용할 수 있다.


webworker = undefined;


7) Web Worker 예제

  • 다음 예제는 앞에서 살펴본 Web Worker의 동작을 하나의 예제로 보여주는 예제이다.


var webworker;

function startWorker() {
  if (typeof Worker !== "undefined") {
    if (typeof webworker == "undefined") {
      webworker = new Worker("/examples/web_worker.js");
    }

    webworker.onmessage = function (event) {
      document.getElementById("result").innerHTML = event.data;
    };
  }
}

function stopWorker() {
  webworker.terminate();
  webworker = undefined;
}


7. Server Sent Events

  • Server Sent Events API는 웹 페이지가 서버로부터 갱신된 정보를 자동으로 받을 수 있도록 설정한다.


1) Server Sent Events 지원 여부 확인

  • Server Sent Events를 사용하기 전에, 우선 사용자의 웹 브라우저가 이를 지원하는지 안 하는지 확인해야 한다.


if (typeof EventSource !== "undefined") {
  // server sent events를 위한 코드 부분
} else {
  // server sent events를 지원하지 않는 브라우저를 위한 안내 부분
}


  • 다음 예제는 Server Sent Events를 이용해 5초마다 웹 페이지를 갱신하는 예제이다.


if (typeof EventSource !== "undefined") {
  var source = new EventSource("/examples/media/sse.php");

  source.onmessage = function (event) {
    document.getElementById("result").innerHTML += event.data + "<br>";
  };
}


  • 위의 예제에서 사용한 서버 측 PHP 파일인 sse.php 파일은 다음과 같다.


<?php
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');

$time = date('r');

echo "data: The server time is: {$time}\n\n";

flush();
?>

References