반응형
블로그 이미지
개발자로서 현장에서 일하면서 새로 접하는 기술들이나 알게된 정보 등을 정리하기 위한 블로그입니다. 운 좋게 미국에서 큰 회사들의 프로젝트에서 컬설턴트로 일하고 있어서 새로운 기술들을 접할 기회가 많이 있습니다. 미국의 IT 프로젝트에서 사용되는 툴들에 대해 많은 분들과 정보를 공유하고 싶습니다.
솔웅

최근에 올라온 글

최근에 달린 댓글

최근에 받은 트랙백

글 보관함

카테고리


반응형

Routing, Deep Linking and the Back Button

센차 터치 2는 history 와 deep-linking 을 지원합니다. 이것은 여러분의 애플리케이션에 두가지 큰 잇점을 드립니다.

- 앱 내에서 back 버튼을 사용할 수 있고 여기 저기 메뉴(화면)간 이동을 페이지 refresh 없이 정확하고 빠르게 할 수 있습니다.
- deep-linking은 유저가 앱 내의 어떤 부분이든 한번에 이동할 수 있도록 합니다.


이 기능은  native 앱에서 느낄 수 있는 효과를 줍니다. 특히 안드로이드 디바이스에서는 back button 이 있는데 이 기능을 완전히 지원합니다.





Setting up routes

history를 사용하는 방법은 아주 간단합니다. routes라는 개념을 염두에 두고 작업 하셔야 합니다. Route는 url과 콘트롤러 action들과의 간단한 매핑입니다. 해당 Controller action 중에  address bar 에서 특정 형식의 url을 감지하면 자동적으로 이 Route가 call 됩니다. 아래 Controller에 대한 간단한 예제를 살펴보겠습니다.

Ext.define('MyApp.controller.Products', {
    extend: 'Ext.app.Controller',

    config: {
        routes: {
            'products/:id': 'showProduct'
        }
    },

    showProduct: function(id) {
        console.log('showing product ' + id);
    }
});


위와 같이 route를 특정해 줌으로서 Main controller는 브라우저 url 이 #products/123 같은 형식이면 반응하게 됩니다. 예를 들어 여러분의 어플리케이션이 http://myapp.com 에 디플로이 됐다면 http://myapp.com/#products/123, http://myapp.com/#products/456, http://myapp.com/#products/abc 같은 형식의 url 이 되면 자동적으로 showProduct 함수가 call 됩니다.

showProduct 함수가 이렇게 call 되면 url을 제외한 id 토큰을 pass  합니다. route에 :가 포함돼 있으면 :id를 사용하게 됩니다. 그러면 url을 제외한 정보를 가져와서 함수에 전해주게 됩니다. 이 파싱된 토큰은 항상 string 입니다. (왜냐하면 url은 언제나 string 이기 때문입니다.) 그렇기 때문에 http://myapp.com/#products/456 를 입력하는 것은 showProduct('456')을 call 하는 것과 같습니다.

아래와 같이 여러개의 route를 가질수도 있고 route는 여러개의 토큰 가질 수도 있습니다.

Ext.define('MyApp.controller.Products', {
    extend: 'Ext.app.Controller',

    config: {
        routes: {
            'products/:id': 'showProduct',
            'products/:id/:format': 'showProductInFormat'
        }
    },

    showProduct: function(id) {
        console.log('showing product ' + id);
    },

    showProductInFormat: function(id, format) {
        console.log('showing product ' + id + ' in ' + format + ' format');
    }
});


두번째 route는 url이 #products/123/pdf 일 경우 showProductInFormat 함수를 통해서 콘솔에 showing product 123 in pdf 를 찍을 겁니다.

물론 실제로는 콘솔에 문자를 찍는 일은 필요 없겠죠. 그냥 여러분들이 필요한 기능을 이곳에 넣으시면 됩니다. 데이터를 수집한다던가 UI를 업데이트 한다던가 하는 일들을요.

Advanced Routes

디폴트로 라우트 안의 와일드 카드는 어떤 문자나 숫자가 와도 해당됩니다. 즉 products/:id/edit 는 #products/123/edit 과 매치 됩니다. 하지만 #products/a ,fd.sd/edit 와는 매치되지 않습니다. 두번째에 있는 스페이스나 쉼표 그리고 점은 정해 놓은 규칙에 맞지 않기 때문입니다.

경우에 따라서는 이러한 스페이스나 쉼표 점도 url에 매치될 필요가 있습니다. 예를 들어 url이 가져오고 전달할 파일 이름을 포함하고 있는 경우가 그것에 해당 될 겁니다. 이것을 구현하기 위해서는 route에 configuration 객체를 패스할 수 있습니다.

Ext.define('MyApp.controller.Products', {
    extend: 'Ext.app.Controller',

    config: {
        routes: {
            'file/:filename': {
                action: 'showFile',
                conditions: {
                    ':filename': "[0-9a-zA-Z\.]+"
                }
            }
        }
    },

    //opens a new window to show the file
    showFile: function(filename) {
        window.open(filename);
    }
});


action string 대신에 action 프로퍼티를 포함한 configuration 객체를 가지게 되었습니다. 여기에 conditions configuration도 추가했습니다. :filename 토큰에는 어떤 숫자나 문자 그리고 마침표가 올 수 있게 됬습니다. 이렇게 되면 http://myapp.com/#file/someFile.jpg 를 someFile.jpg 를 controller의 showFile 함수에 인자로서 패스하게 됩니다.

Restoring State

history나 deep linking을 지원하려면 유저가 deep link로 어떤 페이지에 가고자 했을 때 그 페이지의 UI 상태가 완전히 어딘가에 restore 돼 있을 필요가 있습니다. 그래야지 그 페이지를 신속하게 보여줄 수 있으니까요. 이것은 약간 트릭으로 보일 수 있지만 좀 더 간편한 애플리케이션 사용을 위해 필요한 사항 입니다.

http://myapp.com/#products/123 이런 식의 url 일 경우 product를 로딩하는 간단한 예제를 만들어 봅시다. 위 예제에서 Products Controller를 약간 수정하겠습니다.

Ext.define('MyApp.controller.Products', {
    extend: 'Ext.app.Controller',

    config: {
        refs: {
            main: '#mainView'
        },

        routes: {
            'products/:id': 'showProduct'
        }
    },

    /**
     * Endpoint for 'products/:id' routes. Adds a product details view (xtype = productview)
     * into the main view of the app then loads the Product into the view
     *
     */
    showProduct: function(id) {
        var view = this.getMain().add({
            xtype: 'productview'
        });

        MyApp.model.Product.load(id, {
            success: function(product) {
                view.setRecord(product);
            },
            failure: function() {
                Ext.Msg.alert('Could not load Product ' + id);
            }
        });
    }
});


끝이 products/:id 일 경우 앱의 메인 뷰(TabPanel 이나 다른 컨테이너 등)에 즉각 view가 추가 됩니다. 그리고 나서 서버로부터 Product를 구하기 위해 product model (MyApp.model.Product)를 사용합니다. 여기에 call back을 추가하고 새로 로드된 Product와 함께 product detail view를 보유 합니다. 즉시 UI를 렌더링 해서 유저에게 가능한한 빨리 비쥬얼한 화면을 보여주도록 합니다. (Product 가 로드돼 있다면 렌더링만 하는것 과 같은...)

deeply-linked view 에 대한 restoring state를 만들려면 각 앱마다 서로 다른 logic을 필요로 하게 될 겁니다. 예를 들어 Kitchen Sink는 NestedList 네비게이션 상태가 restore 될 필요가 있고 해당 url에 맞는 view를 렌더링 해야 할 겁니다. 이 기능이 Phone과 Tablet 프로파일들에서 구현되는지를 보시려면 Kitchen Sink 의  app/controller/phone/Main.js 와 app/controller/tablet/Main.js 파일들의 showView 함수를 살펴 보세요.

Sharing urls across Device Profiles

대부분 여러분은 Device profiles 사이에서 같은 route structure를 공유하기를 원할 겁니다. 이렇게 하면 유저가 폰에서 해당 url을 태블릿을 사용하는 친구에 보낼 수 있고 그 친구가 태블릿에서 제대로 된 정보를 같이 볼 수 있게 될 겁니다. 이렇게 하려면 Phone 과 Tablet-specific Controllers 의 수퍼클래스에 이 route configuration을 정의하는것이 가장 좋은 방법일 겁니다.

Ext.define('MyApp.controller.Products', {
    extend: 'Ext.app.Controller',

    config: {
        routes: {
            'products/:id': 'showProduct'
        }
    }
});


이제 Phone-specific subclass에서는 해당 product에 대한 Phone에 맞는 view를 보여주기 위해 이 showProduct  함수를 implement 할 수 있습니다.

Ext.define('MyApp.controller.phone.Products', {
    extend: 'MyApp.controller.Products',

    showProduct: function(id) {
        console.log('showing a phone-specific Product page for ' + id);
    }
});


Tablet-specific subclass 에서도 같은 작업을 해서 tablet에 맞는 view를 보여줄 수 있습니다.

Ext.define('MyApp.controller.tablet.Products', {
    extend: 'MyApp.controller.Products',

    showProduct: function(id) {
        console.log('showing a tablet-specific Product page for ' + id);
    }
});


이 규칙에는 몇가지 예외가 있습니다.  Kitchen Sink 예제에는 phone 과 tablet 에 맞는 view들이 있습니다. 두 프로파일에서 우리는 NestedList를 사용해서 navigation을 합니다. 하지만 Tablet 에서만 스크린의 왼쪽에 NestedList 가 옵니다. Phone에서는 화면에 꽉 찰겁니다. Phone에서 back 버튼이 원하는대로 작동하게 하려면 매번 NestedList 안에서 navigate 할 때마다 새로운 url을 history에 push 해야 합니다. 이 말은 Phone-specific controller는 추가적인 route를 가진다는 의미입니다. 이 경우를 보시려면 app/controller/phone/Main.js 를 살펴 보시기 바랍니다.


반응형

Tutorial: Detecting Touches in Corona

2012. 4. 12. 22:03 | Posted by 솔웅


반응형

Tutorial: Detecting Touches in Corona

오늘날 가장 구별되는 모바일 디바이스의 특징은 Touch screen 이라는 겁니다. 그러니까 개발자로서 코로나로 만드는 앱에 대해 유저에게 좀 더 리얼하고 풍부한 효과를 주기 위해  어떻게 user의 touch를 감지하는지를 정확히 아는 것은 중요합니다.

이 touch 에 대해 여러분들이 생각하는 것보다 더 많은 생각해야 할 것이 있습니다. 이 튜도리얼에서는 단지 touch를 어떻게 감지하는지 이외에도 user touch의 다양한 경우에 대해서도 생각해 보고 이것을 앎으로서 구현하고자 하는 기능을 좀 더 정확히 구현할 수 있도록 도움을 드리고자 합니다.

이 튜토리얼을 끝내시게 되면 touch phases, focus, dragging 같은 것들에 대해 좀 더 친숙해 지실겁니다. 이 튜토리얼은 가장 single touch 에 대해서만 다루겠습니다. Multi-touch는 좀 더 깊이 들어가야 할 주제입니다. 이 주제에 대해서는 나중에 다루겠습니다. 그 멀티 터치에 대해서 알기 위해서도 이 기본 touch 이벤트에대해 먼저 이해하는 것이 중요합니다.

만약 이 글을 읽고 계시는 분이 Corona event들에 대해 친숙하지 않으시다면 Corona Event Model Explained 를 먼저 읽어 보시기를 권합니다. 그 글을 읽으시면 이벤트와 리스너에 대해 이해하실 수 있을 겁니다. 그 글을 통해서 touch event에 대한 기본적인 내용도 아실 수 있습니다. event model에 대해 읽어 보신 후 이 튜토리얼로 돌아와서 보신다면 완벽하게 이해하실 수 있을 겁니다.





Detecting User Touches

User touch는 두가지 방법으로 감지 됩니다. 각 객체단위로 감지될 수 있고 전체 스크린 단위로 감지될 수 있습니다. (Runtime이나 global touch 가 전체 스크린 단위에서 감지 되는 겁니다.) 이 두가지가 어떻게 다른지에 대해 이해하는 것은 아주 중요합니다.

Per-object touches

우선 다른 특정한 이벤트가 감지되기 전에 이벤트를 add 해야 합니다. add 방법은 두가지 방법이 있습니다. table 리스너를 이용하던가 function 리스너를 이용하는 방법입니다.
아래 두개에 대한 예제가 있습니다.

Table Listener A와 Table Listener B는 기본적으로 같습니다. 약간의 다른점만이 있을 뿐입니다. 예제를 보면서 그 다른 점을 공부해 보세요.


* Table Listener A


local obj = display.newImage( "image.png" )

-- touch listener
function obj:touch( event )
    -- 'self' parameter exists via the ':' in function definition
end

-- begin detecting touches
obj:addEventListener( "touch", obj )


* Table Listener B

local obj = display.newImage( "image.png" )

-- touch listener
local function onObjectTouch( self, event )
    -- 'self' parameter must be defined via function argument
end

-- begin detecting touches
obj.touch = onObjectTouch
obj:addEventListener( "touch", obj )


* Function Listener

local obj = display.newImage( "image.png" )

-- touch listener
local function onObjectTouch( event )
    -- no 'self' parameter exists in this scenario
end

-- begin detecting touches
obj:addEventListener( "touch", onObjectTouch )


리스너 함수 안에서 어떤 일이 벌어지고 있는지에 대해서는 잠시 후에 다루겠습니다. 여기서는 객체에 어떻게 리스너가 add 되는지에 대해 주목해 주세요. 위 예제는 코로나에서 touch 이벤트에 대해 리스너를 다는 모든 방법에 대해 보여줍니다. 세번째 예제를 예를 들어 설명해 볼께요.

"유저가 obj를 touch 하면 onObjectTouch() 함수를 call 한다."


NOTE : 한 번 touch를 하면 touch event는 여러번 dispatch 됩니다. 그 이유는 touch 이벤트 안에는 여러개의 phases가 있기 때문입니다. 이 부분은 중요합니다. 잠시 후에 여기에 대해서 자세히 다루겠습니다.

Runtime Touches

여러분은 또한 Runtime 에 global 하게 touch 리스너를 add 할 수 있습니다. 그렇게 하면 전체 screen에서 touch 이벤트를 감지하게 될 겁니다. Runtime touch는 function listener 만 사용할 수 있습니다. 아래 예제가 있습니다.

local function onScreenTouch( event )
    -- no 'self' parameter
end

-- begin listening for screen touches
Runtime:addEventListener( "touch", onScreenTouch )


How to STOP detecting touches

특정 object에 대한 (global Runtime object도 포함해서) touch 이벤트 listening을 중지하시려면 addEventListener() 하셨던 방법대로 간단히 removeEventListener()를 call 하시면 됩니다.

-- example 1:
obj:removeEventListener( "touch", obj )

-- example 2:
obj:removeEventListener( "touch", onObjectTouch )

-- example3 :
Runtime:removeEventListener( "touch", onScreenTouch )


VERY IMPORTANT: Runtime 이벤트 리스너는 절대 자동적으로 remove 되지 않습니다. 만약 global Runtime object에 어떤 리스너를 add 하셨다면 이 리스너가 필요 없게 될 때 반드시 여러분이 직접 remove 해 주셔야 합니다. 그렇지 않으면 버그나 충돌이 일어날 수 있습니다.

개별적인 객체에 add된 이벤트 리스너는 그 객체(object)가 remove 될 때 자동적으로 remove 됩니다. 하지만 그 객체에 있는 리스너가 필요 없을 때 여러분이 직접 remove 해 주실것을 권장합니다. 항상 같은 객체에 같은 이벤트를 여러번 add 하는 일이 없도록 주의하셔야 합니다.

Touch Event Phases

초보 코로나 개발자분들은 touch listener를 사용하면서 몇가지 문제점에 당면하기 쉽습니다. 왜냐하면 유저가 한번 touch 할 때마다 listener fucntion이 한번만 call 될 걸로 기대하고 있기 때문입니다. 하지만 유저가 한번 Touch 한다고 그 리스너 함수가 한번만 call 되는 것이 아닙니다. 터치 이벤트가 발생하면 아래와 같은 phases 가 있습니다.

    began – 유저가 touch 하는 순간에 감지 됨
    moved – 유저가 터치한 손가락을 움직일 때 감지 됨
    ended & cancelled – 유저가 터치한 손가락을 화면에서 뗄 때 감지됨. 혹은 어떤 이유에서건 이 touch 이벤트가 cancel 됐을 때 감지 됨


이 touch phase가 감지될 때마다 지정한 터치 이벤트 리스너 함수가 call 되는 것입니다. 유저가 터치할 때마다 최소한 두번 내지는 세번 이 함수가 call 되는 것입니다.

그렇기 때문에 여러분들은 터치 했을 때 구현될 동작들이 어떤 phase에서 할 것인지 결정 하셔야 합니다. 그리고 나서 각 phase가 일어날 때 그 동작을 하도록 코딩을 하셔야 합니다. 아래 그 예제가 있습니다.

local function onObjectTouch( self, event )
    if event.phase == "began" then

        -- Touch has began

    elseif event.phase == "moved" then

        -- User has moved their finger, while touching

    elseif event.phase == "ended" or event.phase == "cancelled" then

        -- Touch has ended; user has lifted their finger
    end

    return true    -- IMPORTANT
end


위 예제 처럼 각 phase 를 if 문에서 감지하고 해당 phase에 여러분들이 넣고 싶은 동작들을 넣으시면 됩니다. 한번 터치 할 때마다 4가지 phase가 발생하고 이 phase가 발생할 때마다 onObjectTouch 함수가 call 되는 겁니다. 위의 예제처럼 대부분 ended와 cancelled phase는 같이 다룹니다.

To return true, or not to—THAT is the question.

위 예제 마지막에 보면 제가 OMPORTANT라고 주석을 단 것을 보실 수 있을 겁니다. 함수 끝에는 이와 같이 true 나 false 가 return 되어야 합니다.

touch 리스너가 true를 return 하면 그 touch 가 successful 하다는 의미입니다. touch 된 그 객체는 그 시간에 touch 됐음을 알립니다. 그렇게 함으로서 그 다음 event 가 제대로 dispatch 되게 됩니다. 그 object 밑에 touch 될 다른 object가 있다면 그 touch는 그 아래 object 에는 해당되지 않을 겁니다. 왜냐하면 그 위의 object 가 이미 그 touch에 대해 사용했기 때문입니다.

만약 리스너가 false를 return 했다면 (아무것도 return 하지 않아도 false를 return 한 것과 같습니다.) 그 touch는 뭔가 잘 못 됐다고 판단될 것이고 오직 began phase 만이 감지되고 끝날 겁니다. 이 경우 만약에 그 객체 밑에 터치 리스너를 감지하는 다른 객체가 있다면 그 터치 이벤트는 그 다음 객체에 전달이 될 겁니다. (이것을 이용하면 한 번의 터치로 두개의 object 에서 어떤 동작이 일어나도록 할 수 있을 겁니다. 단지 fault를 return 한 함수에서는 began phase 밖에 사용 못 하겠죠.)

이 부분이 새로 코로나 개발을 시작하는 분 들에게 혼동을 주기도 합니다. 이러한 touch 이벤트를 사용할 경우에 꼭 함수 끝날 때 true를 return 해야 한다는 것만 잊지 마세요.

Touch Focus

터치 리스너를 셋업했다면 아마 아래와 같은 모습을 하고 있을 겁니다.

local function onObjectTouch( self, event )
    if event.phase == "began" then

        -- specify the global touch focus
        display.getCurrentStage():setFocus( self )
        self.isFocus = true

    elseif self.isFocus then
        if event.phase == "moved" then

            -- do something here; or not

        elseif event.phase == "ended" or event.phase == "cancelled" then

            -- reset global touch focus
            display.getCurrentStage():setFocus( nil )
            self.isFocus = nil
        end
    end

    return true
end


해당 객체에 대한 터치 이벤트가 감지 됐을 때 touch focus를 global로 선언하는 것도 중요합니다. 이것은 began phase 단계에서 해야 합니다. 그리고  ended/cancelled phase 에서 이 Touch focus를 reset 시키게 됩니다. 그래야지 다른 객체들에 대한 touch 를 감지할 수 있게 됩니다. 이러한 내용들은 위 예제에 모두 구현돼 있습니다.

이 touch focus를 사용하신다면 힘들게 type 할 필요 없이 그냥 저 위의 예제를 복사해서 붙여 넣기만 하시면 됩니다.

Other Event Properties

터치 이벤트에는 phase 이외에도 여러가지 프로퍼티들이 있습니다. 아래 내용을 참고하세요.

    event.id – 해당 touch 이벤트에 대한 유닉한 구분자. (multi-touch에서 주로 사용됨)
    event.name – 해당 이벤트의 이름
    event.phase – 유저가 touch 한 현재의 phase 상태. began, moved, ended, cancelled 등이 있습니다.
    event.target – touch 된 object; self랑 똑 같은 의미임
    event.time – 이벤트가 일어난 이후부터 지금까지의 시간
    event.x, event.y – 이벤트가 일어난 x,y 좌표
    event.xStart, event.yStart – 최초 이벤트가 일어난 x,y 좌표. (began의 좌표가 됨). 유저가 drag 하게 될 경우 현재의 위치와 최초의 위치를 구분해서 사용할 수 있음
. 사용 예제를 보시려면 여기를 클릭 하세요.

프로퍼티에 대해 좀 더 자세한 내용을 알고 싶으시면 event API reference page를 참조하세요.

코로나에서는 이 touch 이벤트 이외에 tap 이벤트도 지원합니다. 이것은 touch 이벤트이지만 phase가 없습니다. 이것은 유저가 스크린 내 한 객체에 아주 빠른 tap이 일어나는것을 감지하고자 할 때 유용합니다.

tap 이벤트에 대한 자세한 정보는 Basic Interactivity 에 있습니다. 터치 이벤트에 대해 좀 더 자세히 할고 싶으시면 Events and Listeners documentation의 Touch Event 섹션을 보실것을 권장합니다.

반응형


반응형
Sharing sub views

전 시간 마지막에 다뤘던 예제도 유용하지만 서로 다른 프로파일별로 부분적인 특정 view를 공유하고 또 그 부분적인 view들을 서로 합치고 하는 방법도 일반적으로 사용됩니다. 예를 들어 태블릿 UI의 이메일 앱은 왼쪽에 메세지 리스트가 있고 오른쪽에 현재의 메세지가 나타나도록 스크린을 나눈다고 가정해 봅시다. Phone 버전에서는 똑 같은 message list 와 비슷한 message 뷰가 사용됩니다. 하지만 이 경우 스크린이 태블릿과 비교해서 많이 작기 때문에 card layout에 두가지를 한꺼번에 나타내기가 힘듭니다.

이 문제를 해결하기 위해 우리는 두 개의 서로 공유되는 sub view들을 생성하겠습니다. 메세지 리스트와 메세지 뷰어를 따로따로 sub view로 만들게 되겠죠. 어떤 경우든 class config를 구성해야 합니다.

Ext.define('Main.view.MessageList', {
    extend: 'Ext.List',
    xtype: 'messagelist',

    //config goes here...
});


And the Message Viewer:

Ext.define('Main.view.MessageViewer', {
    extend: 'Ext.Panel',
    xtype: 'messageviewer',

    //config goes here...
});


이제 태블릿 main view 에서는 아래와 같은 식으로 이 sub view를 이용하게 될 겁니다. :

Ext.define('Main.view.tablet.Main', {
    extend: 'Ext.Container',

    config: {
        layout: 'fit',
        items: [
            {
                xtype: 'messagelist',
                width: 200,
                docked: 'left'
            },
            {
                xtype: 'messageviewer'
            }
        ]
    }
});


이렇게 하면 200 픽셀크기의 메세지 리스트가 왼쪽에 나타날거구요 나머지 공간에 메세지 뷰어가 나타날 겁니다. 그럼 이제 phone 의 경우는 어떻게 될지 살펴 보죠.

Ext.define('Main.view.phone.Main', {
    extend: 'Ext.Container',

    config: {
        layout: 'card',
        items: [
            {
                xtype: 'messagelist'
            },
            {
                xtype: 'messageviewer'
            }
        ]
    }
});


이 경우 card layout과 함께 Container를 사용하면 됩니다. (이렇게 되면 한번에 한 아이템만 화면에 나타납니다.) 그리고 나서 리스트와 뷰어를 이 콘테이너에 집어 넣으면 됩니다. 이제 리스트 안의 어떤 메세지를 유저가 tap 했을 경우 메세지 뷰어를 보여주는 기능만 만들면 됩니다 . 이렇듯이  우리는 로드된 프로파일을 근거로 서로 다른 configuration만 함으로서 두개의 sub view를 쉽게 재 사용할 수 있습니다.




Specializing Controllers

View와 마찬가지로 많은 어플리케이션들은 여러 Profile 에서 공유될 수 있는 많은 Controller 로직들이 있습니다. Profile들 사이에서 달라져야 할 점은 대개 workflow와 관련된 것들입니다. 예를 들어 앱의 태블릿 프로파일은 한 페이지로 해결 될 수 있는 workflow가 Phone에서는 여러 화면으로 나누어야 되는 경우가 많습니다.

아래 간단한 Phone 프로파일이 있습니다. 여기서는 Main이라는 view와 Message라는 Controller 를 로드 합니다. 이전에 살펴 봤듯이 이럴경우 실제로는 app/view/phone/Main.js와 app/controller/phone/Messages.js 를 로드할 겁니다.

Ext.define('Mail.profile.Phone', {
    extend: 'Ext.app.Profile',

    config: {
        views: ['Main'],
        controllers: ['Messages']
    },

    launch: function() {
        Ext.create('Mail.view.phone.Main');
    }
});


여기서 폰과 태블릿에서는 대부분 controller들을 공유합니다. 그래서 우선 app/controller/Messages.js 에 controller 수퍼클래스를 생성하겠습니다.

Ext.define('Mail.controller.Messages', {
    extend: 'Ext.app.Controller',

    config: {
        refs: {
            viewer: 'messageviewer',
            messageList: 'messagelist'
        },
        control: {
            messageList: {
                itemtap: 'loadMessage'
            }
        }
    },

    loadMessage: function(item) {
        this.getViewer().load(item);
    }
});


이 Controller는 3가지로 구성돼 있습니다.

- 우리가 다룰 view와 관련해서 refs를 셋업합니다.
- Message List item의 tap 이벤트를 Listening 합니다. tap 되면 loadMessage 함수를 call 합니다.
- loadMessage 함수에서는 선택된 메세지 아이템을 Viewer 에 로드합니다.


이제 Phone 에 맞는 controller 작업을 하겠습니다.

Ext.define('Mail.controller.phone.Messages', {
    extend: 'Mail.controller.Messages',

    config: {
        refs: {
            main: '#mainPanel'
        }
    },

    loadMessage: function(item) {
        this.callParent(arguments);
        this.getMain().setActiveItem(1);
    }
});


보시면 Messages 수퍼클래스 controller를 extend 했습니다. 그리고 두개의 기능을 정의했습니다.

We add another ref for the phone UI's main panel

Phone UI의 panel에 맞게 하기 위해 수퍼클래스와는 다른 ref를 add 했습니다. 원래의 로직을 수행하기 위해 loadMessage 함수를 extend 했고 main 패널의 active 아이템을 message viewer에 셋업합니다. 수퍼클래스의 모든 configuration은 subclass에 의해 inherite 됐습니다. refs 같이 duplicated config가 있을 경우 이 config는 통합됩니다. 그래서 phone Message controller 클래스에는 3개의 refs 가 있게 됩니다. (main,viewer, messageList) 이와 같이 수퍼클래스를 extend 해서 사용할 경우 superclass의 config를 사용할 수 있게 됩니다.

Mail.controller.Messages 수퍼클래스는 애플리케이션이나 프로파일에 의해 사용되거나 변경되지 않았습니다. 이렇게 되면 자동적으로 로드되게 됩니다. Mail.controller.phone.Message controller 가 이것을 extends 했기 때문입니다.

What to Share

위 예제에서 refs 중 일부를 공유할 수 있습니다. 또한 Controller의 control config에 대해 Listen 하는 이벤트를 공유할 수도 있습니다. 일반적으로 프로파일별로 이보다 더 그 로직들이 나눠집니다. refs와 control config 들 중 좀 더 적은 수만이 공유될 겁니다.

모든 프로파일에 걸쳐 공유되어야 할 Controller config는 route 입니다. 이 map url은 콘트롤러 action을 위한 그리고  back button 지원과 좀 더 깊게 menu link 를 하기 위한 겁니다. 수퍼클래스에 route를 가지고 있게 만드는 것은 중요합니다. 왜냐하면 device에 상관 없이 같은 url은 같은 content에 map 되어야 하기 때문입니다.

예를 들어 여러분의 친구가 여러분 앱의 phone version을 사용한다면 그리고 여러분에게 그 친구가 현재 사용하고 있는 앱의 현재 페이지 링크를 send 한다면 태블릿을 사용하고 있는 여러분도 그 링크를 tab 함으로서 같은 내용을 볼 수 있어야 하기 때문입니다. 모든 route들을 수퍼클래스에서 관리하는것은 device에 상관없이 url structure의 consistent를 유지 가능하게 해 줄 겁니다.

Specializing Models

Model 은 Controller와 View에 비해 profile 별로 다른 기능이 적용되어야 하는 경우가 적습니다. 그래서 대개 subclass가 필요하지 않습니다. 이 에제에서는 model을 모든 device에 같이 적용되도록 하나의 클래스로 관리합니다.

Ext.define('Mail.profile.Tablet', {
    extend: 'Ext.app.Profile',

    config: {
        models: ['Mail.model.Group']
    }
});


반응형


반응형
머나먼 미국까지 왔습니다. 

프로그래머로서 열심히 공부하고 일하고 있습니다.

그리고 지난 주 투표 했습니다.

프로그램 열심히 짜고 있구요.. 새로운 것 열심히 배우고 있구요.. 한국 개발자분들과 열심히 나누고 있습니다.

그러면서도 대한민국 국민의 한 사람으로서 내가 할 수 있는 일을 계속 찾고 있습니다.

정치의 주인이 주인 노릇을 하려구요.

매니저가 매니저 노릇을 제대로 해야 팀원들이 제 역량을 발휘해서 경쟁력 있는 제품을 만들어 내듯이.....

주인이 진짜 주인이 되야 정치하는 애들이 제대로 일해서 좋은 나라 만듭니다.


꼭 투표 합시다....

















반응형


반응형

Using Device Profiles 

오늘날 모바일 웹 애플리케이션들은 다양한 디바이스들에서 동작하도록 해야 합니다. 아주 작은 모바일 폰에서부터 큰 태블릿까지 아주 다양한 디바이스들에서 말이죠. 이러한 디바이스들은 아주 다양한 스크린 해상도를 가지고 있고 각기 다른 사용법과 목적이 있습니다. 사람들은 집 밖에서 빠르게 정보를 구하거나 어떤 급한 일을 하기 위해 모바일 폰의 앱을 사용합니다. 태블릿 앱들은 폰 앱들보다는 비교적 긴 시간동안 사용되어 지는 경향이 있습니다. 태블릿은 집이나 어딘가에 앉아 있을 때 긴 시간동안 다루는 기기인 셈이죠.

이와같이 사람들은 각각의 기기(device)별로 각각의 앱 experience를 기대합니다. 또한 개발자 입장에서는 이런 다른 experience들 사이에서도 애플리케이션의 로직이나 asset들은 같이 사용할 수도 있습니다. 각각의 플랫폼에 맞춰 별도로 앱을 개발한다는 것은 시간을 많이 소비해야 하고 에러가 날 확률도 많습니다. 그리고 무엇보다 아주 지루하구요. 고맙게도 Device profile은 각각의 device 별로 맞춰서 코딩을 할 수 있도록 device type을 구하고 코드 내에서 별도의 로직으로 분화시킬 수 있어 각 플랫폼 별 별도의 앱 개발이라는 문제점에서 어느정도 벗어날 수 있도록 해 줍니다.





Setting up Profiles

Device Profile은 어플리케이션의 context 안에 존재합니다. 예를 들어 폰이나 태블릿에 이메일 앱을 생성하기를 원한다면 개발자는 app.js에 아래와 같이 하시면 됩니다. (이 방법이 생소하시면 Intro to Apps guide 를 보세요.

Ext.application({
    name: 'Mail',

    profiles: ['Phone', 'Tablet']
});


위 코드에서는 아직 Aplication에 launch function을 넣지 않았죠? 그러니까 저 코드에서는 이 두개의 프로파일들만 로드 할 겁니다. 관례적으로 이렇게 되면 app/profile/Phone.js 와 app/profile/Tablet.js 를 로드하게 됩니다. 그럼 아래에 Phone.js 가 주로 어떤 모습을 하고 있는지 예제 코드를 보겠습니다.

Ext.define('Mail.profile.Phone', {
    extend: 'Ext.app.Profile',

    config: {
        name: 'Phone',
        views: ['Main']
    },

    isActive: function() {
        return Ext.os.is.Phone;
    }
});


태블릿 프로파일도 위 폰 프로파일과 같은 패턴으로 만듭니다. 위 Phone profile을 보시면 단 3파트로만 구성돼 있죠? Profile name, 옵션으로 세팅하는 추가적인 view 그리고 profile이 activated 됐을 때 실행될 isActive 함수 이렇게 간단하게 세 파트로만 구성하시면 됩니다.

isActive 함수는 디바이스에서 이 앱이 실행 될 때 체크한 device type이 이에 해당되면 실행하게 됩니다. 가장 일반적인 경우는 built-in 프로퍼티인 Ext.os.is.Phone 과 Ext.os.is.Tablet를 사용해서 Phone 과 Tablet 프로파일을 별도로 만드는 겁니다. isActive function 안에는 여러분이 넣고싶은 어떤 코드도 들어갈 수 있습니다.

Determining the Active Profile

한번 프로파일이 로드되면 isActive function이 call 됩니다. 애플리케이션이 부팅되면서 처음 true를 리턴하는 것이 바로 profile 입니다. 그 다음 프로파일은 어플리케이션의 currentProfile을 세팅합니다. 그리고 어플리케이션은 그와 관련된 것들 (model,view,controller 기타 관련된 클래스들)을 모두 로드하기 위해 준비합니다. 이것은 현재 실행중인 프로파일에 맞게 필요한 것들을 조합하는 작업들을 하게 됩니다.

예를 들어 애플리케이션이 몇개의 model들과 몇개의 view들을 가지고 있다고 가정해 봅시다.

Ext.application({
    name: 'Mail',

    profiles: ['Phone', 'Tablet'],

    models: ['User'],
    views: ['Navigation', 'Login']
});


이렇게 되면 폰에서 앱을 로드할 때 Phone 프로파일이 activated 되고 어필리케이션은 아래 파일들을 로드하게 될 겁니다.

- app/model/User.js
- app/view/Navigation.js
- app/view/Login.js
- app/view/phone/Main.js


처음 세개의 아이템들은 Application 그 자체에 맞춰진 것들입니다. User 모델에 Navigation 뷰와 Login 뷰가 로드될 겁니다. 네번째 아이템이 바로 Phone 프로파일에만 해당하는 아이템입니다. 여기서 Phone에 맞는 form이 로드될 겁니다. 일반적으로 클래스들이 들어가는 폴더는 해당하는 프로파일의 이름을 사용하게 됩니다. 예를 들어 Phone 에 맞는 form 을 가지고 있는 Main 뷰는 app/view/phone/Main.js 경로에서 로드 될 겁니다. 그렇지 않고 프로파일에 속하지 않는 Main 뷰는 app/view/Main.js 경로에서 불려지게 될 겁니다.

models, views, controllers, stores 같은 프로파일에서 로드된 것들도 마찬가지 입니다. 이것은 behabior, view 로직들을 서로 공유할 수 있게 하므로 아주 중요한 부분입니다. 이 프로파일에 해당하지 않는 클래스들을 로드하려면 대신에 전체 클래스 경로와 이름을 넣어주시면 됩니다.

Ext.define('Mail.profile.Phone', {
    extend: 'Ext.app.Profile',

    config: {
        name: 'Phone',
        views: ['Main', 'Mail.view.SpecialView'],
        models: ['Mail.model.Message']
    },

    isActive: function() {
        return Ext.os.is.Phone;
    }
});


위에서 보듯이 전체 경로를 적는 클래스 이름을 명시할 수도 있고 (예: Mail.view.SomeView) 특정 클래스 이름만 적을 수 있고 ( Main - Mail.view.phone.Main 을 간략하게 표현) 또 이를 Mix 해서 사용할 수도 있습니다. 프로파일에 속한 모든 models,views,controllers, stores 는 이 방법을 사용해야 함을 명심하세요. 만약 태블릿 디바이스일 경우에만  로드되기를 원하는 Models 나 Stores 가 있다면 그리고 Mail.model.tablet.User 같은 식으로 클래스를 사용하고 싶지 않다면 fully-qualified 클래스 이름을 사용해야 합니다. (예. Mail.model.User)

The Launch Process


Profile을 이용한 launch 프로세스는 profile을 이용하지 않는 경우와 전혀 다를 것이 없습니다. Profile base 앱은 3단계의 launch process가 있습니다. 해당 프로파일과 관련된 클래스들이 로드 된 이후 다음과 같은 일들이 일어납니다.

1. Controllers 들이 instantiat 됩니다. 각 Controller들의 init 함수가 call 됩니다.
2. Profile의 launch 함수가 call 됩니다.
3. 어플리케이션의 launch 함수가 call 됩니다.


Profile을 사용할 때는 앱의 initial ui를 생성하기 위해 Profile launch 함수를 사용하는것이 일반적입니다. 많은 경우 Application의 launch 함수는 해당 프로파일의 initial UI가 다르다면 remove되고 Profile launch 함수의 initial UI가 실행 됩니다. (하지만 이 Application launch 함수에는 analytic이나 다른 profile-agnostic 셋업 등은 계속 존재 합니다.)

일반적인 Profile launch 함수는 아래와 같습니다.

Ext.define('Mail.profile.Phone', {
    extend: 'Ext.app.Profile',

    config: {
        name: 'Phone',
        views: ['Main']
    },

    isActive: function() {
        return Ext.os.is.Phone;
    },

    launch: function() {
        Ext.create('Mail.view.phone.Main');
    }
});


profile과 Application launch 함수들은 optional 한 겁니다. 이 부분을 정의하지 않으면 단지 call이 안될 뿐입니다.

Specializing Views

Most of the specialization in a Profile occurs in the views and the controllers. Let's look at the views first. Say we have a Tablet Profile that looks like this:
Profile 이 적용 되면 대부분 View나 Controller 부분이 그 프로파일에 맞는 클래스가 로드되야 합니다. view 부터 먼저 살펴 보겠습니다. 아래와 같은 Tablet Profile이 있다고 가정해 봅시다.


Ext.define('Mail.profile.Tablet', {
    extend: 'Ext.app.Profile',

    config: {
        views: ['Main']
    },

    launch: function() {
        Ext.create('Mail.view.tablet.Main');
    }
});


When we boot this app up on a tablet device, the file app/views/tablet/Main.js will be loaded as usual. Here's what we have in our app/views/tablet/Main.js file:
이 앱을 태블릿 기기에서 시작을 할 때 app/views/tablet/Main.js 파일이 로드될 겁니다. 이 Main.js 파일은 아래와 같습니다.

Ext.define('Mail.view.tablet.Main', {
    extend: 'Mail.view.Main',

    config: {
        title: 'Tablet-specific version'
    }
});


대개 view 클래스는 Sencha Touch에서 제공하는 view 를 extend 하게 되는데요 이 예제의 경우는 Mail.view.Main 을 Extend 했습니다. 이것은 자체적으로 만든 view 입니다. 아래 그 예제 코드가 있습니다.

Ext.define('Mail.view.Main', {
    extend: 'Ext.Panel',

    config: {
        title: 'Generic version',
        html: 'This is the main screen'
    }
});


이렇게 되면 우리는 Mail.view.Main이라는 수퍼클래스가 있고 수퍼클래스를 기반으로 customize 될 수 있는 Profile-specific subclass (Main.view.tablet.Main)를 가지게 됩니다. 여기서 우리는 Phone 인 경우 title 을 Generic version 에서 Phone-specific version으로 바꿀 겁니다.

이것은 일반적인 클래스이기 때문에 유연성있는 config 시스템을 이용해서 수퍼클래스의 어떤 부분이든지 쉽게 customizing 할 수 있습니다. 예를 들어 phone 버전도 있다고 하면 이 phone 버전의 Main view는 아래와 같이 customizing 할 수 있습니다. (app/view/phone/Main.js);

Ext.define('Mail.view.phone.Main', {
    extend: 'Mail.view.Main',

    config: {
        title: 'Phone-specific version',

        items: [
            {
                xtype: 'button',
                text: 'This is a phone...'
            }
        ]
    }
});


반응형


반응형

오늘도 어제에 이어서 Kurogo PDF 문서를 공부했는데요.

다양한 플랫폼과 해상도를 가진 모바일 기기에서 웹과 안드로이드, 아이폰용 앱을 만드는데 편리한 기능을 제공하는 Kurogo 라는 미들웨어가 정말 흥미로운데요?


처음에 안드로이드 앱만 만들다가 아이폰용으로도 개발하려고 했을 때 너무 어려워서 두 가지를 모두 지원하는 또는 손쉽게 개발할 수 있는 방법을 공부한다는 것이 이 블로그를 만든 목적이었는데요.


점점 공부하면 공부할 수록 다양하고 깊이 있는 정보들을 접하게 되네요.


점점 흥미있어지고 저도 다양하게 공부하면서 나름대로 전문적인 토양을 마련하는 기회를 점차 확보해가는 것 같아 뭔가 새로운 활력소가 되네요.


오늘 Kurogo 문서 남은 부분을 마저 다루겠습니다.


===== o ===== o ===== o ===== o =====


Kurogo's Architecture

So, how does Mobile Optimized Middleware work?

Kurogo Mobile Optimized Middleware는 여러분의 전사적인 시스템으로부터 정리되지 않은 데이타 소스들을 모으고 조직화 하고 그 데이터들을 모바일 웹사이트나 네이티브 모바일 어플리케이션들에 전달합니다. 모바일에 특화 되서 맞춘 connector, 비지니스 로직, presentation 탬플릿 그리고 API들의 조합들로 Kurogo Mobile Optimized Middleware 가 구성되는 겁니다.




Pre-Built and Custom Modules

그림 3에서 보듯이 데이터 소스들은 people, news, calendar, map, video, content, login, stats, emergency 등등 사전에 구성된 자원을 base로 모아지거나 별도로 customize된 모듈을 base로 모아지게 됩니다. 그리고 그 데이터들을 Kurogo Server로 보냅니다. 이 때 Mobile Campus 와 Mibile Enterprise 같은 Native 혹은 모바일 웹 베이스 솔루션들이 Kurogo로부터 데이타와 content를 request 하게 됩니다.

이 때 Kurogo는  유저의 screen size, 데이터 입력 방법(keyboard나 touch screen 등), 플랫폼, 디바이스 종류 등을 파악한 다음에 데이터와 콘텐트들을 파악된 여러 조건들에 적합화 된 방법으로 이 solution(Mobile Campus,Mibile Enterprise) 들에 전달합니다.

Kurogo’s Simple Admin Console

Kurogo Mobile Optimized Middleware는 사용하기 간단하고 site 관리를 빠르게 할 수 있는 웹 베이스의 admin consol을 제공하고 있습니다. 이 admin console은 모바일 앱이나 웹사이트를 구성하는데 있어 아주 간단한 코딩만 하면 되도록 만들어져 있습니다.

이 admin console로 여러분은 각각의 모듈에 대한 프로퍼티들을 보고 관리할 수 있습니다. 그리고 인증관련해서 관리하고 다양한 모듈의 behavior를 결정하고 site의 setup 등을 할 수 있습니다. admin console에는 SSL, theme, 디바이스 감지, 에러 핸들링 그리고 로그, 데이터베이스 configuration, 쿠키, 캐싱 이나 퍼포먼스, 분석, 파일 경로와 위치, text string, 싸이트 관리 등등의 광범위한 일들을 할 수 있는 기능을 제공하고 있습니다.




The Benefits of Kurogo Mobile Optimized Middleware

Open source

Kurogo는 오픈 소스 입니다. 그렇기 때문에 사용자는 그들의 소스코드에 100% 직접 access 할 수 있고 완전한 투명성을 제공합니다. 또한 이 Kurogo를 만드는 것은 Modo Labs의 엔지니어만이 아니라 아주 활도적인 Kurogo 커뮤니티를 통해 다양한 기술 발전이 이뤄지고 있습니다.

Faster App and Website Creation

Mobile Optimized Middleware는 CIO,전사적인 Architect 그리고 개발자들의 고된 일들을 싹 걷어 줍니다. 개방돼 있고 융통성 있는 API와 pre-built 된 애플리케이션들이 출동할 준비가 돼 있기 때문입니다. 모바일 웹 탬플릿들을 상속 받을 수 있고 데이터 핸들링은 flexible하고요, admin console 도 있고... integration과 개발 시간이 아주 많이 줄어 듭니다. 모바일 웹사이트들과 앱들은 보통 걸리던 시간에 비해 아주 적은 시간으로 작업을 완료할 수 있습니다.

Code Specifically Written for Mobile

현재 존재하는 미들웨어 플랫폼들은 규모가 큽니다. 왜냐하면 그 미들웨어 플랫폼들은 컴퓨터의 큰 화면과 빠른 네트워크에 맞게 디자인 되었기 때문입니다. Kurogo는 모바일 웹사이트와 앱들을 대상으로 모바일이나 태블릿이라는 제한된 대역폭, 작은 스크린 사이즈, 상호 작용 방법등에에 맞게 디자인 되었습니다.

Standard Languages and Systems


개발자들은 이 Kurogo 애플리케이션과 connector를 생성하는데 아주 간편해 할 겁니다. PHP, HTML5, CSS, Java Script 같은 친숙한 languages와 표준을 사용하기 때문이지요. 이것은 다양한 device platform 들에 대한 아주 좋은 user experience를 가능하게 해 주기 때문에 개발 비용을 크게 줄일 수 있습니다.

Taming the Jungle

Mobile Optimized Middleware는 integrate를 빠르고 깔끔하고 서로 조화롭게 해 줍니다. 이질적인 데이터 소스를 임시변통의 코딩들로 연결해서 정글처럼 만들어 컨트롤 할 수 없는 풍선이 되거나 전혀 이해할 수 없이 복잡하게 만드는 대신에 Kurogo Mobile Optimized Middleware는 빠르게 일 하면서도 서로 조화로운 데이터 소스들의 연결을 만들어 줍니다. Connection들은 유지보수 하기가 쉽습니다.

Focus on the User

Kurogo Mobile Optimized Middleware는 다양한 디바이스와 플랫폼들 사이에서 사용자들에게 사용하기 편한 환경(user experiences)을 제공합니다. 많은 모바일 개발 툴들은 한 디바이스에 맞게 작업을 하고 다른 하나는 거의 포기 해야 합니다. 하지만 한 디바이스를 포기한다는 것은 당신이 필요로 하는 고객들을 얻지 못한다는 말이기도 합니다. Kurogo의 유니크한 탬플릿 엔진은 다양한 디바이스들과 플랫 폼 또는 각각의 하드웨어단에서 맞춤형의 User experience를 가능하도록 합니다.

Customization Options

Kurogo 플랫폼과 함께 Modo Labs의 prebuilt 모듈은 곧바로 끌어다가 사용하기만 하면 됩니다. Customization은 모바일 앱이나 모바일 웹사이트를 출시하기 위해 작업하는데 특별히 추가의 작업이 필요 없는 경우가 대부분 입니다. 프로젝트의 시작 부분에 customizing을 시작하거나 이미 마련된 function을 사용하고 customizing작업을 잊어버려도  나중에 이것을 보완하던지 손쉽게 작업하실 수 있습니다. Kurogo Mobile Optimized Middleware 모듈들은 업무상의 user experience 의 필요에 맞는 Customizing 작업을 빠르고 쉽게 할 수 있습니다. 한번 그것들이 탑재되서 작동하면 업무상의 필요에 따라 모듈들을 확장하고 앱의 기능을 좀 더 추가하는 데에도 최소한의 개발 시간만 들이면 쉽게 할 수 있습니다.

Clean Break Between Business and Presentation Logic

적재 적소의 작업을 이룰 수 있습니다. 왜냐하면 이것은 모바일 웹사이트와 모바일 앱을 위해 디자인 되었기 때문에 Kurogo Mobile Optimized Middleware은 비지니스 로직 프로세싱과 presentation 로직 사이에 종종 나타나는  불확실한 경계에 대해 명료하게 나누는 작업을 해 줍니다.


The Mobile Enterprise and Mobile Campus Solutions from Modo Labs


비지니스와 교육에 대한 Modo Labs 솔루션들은 kurogo platform을 기반으로 만들어 졌고 Kurogo Mobile Optimized Middleware와 연결돼 있습니다.

이 솔루션들은 특정 모듈들로 구성돼 있습니다. 이 모듈들은 Kurogo를 통해 source로부터 나온 data와 content들을 request 합니다. Mobile Enterprise와 Mobile Campus는 Mobile Web, iOS 그리고 안드로이드 플랫폼에서 사용 가능합니다. 그들은 implement 될수 있고 특정 고객의 needs에 따라 modify 될 수 도 있습니다.





What to Look for in Mobile Optimized Middleware


여러분의 vendor에게 물어봐야할 것들
당신의 Mobile Optimized Middleware 로부터 얻어야 될 사항들을 확실히 하기 위해 아래 질문을 던져 보세요.

- 언제 데이터 소스가 바뀌고 코드를 바꾸는 일은 얼마나 쉬운가?
- 고객이 소스코드를 100% 볼 수가 있는가?
- 그 미들웨어는 open standard를 기반으로 했고 그 미들웨어 자체가 open source 인가?
- 기존에 존재하는 데이터과 레가시 시스템들과 얼마나 쉽게 integrate 할 수 있는가?
- 각기 다른 모바일 플랫폼들에서 최상의 user experience를 유지하기 위해 서로 다른 모바일 디바이스를 대상으로 웹 사이트와 애플리케이션에 대한 맞춤 작업이 얼마나 쉬운가?
- 그 플랫폼은 일반적인 (익숙한) user experience만을 제공하는가?


Kurogo Mobile Optimized Middleware나 Modo Labs에 대한 좀 더 많은 정보를 얻기 원하신다면 www.modolabs.com 를 방문해 주시거나 sales@modolabs.com 으로 연락 주세요.

반응형

'WEB_APP > Kurogo' 카테고리의 다른 글

Kurogo Tutorial 08 - Configuration-  (1) 2012.05.11
Kurogo Tutorial 07 - Device Detection -  (0) 2012.05.09
Kurogo Tutorial 06 - 소스 코드 여행 -  (0) 2012.05.08
Kurogo Tutorial 05 - 모듈 생성하기 -  (0) 2012.05.08
Kurogo Tutorial 04  (0) 2012.05.08
Kurogo Tutorial 03  (1) 2012.05.08
Kurogo Tutorial 02  (0) 2012.05.08
Kurogo Tutorial 01  (0) 2012.05.04
Kurogo Platform Demo 체험기  (0) 2012.04.25
Kurogo Mobile Optimized Middleware에 대해 -1-  (1) 2012.04.08


반응형

제가 이 블로그를 통해 하고 싶은 일은 다양한 모바일 기기를 지원하는 앱을 좀 더 쉽게 만들 수 있는 기술을 배우기 위해서 입니다.

이제 모바일 기기의 시대로 가고 있고 개인이든 기업이든 이 기술을 활용해야 더 편리하고 효율적인 작업을 할 수 가 있게 됩니다.

그런데 문제는 아이폰, 안드로이드폰, 윈도우폰, 블랙베리, 심비안 등 다양한 종류의 모바일 기기 OS 가 있고 다양한 폰과 다양한 태블릿이 있다는 겁니다.

처음에 안드로이드 폰용 앱을 개발하다가 아이폰용으로도 개발하고 싶어서 Objective-C 를 배웠는데요. 맥 컴터가 있어야 하고 또 완전 새로운 언어를 배워야 하고 그리고 앱 유지보수도 같은 앱이지만 따로 해야 되서 많이 불편했습니다.

그래서 접한 것이 Multi- Mobile Platform 을 위한 개발 언어인 Corona SDK 였습니다.
이 Corona SDK를 이용하면서 한번 개발하고 안드로이드와 아이폰용 앱으로 동시에 앱을 build 해서 안드로이드 마켓과 앱스토어에 올릴 수 있었습니다.

그리고 모바일 웹 기술을 이용하면 이 더 다양한 디바이스에서 사용할 수 있는 앱을 개발 할 수 있어서 HTML5, CSS3, Sencha Touch, JQuery Mobile 등을 공부하고 있습니다.

공부하던 중에 이 Kurogo Mobile Optimized Middleware 에 대해서도 접하게 되었습니다.

개발 단위의 멀티 모바일 플랫폼 지원 기술이 아니라 그 아래인 미들웨어단의 멀타 모바일 플랫폼 지원 기술입니다.

이 기술은 Modo Labs 에서 MIT Mobile Framework 을 기반으로 해서 만들어 졌습니다. Modo Labs 홈페이지 갔더니 주소가 메사추세츠의 캠브리지에 있더라구요. 거긴 하버드 대학하고 MIT 대학이 있는 곳이니까 아마 MIT 출신들이 만들었나 봅니다.

이 Kurogo Mobile Optimized Middleware 에 대해 이해하기 위해 홈페이지에서 제공하는 white paper 를 얻어서 읽어 봤는데요. 역시 가방끈이 긴 사람들이 만든거라서 그런지 영어가 많이 어렵네요. 

아래에 제 나름대로 번역한 글 정리합니다. (나중에 다시 볼 때 저도 영어보다는 한글로 정리된거 보면 좀 더 이해가 가거든요.) 혹시 영어 되시는 분은 직접 홈페이지 가서 다운 받아 보시면 더 도움이 되실 겁니다.

이 white pater 는 총 9페이지가 있는데요. 오늘은 4페이지까지 다루겠습니다.


White Page

Kurogo Mobile Optimized Middleware:
At The Heart Of Mobile Apps And Websites

Executive Summery

Mobile Optimized Middleware 는 fragmented mobile value chain(파편화된 모바일 가치사슬)에 적합하도록 개발된 미들웨어의 새로운 종류 입니다. 이 파편화는 복잡한 integration 과 유지보수, 개발 비용 증가 그리고 많은 예외적인 상황등과 같은 문제점을 일으킵니다.

-- 단어들이 좀 어렵습니다. 그냥 모바일 관련된 기기의 OS나 해상도 등이 너무 다양해서 거기에 맞춰 개발하려면 많이 힘들고 비용도 많이 든다는 내용으로 전 이해했습니다. --

Kurogo Mobile Optimized Middleware는 새로운 시도를 했습니다. 이것은 MIT 모바일 프레임워크에 기초해서 모바일에 특화해서 디자인 됐습니다.

이 문서는 파편화 된 모바일 가치 사슬과 관련해 이를 보완하기 위해 만들어진 Kurogo Mobile Optimized Middleware 의 구조와 어떻게 동작하는지를 설명하고 이것을 사용하면 어떠한 잇점이 있는지와 여러가지 팁 들을 알려 드립니다.

Why Mobile Optimized Middleware?

Fragmentation In the Mobile Value Chain

현재의 모바일 가치 사슬은 근본적으로 많이 분화(파편화) 돼 있습니다. 아 파편화는 모바일을 대상으로 한 비지니스의 전사적인 구조, 지식관리 노력, 애플리케이션 개발 과정 그리고 모바일 어플리케이션 설계를 위한 접근 등에 영향을 줍니다. 파편화는 가치 사슬(value chain)의 모든 과정에 존재합니다. organization의 데이터 자원부터 그것의 모바일 어플리케이션 그리고 모바일 지원 프로세스와 인력까지 이 파편화의 영향을 받습니다.




이 파편화는 아래 4가지의 기본적인 문제점을 야기 합니다.

1. 복잡한 integration과 유지보수 : CIO와 전사적인 Architect들은 그들의 비지니스를 위한 핵심 테크놀로지에 대한 작업 대신 모바일 앱과 데이타 소스간의 연결과 관련된 유지보수에 더 많은 비용과 시간을 지출해야 합니다.

2. 광범위한 개발과 QA : 모바일 프로그래머는 모바일 어플리케이션을 개발하는데 아주 많은 시간을 투자해야 합니다. 왜냐하면 이 다양한 플랫폼 (multiple platform)과 프로그래밍 언어에 대해 유지 보수 작업이 있어야 하기 때문입니다. 추가적으로 테스트도 복잡합니다. 왜냐하면 각각 다른 모바일에 대해 여러번 테스트를 진행해야 하기 때문입니다.

3. 기본 골격에 대한 프로세스 레벨 지원 : 앱 유저들은 모바일 작업의 중요한 일을 완료하기 위해 여러 다양한 모바일을 사용하고 심지어는 데스크 탑 어플리케이션까지 사용해야 할 때도 있습니다. 이것은 아주 불편하고 비 효율적이고 생산성이 떨어지는 작업입니다.

4. Under-supported roles : 유저들은 항상 다양한 모바일에 대한 사용법을 다 알지도 못하고 그러한 다양한 모바일을 제공받지도 못합니다. 이것은 직원들이나 고객들이 해당 모바일 앱을 사용하기 어렵게 만드는 요인이 됩니다.

The Jungle and How it Got that way

이 복잡한 정글이 어떻게 불쑥 나타났는지는 쉽게 볼 수 있습니다. 시장의 수요를 따라가기 위해서 소프트웨어 기업들은 그들이 사용하던 앱들을 모바일 버전으로 개발을 하게 됩니다. 그와 동시에 개발자들이 모바일에 맞게 작업을 하다 보면 그 기업의 새로운 프로세스나 역할들에 대한 지원 같은 특정한 needs를 만나게 됩니다.

이러한 과정은 모바일 앱 개발 뿐만 아니라 그 앱들을 다양한 데이터 소스와 연결해야만 하는 상황에 놓여지게 되는 것입니다.

A Solution Is Developed

이 데이터소스, connector, 앱, 프로세스, 역할(role) 등등으로 구성된 정글에 대한 해법은 새로운 접근 방식을 요구하게 됩니다. MIT 모바일 프레임워크를 기반으로 한 Kurogo Mobile Optimized Middleware는  위에 열거된 문제점들을 해결하기 위해 기획 되었습니다.




Simplicity at its Heart

그림 2를 보세요. 맨 윗부분 enterprise IT infrastructure(item 5) 부터 시작하겠습니다. Kurogo Mobile Optimized Middleware는 CIO와 전사적인 architect들을 위해 integration과 유지보수 과정을 단순화 했습니다. 다양한 데이터 소스들과 다양한 데이터 포맷들을 잘 다룰 수 있는 단 하나의 open API를 제공함으로서 그것을 가능하게 했습니다. PHP 같은 친숙하고 어떤 표준이 되는 언어를 사용함으로서 개발자들은 쉽게 많은 소스들로부터 데이터를 쉽게 얻을 수 있고 또 이를 모바일 앱에 쉽게 전달 할 수 있습니다.

Kurogo Mobile Optimized Middleware는 Modo Labs의 Mobile Enterprise 나 Mobile Campus (item 6) 같은 미리 구성(configure) 된 솔루션에 데이터를 공급합니다. 모바일 프로그래머의 개발 시간을 획기적으로 줄일 수 있습니다. 이 솔루션들은 인증, 디렉토리들, 뉴스 그리고 notification, calendar 등등 많은 자체 모듈을 가지고 있습니다.

Kurogo Mobile Optimized Middleware에 연결된 모바일 솔루션은 데이터를 다양하고 광범위한 데이타 소스들로부터 데이터를 땡겨와서 모바일 디바이스에서 그 데이터를 다루고 트랜잭션을 실행하는 결정을 하는 유저들에게 제공을 합니다. (item 7). Kurogo 가 디바이스에 이 데이터를 보여주기 전에 유저의 device type을 체크하고 컨텐트를 optimize 하기 때문에 Kurogo 기반의 모바일 앱은 best user experience를 얻을 수 있고 더 낳은 지원을 할 수가 있게 되는 겁니다. (item 8)

---- Kurogo's Architecture 는 다음 글에서 이어 집니다. ---

======= o ====== o ===== o ========= o ======== o ======

아래 글은 홈페이지에 설명된 간단한 Kurogo 에 대한 설명들 입니다.

Kurogo Mobile Platform
Mobile Optimized Middleware™


Kurogo는 파워 모바일 웹사이트와 아이폰,안드로이드 앱을 위해 만들어진 오픈 소스 플랫폼 입니다. 쿠로고는 clean integration, 예외적인 크로스 플랫폼 user experience 그리고 높음 customization 능력을 추구합니다.

Kurogo Technology

Kurogo Mobile Optimized Middleware (MOM)는 여러분의 enterprise 시스템으로부터 raw, 분산된 데이터 소스등을 통합하고 조직화 합니다. 그리고 그 데이터를 모바일 웹사이트와 native 모바일 애플리케이션에 전달 합니다. Kurogo 에는 AppQ, module wrapper 가 포함돼 있습니다. 많은 벤더들이 한번 코딩하고 다양한 플랫폼에 디플로이 하는 솔루션을 제공하고 있는 반면에  AppQ는 developer가 HTML과 CSS 모듈을 안드로이드와 iOS 코드로 convert 할 수 있도록 해 주는 유일한 기술입니다. 개발자는 어떤 모듈에 맞춰서 개발이 되고 또 그것을 어떤 모듈에서 잘 작동 되도록 convert 할 것인지 선택만 하면 됩니다. connector와 비지니스 로직, 탬플릿, module wrapper 그리고 API들의 조합들을 통해 Kurogo Mobile Optimized Middleware를 만들게 됩니다.


반응형

'WEB_APP > Kurogo' 카테고리의 다른 글

Kurogo Tutorial 08 - Configuration-  (1) 2012.05.11
Kurogo Tutorial 07 - Device Detection -  (0) 2012.05.09
Kurogo Tutorial 06 - 소스 코드 여행 -  (0) 2012.05.08
Kurogo Tutorial 05 - 모듈 생성하기 -  (0) 2012.05.08
Kurogo Tutorial 04  (0) 2012.05.08
Kurogo Tutorial 03  (1) 2012.05.08
Kurogo Tutorial 02  (0) 2012.05.08
Kurogo Tutorial 01  (0) 2012.05.04
Kurogo Platform Demo 체험기  (0) 2012.04.25
Kurogo Mobile Optimized Middleware에 대해 -2-  (0) 2012.04.09


반응형

오랜만에 트위터 갔는데 팔로워가 한분 늘었더라구요.

그분 트위터 보다가 발견한 환상적인 iPad 마술 쇼 예요.

감상하세요. ^^





반응형


반응형

지난번에 보았던 센차 터치 쇼핑몰 소스를 분석해 보겠습니다.

일단 Index.html 을 볼께요.

<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title>Shopping List</title>

    <link rel="stylesheet" href="css/app.css" type="text/css">
</head>

head 부분을 보시면 css를 css/app.css 를 사용하는 것을 볼 수 있습니다.


<body>
    <!-- In production use sencha-touch.js  -->
    <script type="text/javascript" src="sencha-touch/sencha-touch-1.1.0/sencha-touch-debug.js"></script>


이 부분을 보니까 이 소스코드는 sencha touch 1.1.0 버전을 사용하는 군요. sencha-touch-debug.js 파일을 불러오고 있습니다. 이 부분은 head 안에 있어도 되는데 이 소스코드에서는 body  첫 부분에 넣었군요. 이 js 파일은 따로 분석할 필요는 없습니다. 이 파일에 sench touch 의 수 많은 기능이 있는 파일이니까 그냥 계속 복사하면서 사용하시면 됩니다.


    <!-- Application starting point  -->
    <script type="text/javascript" src="js/app.js"></script>

    <!-- controllers -->
    <script type="text/javascript" src="js/controllers/Controller.Item.js"></script>

    <!-- models -->
    <script type="text/javascript" src="js/models/Model.Item.js"></script>
    <script type="text/javascript" src="js/models/Model.Unit.js"></script>

    <!-- stores -->
    <script type="text/javascript" src="js/stores/Store.Items.js"></script>
    <script type="text/javascript" src="js/stores/Store.Unit.js"></script>

    <!-- templates -->
    <script type="text/javascript" src="js/templates/Template.Item.js"></script>
    <script type="text/javascript" src="js/templates/Template.ItemDetail.js"></script>

    <!-- views -->
    <script type="text/javascript" src="js/views/View.ItemDetail.js"></script>
    <script type="text/javascript" src="js/views/View.ItemForm.js"></script>
    <script type="text/javascript" src="js/views/View.ItemList.js"></script>
    <script type="text/javascript" src="js/views/View.Viewport.js"></script>
</body>
</html>


body 부분에선 주로 js 파일을 불러오는 군요. 그래서 통일성을 주려고 sencha-touch-debug.js 도 body 안에서 불러온 것 같습니다.
괜찮은데요. 저도 센차터치로 프로그래밍을 할 때 이 프레임워크를 사용하게 될 것 같네요.

보시면 맨 처음에 앱이 시작할 때 참조하게 될 app.js를 지정해 줬습니다.

그리고 나서 MVC 패턴에 맞게 분리된 js 파일들을 불러오고 있습니다.

총 5개의 카테고리로 나눴네요. 맨 먼저 controllers 그리고 models, stores, templates, views 와 관련된 js 파일들을 불러옵니다.

폴더들은 이 카테고리에 맞게 js 폴더 밑에 따로 만들어진 것이 보이죠?

폴더 구조는 아래와 같습니다.


폴더 구조는 크게 css, img, js, scss 4가지 카테고리가 있습니다. sencha-touch 는 센차 터치에서 제공하는 파일들이구요. 이건 소스 분석 대상은 아니고 그냥 가져다가 사용하면 되는 센차터치 콘테이너죠. STEPS는 개발자가 이 소스코드를 설명하기 위해 강좌에 쓰인 각 개발 단계별 소스르 넣은 폴더 이구요.

제가 보고 싶은 부분은 js 폴더 였습니다.
MVC 모델을 이런식으로 사용하는 군요.
Model, View, Controller 가 기본적으로 있고 그 이외에 stores 폴더가 눈에 띕니다. local storage 기능을 사용할 거니까 이와 관련된 로직은 이 폴더 밑의 js로 따로 코딩을 했나 봅니다.
그리고 build,templates 가 있네요. 아직까지는 정확히 어떤 기능들을 따로 분리해 놓은 폴더인지는 모르겠지만 센차터치에서는 이렇게 js 파일들을 기능별로 나눠 관리하면서 MVC 모델을 사용하면 되는 것 같습니다.

이제 제가 이 소스코드를 통해서 얻고 싶은것의 80%는 다 공부 한 것 같습니다.

(참고로 scss는 css를 사용할 때 변수등을 사용해서 보다 간편하게 코딩할 수 있도록 도와주는 스크립트 언어입니다. 관심 있으신 분은 따로 찾아서 공부하셔도 좋을 거예요.)

index.html을 보았으니까 앱을 시작했을 때 가장 먼저 보게 될 app.js 파일을 보겠습니다.

이 app.js는 js 폴더 바로 밑에 있습니다. 같은 depth에 바로 models, views, controllers, stores ... 등등의 폴더가 있고 그 폴더 밑에 다른 js 파일들이 있게 됩니다.

Ext.regApplication('App', {
    name         : 'App',
    useLoadMask : true,
    phoneStartupScreen: './img/iStock_000004720241XSmall.jpg',

    launch: function() {
        this.viewport = new App.View.Viewport({
            application: this
        });

        Ext.dispatch({
            controller: 'Item',
            action    : 'showList'
        });
    }
});

음 이 app.js 파일을 보니까 이전에 본 구조이긴 하지만 Corona SDK 처럼 딱 한 눈에 해석이 되지 않네요.

센차 터치 튜토리얼을 좀 더 공부 해서 이 정도는 그냥 쉽게 해석이 되도록 해야 겠어요.
제 경험으로는 프로그래밍이든 뭐든 머리로 이해하려고 하는 것보다 계속 계속 반복해서 몸으로 이해하는게 더 좋은것 같더라구요.. ^^

찾아보니까 Ext.regApplication 는 1.1.0에서는 사용했지만 2.0.0 부터 없어진 메소드라고 하네요. 그래서 더 생소했나 봅니다. 2.0.0에서는  Ext.create 을 사용하면 될 겁니다. 그리고 그 다음에 Panel을 사용하죠. 지난 글에서 View를 할 때 아래 소스를 이용 했었습니다.

Ext.create('Ext.Panel', {
    html: 'Welcome to my app',
    fullscreen: true
});

그 다음에 launch: function()은 눈에 익네요. 튜토리얼 몇개 정리했더니  이 부분은 조금 감이 잡힙니다.

이 앱의 viewport를 설정하고 그 다음에 Ext.dispatch 가 있습니다. 이 부분도 2.0.0 부터는 없어진 메소드 입니다. 2.0.0 에서는 Ext.app.Application.dispatch 를 사용하시면 됩니다.

일단 애초 이 소스코드를 통해서 제가 배우고자 했던 것은 센차 터치로 MVC 모델 사용하는 것 과 실전에서 자주 사용되는 메소드를 익혀서 튜토리얼 공부할 때 좀 더 집중하고자 하는 거였는데요.

첫번째 목표는 달성했고.. 두번째는 이 소스코드가 1.1.0 을 기반으로 한 거라서 2.0.0 과는 많이 다르네요.

이 소스코드 분석은 이정도로 하고 계속 튜토리얼 공부를 하도록 하겠습니다.

어쨌든 센차터치로 앱 만들 때의 기본적인 프레임워크에 대해서는 충분히 새로운 것을 배운 것 같습니다.

튜토리얼 공부를 통해서 기본 지식을 좀 더 쌓고 여러 샘플 코드들을 분석해 보아야겠습니다.

그럼 다음 시간에 뵐께요.

반응형


반응형

구글에서 안경을 새로 발표 했지요?

쓰고 있으면 안경을 통해서 다양한 정보를 제공한다고 하던데...
날씨도 알 수 있고 교통편도 알 수 있고 또 지도도 볼 수 있고...

전화가 오면 전화건 사람이 누군지 볼 수 있고 또 그리고...

아.... 말을 하면 자동으로 문자로 바꿔서 친구한테 문자 메세지도 보낼 수 있다고 하던데..

진짜 그게 되는지는 모르겠어요.


구글에서 만든 홍보 동영상이 있던데 한번 보세요.


아주 죽이네요.

사진 찍으라고 말하면 사진도 찍고 말로 전화 걸고 받고 다하고 또 음악도 껐다 켜기도 하고 전화하는 사람이 내가 보고 있는 광경을 같이 볼 수도 있고...


패션은 어떤것 같으세요?

아직 생소해서 그런지 별로 그렇게 딱 와 닿지는 않네요.

그냥 이쁜 여자가 쓰고 있어서 좋게 보이긴 합니다.

만약 애플이 만들었다면 디자인이 좀 더 쌈박하지 않았을까 싶기도 하구요.


이대로 가다간 조만간에 안경 뿐만이 아니라 콘텍트렌즈까지 나올것 같은 분위기네요.
실제로 지금 연구중이래요.

유튜브에 이 구글안경 (Google Glasses) 와 관련해서 재밌는 패러디 하나가 올라왔어요.



패러디 실력이 아주 멋지죠?

어쨌든 구글 안경.... 안드로이드로 프로그래밍 할 수도 있을까요?

벌써 기대되는데요..... ^^


반응형