레이블이 javascript인 게시물을 표시합니다. 모든 게시물 표시
레이블이 javascript인 게시물을 표시합니다. 모든 게시물 표시

2015년 11월 23일 월요일

이펙티브 자바스크립트, Effective JavaScript

이펙티브 자바스크립트
데이비드 허먼 저/김준기 역 | 인사이트(insight) | 원서 : Effective JavaScript
http://www.yes24.com/24/goods/9375384?scode=032




JavaScript에 대한 이해가 깊지 않아 아직 코딩이 미숙하다.

JavaScript 기본 문법만 공부한지라 변수의 scope이나 클로저 등 좀 더 필수 적인 부분을 모르는 상태에서 코딩을 하고 있는지라 코드를 보면 참 안습이다. 그래서 좀 더 자세한 JavaScript 책을 찾던 차에 동료가 보고 있던 책이 눈에 들어왔다.

한가지 이유는 제목이 참 익숙해서 였다. 그리고 함께 마이어스아저씨가 생각 나며 괜찮겠다라는 생각과 동시에 Effective Java에서의 아쉬웠던 기억이 문득 머리를 스쳤지만 뭐... JavaScript 왕초보인 나에게는 큰 도움이 될 것으로 생각 했다.

막상 읽어 보니 초중급 책들에서 슬쩍 대충 다루는 좀 막연한 상황들을 저자의 경험을 통해 잘 찝어 내어 설명해주는 것 같다. 하지만 아직 내가 모든 항목들을 이해하기는 쉽지 않는 상태라 JavaScript 기본 문법은 이해를 한 상태에서 좀 코드를 짜본 경험이 있으면 아쉬운 부분에 대한 정답과 이해가 쉬울 것으로 보인다.

그리고 이 책 다보고 아래 책들도 한번 찾아보련다....
http://www.yes24.com/24/Category/Series/001001003016003010?SeriesNumber=184582


목차는 다음과 같다. 뭐 Effective 시리즈는 제목이 정답이니...

1장 자바스크립트에 익숙해지기
__아이템 1 어떤 자바스크립트를 사용하고 있는지 알아야 한다
__아이템 2 자바스크립트의 부동 소수점 숫자 이해하기
__아이템 3 암묵적인 형변환을 주의하라
__아이템 4 객체 래퍼보다 원시 데이터형을 우선시하라
__아이템 5 혼합된 데이터형을 ==로 비교하지 마라
__아이템 6 세미콜론 삽입의 한계에 대해서 알아두자
__아이템 7 문자열을 16비트 코드 단위의 시퀀스로 간주하라

2장 변수 스코프
__아이템 8 전역 객체의 사용을 최소화하라
__아이템 9 항상 지역 변수를 선언하라
__아이템 10 with를 사용하지 마라
__아이템 11 클로저에 익숙해져라
__아이템 12 변수 호이스팅에 대해 이해하라
__아이템 13 지역 변수 스코프를 만들기 위해 즉시 실행 함수 표현식을 사용하라
__아이템 14 기명 함수 표현식의 스코프에 주의하라
__아이템 15 블록-지역 함수 선언문의 스코프에 주의하라
__아이템 16 eval을 이용해 지역 변수를 생성하지 마라
__아이템 17 직접적인 eval보다 간접적인 eval을 사용하라

3장 함수 사용하기
__아이템 19 함수, 메서드, 생성자 호출의 차이를 이해하라
__아이템 20 고차 함수에 익숙해져라
__아이템 21 지정된 수신자 객체로 함수를 호출하기 위해 call 메서드를 사용하라
__아이템 22 다른 개수의 인자로 함수를 호출하기 위해 apply를 사용하라
__아이템 23 가변 인자 함수를 생성하기 위해 arguments를 사용하라
__아이템 24 절대 arguments 객체를 수정하지 마라
__아이템 25 자바스크립트의 부동 소수점 숫자 이해하기
__아이템 26 고정된 수신자 객체로 메서드를 추출하기 위해 bind를 사용하라
__아이템 27 커링 함수에 bind를 사용하라
__아이템 28 코드를 캡슐화하기 위해 문자열보다 클로저를 사용하라
__아이템 29 함수의 toString 메서드에 의존하지 마라
__아이템 30 비표준 스택 검사 프로퍼티를 사용하지 마라

4장 객체와 프로토타입
__아이템 31 __proto__보다 Object.getPrototypeOf를 사용하라
__아이템 32 __proto__를 절대 수정하지 마라
__아이템 33 생성자가 new와 관계 없이 동작하게 만들어라
__아이템 34 메서드를 프로토타입에 저장하라
__아이템 35 비공개 데이터를 저장하기 위해 클로저를 사용하라
__아이템 36 인스턴스의 상태는 인스턴스 객체에만 저장하라
__아이템 37 this의 명시적인 바인딩에 대해 이해하라
__아이템 38 서브 클래스 생성자에서 수퍼 클래스 생성자를 호출하라
__아이템 39 수퍼 클래스 프로퍼티 이름을 절대 재사용하지 마라
__아이템 40 표준 클래스를 상속하지 마라
__아이템 41 프로토타입을 세부 구현 사항처럼 처리하라
__아이템 42 무모한 몽키 패칭을 하지 마라

5장 배열과 딕셔너리
__아이템 43 직접적인 객체의 인스턴스로 가벼운 딕셔너리를 만들어라
__아이템 44 프로토타입 오염을 막기 위해 null 프로토타입을 사용하라
__아이템 45 프로토타입 오염을 막기 위해 asOwnProperty를 사용하라
__아이템 46 순서가 정해진 컬렉션에는 딕셔너리 대신 배열을 사용하라
__아이템 47 Object.prototype에 열거 가능한 프로퍼티를 절대 추가하지 마라
__아이템 48 열거하는 동안 객체를 수정하지 마라
__아이템 49 배열을 반복할 때 for...in 대신 for 반복문을 사용하라
__아이템 50 반복문 대신 반복 메서드를 사용하라
__아이템 51 유사 배열 객체에 범용적인 배열 메서드를 재사용하라
__아이템 52 Array 생성자 대신 배열 리터럴을 사용하라

6장 라이브러리와 API 설계
__아이템 53 일관된 컨벤션을 유지하라
__아이템 54 undefined를 ‘값 이 없는’ 것처럼 처리하라
__아이템 55 키워드 인자를 위해 옵션 객체를 받아들여라
__아이템 56 불필요한 상태 유지를 피하라
__아이템 57 유연한 인터페이스를 위해 구조화된 형식을 사용하라
__아이템 58 배열과 유사 배열 객체를 구별하라
__아이템 59 과도한 강제 형변환을 피하라
__아이템 60 메서드 체이닝을 지원하라

7장 동시성
__아이템 61 이벤트 큐를 I/O에 블로킹시키지 마라
__아이템 62 비동기 시퀀스를 위해 감싸지거나 이름이 지정된 콜백을 사용하라
__아이템 63 오류를 놓치지 않도록 조심하라
__아이템 64 비동기적인 반복문을 위해 재귀를 사용하라
__아이템 65 계산 중 이벤트 큐를 블로킹하지 마라
__아이템 66 동시성 연산을 수행하기 위해 카운터를 사용하라
__아이템 67 비동기 콜백을 절대 동기적으로 호출하지 마라
__아이템 68 더 깔끔한 비동기 로직을 위해 promise를 사용하라
 


아래는 책을 보다 알게 된 내용들을 아주 일부만 발췌하였고
이 책은 빌려봤는데 직접 사서 두고 봐야 모두 이해할 수 있겠고
나중에 개발을 하면서 참고용으로도 좋을 것 같다.


- 좌측 결합성(left-associative)
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_Precedence


- NaN(IEEE 부동 소수점 표준에 따른 역설적인 이름 'not a number')값을 테스트하기는 특히나 어렵다.

var x = NaN;
x === NaN; // false

- 암묵적인 강제 형변환으로는 데이터 형이 실제로 주어지지 않는다.
자바스크립트는 보이지 않게 valueOf 메서드를 (먼저) 실행한 후 toString을 실행하여 이런 불확실함을 해소 함

- false로 처리되는 값은 false, 0, -0, "", NaN, null, undefined

- 선언문에서 세미콜론을 생략하려면 현재 파일의 다음 토큰뿐만 아니라 스크립트 병합으로 인해 따라올 수 있는 다른 토큰도 함께 고려해야한다.

// a.js
; (function() {
//
})()
// b.js
; (function() {
//
})()

- 클로저가 외부 변수의 값을 변경할 수 있다는 점이다. 클로저는 실제로 외부 변수의 값을 복사하지 않고 참조를 저장한다.

http://www.slideshare.net/duggj/javascript-the-good-parts-43716401
Closures
Closures are functions that refer to independent (free) variables.
In other words, the function defined in the cl...

- 자바스크립트는 암묵적으로 둘러싼 함수의 맨 윗부분으로 선언을 끌어올리고(호이스팅) 할당 부분은 그 자리에 그대로 둔다.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/var#var_hoisting

http://www.slideshare.net/duggj/javascript-the-good-parts-43716401
Hoisting
 Variable declarations hoisted to top of function (top of scope)
 Function statements also hoisted
(function ()...

- 지역 변수 스코프를 만들기 위해 즉시 실행 함수 표현식을 사용하라

바인딩과 할당의 차이점을 이해해야 한다. ... 변수들을 바인딩하기 위해 메모리에 '슬롯'을 할당한다. ... 반복문의 본문은 감싸는 함수를 위한 클로저를 할당한다. ... 감싸진 함수가 생성되는 시점에 그 함수가 i의 값을 저장하고 있다고 기대 ... 사실은 i로의 참조를 포함할 뿐이다. ... 클로저는 외부 변수의 값이 아니라 참조를 저장한다.

- 어떤 실행 환경에서도 올바르게 동작하는 함수를 작성하기 위한 최선의 방법은 함수 선언문을 지역 블록이나 하위 명령에 절대 두지 않는 것이다. ... 함수를 조건에 따라 선택할 필요가 있다면 최선의 방법은 var 선언문과 함수 표현식을 사용하는 것이다.

- obj.hello() 표현식은 obj의 hello 프로퍼티를 찾고 수신자 객체 obj로 호출한다.

- apply 메서드는 인자의 배열을 받아 그 배열의 각 요소가 개별 인자 인 것처럼 함수를 호출한다. 인자의 배열 뿐만 아니라, ... 첫 번째 인자로 함수가 호출될 this의 바인딩을 명시할 수 있다.

- arguments 객체는 실제 인자의 배열과 비슷한 인터페이스를 제공한다. ... 이를 이용하면 arguments 객체의 각 요소를 순회하여 가변 인자 average 함수를 표현할 수 있다.

- prototype, getPrototypeOf, __proto__의 차이점을 이해하라.
. C.prototype은 new C()로 생성된 객체의 프로토타입을 만드는 데 사용된다.
. Object.getPrototypeOf(obj)는 obj의 프로토타입 객체를 가져오기 위한 표준 ES5 매커니즘이다.
. obj.__proto__는 obj의 프로토타입 객체를 가져오는 비표준 메커니즘이다.

- 비공개 데이터를 저장하기 위해 클로저를 사용하라.

- 인스턴스의 상태는 인스턴스 객체에만 저장하라.
. 수정 가능한 데이터는 공유 시 문제의 소지가 있으며, 프로토타입은 모든 인스턴스간에 공유된다.
. 각 인스턴스의 수정 가능한 상태 값은 인스턴스 객체에 저장하라.

- 객체를 열거하는 도중 새로운 프로퍼티가 이 객체에 추가된다면, 새롭게 추가된 프로퍼티는 현재 열거에 포함됨을 보장하지 않는다.

- for...in 반복문은 항상 키를 열거한다. ... 전통적인 for 반목문을 사용 ... 필요한 정수형 인덱스와 배열 요소를 얻을 수 있고 ... 기대하지 않은 문자열로의 강제 형변환도 발생시키지 않음을 보장해 준다. 게다가, 적절한 순서로 반복이 진행되며 배열 객체나 프로토타입에 저장된 정수가 아닌 프로퍼티를 우연히 포함하지 않음을 보장한다.

- Array 생성자 대신 배열 리터럴을 사용하라.
: 리터럴은 배열을 표현하기 위한 아주 매력적인 방법이다.

2015년 9월 16일 수요일

window.localStorage, Android webview localStorage 사용 설정

Webview 사용 중 HTML5 local storage 사용을 위해 찾아 봄

Web Storage로 local storage, session storage를 지원하고 있고
사용자 브라우저상에서 간단히 key/value쌍으로 저장할 수 있어 간편함.

표준 : http://www.w3.org/TR/webstorage/
MDN : https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API


localStorage와 sessionStorage의 차이점은
sessionStorage는 브라우저가 열려서 닫히기 전까지 유지된다는 점이고
localStorage는 삭제 시점이 없어 거의 영구적(local에서 삭제 되기 전까지)으로 유지된다는 점이다.

Window.sessionStorage
: https://developer.mozilla.org/ko/docs/Web/API/Window/sessionStorage


Window.localStorage
: https://developer.mozilla.org/ko/docs/Web/API/Window/localStorage
HTML5 Local Storage API 설정, 기본적으로 false로 되어 있음.
=> webview.getSettings().setDomStorageEnabled(true);

database storage API 사용 설정, 페이지 로드 전에 되어야 함.
=> settings.setDatabaseEnabled(true);

Application Cache API사용 설정, database path도 함께 설정 필요
=> settings.setAppCachePath(dir.getPath());
=> settings.setAppCacheEnabled(true);


롤리팝 부터는 WebView가 Platform 차원에서 관리 되던데
관련하여 API 사용이 변경되는 게 없는지 궁금함.
특히나 application cache 설정이 좀 바뀌지 않을까 생각되는데
자세한 내용은 못 찾겠음.


그래서 일단은 아래와 같이 사용..

WebSettings settings = webview.getSettings();
settings.setJavaScriptEnabled(true);
settings.setDomStorageEnabled(true);
settings.setDatabaseEnabled(true);

File dir = getCacheDir();
if (!dir.exists()) {
    dir.mkdirs();
}
settings.setAppCachePath(dir.getPath());
settings.setAppCacheEnabled(true);


그 외 setAppCacheMaxSize() 호출 하던데,
API level 18에서 deprecated 되어 굳이 필요 없을 듯.

2015년 9월 9일 수요일

Google Analytics api 사용하여 계정 통계 한번에 보기

Google Analytics를 사용해서
여러 site의 통계를 매일 확인 하다보면 좀 귀찮습니다.

한페이지에서 한번에 보고 싶은게 당연한데요.

역시나 Google에서는 Open API를 제공하고 있어서
그냥 자신이 보고싶은 통계들을 뽑아서 볼 수 있습니다.
 

[Google Analytics API를 사용해서 할 수 있는 것들]

: https://developers.google.com/analytics/devguides/config/mgmt/v3/#intro
  • List all the Account, Property and View (Profile) information for a user.
  • Manage Properties, Views (Profiles), and Goals.
  • Manage user permissions for an account hierarchy.
  • Retrieve a View (Profile) ID to use with the Core Reporting API.
  • Determine which goals are active and access their configured names.
  • Retrieve a user's Custom Segments to apply them to Core Reporting API queries.
  • Upload cost data to Google Analytics for non-Google paid campaigns.
  • Manage Content Experiments.
  • Manage Unsampled Reports.
  • Manage Filters and the links between Filters and Views (Profiles).
  • Manage Links between Analytics properties and AdWords accounts.


간단한 인증과 쉬운 구현을 위해
JavaScript API를 사용해서 페이지를 만들고자 하며
GA의 JavaScript API에 대해서는 다음 링크에서 자세히 알려주고 있습니다.

[JavaScript Quick start]

: https://developers.google.com/analytics/devguides/config/mgmt/v3/quickstart/web-js


* 기존 GA에 등록된 사이트(계정/property, 보기/view)가 하나라도 있어야 합니다.


간단히 정리하면 


Step 1. Enable the Analytics API
(GA API를 사용하기 위한 사용자 인증 정보 생성하기)

 : GA API를 사용하기 위해서 사용자 인증 정보를 생성해서 인증하여 API를 사용해야 합니다.

- Google Developers Console에서 Credentials page 링크를 들어가서 새로운 project를 생성합니다.

- Client ID 생성하기
 . 프로젝트 생성 후 "API 사용자 인증 정보" 창이 뜹니다.
 . 아래 "사용자 인증 정보 추가"를 눌러 "OAuth 2.0 클라이언트 ID 선택"
 . "클라이언트 ID 만들기" 창에서 아래 "동의 화면 구성"을 눌러 인증 시 표시될 이름 입력
 . 애플리케이션 유형은 "웹 애플리케이션"
 . 승인된 자바스크립트 원본은 "http://localhost:8080"
 . 승인된 리디렉션 URI는 "http://localhost:8080/oauth2callback"
 . "생성"

* 여기서는 샘플 어플리케이션을 localhost에서 8080번 포트의 웹서버에서 실행하는 지라 위에 처럼 자바스크립트 원본을 localhost:8080으로 입력 했는데 각자 아래에서 나올 샘플을 실행하실 서버 설정에 따라서 자바스크립트 원본의 domain, port, 리디렉션 URI의 port를 변경하셔야 합니다.

* 생성 후에는 클라이언트 ID를 잘 저장해 두세요. 샘플에서 인증 시 필요합니다.


Step 2. Setup the sample (샘플 코드 복붙)


GA 페이지에서 제공하는 샘플코드을 저장하시고
코드 중 var CLIENT_ID = '<YOUR_CLIENT_ID>' 에서 <>부분에 위에서 저장하신 클라이언트 ID를 붙붙으로 변경해 주시면 됩니다.

샘플 코드는 사용자의 GA에 등록된 첫번째 계정의
일주일 전부터 오늘까지의 세션 수를 요청하여
json format의 결과를 textarea에서 간단하게 보여줍니다.

Step 3. Run the sample 


코드를 서버에 올리시고 브라우저에서 실행 하세요.
처음에는 인증이 필요하니 버튼을 눌러 인증 하시면
GA에 등록된 계정과 뷰를 가져와서 보여줍니다.


간단하죠?


여러 계정의 통계를 보고자 할 경우
여기서 좀 더 추가하셔야 할 것들은

통계를 확인 하고자 하는 계정들의 id를 확인하고
보여주고자 하는 metric, dimensions, sort를 정하고
query 결과를 parsing하여 숫자나, 그래프로 보여 주면 됩니다.

여러 계정의 통계들을 보려면
어쩔 수 없이 여러번 API를 호출해서 확인해야하므로
사용하고자 하는 API에 대한 제약을 아래 API Limits and Quotas에서 꼭 확인하세요.
 : https://developers.google.com/analytics/devguides/config/mgmt/v3/limits-quotas

실제 Query시 결과를 보거나 matric,dimension을 변경하면서 테스트 하시려면 
아래 Query Explorer를 사용하시면 됩니다.

Query Explorer
: https://ga-dev-tools.appspot.com/query-explorer/


아래는 계정의 어제 국가별 방문 현황을 가져오는 sample function 입니다.

function query_country(id, gacode, tagid){

    gapi.client.analytics.data.ga.get({
        'ids': gacode,
        'start-date': 'yesterday',
        'end-date': 'yesterday',
        'metrics': 'ga:sessions',
        'dimensions' : 'ga:country',
        'sort' : '-ga:sessions'
    })
    .then(function(response) {           
        set_table_content("Country", response.result.rows, $("#" + tagid));           
    })
    .then(null, function(err) {
        $("#modal-content").text("일부 데이터를 불러오는 중에 에러가 발생했습니다.");
        console.log(err);
    });
}


2015년 5월 13일 수요일

Tizen WebView 사용 방법 정리, 설정, page 관련 signal, navigation policy 관리

Tizen Native app 개발 중 WebView를 사용하다 답답해서 정리함.

Tizen에서 제공하는 webview는 ewebkit2 기반이라고 한다.
자세한 내용과 간단한 사용 방법은 아래 링크 참고

Hello ewebkit?
: http://bunhere.tistory.com/m/post/417

Tizen WebView tutorial
https://developer.tizen.org/documentation/tutorials/native-application/web

Tizen WebView API reference
https://developer.tizen.org/dev-guide/2.3.0/org.tizen.native.mobile.apireference/group__WEBVIEW.html


Tizen document를 봐도 간단히 page만 loading하는 수준으로만 설명 되어 있고
그리고 몇가지 생각 나는 것은

- Tizen 2.2 platform API 대비 API 수준이 퇴화 한 것 같다.
 : 하나의 예로 WebView -> Native Interface가 없어졌음.

- WebView 내 page의 디버깅할 방법이 없다.
 : console log를 확인할 방법이 없고 안드로이드 처럼 크롬 개발자 도구 연동도 못한다.

- Documentation이 부실하다.
 : 예로 API reference상의evas_object_smart_callback_add()를 사용해서 처리하는 signal에 대해서는  signal definition과 argument type만 나오고 어떻게 사용하는지는 알 수 없다.


암튼... 삽질 하면서 몇가지 알게 된 것과
일반적인 Tizen Webview 사용 방법을 정리함.


[User agent 설정, Javascritp enable, cookie 사용 설정]

이부분은 API reference에 나와 있어서 쉽게 사용할 수 있는 부분임.

// user agent 설정
ewk_view_user_agent_set(ewk_view, "사용하고 싶은 USER AGENT");
Ewk_Settings* settings = ewk_view_settings_get(ewk_view);
// javascritp 사용 설정
ewk_settings_javascript_enabled_set(settings, true);

// 모든 cookie 사용 설정
  if(NULL != ewk_view_context_get(ewk_view) &&
NULL != ewk_context_cookie_manager_get(ewk_view_context_get(ewk_view)))
{
ewk_cookie_manager_accept_policy_set(ewk_context_cookie_manager_get(ewk_view_context_get(ewk_view)), EWK_COOKIE_ACCEPT_POLICY_ALWAYS);
}

근데.. webview 내에서 cookie를 설정할 때
webview 내의 web page에서 javascript로 cookie를 설정할 경우는 생성이 되지만
native에서 webview로 javascript execute로 cookie를 설정할 경우는 잘 안된다.

그리고 안드로이드는 platform 차원에서 cookie를 관리하는 cookie manager가 있지만
Tizen은 그런 것 없다. 만약 일반 브라우저에서 로그인 후 생성된 cookie를 동기화 해야할 경우가 있다면.... 방법을 모르겠다.


[JavaScript 실행]

Native에서 WebView 내 API를 호출할 수 있고 이는 Native에서 WebView로 전달할 것이 있을 때 유용함.

ewk_view_script_execute(ewk_view,"자바스크립트 코드", 
            "결과 전달 callback", "callback으로 전달할 user_data");

typedef void(*Ewk_View_Script_Execute_Cb )(Evas_Object *o, const char *result_value, void *user_data)

근데 재미 있는 것은 callback의 result_value가 항상 null로 넘어온다. 언젠가 수정 될듯.
(다른분께서 알려주신건데 result_value가 script에서 마지막의 변수나 return값을 가지는 함수의 결과값이 전달된다고 하니 참고..)


[Page 관련 signal]

page loading 관련, URL 변경 관련 처리를 할 수 있는 signal들을 아래와 같이 등록 가능 함.

evas_object_smart_callback_add(ewk_view, "url,changed", __on_url_changed, user_data);
evas_object_smart_callback_add(ewk_view, "load,started", __on_load_started, user_data);
evas_object_smart_callback_add(ewk_view, "load,finished", __on_load_finished, user_data);
evas_object_smart_callback_add(ewk_view, "load,error", __on_load_error, user_data);

아래와 같이 page 시작 시 signal을 등록하여 처리할 수 있음.
다만 WebView engine에서 loading은 이미 시작된 후 efl port에서 IPC를 전달 받아
callback이 실행되므로 시점 차이가 있을 수 있다.

void __on_load_started(void *user_data, Evas_Object *webview, void *event_info)
{
const char* url = ewk_view_url_get(webview);
DLOG("__on_load_started, URL = %s", url);

}

URL 변경 시 변경된 URL에 따라서 처리할 수 있음.
Hash값이 변경 되었을 경우에도 이 callback이 불리어 hash에 따라서
native에서 처리할 수 있다.

void __on_url_changed(void *user_data, Evas_Object *webview, void *event_info)
{
appdata_s *ad = (appdata_s *)user_data;
const char* url = ewk_view_url_get(webview);

DLOG("__on_url_changed, URL = %s", url);

// Do something for the changed URL.
}

이것을 활용하면 JavaScript -> Native 코드 호출이 가능하다.
JavsScript에서 hash 값을 변경하여 url 뒤에 필요한 명령을 붙이고
Native에서 __on_url_changed event callback 내에서 url의 hash값을 보고
native 코드를 처리하면 된다.


[WebView page navigation policy]

특정 domain내의 page만 webview를 통해서 보여주고 싶을 경우
아래와 같이 signal을 등록해서 처리해야 한다.

evas_object_smart_callback_add(ewk_view, "policy,navigation,decide", __on_policy_navigation, ad);

callback 내에서 이동하려는 url을 ewk_policy_decison_url_get()으로 확인한 뒤
허용되는 domain 내의 page이면 ewk_policy_decision_use()로 이동 허용
아니면 ewk_policy_decision_ignore()로 이동 취소를 하면 됨.


void __on_policy_navigation(void *user_data, Evas_Object *webview, void *event_info)
{
Ewk_Policy_Decision* decision = (Ewk_Policy_Decision*)event_info;

string _loading_url((char*)ewk_policy_decision_url_get(decision));
string _current_url(ewk_view_url_get(webview));

// 허용되는 SITE_DOMAIN 인지 확인
if(0  == _loading_url.compare(0, strlen(SITE_DOMAIN), SITE_DOMAIN) )
{
ewk_policy_decision_use(decision);
return;
}

// 허용되지 않는 URL
ewk_policy_decision_ignore(decision);
}


2015년 1월 6일 화요일

mobile device에서 touch 시 zoom 방지 하는 방법

젠장.. GB같은 옛날 기기에서는 안된다..
-----------------------------------

보통 web page의 확대/축소를 방지하기 위해서 아래와 같이 viewport를 설정하는 방법을 많이 사용함.

<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" />

하지만 일부 예전 device들 중에서는 제대로 되지 않는 경우가 있음.
이럴 때는 touch를 방지하는 방법으로 가능함.

http://stackoverflow.com/questions/8071603/safari-ipad-1-how-to-disable-zoom-centering-on-double-tap-but-keep-pinch-zoom


6down vote
+100
There's no other way than catching the events you want to prevent, and call preventDefault() on them, as you had already more or less figured out.
Indeed, some particular CSS properties / values may change the global site behavior (fixed width or fixed, for example), but you're not safe from changes to the OS (see fixedhandling change in iOS5), nor do these changes necessarily prevent all behavior (pinch might be off, but not double-tapping).
So, the best way to disable default behavior only for double-tapping is to take advantage of the count of touches iOS provides: if we have only one contact, then we're tapping. Two, this means we're pinching.
The following setup code provides that functionality:
var elm = document.body; // or some selection of the element you want to disable

var catcher = function(evt) {
    if (evt.touches.length < 2)
        evt.preventDefault();
};

elm.addEventListener('touchstart', catcher, true);
Demo on jsFiddle.
Note: the third parameter (true) to addEventListener means that we want to capture events, that is catch them all, even for our descendant children.
share|improve this answer


하지만 이렇게 되면 
전체 화면에서 touch가 먹지 않으므로 touch 필요한 버튼 같은 부분들에서는 문제가 발생그래서 touch가 된 html dom element를 확인하여 touch event를 허용, 취소 여부를 판단하는 코드를 추가함.

touch 필요한 dom element에 대해서는 class='button'와 같이 설정 하였음.

그래서 터치된 element의 class에 button이 포함 되어 있을 경우는 touch event가 전달 되고 그외에는 evt.preventDefault()로 인해서 touch event가 전달되지 않음.


var changedTouch = event.changedTouches[0];
var elem = document.elementFromPoint(changedTouch.clientX, changedTouch.clientY);

if($(elem).attr('class').search("button") != -1){
   return;
}

2014년 12월 11일 목요일

jQuery에서 ajax() 호출 시 response가 항상 똑같은 경우 (ajax GET, PUT method의 caching 방지)

일부 브라우저에서는 jQuery ajax로 GET, PUT method 호출 시
받아온 결과값이 항상 일정하거나 PUT이 제대로 먹히지 않는 경우가 있음.

원인을 몰라 난감하던 차에 아래 사이트 발견

selfesteem님의 [jquery] $.ajax 에서 GET일때 cache가 남는경우...
http://selfesteem.tistory.com/entry/jquery-ajax-%EC%97%90%EC%84%9C-GET%EC%9D%BC%EB%95%8C-cache%EA%B0%80-%EB%82%A8%EB%8A%94%EA%B2%BD%EC%9A%B0

http://stackoverflow.com/questions/367786/prevent-caching-of-ajax-call


위의 사이트를 참조하여
ajax로 GET method 호출 시

cache : false, 를 항상 추가하고

ajax로 PUT method 호출 시

URL + '?' + $.now() 로 해결함.


그리고 이 문제는 Galaxy S2에서 항상 재현된다.


2014년 12월 10일 수요일

jQuery ajax() 사용시 jqXHR의 error code가 0일 경우

jQuery를 사용하여 Ajax를 사용해서 REST API를  잘 호출 하고 있었으나
종종 앱 종료 시 호출되는 Ajax 호출이 error로 처리 되어
서버에서 종료 처리가 되지 않고 앱이 그냥 종료되는 상황이 발생함.

Ajax 호출 코드는 다른 곳에서도 잘 실행되던 거라
종료 처리를 하는 DELETE method가 문제인가 계속 확인을 하던 중
아래 링크들을 확인함.

http://cricri4289.blogspot.kr/2013/10/jquery-ajax-error-code-0.html
http://stackoverflow.com/questions/14313283/jquery-ajax-jqxhr-status-is-always-0


일반적인 경우는 Ajax 호출 후 바로 페이지가 새로고침이 되거나 전환 될 경우
Ajax 호출이 실패하고 error code가 0으로 리턴 될 경우가 있다고 함.
그게 아니라면 실제로 서버 연결이 안되거나 할 경우이고.

암튼 나의 경우는 Ajax 호출 후 바로 앱을 닫아 버려서
미처 Ajax 호출이 완료되지 않은 상태에서 앱이 종료되어 문제가 되었던 경우라서
Ajax 호출이 완료 되어 callback에서 종료 처리를 하고
혹시나 몰라 timeout을 사용해서 종료 처리를 하도록 함.

2014년 11월 24일 월요일

JavaScript Timer가 어떻게 동작하는가?

얼마전 JavaScript timer가 궁금해서 찾던 중 아래 글을 발견하고
JavaScript timer의 동작에 대해서 알게 되었음.

How JavaScript Timers Work, John Resig
http://ejohn.org/blog/how-javascript-timers-work/

작성된지는 꽤 오래전 글이라 다른 블로그에서 잘 다루고 있음.
http://holdonj.tistory.com/9


내용을 대충 정리하면 아래 두 함수는 JavaScript 코딩 중에 일정 주기로 코드를 실행되게 할 때 사용하는 함수들이다.

- setTimeout(fn, delay) : delay 이후 실행되는 single timer
- setInterval(fn, delay) : delay 마다 실행되도록 하는 주기적인 timer

함수의 효과는 동일하게 느껴 지지만 실제 사용할 때는 아래 사항들을 알고 사용해야 한다.

- JavaScript timer의 delay는 보장되지 않는다.
- JavaScript 코드는 실행가능한 조건에서 실행되며 이는 웹브라우저가 single thread상에서 비동기적 event들(mouse click, timer 등)을 처리하기 때문이다.

이를 아래 그림을 통해 자세히 설명 하고 있다.





위 그림 내에서
왼쪽의 숫자들은 시간(ms단위)를 의미하고, 오른쪽은 비동기적 event들을 나타내고,
중간의 블럭들은 실행되는 JavaScript 코드들이다.
 * JavaScript 코드들은 single thread 상에서 처리되므로 하나의 한 block만 처리된다.

시간 순서대로 보면 

- 20ms 내에서는 순차적으로 timer, mouse click, interval event들이 발생된다. 
 . mouse click 발생 시 event cb(callback)를 Queue에 등록한다.
 . 10ms 이후 등록된 timer cb을 실행되려 하지만 아직 JavaScript 코드가 실행중이므로 Queue에 등록한다. (Queue : mouse click event cb, timer cb)

- 20ms 전, JavaScript 코드가 완료되면 Queue의 첫번째 mouse click event cb을 처리한다.
 . 20ms 시점에 mouse click event cb처리 도중 interval cb이 실행되려 하지만 실행할 수 없어 Queue에 등록한다. (Queue : timer cb, interval cb)

- 30ms 전, mouse click event cb이 완료되고 Queue의 첫번째 timer cb이 실행된다. 
 . 30ms 시점에 interval cb을 실행하려 하지만 역시나 실행할 수 없는 상태라 Queue에 등록해야 하지만 브라우저에서 drop 시킨다. 
   > 긴 코드의 실행 시 발생되는 interval cb이 모두 Queue 등록되어 처리가 된다면 코드 완료 후 연속적인 interval 등록 코드들이 호출 되므로 브라우저에서 interval cb의 기등록 여부를 판단하여 drop 하는 것으로 보임.
 . 35ms 이후 timer cb이 완료 되고 Queue에 있던 interval cb이 실행된다.

- 40ms, interval cb이 실행되려 하지만 역시나 실행할 수 없는 상태라 Queue에 등록 (Queue : interval cb)
 . 40ms 이후 intervale cb이 완료되고 Queue에 남아 있던 interval cb이 실행된다. (Queue : nothing)


정리해보면
- JavaScript engine은 single thread 기반이라 비동기 event들을 queuing하여 실행한다. 
- setTimeout, setInterval은 비동기 코드를 실행하는 방법이 근본적?으로 다르다.
- timer cb의 실행이 block될 경우 다음 가능한 시점까지 delay된다.
- interval cb의 실행 시간이 delay보다 크다면 delay 없이 반복적으로 계속 실행 될 수 있다.


추가로 예제 코드를 보면

  1.   setTimeout(function(){
  2.     /* Some long block of code... */
  3.     setTimeout(arguments.callee, 10);
  4.   }, 10);
  5.   setInterval(function(){
  6.     /* Some long block of code... */
  7.   }, 10);

함수 정의 상으로는 두 코드 모드 10ms 간격으로 실행되는 것이 맞지만
setTimeout은 long code block이 실행된 뒤 10ms 이후에 실행 시도 하는 것이고
setInterval은 long code block을 이전 코드 실행완료 여부에 상관없이 10ms 간격으로 실행 시도 하는 것으로 차이가 있다는 것을 판단할 수 있을 것이다.


- 추가로 10ms 이하로 시간에 특정 코드를 호출하는 방법에 대한 포스팅

setTimeout with a shorter delay, David Baron
http://dbaron.org/log/20100309-faster-timeouts

2014년 5월 29일 목요일

TypeScript 특징

HTML5 Game Engine을 조사하던 차에 Turbulenz라는 곳에서
TypeScript를 사용해서 엔진을 개발했다고 해서 한번 찾아보게 되었음.
TypeScript는 Microsoft에서 개발 되어 공개되었고 type checking이 추가된 JavaScript의 superset이라 기존 JavaScript에 익숙하면 전이하기는 쉽고 TypeScript를 컴파일?한 결과물은 Javascript이므로 기존 Browser가 변경될 필요가 없다는게 특징이다.
OOP 개념을 가진 JavaScript 초보들에게는 좋을 수도....

다만 JavaScript의 subset이어서 기본 JavaScript library들을 사용하고자 할 경우 별도의 definition이 필요하다..

아래는 MS에서 공개한 TypeScript의 resource들이며
그 중 Tutorial을 먼저 보되 Simple Guide를 함께 보는게 편하겠음.
Specification은 120페이지라 필요할 때 보면 되고....


TypeScript
 : http://www.typescriptlang.org/
 : http://typescript.codeplex.com/

Simple Guide : http://www.typescriptlang.org/Handbook
Tutorial : http://www.typescriptlang.org/Tutorial
Language specification : http://www.typescriptlang.org/Content/TypeScript%20Language%20Specification.pdf

: TypeScript sample code

class Student {
    fullname : string;
    constructor(public firstname, public middleinitial, public lastname) {
        this.fullname = firstname + " " + middleinitial + " " + lastname;
    }
}

interface Person {
    firstname: string;
    lastname: string;
}

function greeter(person : Person) {
    return "Hello, " + person.firstname + " " + person.lastname;
}

var user = new Student("Jane", "M.", "User");

document.body.innerHTML = greeter(user);

[Type Script 특징]

보다보니 Simple Guide 중에서 아래와 같은 문구가 있음.

One of TypeScript's core principles is that type-checking focuses on the 'shape' that values have. This is sometimes called "duck typing" or "structural subtyping". In TypeScript, interfaces fill the role of naming these types, and are a powerful way of defining contracts within your code as well as contracts with code outside of your project. 

TypeScript의 기본 원칙들 중 하나가 변수가 가진 값의 형태에 따라 type-checking을 하는 것이고 이를 duck typing, structural subtyping이라고 한다. 라고 하고 있어 근본적으로 JavaScript와 다른 점을 알 수 있음.


[TypeScript: First Impressions]
: http://tirania.org/blog/archive/2012/Oct-01.html

위에서 Miguel de Icaza께서 TypeScript에 대해서 정리한 글임. pros, cons를 통해서 특징을 살펴 볼 수 있음.
간단히 보면 쉽게 배울 수 있고 type checking으로 통한 장점을 수용할 수 있고 컴파일 결과물은 JavaScript 코드 이므로 기존 browser나 runtime을 변경할 필요가 없음. 다만 개발환경이 VisualStudio에 국한된 것은 단점 임.

 - Pros
  : Javascript의 superset으로 기존 쉽게 전이할 수 있음.
  : Apache License로 Open Source
  : Code deploy전 type assist와 error 확인이 가능
  : Extensive type inference을 통해 type checking의 장점과 함께 JavaScript의 dynamism의 지킬 수 있음.
  : Classes, interfaces의 사용과 visibility 향상
  : explicit construct의 사용의 장점 (장점을 Nice syntactic sugar reduces boilerplate code 라 표현함)
  : TypeScript는 Node.JS pacakage로서 배포되므로 Linux, MacOS에서도 설치 가능
  : TypeScript는 compile time이나 server side에 적용되므로 code 실행을 위해 기존 browser나 runtime이 수정될 필요는 없음.

 - Cons
  : 사실상 Web은 Unix 기반이다.
  : 대부분 개발자들은 MacOS, Linux 상에서 code를 작성하고 Linux server로 deploy한다.
    그러므로 위에서 말한 type checking의 장점 주는 적절한 tool은 현재 Visual Studio Professional만 존재하므로 Windows외 환경에서는 이점을 누릴 수 없음.


그외 Google Dart team member가 작성한 자세한 정리글이 있는데 reddit은 너무 보기 지겹다.. ㅜㅜ
http://www.reddit.com/r/programming/comments/10rkd9/welcome_to_typescript/

그리고 TypeScript introduction video의 답글을 보면 꽤나 부정적임.. ㅎㅎㅎ
http://channel9.msdn.com/posts/Anders-Hejlsberg-Introducing-TypeScript


[TypeScript개발을 위해 필요한 것들]

[Compiler]

Visual Studio 2012용 설치 파일이 있어 설치하면 editor, compiler가 설치된다.
그외에는 Node.js package maanger를 통해서 설치할 수 있다고 하는데 안해봤음.

그리고 Visual Studio 2013 Update 2가 설치되어 있다면 기본으로 깔려 있으나
재미있는건 Visual Studio 2013 Update 2가 아니라면
아래 링크의 TypeScript 1.0 Tools를 설치해도 VS2013에서는 메뉴가 나타나지 않는다.

TypeScript 1.0 Tools for Visual Studio 2012
: http://visualstudiogallery.msdn.microsoft.com/fa041d2d-5d77-494b-b0ba-8b4550792b4d
: http://www.microsoft.com/en-us/download/details.aspx?id=34790

[Editors]
- Visual Studio 2012, 2013
- Vi, Emacs
 : http://msopentech.com/blog/2012/10/01/sublime-text-vi-emacs-typescript-enabled/

2014년 5월 28일 수요일

HTML5, JavaScript based Game Engines, Platforms

솔직히 모두 다 사용하지 않았고 game 관련 일을 하지 않으니 뭐가 대중성이 있고 사용성, feature가 좋은지 모르겠어서 아래 간략 정리표에서 눈에 띄는 것만 서치해서 적어봄.
그렇게 정리하다보니 대부분 game engine에 대한 documentation이 제대로 되어 있지 않아 주로 CocoonJS, Turbulenz에 대해서만 자세히 씀.

특이한것은 Turbulenz는 나름대로 자신들의 HTML5 게임 publishing을 제공하고 있다는 것과CocoonJS는 PhoneGap과 같지만 HTML5 게임에 특화되어 여러 모바일에서 HTML5 게임 실행을 가능하게 해준다는 것이다. (어떻게 보면 CocoonJS는 Game Engine 보다는 launcher의 개념이 맞을 듯)

CocoonJS 기반 앱에서 HTML5 game을 돌리는 건 생각보다 Quality가 좋았음. 아무래도 HTML5 feature들이 optimization이 잘 되어 있는 듯 하다. 다만 Apacha codova 기반으로 돌리다보니 여러 platform으로의 배포는 좋겠지만 앱 자체가 무거워질 수 밖에 없는 것은 단점일 듯.

Turbulenz의 게임들은 desktop Chrome에서는 동작이 되지만 FireFox, IE11에서는 동작이 안되는 앱들이 꽤 있었다. Game Engine을 설치해도 동작에 큰 도움이 되진 않는 것으로 보였다.
Mobile browser중 Chrome, Safari는 WebGL이 지원이 안되 실행이 불가능했고 그나마 FireFox 가 가장 동작이 되었고 기본 Android Browser도 일부 실행은 되었지만 touch가 먹지 않았음. (Developer Client를 설치해도 마찬가지...)


[HTML5, Javascript 기반 Game Engine들]
http://designzum.com/2014/03/29/best-html5-and-javascript-gamen-engine-libraries/

HTML5 Game Engine들 간략 정리표
http://html5gameengine.com/



HTML5 game 개발 관련 링크들 정리(Indie HTML5 game development)
: https://devcharm.com/pages/78-indie-html5-game-development

HTML5 Game App 개발 및 이슈, by 이창환(yich@dongguk.edu)
Game Engine에 대해서는  간략히 정리되어 있는 듯.
: http://www.slideshare.net/yich/html5-game-app-r2

Mobile browser의 HTML5 WebGL 3D graphics 지원 비교
: http://html5test.com/compare/browser/android-4.4/chromemobile-33/firefoxmobile-27/ios-7.0.html

근데 재미있는 것은 아래 Chrome 33(mobile)이 WebGL을 지원한다고 나와 있지만 실제 Galaxy S4로 측정해보면 안나오고 hidden flag를 켜야 함. (http://blog.laptopmag.com/how-to-enable-webgl-support-on-chrome-for-android)




[Construct2]



: http://en.wikipedia.org/wiki/Construct_(game_engine)
: cross platform 이며  IDE와 tool들을 제공하여
  초보자들도 쉽게 익히고 게임을 만들 수 있음.
  drap-and-drop 방식과 visual editor, behaviour-based logic system을 제공



- 홈피에서 제시하고 있는 features를 설명하는 문구들, 자세한건 읽어봐야 겠지만 문구들로 대략 감만 잡아보자... ㅜㅜ
 : Quick and Easy, Powerful Event System, Flexible Behaviors, Instant Preview, Stunning Visual Effects, Multiplatform Export, Easy Extensibility
- HTML5를 지원하는 browser를 대부분 지원하며 일반적인 major mobile browser들도 지원함.


[CocoonJS]

: https://www.ludei.com/cocoonjs/
: HTML5 app들이나 game들을 mobile기기들에서 test, accelerate, deploy, monetize할 수 있도록 하는 platform

- 사실 상 HTML5 게임에 특화되어 mobile 기기(iOS, Andorid, Windows mobile 등)에서 실행할 수 있도록 도와주는 역할. HTML5, Javascript game engine들로 구현된 game들을 CocoonJS를 사용하여 배포 가능함.
- iOS(5.0), Android(2.3+)에서 최적의 Canvas 2D, WebGL feature를 제공하고 HTML5 feature에 특화된 customized된 webview를 제공함.

[Architecture Overview]



  • Canvas+ : HTML5 API들의 subset을 포함하고 있음.
  • Webview+ : HTML5 app 개발을 위해 특화된 web view (단 Android 4.0 이상)
  • Apache Cordova : 다양한 OS(iOS, Android, Windows Phone 등)상에서의 deploy를 위해 사용하고 사용되는 Cordova는 Webview+를 기본 webview로 사용함.
  • System's Webview : 개발자가 원한다면 system webview를 사용가능
  • Extensions : In App purchases, Ads, Notification, Social extension, Google Play Games, Gamepad와 같은 Javascript extension들이 제공.
    • In App purchases: to add monetization support to your app game. Show me more
      • IAP는 publish될 platform의 IAP에 대한 interface임.
    • Ads extension: you can monetize with ads using this extension. Show me more
    • Notification: to add either push notifications or local notifications. Show me more
    • Social extension: to add facebook and social integration to your app/game. Show me more
    • Gamecenter: add gamecenter functionalities to your app.
    • Google Play Games: add google play games functionalities to your app either in iOS or Android.
    • Gamepad: Empower your games with gamepad support.

[devlopment, publish process]
https://www.ludei.com/cocoonjs/how-to-use/



1. HTML5 게임을 개발
2. Android, iOS에서 CocoonJS launcher app을 설치하여 테스트
3. HTML5 code를 cloud-based platform에 업로드 하면 결과물 생성

- 결과물은 zip 형태로 압축되어 제공됨
- 계정 등급에 따라서 컴파일 시간 제약이 있음.

[CocoonJS Launcher]



http://support.ludei.com/hc/en-us/articles/201048463-How-to-use
- Demo app들과 개발중인 HTML5 게임을 실제 device(iOS, Android)에서 실행해 볼 수 있고 디버깅도 가능함.

* ludei showcase 페이지에서 cocoonJS로 만들어진 게임들을 볼 수 있음.
* 생각보다 Demo game들의 Quality가 좋음.. 역시나 HTML5 featrure에 최적화가 잘 되어 있는 듯.


[Turbulenz]

: http://biz.turbulenz.com/home
: High quality HTML5 games를 대상으로 하며 개발사/개발자를 대상으로 hub를 제공하여 remote site에서 테스트를 하여 게임을 publish할 수 있도록 지원함. 아직 mobile 지원은 beta testing 중
- 2010년 $5M funding을 받아 2011년 출시됨. (https://angel.co/turbulenz)
- 2013년 Game Engine을 Open source 화 함.

[Platform Overview]



Turbulenz Platform은 개발자, 개발사가 게임을 publishing, monetizing을 가능하게 하는 server side infrastructure 형태의 구조
개발자, 개발사는 Turbulenz local server를 통해 게임을 개발.
Turbulenz Hub로 게임을 'Deploy'하여 remote environment에서 테스트 함.
Main Turbulenz game site로 'Publish'하여 clients(gamer)들이 game을 사용할 수 있게 함.


[Turbulenz products]

- Turbulenz Local Server
 : Turbulenz SDK의 일부, web server와 packaged API들을 제공함. 개별 컴터에서 실행 가능

- Turbulenz game site
 : Turbulenz website, 사용자들이 로그인, 게임 플레이, 다른 사용자들과 interaction이 가능

- Turbulenz Hub (https://hub.turbulenz.com)
 : 개발자/개발사에서 게임을 publish하기 전 테스트할 수 있는 환경

A visual guide to the Hub


[게임 개발 process]

- 개발자와 Artist들은 Turbulenz SDK의 tool을 사용하여 게임을 만든다.
- 개발사는 Turbulenz local server(SDK에 포함)를 통해 게임을 개발하고 테스트하여 외부에 delploy할 수준까지 만듬.
- 게임을 테스트를 위한 다양한 stage들(pre-alpha, alpha, beta) 마다 Turbulenz local server에서 Turbulenz Hub로 각 버전들을 'Deploy'한다.
- 성공적으로 version이 Deploy되면 개발사는 게임을 internal/external team들과 live environment(게임방 같은)에서 테스트 한다.
- 적당한 release candidate이 만들어진 경우 해당 버전을 Turbulenz Hub에서 main turbulenz game site로 'Publish'함.

http://docs.turbulenz.com/hub/user_guide.html


[Turbulenz Hub를 통해 개발자는...]

Testing Game with access control in a Staging server
- 자신의 게임을 Hub(remote 환경)에서 deploy하여 test 할 수 있음.
- Pre-Released game을 Trusted parties에게 사용할 수 있도록 할 수 있음.
- Self-Publishing을 위한 방법을 제공하여 publishing 전에 개발자 자신이 content를 생성하고 실행할 수 있음.
- Limited Access Preview Version publishing을 지원함.

Get online game execution's Metrics
- game을 실제 deploy된 환경과 같은 online에서 테스트 하여 performance, latency, distribution channel 등의 측정 정보(metric)를 획득할 수 있음.
- published된 game과 진행되는 test에 대한 측정 정보(metrics)들을 볼 수 있음.


[Hub에서 확인 가능한 Metrics]
  • Total Play Count
  • Average Play Duration (secs)
  • Total Play Duration (secs)
  • Total Sessions Completed
  • Daily Active Users (DAU)
  • Weekly Active Users (WAU)
  • Monthly Active Users (MAU)
  • Engagement Ratio (Weekly)
  • Engagement Ratio (Monthly)
  • Daily User Retention
  • Weekly User Retention
  • Monthly User Retention
  • Lifetime Total Users
  • Cumulative Daily Retention
  • Cumulative Weekly Retention
  • Cumulative Monthly Retention
  • Feed Add Count
  • Feed Reply Count
  • Followed Count
  • Unfollowed Count
  • Completed transactions
  • Daily Revenue (USD)
  • X Completed transactions
  • X Daily Revenue (USD)
  • Offering “X” Revenue (USD): 

[Game Engine's supporting Platforms and Browsers]
  • Windows (both 32 & 64-bit) XP / Vista / 7 / 8
    • IE 8, 9, 10
    • Firefox 3.6 and above
    • Chrome
  • Mac OS X 10.7 and above
    • Safari 6 and above
    • Firefox
    • Chrome
  • Linux (with WebGL support only)
    • Firefox
    • Chrome
  • Android
    • Chrome Beta
    • Firefox Beta
* 위에서 지원한다는 브라우저는 많지만 게임에서 사용하는 HTML5 feature에 따라 실행안되는 것도 많음.
* Android Browser, Android FireFox에서는 일부 demo 게임들이 돌아감. 하지만 Android Chrome이 WebGL을 지원하지 않아 게임 실행 불가
* iOS Safari가 WebGL을 지원하지 않아 게임 실행 불가


[Game Engine]

Runtime API들과 Offline tools로 구성됨.

Runtime API
- Low-level API
 : libraries(ex OpenAL, WebGL)의 interface, low leve hardware access(ex input mechanism, vector math operation)의 interface들로 구성되어 있음.
 : 하위 module(Device)
  . GraphicsDevice, MathDevice, PhysicsDevice, SoundDevice, NetworkDevice, InputDevice

- HIgh-level API : JavaScript libraries의 모음. Scene Graph, Material System, Forward, Deferred Renderers 등과 같은 feature들.
 : Features
  . Scene Graph, Amination, Resource Manager, Server Requests, Deferred Renderer, Forward Renderer, Default Renderer, Simple Renderer, 2D Rendering, Utilities



[Code skeleton]

Javascript, TypeScript(http://www.typescriptlang.org/)를 지원함.

<html>
<head>
    <title>Turbulenz - Getting Started Guide - API Example</title>
    <!-- Script includes go here -->
    <script src="jslib/debug.js"></script>
    <script src="jslib/webgl/turbulenzengine.js"></script>
    <script src="jslib/webgl/graphicsdevice.js"></script>
</head>
<body>
    <canvas id="canvas" width="640px" height="480px"/>
    <script>
        /* Game code goes here */

        TurbulenzEngine = WebGLTurbulenzEngine.create({
            canvas: document.getElementById("canvas")
        });

        var graphicsDevice = TurbulenzEngine.createGraphicsDevice({});

        var r = 1.0, g = 1.0, b = 0.0, a = 1.0;
        var bgColor = [r, g, b, a];

        function update() {
            /* Update code goes here */

            if (graphicsDevice.beginFrame())
            {
                graphicsDevice.clear(bgColor, 1.0);
                /* Rendering code goes here */

                graphicsDevice.endFrame();
            }
        }

        TurbulenzEngine.setInterval(update, 1000 / 60);
    </script>
</body>
</html>

3개의 javascript들을 include하고 'canvas' id를 가진 <canvas>에 game engine이 drawing을 함. 화면 rendering은 update() function내에서 처리 되어야 한다.


[Turbulenz Developer Client]

- Mobile 환경에서  Turbulenz HTML5 engine의 low-level component들을 사용하기 위해 필요한 native implementation.
- 개발된 게임을 mobile환경에서 다양한 app stores, platform services(payment, user notification 등) feature들 사용할 수 있게도 한다.
- Local server와 연동되어 게임을 테스트 해볼 수 있으나 실제 Android market으로 deploy하는 방법에 대해서는 나와 있지 않음.


[기타]

- Game Engine License : MIT license
 : https://github.com/turbulenz/turbulenz_engine/blob/master/LICENSE

- In app purchase를 위한 StoreManager Object를 제공함.
 : Game에서 item을 생성하고 User가 해당 item들을 basket에 등록하고 계산하는 flow.
 : Turbulenz에서 basket에 담기거나 구입된 item들을 관리하므로 내부적으로 store를 따로 구현할 필요 없고 StoreManager Object를 이용하면 됨.
 : 관련된것인지는 모르겠지만 Android Developer client의 경우 permission들 중 billing을 추가해야 함.




[Pixi.js]

pixi.js logo

http://www.pixijs.com/
https://github.com/GoodBoyDigital/pixi.js
: lightweight 2D library, WebGL을 지원해 hardware acceleration 가능 (지원 browser한)

Features
 - WebGL renderer (with automatic smart batching allowing for REALLY fast performance)
 - Canvas renderer (Fastest in town!)
 - Full scene graph
 - Super easy to use API (similar to the flash display list API)
 - Support for texture atlases
 - Asset loader / sprite sheet loader
 - Auto-detect which renderer should be used
 - Full Mouse and Multi-touch Interaction
 - Text
 - BitmapFont text
 - Multiline Text
 - Render Texture
 - Spine support
 - Primitive Drawing
 - Masking
 - Filters


[ImpactJS]



http://impactjs.com/
: web, mobile에서 동작하는 high performance 2D game들을 만들기 위한 JavaScript game framework.

- Impact Game Engine + Weltmeister Level Editor + Ejecta Framework for IPhone App Store
- GameEngine에서는 iPhone, modile device, desktop browser 로 client를 구분함.

[기타]
- License : Impact Commercial Software License Agreement
 : http://impactjs.com/impact-commercial-software-license-agreement

2013년 12월 20일 금요일

jQuery Ajax 관련 간단 정리, same-origin policy, JSONP, CORS

이전 블로그에서 이전 함 (원본 글 2013/12/20 작성)

[Ajax, Asynchronous JavaScript and XML]

 : client-server간 asynchronous web application을 만들기 위한 방법으로 웹페이지의 조작, 변동 없이 background에서 asynchronous하게 server로 부터 data를 받아 오는 것.
 : 일반적으로 data 수신을 위해서는 지속적인 polling을 사용 함.

By Gengns-Genesis - Own work, CC BY-SA 4.0,
https://commons.wikimedia.org/w/index.php?curid=41186925

[Same-origin policy, 동일 도메인 참조 정책?]

JavaScript 같이 browser-side programming 언어에서는 보안상의 이유로 스크립트가 실행되는 페이지와 다른 도메인(protocol[http,https], Host[x.x.x.x], port[:y] 가 모두 같아야 함.)의 페이지를 참조할 수 없게 하는 정책

: 도메인 비교 예시
 To illustrate, the following table gives an overview of typical outcomes for checks against the URL"http://www.example.com/dir/page.html".
Compared URL
Outcome
Reason
httpː//www.example.com/dir/page2.html
Success
Same protocol and host
httpː//www.example.com/dir2/other.html
Success
Same protocol and host
httpː//username:password@www.example.com/dir2/other.html
Success
Same protocol and host
httpː//www.example.com:81/dir/other.html
Failure
Same protocol and host but different port
Failure
Different protocol
http://en.example.com/dir/other.html
Failure
Different host
http://example.com/dir/other.html
Failure
Different host (exact match required)
http://v2.www.example.com/dir/other.html
Failure
Different host (exact match required)
httpː//www.example.com:80/dir/other.html
Don't use
Port explicit. Depends on implementation in browser.

이를 해결하는 방법으로는 여러 방법들(document.domain property, Cross-Origin Resource Sharing, Cross-document messaging, JSONP)이 있다고 함. 그외에는 서버의 도움을 빌려 Proxy를 만들고 Proxy를 사용하여 타 도메인의 페이지들을 참조하는 방법도 있음.

자세한것은 위 링크를..

[JSONP, JSON-P, JSON with Padding]

간단히 말하면 JSONP는 client단에서는 서버의 JSONP 주소를 script로 추가하고 서버에서는 처리를 한 뒤 client에서 지정된 callback을 결과값과 함께 호출해주는 방법.

client단에서는 아래와 같이 JSONP 주소로 script를 추가하고
<script type="application/javascript" src="http://server2.example.com/Users/1234?jsonp=parseResponse"> </script>
서버단에서는 처리를 마친 뒤 client단에서 지정한 callback(=parseResponse)을 결과값과 호출 하여 전달함.
parseResponse({"Name": "Foo", "Id": 1234, "Rank": 7});

jQuery를 사용하여 twitter의 글들을 가져오는 예제 

 <html>
<head> <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script> <script> $(document).ready(function(){ $.ajax({ url: 'http://twitter.com/status/user_timeline/padraicb.json?count=10', dataType: 'jsonp', success: function(dataWeGotViaJsonp){ var text = ''; var len = dataWeGotViaJsonp.length; for(var i=0;i<len;i++){ twitterEntry = dataWeGotViaJsonp[i]; text += '<p><img src = "' + twitterEntry.user.profile_image_url_https +'"/>' + twitterEntry['text'] + '</p>' } $('#twitterFeed').html(text); } }); }) </script> </head> <body> <div id = 'twitterFeed'></div> </body> </html>

JSONP 관련 jQuery ajax method의 property
- dataType : 'jsonp' 지정
- jsonp : 일반적으로 client에서 지정한 'callback' argument (http:host:port/jsonp_uri?callback=jquery function)를 서버에서는 호출할 function으로 지정한다. 하지만 arguemnt명이 callback이 아니라면 jsonp 속성으로 지정하면 변경됨. 
- jsonpCallback : jsonp 결과값이 전달될 function을 지정할 수 있음. 기본적으로는 jquery에서 알아서 지정한다.

[JSONP의 단점]
하지만 GET 방법만을 지원하고 보안상 이슈로 인해 CORS (Cross-Origin Resource Sharing, http://www.w3.org/TR/cors/http://en.wikipedia.org/wiki/Cross-origin_resource_sharing) 방법을 추천하는 분위기 같음.

JSONP의 단점 및 대안을 소개한 JSONP 사이트의 본문
 The problem

Thus far, JSON-P has essentially just been a loose definition by convention, when in reality the browser accepts any abitrary JavaScript in the response. This means that authors who rely on JSON-P for cross-domain Ajax are in fact opening themselves up to potentially just as much mayhem as was attempted to be avoided by implementing the same-origin policy in the first place. For instance, a malicious web service could return a function call for the JSON-P portion, but slip in another set of JavaScript logic that hacks the page into sending back private user's data, etc.

JSON-P is, for that reason, seen by many as an unsafe and hacky approach to cross-domain Ajax, and for good reason. Authors must be diligent to only make such calls to remote web services that they either control or implicitly trust, so as not to subject their users to harm.

Alternatives

There are many alternatives to JSON-P, but each of them has their own drawbacks or challenges. These techniques will not be covered in detail here, except for one: CORS (aka, "Cross-Origin Resource Sharing") -- the most recent addition to browser JavaScript for making cross-domain Ajax calls. Put simply, CORS is an extension to the standard XMLHttpRequest (aka, "XHR") object, which allows the browser to make calls across domains (despite the same-origin restriction). But it does so by first "preflighting" a request to the target server to ask it for permission.

[CORS]
브라우저 별 CORS 지원 여부 : http://caniuse.com/cors

앞서 말한 cross-domain request를 허용하게 하기 위한 표준적인 방법으로 다른 same-origin policy를 회피하기 위한 방법들 보다 다소 안전하다라고 소개하고 있음.

flow 는 다음과 같고 Javascript에서 XMLHttpRequest에 대해서 아래 옵션을 제공해 주면 
xhr.withCredentials = "true";
xhr.setRequestHeader("Content-Type", "text/plain;charset=UTF-8");

jQuery에서는
$.support.cors = true;

Browser에서는 Origin, Access-Control-Request-Headers header들과 함께 다른 도메인으로 request를 보내서 preflight 절차를 지나 response를 전달 받게 됨.


근데 난 mobile web app을 개발하기 위해서 localhost상에서 개발중인데 서버에서 localhost origin은 허용을 하지 않는 것 같고 계속 Chrome에서는 "Access-Control-Request-Headers" 헤더가 입력되어 전달되지 않는 것으로 보인다. 결국 서버 사이드에서 동작하는 JavaScript 상에서만 가능한건가?
나중에 Hybrid framework 상에서도 확인을 해봐야 겠음.

암튼 다음 링크들은 CORS 관련 링크들

 : http://www.html5rocks.com/en/tutorials/cors/
  => 전반적인 설명이 잘 되어 있음.
  => MDN documentation은 언제나 잘 되어 있음.
  => Server side, Client side에서 처리해야할 것들에 대해서 정리
  => 초반부에서 JSONP와 CORS의 제약에 대해서 설명해주고 있음.


[jQuery Ajax methods]

뭐 설명이 필요없고 링크의 API reference를 참고하시라.
 jQuery.ajax()
 : Perform an asynchronous HTTP (Ajax) request.

jQuery.ajaxPrefilter()
 : Handle custom Ajax options or modify existing options before each request is sent and before they are processed by $.ajax().

jQuery.ajaxSetup()
 : Set default values for future Ajax requests. Its use is not recommended.

jQuery.ajaxTransport()
 : Creates an object that handles the actual transmission of Ajax data.

jQuery.get()
 : Load data from the server using a HTTP GET request.

jQuery.getJSON()
 : Load JSON-encoded data from the server using a GET HTTP request.

jQuery.getScript()
 : Load a JavaScript file from the server using a GET HTTP request, then execute it.

jQuery.param()
 : Create a serialized representation of an array or object, suitable for use in a URL query string or Ajax request.

jQuery.post()
 : Load data from the server using a HTTP POST request.


[jQuery.ajax Examples]
Example: Save some data to the server and notify the user once it's complete.
1
2
3
4
5
6
7
8
$.ajax({
type: "POST",
url: "some.php",
data: { name: "John", location: "Boston" }
})
.done(function( msg ) {
alert( "Data Saved: " + msg );
});

Example: Retrieve the latest version of an HTML page.

1
2
3
4
5
6
7
$.ajax({
url: "test.html",
cache: false
})
.done(function( html ) {
$( "#results" ).append( html );
});

Example: Send an xml document as data to the server. By setting the processData option to false, the automatic conversion of data to strings is prevented.

1
2
3
4
5
6
7
8
var xmlDocument = [create xml document];
var xmlRequest = $.ajax({
url: "page.php",
processData: false,
data: xmlDocument
});
xmlRequest.done( handleResponse );

Example: Send an id as data to the server, save some data to the server, and notify the user once it's complete. If the request fails, alert the user.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var menuId = $( "ul.nav" ).first().attr( "id" );
var request = $.ajax({
url: "script.php",
type: "POST",
data: { id : menuId },
dataType: "html"
});
request.done(function( msg ) {
$( "#log" ).html( msg );
});
request.fail(function( jqXHR, textStatus ) {
alert( "Request failed: " + textStatus );
});

Example: Load and execute a JavaScript file.

1
2
3
4
5
$.ajax({
type: "GET",
url: "test.js",
dataType: "script"
});