Skip to content

Instantly share code, notes, and snippets.

@stzhyegeun
Created February 6, 2018 01:53
Show Gist options
  • Save stzhyegeun/f65d9eb4a1f45050627f02d1af9345b1 to your computer and use it in GitHub Desktop.
Save stzhyegeun/f65d9eb4a1f45050627f02d1af9345b1 to your computer and use it in GitHub Desktop.

κ°œμš”

HTML5λŠ” 정보λ₯Ό λ§ν¬ν•΄μ„œ 보여주기 μœ„ν•œ νƒœκ·Έ 문법 이외에 μžλ°”μŠ€ν¬λ¦½νŠΈλ‘œ λ™μž‘ν•˜λŠ” API듀을 ν¬ν•¨ν•˜μ—¬ μ›Ή 자체의 κΈ°λŠ₯을 ν™•μž₯ν•˜μ˜€λ‹€. μΆ”κ°€λœ API듀을 μ‚΄νŽ΄λ³΄λ©΄ 마치 웹을 λͺ¨λ°”일 μ•±μ²˜λŸΌ λ§Œλ“€κ³ μž ν•˜λŠ” κ²ƒμœΌλ‘œ 보인닀.

HTML5 APIλŠ” λ‹€μŒκ³Ό κ°™λ‹€.

  • Video, Audio
  • Canvas
  • Form
  • Drag & Drop
  • Geo Location
  • Web Storage
  • IndexedDB
  • File
  • Communication
  • Web Worker

ν˜„μž¬ HTML5 κ²Œμž„μ„ λ§Œλ“œλŠ” 데 ν™œμš©ν•˜κ³  μžˆλŠ” Phaser 엔진은 λ‚΄λΆ€μ λ‘œ Audio와 Canvas κΈ°λŠ₯을 μ‚¬μš©ν•˜κ³  μžˆλ‹€.

Video

κ°œμš”

μ›Ή νŽ˜μ΄μ§€μ—μ„œ λΉ„λ””μ˜€λ₯Ό μž¬μƒν•˜λŠ” κΈ°λŠ₯

μ‚¬μš© μ˜ˆμ‹œ

<video src="../video/big_buck_bunny.webm"
    width="640" height="360"
    controls="controls"
    loop="loop"
    autoplay="autoplay"
    poster="../images/virus.png"
    preload="auto">
    λ‹Ήμ‹ μ˜ λΈŒλΌμš°μ €λŠ” HTML5의 video νƒœκ·Έλ₯Ό μ§€μ›ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.
</video>

ν˜„μž¬ HTML5의 video νƒœκ·ΈλŠ” ν‘œμ€€ν™”λœ 코덱이 μ—†λ‹€. MP4λŠ” λͺ¨λ“  λΈŒλΌμš°μ €μ—μ„œ μ§€μ›λ˜κ³  WebMκ³Ό OggλŠ” μ‚¬νŒŒλ¦¬, IEμ—μ„œλŠ” μ§€μ›λ˜μ§€ μ•ŠλŠ”λ‹€. 코덱 문제λ₯Ό ν•΄κ²°ν•˜κΈ° μœ„ν•΄μ„œλŠ” video νƒœκ·Έ μ•ˆμ— λ‹€λ₯Έ 코덱을 μ‚¬μš©ν•΄μ„œ μΈμ½”λ”©ν•œ srcλ₯Ό μΆ”κ°€ν•˜λ©΄ λœλ‹€. 그러면 μžλ™μœΌλ‘œ λΈŒλΌμš°μ €μ—μ„œ μž¬μƒν•  수 μžˆλŠ” srcλ₯Ό μ„ νƒν•΄μ„œ μž¬μƒν•œλ‹€.

video νƒœκ·ΈλŠ” HTMLMediaElement APIλ₯Ό μ‚¬μš©ν•΄μ„œ μ»¨νŠΈλ‘€ν•  수 μžˆλ‹€. 이 APIλ₯Ό 톡해 λΉ„λ””μ˜€ μž¬μƒμ„ 컨트둀 ν•˜κ±°λ‚˜, λΉ„λ””μ˜€ ν”Œλ ˆμ΄μ–΄μ˜ UIλ₯Ό 직접 λ§Œλ“€ μˆ˜λ„ μžˆλ‹€.

κ²Œμž„μ—μ„œμ˜ ν™œμš©

μ˜ˆμ „ μ›Ή κ²Œμž„μ˜ 경우 μ˜€ν”„λ‹μ΄λ‚˜ μ—”λ”© μ˜μƒμ„ Youtubeλ₯Ό μ΄μš©ν•΄ μž¬μƒμƒˆν‚€λŠ” κ²½μš°κ°€ μ’…μ’… μžˆμ—ˆλ‹€. λ‹€μ΄λ…Έλ³Όμ¦ˆμ—μ„œλ„ 유튜브λ₯Ό μ΄μš©ν•œ μ˜μƒ μ‚½μž…μ„ μ‹œλ„ν–ˆμ—ˆμ§€λ§Œ Facebook의 μ •μ±…μœΌλ‘œ μ‹€νŒ¨ν–ˆλ‹€. (iframe μ‚¬μš© λΆˆκ°€) λ§Œμ•½ video νƒœκ·Έλ₯Ό μ‚¬μš©ν•΄ μ˜μƒμ„ μž¬μƒν•˜κ³  video API둜 μ»¨νŠΈλ‘€λ“€μ„ 보이지 μ•Šκ²Œ μ»€μŠ€ν„°λ§ˆμ΄μ§• ν•œλ‹€λ©΄ λ™μ˜μƒμœΌλ‘œ μΈκ²Œμž„ μ—°μΆœμ„ ν•  μˆ˜λ„ μžˆμ„ 것이닀.

μ˜ˆμ‹œμ—μ„œλŠ” μ„œλ²„μ—μ„œ νŒŒμΌμ„ μ „λΆ€ λ‘œλ“œν•œ ν›„ μž¬μƒν•˜λŠ” κΈ°λŠ₯λ§Œμ„ μ†Œκ°œν•˜κ³  μžˆμ§€λ§Œ, MediaSource API λ₯Ό μ‚¬μš©ν•  경우 λΉ„λ””μ˜€ μŠ€νŠΈλ¦¬λ°λ„ ν•  수 μžˆλ‹€.

Drag & Drop

κ°œμš”

μ›Ή λ¬Έμ„œ μƒμ˜ Elementλ₯Ό Drag & Drop ν•  수 μžˆλ„λ‘ 지정 둜컬 μ»΄ν“¨ν„°μ˜ νŒŒμΌμ„ λΈŒλΌμš°μ €λ‘œ λ“œλž˜κ·Έ & λ“œλ‘­ ν–ˆμ„ λ•Œ μ‚¬μš©λ˜λŠ” API 이닀.

HTML νƒœκ·Έμ—μ„œ draggable 속성을 true둜 μ„€μ •ν•˜λ©΄ ν•΄λ‹Ή μš”μ†ŒλŠ” λ“œλž˜κ·Έν•  수 있게 λœλ‹€.

이후 ν•΄λ‹Ή μš”μ†Œμ— dragstart, drag, dragenter, dragover, dragleave, drop, dragend와 같은 이벀트λ₯Ό λ“±λ‘ν•˜μ—¬ λ“œλž˜κ·Έ μ΄λ²€νŠΈμ— λ”°λ₯Έ λ™μž‘μ„ μ„€μ •ν•œλ‹€.

μ΄λ•Œ DataTransfer 객체가 λ“œλž˜κ·Έ 이벀트λ₯Ό 톡해 μ „νŒŒλ˜λŠ”λ° 이 κ°μ²΄λŠ” λ“œλž˜κ·Έ μ†ŒμŠ€μ—μ„œ λ“œλ‘­ λͺ©μ μ§€λ‘œ 전달될 데이터λ₯Ό λ³΄κ΄€ν•˜λŠ” 역할을 ν•œλ‹€.

μ‚¬μš© μ˜ˆμ‹œ

νƒœκ·Έ μ„€μ •

<img src="../images/beer.png" draggable="true">

이벀트 등둝 및 API μ‚¬μš©

var item = document.querySelector(".menuItem");
var target = document.querySelector(".dropTarget");

item.addEventListener("dragstart", function(e) {
    e.dataTransfer.setData("text/plain", e.target.dataset.type);
    e.dataTransfer.setData("id", e.target.id);
});

target.addEventListener("drop", function(e) {
    var id = e.dataTransfer.getData("id");
    var type = e.dataTransfer.getData("text/plain");
    this.appendChild(document.querySelector("#" + id));
});

κ²Œμž„μ—μ„œμ˜ ν™œμš©

Canvas λ‚΄λΆ€μ μœΌλ‘œ Drag 이벀트λ₯Ό μ²˜λ¦¬ν•  수 μžˆμœΌλ―€λ‘œ κ²Œμž„ μ œμž‘ μ‹œμ—λŠ” 자주 μ‚¬μš©ν•˜μ§„ μ•Šμ„ 것 κ°™λ‹€.

λ‹€λ§Œ μΈκ²Œμž„κ³Ό Canvas μ™ΈλΆ€ μš”μ†Œ μ‚¬μ΄μ˜ λ“œλž˜κ·Έ μ΄λ²€νŠΈκ°€ ν•„μš”ν•˜λ‹€κ±°λ‚˜ μΈκ²Œμž„μ— 컴퓨터 νŒŒμΌμ„ λ“œλž˜κ·Έ ν•œλ‹€κ±°λ‚˜ ν•˜λŠ” 일도 μžˆμ„ 수 μžˆμœΌλ―€λ‘œ μ•Œμ•„λ‘λŠ” 것이 쒋을 것 κ°™λ‹€.

GeoLocation

κ°œμš”

μ›Ήμ—μ„œ μ‚¬μš©μžμ˜ ν˜„μž¬ μœ„μΉ˜λ₯Ό μœ„λ„/경도 μ •λ³΄λ‘œ 확인할 수 μžˆλŠ” API이닀.

μœ„μΉ˜ 정보 νšλ“ 방법은 μ•„λž˜ 3가지가 μžˆλ‹€. HTML5 APIμ—μ„œλŠ” μ•„λž˜ 방법듀을 μ‘°ν•©ν•΄μ„œ μ‚¬μš©ν•œλ‹€.

  • IP μ£Όμ†Œ 기반 : 컴퓨터 기기에 IPλ₯Ό λΆ€μ—¬ν•˜λŠ” ISPμ—μ„œ 정보λ₯Ό λ„˜κ²¨λ°›μ•„ 확인. μ •ν™•νžˆλŠ” ISP의 μœ„μΉ˜κ°€ μž‘νžŒλ‹€.
  • GPS 기반 : GPS 단말이 μžˆμ–΄μ•Όλ§Œ μ‚¬μš©ν•  수 μžˆλ‹€. μœ„μ„±μœΌλ‘œλΆ€ν„° 정보λ₯Ό λ°›κΈ° λ•Œλ¬Έμ— μ‹œκ°„μ΄ 였래 걸리고 배터리 μ†Œλͺ¨κ°€ 크닀.
  • 이동 톡신 기반 : 이동 톡신 기지ꡭ을 ν™œμš©
  • Wi-Fi 기반 : Wi-Fi μ†‘μˆ˜μ‹ μ„ μœ„ν•œ APλ₯Ό μ΄μš©ν•΄ μœ„μΉ˜λ₯Ό 확인

κΈ°κΈ° ν™˜κ²½κ³Ό μœ μ €μ˜ 섀정에 따라 정확도가 λ–¨μ–΄μ§ˆ 수 있으며, GPS μ‚¬μš©μ„ μœ„ν•΄μ„œλŠ” λ³„λ„λ‘œ μœ μ € λ™μ˜κ°€ ν•„μš”ν•  수 μžˆλ‹€.

μ§€μ˜€λ‘œμΌ€μ΄μ…˜ API의 μ‚¬μš©λ²•μ€ μΌνšŒμ„± μœ„μΉ˜ 정보 μš”μ²­κ³Ό 반볡적인 μœ„μΉ˜ μ—…λ°μ΄νŠΈ 두 가지가 μžˆλ‹€.

μ‚¬μš© μ˜ˆμ‹œ

μΌνšŒμ„± μœ„μΉ˜ 정보 μš”μ²­

var geolocation = navigator.geolocation;
var options = {
    enableHighAccuracy: false, 
    timeout: 30000, 
    maximumAge: 0
};
geolocation.getCurrentPosition(success, error, options);

function success(position) {
    var coords = position.coords;
    var date = new Date(position.timestamp);
    
    var latitude = coords.latitude;
    var longitude = coords.longitude;
    var accuracy = coords.accuracy;
}

function error(positionError) {
    switch (positionError) {
    case 1:
    	console.log("μ‚¬μš©μžκ°€ κΆŒν•œ λΆ€μ—¬λ₯Ό κ±°λΆ€ν•˜μ˜€μŠ΅λ‹ˆλ‹€.");
        break;
    case 2:
    	console.log("λ‚΄λΆ€ 였λ₯˜λ‘œ μœ„μΉ˜ 정보λ₯Ό κ°€μ Έμ˜€μ§€ λͺ»ν–ˆμŠ΅λ‹ˆλ‹€.");
        break;
    case 3:
    	console.log("Timeout 초과둜 정보λ₯Ό κ°€μ Έμ˜€μ§€ λͺ»ν–ˆμŠ΅λ‹ˆλ‹€.");
        break;
    }
}

반볡적인 μœ„μΉ˜ μ—…λ°μ΄νŠΈ

ν•œλ²ˆ μš”μ²­ν•˜λ©΄ μ§€μ†μ μœΌλ‘œ μœ„μΉ˜ 정보λ₯Ό μ—…λ°μ΄νŠΈν•˜λŠ” κΈ°λŠ₯으둜 watchPosition() ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•œλ‹€.

ν•¨μˆ˜μ˜ μ‹€ν–‰κ²°κ³Όλ‘œ idλ₯Ό λ°˜ν™˜ν•˜λŠ”λ°, 이 idλ₯Ό clearWatch() ν•¨μˆ˜μ— νŒŒλΌλ―Έν„°λ‘œ μ „λ‹¬ν•˜μ—¬ μœ„μΉ˜ 정보 μ—…λ°μ΄νŠΈλ₯Ό μ€‘μ§€ν•œλ‹€.

λ””λ°”μ΄μŠ€μ˜ μœ„μΉ˜κ°€ 변경될 λ•Œλ§ˆλ‹€ success μ½œλ°±μ„ λ™μž‘μ‹œν‚¨λ‹€.

var geolocation = navigator.geolocation;
var options = {
    enableHighAccuracy: false, 
    timeout: 30000, 
    maximumAge: 0
};
var watchId = geolocation.watchPosition(success, error, options);

function success(position) {
    var coords = position.coords;
    var date = new Date(position.timestamp);
    
    var latitude = coords.latitude;
    var longitude = coords.longitude;
    var accuracy = coords.accuracy;
}

function error(positionError) {
    switch (positionError) {
    case 1:
    	console.log("μ‚¬μš©μžκ°€ κΆŒν•œ λΆ€μ—¬λ₯Ό κ±°λΆ€ν•˜μ˜€μŠ΅λ‹ˆλ‹€.");
        break;
    case 2:
    	console.log("λ‚΄λΆ€ 였λ₯˜λ‘œ μœ„μΉ˜ 정보λ₯Ό κ°€μ Έμ˜€μ§€ λͺ»ν–ˆμŠ΅λ‹ˆλ‹€.");
        break;
    case 3:
    	console.log("Timeout 초과둜 정보λ₯Ό κ°€μ Έμ˜€μ§€ λͺ»ν–ˆμŠ΅λ‹ˆλ‹€.");
        break;
    }
}

function stopWatching() {
    geolocation.clearWatch(watchId);
}

κ²Œμž„μ—μ„œμ˜ ν™œμš©

HTML5 κ²Œμž„μ˜ 강점 쀑 ν•˜λ‚˜λŠ” λ°”λ‘œ λ‹€μ–‘ν•œ ν”Œλž«νΌκ³Ό κΈ°κΈ°μ—μ„œ λ™μΌν•œ κ²½ν—˜μ„ κ°–κ²Œ ν•˜λŠ” 것에 μžˆλ‹€.

κ·ΈλŸ¬λ‚˜ GeoLocation APIλ₯Ό μ„œλ‘œ λ‹€λ₯Έ κΈ°κΈ°μ—μ„œ λ™μΌν•œ κ²°κ³Όλ₯Ό 보μž₯ν•˜μ§€ μ•ŠλŠ”λ‹€.

λ‹Ήμž₯ λ°μŠ€ν¬νƒ‘μ—μ„œλŠ” ISP의 정보가 λ‚˜νƒ€λ‚  뿐이닀.

λ§Œμ•½ 포켓λͺ¬ GO 처럼 GPSκ°€ μžˆμ–΄μ•Όλ§Œ μ‹€ν–‰ν•  수 μžˆλ‹€λ©΄ ν™œμš©ν•  수 μžˆλŠ” 여지가 μžˆκ² μ§€λ§Œ

어뷰징에 μ·¨μ•½ν•œ HTML5 ν™˜κ²½μ˜ νŠΉμ„± 상, μœ„μΉ˜ 정보λ₯Ό ν‚€ 포인트으둜 ν™œμš©ν•˜κΈ°λŠ” νž˜λ“€ κ²ƒμœΌλ‘œ 보인닀.

WebStorage

κ°œμš”

μ›Ή μŠ€ν† λ¦¬μ§€λŠ” μΏ ν‚€λ₯Ό κ°œμ„ ν•œ κΈ°μˆ μ΄λ‹€.

도메인 λ³„λ‘œ μ €μž₯λ˜λ―€λ‘œ μ„œλ‘œ λ‹€λ₯Έ λ„λ©”μΈμ˜ μŠ€ν† λ¦¬μ§€λ₯Ό 직접 μ°Έμ‘°ν•  수 μ—†λ‹€.

μ„œλ‘œ λ‹€λ₯Έ νŽ˜μ΄μ§€λΌκ³  해도 동일 도메인이라면 동일 μ €μž₯μ†Œλ₯Ό μ°Έμ‘°ν•œλ‹€. λ”°λΌμ„œ 도메인 내에 μ—¬λŸ¬ νŽ˜μ΄μ§€κ°€ 있고 νŽ˜μ΄μ§€ λ³„λ‘œ λ‹€λ₯Έ 값을 μ €μž₯ν•˜κ³ μž ν•œλ‹€λ©΄ ν‚€λ₯Ό 길게 ν•˜μž.

μΏ ν‚€μ˜ 문제점

  • λ„€νŠΈμ›Œν¬ λΆ€ν•˜ 유발
    • μ„œλ²„ μš”μ²­ μ‹œ, ν΄λΌμ΄μ–ΈνŠΈμ˜ μΏ ν‚€κ°€ ν•¨κ»˜ μ „μ†‘λœλ‹€.
  • λ³΄μ•ˆμƒμ˜ 문제
    • μΏ ν‚€λŠ” 전솑 κ³Όμ •μ—μ„œ μ‰½κ²Œ νƒˆμ·¨ 및 μ‘°μž‘λ  수 μžˆλ‹€.
  • μΏ ν‚€μ˜ 차단
    • μœ„μ˜ 문제둜 인해 λŒ€λΆ€λΆ„μ˜ λΈŒλΌμš°μ €μ—μ„œ μΏ ν‚€λ₯Ό μ°¨λ‹¨ν•˜κ³  μžˆλ‹€.
  • μ œν•œμ μΈ μš©λŸ‰
    • μΏ ν‚€μ˜ μš©λŸ‰μ€ 기껏해야 4kb 정도이닀.

μ›Ή μŠ€ν† λ¦¬μ§€μ™€ μΏ ν‚€μ˜ μœ μ‚¬μ 

  • 이름과 κ°’μ˜ λ‹¨μˆœν•œ ν˜•νƒœλ‘œ 데이터λ₯Ό μ €μž₯ν•œλ‹€.
  • ν΄λΌμ΄μ–ΈνŠΈμ˜ 곡간에 데이터λ₯Ό μ €μž₯ν•œλ‹€.

μ›Ή μŠ€ν† λ¦¬μ§€μ™€ μΏ ν‚€μ˜ 차이점

  • μ›Ή μŠ€ν† λ¦¬μ§€ λ°μ΄ν„°λŠ” μ„œλ²„λ‘œ μ „μ†‘λ˜μ§€ μ•ŠλŠ”λ‹€.
  • ν‰κ· μ μœΌλ‘œ 5Mb μ΄μƒμ˜ μš©λŸ‰μ„ μ œκ³΅ν•œλ‹€.

μ›Ή μŠ€ν† λ¦¬μ§€μ˜ μ’…λ₯˜

  • μ„Έμ…˜ μŠ€ν† λ¦¬μ§€
    • λΈŒλΌμš°μ €μ˜ μ„Έμ…˜ κΈ°κ°„λ§Œ 데이터λ₯Ό μœ μ§€
    • λ™μΌν•œ λΈŒλΌμš°μ €(νƒ­)μ—μ„œ λ¦¬ν”„λ ˆμ‹œ 해도 데이터 μœ μ§€
    • location.href둜 λ¦¬λ‹€μ΄λ ‰νŠΈ ν›„, λ’€λ‘œκ°€κΈ°λ‘œ λŒμ•„κ°€λ„ 데이터 μœ μ§€
    • λ‹€λ₯Έ λΈŒλΌμš°μ €(νƒ­)을 μ—΄μ–΄ κ²Œμž„μ„ μ‹€ν–‰ν•  경우 데이터 μœ μ‹€
  • 둜컬 μŠ€ν† λ¦¬μ§€
    • 둜컬 μŠ€ν† λ¦¬μ§€λŠ” λΈŒλΌμš°μ €λ₯Ό 닫아도 데이터λ₯Ό μ‚­μ œν•˜μ§€ μ•ŠλŠ”λ‹€.
    • 파일둜 μ €μž₯되며 크둬의 경우 /Local Settings/Application Data/Google/Chrome/UserData/Default/Local Storage에 μ €μž₯

둜컬 μŠ€ν† λ¦¬μ§€μ˜ 데이터 곡유

  • μ„œλ‘œ λ‹€λ₯Έ λΈŒλΌμš°μ €λŠ” 둜컬 μŠ€ν† λ¦¬μ§€ μ €μž₯ 파일이 λ‹€λ₯΄κΈ° λ•Œλ¬Έμ— κ³΅μœ ν•  수 μ—†λ‹€.
  • λ™μΌν•œ λΈŒλΌμš°μ € μ—¬λŸ¬ κ°œμ—μ„œ λ™μΌν•œ 도메인에 μ ‘μ†ν•œ 경우, 둜컬 μŠ€ν† λ¦¬μ§€λ₯Ό κ³΅μœ ν•΄μ„œ μ‚¬μš©ν•  수 μžˆλ‹€.
    • 둜컬 μŠ€ν† λ¦¬μ§€κ°€ 변경될 경우 window에 storage μ΄λ²€νŠΈκ°€ λ°œμƒ

μ‚¬μš©λ²•

기본적인 μ‚¬μš©λ²•μ€ λ‹€μŒκ³Ό κ°™λ‹€.

try {
    if (window.localStorage) {
        localStorage.setItem("test", "test-value");
        localStorage.getItem("test");
        localStorage.removeItem("test");
    }
    
    if (window.sessionStorage) {
        sessionStorage.setItem("test2", "test-value");
        sessionStorage.getItem("test2");
        sessionStorage.removeItem("test2");
    }
} catch (exception) {
    // μš©λŸ‰ 초과 μ‹œ, QuotaExceededError λ°œμƒ 
    return exception;
} finally {
    localStorage.clear();
    sessionStorage.clear();
}

둜컬 μŠ€ν† λ¦¬μ§€ 곡유

window.addEventListener("storage", function(e) {
    console.log(e.key);
});

κ²Œμž„μ—μ„œμ˜ ν™œμš©

λ‹€μ΄λ…Έλ³Όμ¦ˆμ—μ„œλŠ” 곡지사항 확인 μ—¬λΆ€λ₯Ό 둜컬 μŠ€ν† λ¦¬μ§€μ— μ €μž₯ν•˜κ³  μžˆλ‹€. 링크

λ˜ν•œ Facebook Instant SDKμ—μ„œλŠ” μœ μ €μ˜ 이름과 ν”„λ‘œν•„ 이미지 URL을 둜컬 μŠ€ν† λ¦¬μ§€μ— μ €μž₯ν•˜λŠ” 것을 ꢌμž₯ν•˜κ³  μžˆλ‹€.

IndexedDB

ν΄λΌμ΄μ–ΈνŠΈ λΈŒλΌμš°μ €μ— ꡬ쑰적 데이터λ₯Ό μ €μž₯ν•  수 μžˆμ–΄μ„œ μ˜€ν”„λΌμΈμ—μ„œλ„ μž‘μ—…ν•  수 μžˆλ‹€.

MDN μ›Ή λ„νλ¨ΌνŠΈλ₯Ό 보면 λΈŒλΌμš°μ € 및 섀정에 따라 DB μš©λŸ‰ μ œν•œμ΄ λ‹€λ₯Ό 수 μžˆλ‹€.

  • νŒŒμ΄μ–΄ν­μŠ€λŠ” 50MB μ΄μƒμ˜ μš©λŸ‰μ΄ ν•„μš”ν•  경우 κΆŒν•œ 승인 μš”μ²­ μΈν„°νŽ˜μ΄μŠ€κ°€ λ…ΈμΆœλœλ‹€.
  • 크둬은 λΈŒλΌμš°μ € μ‚¬μš© κ°€λŠ₯ μš©λŸ‰μ— 따라 λ‹€λ₯΄λ‹€.

ν‚€-κ°’ 쌍으둜 데이터λ₯Ό μ €μž₯ν•˜λ©°, 이 킀듀을 μ΄μš©ν•΄ 인덱슀λ₯Ό λ§Œλ“€ 수 있고 이λ₯Ό 객체 μ‘°νšŒμ— ν™œμš©ν•œλ‹€.

νŠΈλžœμž­μ…˜ λ°μ΄ν„°λ² μ΄μŠ€ λͺ¨λΈ 기반으둜 λ™μž‘ν•œλ‹€. 인덱슀, ν…Œμ΄λΈ”, μ»€μ„œ λ“±μ˜ μž‘μ—…μ€ λͺ¨λ‘ νŠΈλžœμž­μ…˜ λ‚΄μ—μ„œ μˆ˜ν–‰λ˜μ–΄μ•Ό ν•œλ‹€. indexedDBλŠ” μžλ™ μ»€λ°‹μœΌλ‘œ λ™μž‘ν•˜λ©° μˆ˜λ™ 컀밋은 μ§€μ›ν•˜μ§€ μ•ŠλŠ”λ‹€.

비동기 λ°©μ‹μœΌλ‘œ λ™μž‘ν•˜λ©° λ™μž‘μ΄ μ™„λ£Œλ  λ•Œ 콜백 이벀트λ₯Ό λ°›μ•„ μ²˜λ¦¬ν•΄μ•Ό ν•œλ‹€. λ”°λΌμ„œ λ™κΈ°μ μœΌλ‘œ κ΄€λ ¨ μž‘μ—…μ„ μ²˜λ¦¬ν•˜κ³  μ‹Άλ‹€λ©΄ Promiseλ₯Ό μ΄μš©ν•΄ λž˜ν•‘ν•΄μ•Ό ν•œλ‹€.

SQL을 μ‚¬μš©ν•˜μ§€ μ•Šκ³  ν•¨μˆ˜ 기반으둜 데이터 μ €μž₯, μˆ˜μ •, 검색, μ‚­μ œλ₯Ό μˆ˜ν–‰ν•œλ‹€.

특히 검색을 μœ„ν•΄μ„  인덱슀λ₯Ό 톡해 μƒμ„±ν•œ μ»€μ„œλ₯Ό μ‚¬μš©ν•΄μ•Ό ν•œλ‹€.

동일 근원 정책을 λ”°λ₯΄λ―€λ‘œ ν”„λ‘œν† μ½œ, 도메인, ν¬νŠΈκ°€ 같은 경우 indexedDB λ₯Ό κ³΅μœ ν•˜κ³  λ‹€λ₯Ό λ•ŒλŠ” κ³΅μœ ν•˜μ§€ μ•ŠλŠ”λ‹€.

KeyRange APIλ₯Ό μ‚¬μš©ν•΄μ„œ 인덱슀 값에 λŒ€ν•΄ λ²”μœ„ κ²€μƒ‰μœΌλ‘œ 데이터λ₯Ό μΆ”μΆœν•  수 μžˆλ‹€.

μ‚¬μš©λ²•

DBλ₯Ό μ—¬λŠ” μ‚¬μš© 예 (λ‹€μ΄λ…Έλ³Όμ¦ˆ)

this.openStaticDB = function() {
    var promise = new Promise(function(resolve, reject) {
        if (!window.indexDB) {
            StaticManager.dbConnect = null;
            reject("indexedDB not allowed.");
        }
        
        var staticDB = indexedDB.open("dino_static");
        staticDB.addEventListener("upgradeneeded", function() {
            StaticManager.dbConnect = staticDB.result;
            if (StaticManager.dbConnect.objectStoreNames.contains("dino_static") === false) {
                StaticManager.dbConnect.createObjetStore("dino_static", {keyPath: "name"});
            }
        });
        
        staticDB.addEventListener("success", function() {
            StaticManager.dbConnect = staticDB.result;
            resolve(StaticManager.dbConnect);
        });
        
        staticDB.addEventListener("error", function(err) {
           StaticManager.dbConnect = null;
           reject(JSON.stringify(err));
        });
    });
    return promise;
};

DBμ—μ„œ 데이터 쑰회 예 (λ‹€μ΄λ…Έλ³Όμ¦ˆ)

this.getIndexedData = function() {
    var promise = new Promise(function(resolve, reject) {
        if (!window.indexedDB || !StaticManager.dbConnect) {
            StaticManager.dbConnect = null;
            reject("indexedDB not allowed.");
        }
        
        var tx = StaticManager.dbConnect.transaction(["dino_static"], "readonly");
        var objectStore = tx.objectStore("dino_static");
        var request = objectStorage.getAll();
        request.addEventListener("success", function() {
            var result = {};
            for (var i = 0; i < request.result.length; i++) {
                this[request.result[i].name] = new StaticModel(request.result[i].name, request.result[i].version, JSON.parse(request.result[i].data))
            }
            resolve();
        });
        request.addEventListener("error", function() {
            reject("Transaction Error.");
        });
    });
    return promise;
};

DB 데이터 μˆ˜μ •(λ‹€μ΄λ…Έλ³Όμ¦ˆ)

this.updateIndexedData = function(inName, inVersion, inData) {
    var promise = new Promise(function(resolve, reject) {
        if (!window.indexedDB || !StaticManager.dbConnect) {
            StaticManager.dbConnect = null;
            reject("indexedDB not allowed.");
        }
        
        var data = {
            name: inName, 
            version: inVersion, 
            data: JSON.stringify(inData)
        };
        
        var tx = StaticManager.dbConnect.transaction(["dino_static"], "readwrite");
        var objectStore = tx.objectStore("dino_static");
        var request = objectStore.put(data);
        request.addEventListener("success", function() {
            resolve(data);
        });
        request.addEventListener("error", function() {
            reject("db update failed: " + data.name);
        });
    });
    return promise;
};

κ²Œμž„μ—μ„œμ˜ ν™œμš©

μ›Ή μŠ€ν† λ¦¬μ§€μ™€ 달리 μš©λŸ‰ μ œν•œμ—μ„œ 자유둭기 λ•Œλ¬Έμ— μŠ€νƒœν‹± 데이터λ₯Ό μΊμ‹±ν•˜λŠ” 데 ν™œμš©ν•  수 μžˆλ‹€.

ν˜„μž¬ λ‹€μ΄λ…Έλ³Όμ¦ˆμ— 적용 μ˜ˆμ •μ΄λ‹€.

File

κ°œμš”

File APIλ₯Ό 톡해 νŒŒμΌμ„ μ½κ±°λ‚˜ μ“Έ 수 μžˆλ‹€.

μ“°κΈ° κ΄€λ ¨ APIλŠ” 크둬과 였페라 κ³„μ—΄μ—μ„œλ§Œ μ‚¬μš©κ°€λŠ₯ν•˜λ‹€.

읽기 κ΄€λ ¨ APIλŠ” 읽기 μ „μš©μœΌλ‘œ νŒŒμΌμ— μ ‘κ·Όν•˜κΈ° λ•Œλ¬Έμ— 파일의 μˆ˜μ •, μ‚­μ œλŠ” λΆˆκ°€λŠ₯ν•˜λ‹€.

파일의 정보λ₯Ό ν™•μΈν•˜κΈ° μœ„ν•΄μ„œλŠ” FileReader 객체λ₯Ό μ‚¬μš©ν•œλ‹€.

FileReader κ°μ²΄λŠ” λΉ„λ™κΈ°μ μœΌλ‘œ λ™μž‘ν•˜λ©° μ‚¬μš©μžμ˜ νŒŒμΌμ„ μ½λŠ” 역할을 ν•œλ‹€.

FileReader 객체의 loadstart, progress, loadend와 같은 이벀트λ₯Ό μ‚¬μš©ν•΄μ„œ 파일 읽기 진행상황을 확인할 수 μžˆλ‹€.

File API μ€‘μ—λŠ” Blob APIκ°€ μžˆλŠ”λ°, Blobλ₯Ό 톡해 λŒ€μš©λŸ‰μ˜ μ›μ‹œ 데이터λ₯Ό μ²˜λ¦¬ν•  수 μžˆλ‹€.

Blob API 쀑 slice ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•΄μ„œ 파일 전체 쀑 μΌλΆ€λ§Œ λ©”λͺ¨λ¦¬μ— λ‘œλ“œν•΄μ„œ μ‚¬μš©ν•  수 μžˆλ‹€.

μ‚¬μš©λ²•

FileReader μ‚¬μš©λ²•

var file = inFile;
var fReader = new FileReader();

if (getType(file.type) === "image") {
    // 이미지 파일 읽기
    fReader.readAsDataURL(file);
} else if (getType(file.type) === "text") {
    // λ¬Έμžμ—΄ 파일 읽기
    fReader.readAsText(file);
    // ν˜Ήμ€ Blobλ₯Ό μ΄μš©ν•΄ 파일의 μΌλΆ€λ§Œ 뢈러였기
    var blob = file.slice(0, 100);
    fReader.readAsText(blob);
}

fReader.addEventListener("load", function(e) {
    console.log("파일 읽기 μ™„λ£Œ.");
    // 파일 정보λ₯Ό μ„Έμ…˜ μŠ€ν† λ¦¬μ§€μ— μ €μž₯
    sessionStorage.setItem(file.name, JSON.strigify(e.result));
});

fReader.addEventListener("error", function(e) {});
fReader.addEventListener("loadstart", function(e) {});
fReader.addEventListener("progress", function(e) {});
fReader.addEventListener("loadend", function(e) {});

κ²Œμž„μ—μ„œμ˜ ν™œμš©

λ©”λͺ¨λ¦¬ μΊμ‹œ λ³΄μ•ˆμ— Blobλ₯Ό ν™œμš©ν•  수 μžˆμ„μ§€ κ³ λ―Όν•΄λ΄€μœΌλ‚˜, κ·Έλƒ₯ ArrayBufferλ₯Ό λ°”λ‘œ μ‚¬μš©ν•˜λŠ”κ²Œ λ‚˜μ„ λ“― ν•˜λ‹€.

κ²Œλ‹€κ°€ BlobλŠ” readonly이기 λ•Œλ¬Έμ— κ°’μ˜ 변경이 μžˆμ„ μ‹œ, λ©”λͺ¨λ¦¬ λ‚­λΉ„λ§Œ λ§Žμ•„μ§ˆ 수 μžˆλ‹€.

Communication

κ°œμš”

일반적으둜 XMLHttpRequest Level2λ₯Ό μ΄μš©ν•˜λŠ” Ajax 기술,

λ‹€λ₯Έ κ·Όμ›μ˜ λ¬Έμ„œ λ©”μ‹œμ§•μ„ μ§€μ›ν•˜λŠ” Cross Document Messaging (λ˜λŠ” Web Messaging),

그리고 μ„œλ²„μ™€μ˜ μ‹€μ‹œκ°„ 톡신을 μœ„ν•œ Web Socket을 μ§€μΉ­ν•œλ‹€.

XMLHttpRequest Level 2

ν˜„μž¬ λ‹€μ΄λ…Έλ³Όμ¦ˆμ—μ„œλŠ” jQueryλ₯Ό 톡해 μ‚¬μš© 쀑이닀.

Level 2 μ—μ„œλŠ” μ„œλ²„κ°€ ν—ˆλ½λ§Œ ν•œλ‹€λ©΄ λ‹€λ₯Έ κ·Όμ›μ—μ„œ μ œκ³΅λ˜λŠ” μ„œλΉ„μŠ€λ₯Ό 마음껏 μ‚¬μš©ν•  수 μžˆλ‹€.

μ„œλ²„μ˜ 응닡 헀더에 Access-Control-Allow-Origin μ†μ„±μœΌλ‘œ ν—ˆμš©ν•  μ„œλ²„λ₯Ό λ“±λ‘ν•˜λ©΄ λœλ‹€.

페이슀뢁 μΈμŠ€ν„΄νŠΈ κ²Œμž„μ€ 페이슀뢁 ν˜ΈμŠ€νŒ… μ„œλ²„λ₯Ό μ‚¬μš©ν•˜κΈ° λ•Œλ¬Έμ— κ²Œμž„ μ„œλ²„μ™€λŠ” 근원이 λ‹€λ₯΄λ‹€.

λ”°λΌμ„œ κ²Œμž„ μ„œλ²„μ˜ 응닡 헀더에 페이슀뢁 ν˜ΈμŠ€νŒ… μ„œλ²„λ₯Ό 등둝해주어야 ν•œλ‹€.

Cross Document Messaging

ν•œ λ¬Έμ„œμ—μ„œ λ©”μ‹œμ§€λ₯Ό 생성해 λ‹€λ₯Έ νŽ˜μ΄μ§€ (iframe, νƒ­, μœˆλ„μš°)둜 전솑할 수 μžˆλŠ” κΈ°λŠ₯이닀.

window.postMessage ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•΄ λ©”μ‹œμ§€λ₯Ό μ „μ†‘ν•˜κ³ , λ©”μ‹œμ§€λ₯Ό λ°›λŠ” μΈ‘μ—μ„œλŠ” message 이벀트λ₯Ό 톡해 전달받은 λ©”μ‹œμ§€λ₯Ό μ²˜λ¦¬ν•  수 μžˆλ‹€.

μ›Ή μ†ŒμΌ“

μ›Ή μƒμ—μ„œ ν•˜λ‚˜μ˜ μ†ŒμΌ“μœΌλ‘œ μž‘λ™ν•˜λŠ” μ–‘λ°©ν–₯ 톡신 κΈ°λŠ₯이닀.

μ†ŒμΌ“ 톡신은 기쑴의 HTTP 헀더λ₯Ό ν†΅ν•œ 톡신 λŒ€μ‹  TCP μ†ŒμΌ“μ„ 톡해 이뀄진닀.

헀더에 λŒ€ν•œ 정보가 쀄어듀기 λ•Œλ¬Έμ— μ „μ†‘λœλŠ λ°μ΄ν„°μ˜ 크기가 쀄어듀고, μ†ŒμΌ“μ„ λ‹«κΈ° μ „κΉŒμ§„ 연결이 μ§€μ†λ˜λ―€λ‘œ 응닡 속도도 λΉ λ₯΄λ‹€.

μ‚¬μš©λ²•

postMesage μ‚¬μš©λ²•

// iframe μ—˜λ¦¬λ¨ΌνŠΈ 
var widget = document.getElementById("widget");
var trust = "http://test.com:8080";
widget.src = trust + "/a.html";
widget.contentWindow.postMessage("test", trust);

window.addEventListener("message", function(e) {
    if (e.origin === trust) {
        console.log(e.data);
    }
});

μ›Ή μ†ŒμΌ“ μ‚¬μš©λ²•

var wsUri = "ws://localhost:8080/echo";
socket = new WebSocket(wsUri);
socket.addEventListener("open", function() {
    console.log("μ†ŒμΌ“ μ—°κ²° 성곡.");
});
socket.addEventListener("message", function(e) {
    console.log("λ©”μ‹œμ§€ μˆ˜μ‹ : " + e.data);
});
socket.addEventListener("error", function(e) {
    console.log("μ—λŸ¬ λ°œμƒ: " + JSON.stringify(e));
});

κ²Œμž„μ—μ„œμ˜ ν™œμš©

Cross Document Messaging

λŒ€λΆ€λΆ„ κ²Œμž„μ—μ„œλŠ” μƒˆλ‘œμš΄ νƒ­μ΄λ‚˜ λΈŒλΌμš°μ €λ₯Ό μ—¬λŠ” κ²½μš°κ°€ μ—†λ‹€.

ν˜„μž¬ facebook μ—μ„œλŠ” iframe도 ν—ˆμš©ν•˜μ§€ μ•Šκ³  μžˆλ‹€. ν•˜μ§€λ§Œ λ‹€λ₯Έ ν”Œλž«νΌμ—μ„œλŠ” ν™œμš©ν•  여지가 μžˆλ‹€.

Web Worker

μžλ°” μŠ€ν¬λ¦½νŠΈλŠ” 기본적으둜 단일 μŠ€λ ˆλ“œ 언어이닀.

κ°œλ°œν•˜κΈ° νŽΈλ¦¬ν•˜λ‹€λŠ” μž₯점이 μžˆμ§€λ§Œ, 연산이 κΈΈμ–΄μ§ˆ 경우 메인 μŠ€λ ˆλ“œμ— 큰 뢀담을 μ£Όλ©΄μ„œ UI λ™μž‘ 등을 μˆ˜ν–‰ν•  수 μ—†κ²Œ λœλ‹€.

μ›Ή μ›Œμ»€λ₯Ό 톡해 μžλ°”μŠ€ν¬λ¦½νŠΈλ₯Ό λ©€ν‹° μŠ€λ ˆλ“œ ν˜•νƒœλ‘œ μ‚¬μš©ν•  수 μžˆλ‹€.

슀크립트의 λ™μž‘μ„ 메인 μŠ€λ ˆλ“œμ™€ λΆ„λ¦¬λœ μž‘μ—… μŠ€λ ˆλ“œλ‘œ λ§Œλ“€μ–΄ μŠ€λ ˆλ“œκ°€ λ©ˆμΆ”κ±°λ‚˜ 늦게 λ™μž‘ν•˜λŠ” 것을 방지할 수 μžˆλ‹€.

μ›Ή μ›Œμ»€μ—λŠ” μ›Œμ»€λ₯Ό μƒμ„±ν•œ 메인 μ½”λ“œμ—μ„œλ§Œ μ‚¬μš©ν•  수 μžˆλŠ” μ „μš© μ›Œμ»€(Dedicated Worker)와 μ—¬λŸ¬ λ¬Έμ„œμ—μ„œμ˜ μš”μ²­μ— 응닡할 수 μžˆλŠ” 곡유 μ›Œμ»€(Shared Worker)의 두가지가 μžˆλ‹€.

μ›Œμ»€λ₯Ό μ‚¬μš©ν•˜κΈ° μœ„ν•΄μ„œλŠ” λ¨Όμ € μ›Œμ»€μ—μ„œ μ‹€ν–‰ν•  μ½”λ“œλ₯Ό λ³„λ„μ˜ μžλ°”μŠ€ν¬λ¦½νŠΈλ‘œ λ§Œλ“€μ–΄μ•Ό ν•œλ‹€.

이후 메인 μ½”λ“œμ—μ„œ new Worker() μƒμ„±μžλ₯Ό ν˜ΈμΆœν•˜λ©΄μ„œ νŒŒλΌλ―Έν„°λ‘œ 파일λͺ…을 λ„˜κ²¨μ£Όλ©΄ λœλ‹€.

μ›Œμ»€μ™€ 메인 μ½”λ“œλŠ” MessageEvent 기반으둜 데이터λ₯Ό μ£Όκ³  λ°›λŠ”λ‹€.

λ˜ν•œ μ›Œμ»€λŠ” 메인 μ½”λ“œμ™€λŠ” λ³„κ°œμ˜ μ „μ—­ μ»¨ν…μŠ€νŠΈμ—μ„œ μ‹€ν–‰λ˜λ―€λ‘œ μ›Œμ»€μ—μ„œ DOM에 직접 μ ‘κ·Όν•  수 μ—†κ³ , 일뢀 window 속성도 μ‚¬μš©ν•  수 μ—†λ‹€.

메인 μ½”λ“œμ—μ„œλ„ μ›Œμ»€ λ‚΄λΆ€μ˜ μ½”λ“œμ— μ ‘κ·Όν•  수 μ—†λ‹€.

μ›Œμ»€μ—μ„œ try catch둜 μ²˜λ¦¬ν•˜μ§€ μ•Šμ€ 였λ₯˜λŠ” μžλ™μœΌλ‘œ 메인 μ½”λ“œμ— 이벀트둜 μ „λ‹¬λœλ‹€.

이 였λ₯˜ 이벀트λ₯Ό μ²˜λ¦¬ν•˜κΈ° μœ„ν•΄ 메인 μ½”λ“œμ—μ„œλŠ” μ›Œμ»€ 객체에 error 이벀트 λ¦¬μŠ€λ„ˆλ₯Ό λ“±λ‘ν•΄μ€˜μ•Ό ν•œλ‹€.

ν•œλ²ˆ μƒμ„±ν•œ μ›Œμ»€λŠ” μžλ™μœΌλ‘œ λ©ˆμΆ”μ§€ μ•Šκ³  κ³„μ†ν•΄μ„œ message 이벀트λ₯Ό μˆ˜μ‹  λŒ€κΈ°ν•œλ‹€.

λ”°λΌμ„œ 더 이상 μ›Œμ»€κ°€ ν•„μš”ν•˜μ§€ μ•Šμ€ κ²½μš°μ—λŠ” λͺ…μ‹œμ μœΌλ‘œ 처리λ₯Ό μ€‘μ§€ν•˜κ±°λ‚˜ μ’…λ£Œν•΄μ•Ό ν•œλ‹€.

μ›Œμ»€λ₯Ό μ’…λ£Œν•˜λŠ” λ°μ—λŠ” terminate() ν•¨μˆ˜μ™€ close() ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•  수 μžˆλ‹€.

terminateλŠ” 메인 μ½”λ“œμ—μ„œ μ›Œμ»€λ₯Ό μ’…λ£Œμ‹œν‚€λŠ” ν•¨μˆ˜λ‘œ μ›Œμ»€μ—μ„œ μžμ› λ°˜λ‚©μ˜ 기회λ₯Ό 주지 μ•Šκ³  κ°•μ œλ‘œ μ’…λ£Œμ‹œν‚¨λ‹€.

closeλŠ” μ›Œμ»€ λ‚΄λΆ€μ—μ„œ μ‚¬μš©ν•˜λŠ” ν•¨μˆ˜λ‘œ μ›Œμ»€ λ‚΄λΆ€ μžμ›μ„ λ°˜λ‚©ν•œ ν›„ closeλ₯Ό ν˜ΈμΆœν•˜μ—¬ μ›Œμ»€λ₯Ό μ’…λ£Œν•˜λ©΄ λœλ‹€.

μ‚¬μš©λ²•

Dedicated Worker

메인 μ½”λ“œ

var worker = new Worker("a.js");
worker.addEventListener("message", function(e) {
    console.log(e.data);
});
worker.addEventListener("error", function(e) {
    console.log("error: " + JSON.stringify(e));
});
worker.postMessage("test");
worker.postMessage("close");

a.js

// Worker 객체의 λ©”μ„œλ“œμΈ importScriptsλ₯Ό μ΄μš©ν•΄ μ›Œμ»€ λ‚΄λΆ€μ—μ„œ λ‹€λ₯Έ 슀크립트λ₯Ό μž¬μ‚¬μš©ν•  수 μžˆλ‹€.
importScripts("b.js");

addEventListener("message", function(e) {
    postMessage(e.data + "!");

    if (e.data === "close") {
        close();
    }
});

Shared Worker

메인 μ½”λ“œ

var worker = new SharedWorker("a.js");
worker.addEventListener("error", function(e) {
    console.log("error: " + e.toString());
});
worker.addEventListener("message", function(e) {
    console.log(e.data);
});

// ν•˜λ‚˜μ˜ 곡유 μ›Œμ»€μ—λŠ” μ—°κ²°λœ 메인 μ½”λ“œλ³„λ‘œ portκ°€ ν• λ‹Ήλœλ‹€. portλ₯Ό 톡해 λ©”μ‹œμ§€λ₯Ό μ „μ†‘ν•œλ‹€.
worker.port.postMessage("test");

// λ©”μ‹œμ§€ 큐에 μŒ“μ—¬μžˆλŠ” λ©”μ‹œμ§€λ“€μ„ 보내기 μ‹œμž‘ν•˜λŠ” ν•¨μˆ˜μ΄λ‹€.
// postMessageλ₯Ό 톡해 λ©”μ‹œμ§€λ₯Ό 보내더라도 startκ°€ ν˜ΈμΆœλ˜μ§€ μ•ŠμœΌλ©΄ λ©”μ‹œμ§€λŠ” μ „μ†‘λ˜μ§€ μ•ŠλŠ”λ‹€.
worker.port.start();

a.js

var ports = new Array();
var prev = "";
addEventListener("connect", function(e) {
    var clientPort = e.ports[0];
    ports.push(clinetPort);

    clinetPort.addEventListener("message", function(e) {
        prev += e.data;
        for (var i = 0; i < ports.length; i++) {
            ports[i].postMessage(e.data);
        }
    });
    clientPort.start();
    clientPort.postMessage(prev);
});

κ²Œμž„μ—μ„œμ˜ ν™œμš©

  • λ‹¨μˆœνžˆ 였래 κ±Έλ¦¬λŠ” 연산을 별도 μŠ€λ ˆλ“œλ‘œ λŒλ¦¬λŠ” μ—­ν• 
  • μ„œλ²„μ™€μ˜ 톡신을 μ „λ‹΄ν•˜λŠ” λ°±κ·ΈλΌμš΄λ“œ ν”„λ‘œμ„ΈμŠ€

참고자료

μ–΄ν”Œλ¦¬μΌ€μ΄μ…˜ μΊμ‹œ

μ›ΉκΈ°λ°˜ μ–΄ν”Œλ¦¬μΌ€μ΄μ…˜μ΄ μ˜€ν”„λΌμΈμ—μ„œλ„ μ‹€ν–‰λ˜λ„λ‘ μ–΄ν”Œλ¦¬μΌ€μ΄μ…˜ μΊμ‹œλ₯Ό μ œκ³΅ν•œλ‹€.

μ–΄ν”Œλ¦¬μΌ€μ΄μ…˜ μΊμ‹œλ₯Ό ν•˜λ©΄ μ„œλ²„μ˜ λΆ€ν•˜κ°€ 쀄어듀고 λ¦¬μ†ŒμŠ€ λ‘œλ”©μ΄ 빨라진닀.

μ–΄ν”Œλ¦¬μΌ€μ΄μ…˜ μΊμ‹œλ₯Ό μ‚¬μš©ν•˜κΈ° μœ„ν•΄μ„œ html νƒœκ·Έμ— manifest μ–΄νŠΈλ¦¬λ·°νŠΈλ₯Ό μ„€μ •ν•œλ‹€.

manifest μ–΄νŠΈλ¦¬λ·°νŠΈλŠ” μΊμ‹œ λ§€λ‹ˆνŽ˜μŠ€νŠΈ ν…μŠ€νŠΈ νŒŒμΌμ„ μ°Έμ‘°ν•œλ‹€.

μ–΄ν”Œλ¦¬μΌ€μ΄μ…˜ λ‚΄μ˜ λͺ¨λ“  νŽ˜μ΄μ§€μ— manifest μ–΄νŠΈλ¦¬λ·°νŠΈλ₯Ό μΆ”κ°€ν•΄μ•Ό ν•œλ‹€.

λ§Œμ•½ manifest μ–΄νŠΈλ¦¬λ·°νŠΈλ₯Ό μ„€μ •ν•˜μ§€ μ•Šμ€ νŽ˜μ΄μ§€κ°€ μžˆλ‹€λ©΄ ν•΄λ‹Ή νŽ˜μ΄μ§€λŠ” μΊμ‹±λ˜μ§€ μ•ŠλŠ”λ‹€.

λ‘œλ”© 과정은 λ‹€μŒκ³Ό κ°™λ‹€.

  1. μ–΄ν”Œλ¦¬μΌ€μ΄μ…˜ μΊμ‹œκ°€ μžˆλ‹€λ©΄ λΈŒλΌμš°μ €λŠ” λ„€νŠΈμ›Œν¬μ— μ—°κ²°ν•˜μ§€ μ•Šκ³  λ¨Όμ € μΊμ‹œλ‘œλΆ€ν„° νŽ˜μ΄μ§€ λ Œλ”λ§μ— ν•„μš”ν•œ λ¦¬μ†ŒμŠ€λ₯Ό λ‘œλ“œν•œλ‹€.
  2. κ·Έ λ‹€μŒ μ„œλ²„μ˜ μΊμ‹œ λ§€λ‹ˆνŽ˜μ΄μŠ€νŠΈ νŒŒμΌμ„ ν™•μΈν•˜μ—¬ μ—…λ°μ΄νŠΈλœ λ¦¬μ†ŒμŠ€κ°€ μžˆλŠ”μ§€ μ²΄ν¬ν•œλ‹€.
  3. μΊμ‹œ λ§€λ‹ˆνŽ˜μŠ€νŠΈ 파일이 μ—…λ°μ΄νŠΈ λ˜μ—ˆλ‹€λ©΄ μƒˆλ‘œμš΄ λ²„μ „μ˜ λ§€λ‹ˆνŽ˜μŠ€νŠΈ 파일과 λ¦¬μ†ŒμŠ€λ“€μ„ λ‹€μš΄λ‘œλ“œ ν•œλ‹€.

μΊμ‹œ λ§€λ‹ˆνŽ˜μŠ€νŠΈ νŒŒμΌμ€ 3가지 μ„Ήμ…˜μœΌλ‘œ λ‚˜λ‰˜μ–΄ μžˆλ‹€.

  • CACHE
    • 기본적인 μ„Ήμ…˜μœΌλ‘œ 여기에 λ¦¬μŠ€νŠΈμ—…λœ λ¦¬μ†ŒμŠ€λŠ” μΊμ‹±λœλ‹€.
  • NETWORK
    • 캐싱과 상관없이 맀번 λ„€νŠΈμ›Œν¬ μš”μ²­μ„ ν•΄μ•Όν•˜λŠ” URL κ·œμΉ™
  • FALLBACK
    • λ¦¬μ†ŒμŠ€ μš”μ²­μ΄ μ‹€νŒ¨ν–ˆμ„ λ•Œ λŒ€μ‹  μš”μ²­ν•  URL

μ£Όμ˜ν•  점

λ§€λ‹ˆνŽ˜μŠ€νŠΈ νŒŒμΌμ„ μš”μ²­ν•  λ•Œ header 정보에 Content-Type을 text/cache-manifest둜 μ„€μ •ν•΄μ•Ό ν•œλ‹€.

HTML νŒŒμΌμ€ μžλ™μœΌλ‘œ μΊμ‹±λ˜μ–΄ 버린닀. κ·Έλž˜μ„œ HTML λ¬Έμ„œλ₯Ό μˆ˜μ •ν•΄λ„ μΊμ‹±λœ λ¬Έμ„œλ₯Ό λ‘œλ“œν•˜κΈ° λ•Œλ¬Έμ— μ μš©λ˜μ§€ μ•ŠλŠ”λ‹€.

이 경우, λ§€λ‹ˆνŽ˜μŠ€νŠΈ νŒŒμΌμ„ λ³€κ²½ν•΄μ„œ νŽ˜μ΄μ§€κ°€ μ—…λ°μ΄νŠΈ λ˜λ„λ‘ ν•΄μ•Ό ν•œλ‹€.

자주 λ³€κ²½λ˜λŠ” 파일이 μžˆλ‹€λ©΄ NETWORK μ„Ήμ…˜μ— μΆ”κ°€ν•΄μ„œ μ§€μ†μ μœΌλ‘œ μ—…λ°μ΄νŠΈ λ˜λ„λ‘ ν•˜λ©΄ λœλ‹€.

μ°Έκ³ ν•  λ§Œν•œ 링크

@changmlee
Copy link

changmlee commented Feb 6, 2018

λ„€ 정리 μž˜ν•΄μ£Όμ…¨λ„€μš”.
μŠ¬λ‘―λ©”μ΄νŠΈ μ• λ‹ˆνŒ‘ ν”ŒλŸ¬μŠ€μ—μ„œ μ›Ήμ†ŒμΌ“ μ‚¬μš©ν•  μ˜ˆμ •μΈλ° μ• λ‹ˆνŒ‘ ν”ŒλŸ¬μŠ€ κ°œλ°œμžλ“€λ„ 같이 μ°Έμ—¬ν•  수 있게 κ³΅μ§€ν• κ²Œμš”

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment