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

최근에 올라온 글

최근에 달린 댓글

최근에 받은 트랙백

글 보관함

카테고리


반응형

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...'
            }
        ]
    }
});


반응형