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

최근에 올라온 글

최근에 달린 댓글

최근에 받은 트랙백

글 보관함

카테고리


반응형

Director to Storyboard “Transition” Guide -2-


Switching Scenes

디렉터 클래스나 스토리보드 모두 화면 전환의 목적은 같습니다. 하지만 그 화면의 이면에서는 어떤 일들이 벌어지는지는 완전히 다릅니다. 그 다른 부분 중 어떤 것들은 여러분들이 컨트롤 해야 될 필요가 있고 어떤 부분들은 별로 신경을 쓰지 않아도 되는 부분이 있습니다.

Director Scene Transitions


아래 예제는 디렉터 클래스를 사용해서 scene1에서 scene2 로 전환하는 방법을 보여 드립니다.

-- somewhere in scene1.lua...
director:changeScene( "scene2", "moveFromRight" )


위 코드대로 하면 scene1은 움직여서 보여지지 않고 scene2 가 화면에 나타날 겁니다. moveFrimRIght로 해서 화면은 오른쪽에서 왼쪽으로 옮겨질 겁니다. (이런 화면 전환 효과를 사용하지 않으려면 changeScene의 두번째 파라미터를 없애면 됩니다.) 아래 내용들은 director:changeScene()이 call 됐을 때 화면 뒤에서는 어떤 일들이 일어나는지를 정리한 내용입니다.
   
    - 디렉터가 scene2.lua를 로드하고 제 위치에 위치 시킵니다.
    - 두 scene 모두 최종 목적지로 transition 됩니다.
    - 디렉터는 scene1의 display group이 clean()메소드를 가지고 있는지 체크하고 만약 있으면 메소드를 call 합니다.
    - scene1의 display group이 remove되고 scene1이 unload 됩니다.


아주 간단하고 직관적입니다. 만약 여러분이 디렉터 클래스 사용자라면 위에 정리한 내용이 아주 익숙할 겁니다. 이제 스토리보드에서는 같은 화면전환이면서 그 이면에 어떤 다른 일들이 일어나는지 살펴 보겠습니다.





Storyboard Transitions

아래 스토리보드 API 를 사용해서 scene1에서 scene2로 화면 전환하는 예제입니다.

-- somewhere in scene1.lua...
storyboard.gotoScene( "scene2", "slideLeft" )


아래는 위에서 처럼 gotoScene이 call 됐을 때 화면 뒤에서 어떤 일이 일어나는지를 정리한 내용입니다.

    - scene1 : "exitScene" 이벤트가 dispatch 됩니다.
    - scene2 : 만약 view display group 이 없으면 새로 생성해서 시작 위치에 위치 시킵니다. (시작 위치는 화면전환 효과에 따라 달라집니다.) 그리고 나서 createScene 이벤트가 createScene 이벤트가 dispatch 됩니다.
    - scene2 : 만약 view 가 이미 존재한다면 그것을 시작 위치에 위치 시킵니다.
    - scene2 : willEnterScene 이벤트가 dispatch 됩니다. scene1과 scene2가 제 위치로 이동합니다.
    - scene1 : didExitScene 이벤트가 dispatch 됩니다.
    - scene2 : enterScene 이벤트가 dispatch 됩니다.


아주 많은 것들이 진행 되는 것 같네요. 그것들이 모두 유용한 것들입니다.

위에서 ~event가 dispatch 된다는 것은 그 이벤트를 이용해서 listener 함수를 사용하고 그 안에서 여러분이 어떤 작업을 할 수 있다는 얘기입니다. (뭐든지 필요한 기능을 구현하시면 됩니다.) 너무 복잡하게 느끼실 필요가 없습니다. 스토리보드의 다양한 이벤트를 이용해서 무엇을 구현한다는 것은 필수가 아닙니다. 여러분이 필요한 부분만 사용하시면 됩니다. 만약 여러분이 willEnterScene 이벤트를 작성하지 않았다면 이 이벤트는 dispatch 된 다음게 그대로 cancel 될 겁니다.

Which one should you use?

이 글을 쓴 목적은 디렉터 클래스 대신 스토리보드 API를 사용하라거나 반대로 스토리보드 대신 디렉터 클래스를 사용하라고 설득하기 위해 쓴 것이 아닙니다. 이 글의 목적은 디렉터 클래스의 주요 기능들을 스토리보드 API를 사용할 때 어떻게 사용해야 하는지를 보여드리기 위해 쓴 글입니다.

스토리보드 API는 코로나 SDK에서 화면 관리하는 것을 지원하려고 만든 코로나 SDK의 공식 API 입니다. 그렇다고 해서 여러분이 필요한데도 디렉터 클래스를 사용하지 말고 스토리보드 API를 사용하라는 의미가 아닙니다. 어떤 분들은 간단하게 화면 전환을 컨트롤 할 수 있는 디렉터 클래스를 선호할 것입니다. 그리고 디렉터 클래스는 오픈 소스 스크립트 입니다. 그리고 다른 관점에서 보면 스토리보드를 이용해서 코로나 이벤트 모델을 사용함으로서 좀 더 유연하고 다양한 기능을 사용하기 원하는 분들은 스토리보드 API를 선호할 겁니다.

어느것을 선택하시든 여러분들의 프로젝트에 더 적합한 수단을 사용하시면 되고 이 글을 통해 그 사용 법을 익힐 수 있었기를 바랍니다. 만약 여러분이 디렉터 클래스를 사용하시다가 스토리보드를 사용하시는데 어려운 부분이 있었다면 이 글을 통해서 그 혼란 스러움이 다 가셨기를 바라는 마음입니다.

특별히 스토리보드에 대해 좀 더 알고 싶으시면 이 링크를 클릭하셔서 공식 Storyboard API 문서를 보세요.

반응형


반응형

Director to Storyboard “Transition” Guide -1-

Lights… camera… CUT!

조명... 카메라... 컷!

코로나의 Storyboard API 가 나온지 꽤 됐습니다. 그런에 이 사용법에 대해서는 아직까지 약간의 혼동이 있는 것 같습니다. 최근에 제가 소개해 드린 스토리 보드의 이벤트 에 대한 글이 그 혼동을 해소하는데 약간 도움이 될 수 있을 겁니다. 하지만 스토리보드에 대한 설명은 단 한번으로는 부족할 겁니다.

스토리보드 API 이전에 Corona SDK에서는 scene 관리를 위한 공식적인 솔루션은 없었습니다. 그래서 대부분의 사람들은 Ricardo Rauber의 Director 클래스를 사용 했었죠. scene 관리를 도와주는 정말 대단한 3rd-party 오픈 소스 라이브러리 였습니다. 또한 scene 전환은 여러개의 쿨한 화면전환 효과를 사용해서 구현 할 수도 있었죠. 스토리보드가 나왔을 때 그 디렉터 클래스와는 사용법이 많이 달랐습니다. 그래서 디렉터 클래스 사용자들이 스토리보드를 곧바로 사용하는것은 좀 어려웠었던 것 같습니다.

그래서 오늘 여러분이 Director class를 사용하고 있다면 어떻게 스토리보드를 사용할 수 있는지 간단하면서도 쉽게 설명 드리겠습니다. 그리고 만약 여러분이 director class 유저가 아니라면 곧바로 스토리보드를 배울 수 있는 좋은 기회일 겁니다. 그런 분들은 이 문서를 꼭 보실 것을 권장합니다. (그 곳에는 more information section 있습니다.)





Scene Templates

디렉터 클래스는 오래 전부터 있어 왔습니다. 그 클래스는 꽤 큰 feature set 입니다. 저는 이 튜토리얼에서 module structure와 scene 변환에 대한 기본적인것을 다룰께요.

우선 Director 1.4의 scene template 으로 시작하죠. (이 글을 쓰는 현재 가장 최신 버전입니다.)

template.lua (Director)

module(..., package.seeall)

--====================================================================--
-- SCENE: [NAME]
--====================================================================--

new = function () 
    ------------------
    -- Groups
    ------------------
  
    local localGroup = display.newGroup()
  
    ------------------
    -- Your code here
    ------------------
  
    --- CODE ---
  
    ------------------
    -- MUST return a display.newGroup()
    ------------------
  
    return localGroup
end


디렉터 클래스는 아주 간단하고 사용하기 쉽습니다. (그래서 개발자들이 아직까지 이 방법을 사용하고 있는 이유겠죠). 바로 위에 소개한 scene tamplate 에 대한 설명을 하겠습니다.

new() 함수안에 여러분의 scene과 관련된 코드가 들어갑니다. 그리고 중요한것은 모든 display 객체들은 같은 group에 insert 하셔야 합니다. 그리서 그 그룹이 마지막에 return 되야 합니다. (위 예제에서는 localGroup이 됩니다.)

화면전환 (scene transition)이 발생하면 디렉트 클래스는 현재 화면을 밖으로 보내고 그 다음 화면을 화면으로 불러옵니다. (이 때 화면 전환 효과를 사용하실 수 있습니다.)

화면 전환이 완료 되면 이전 화면은 remove 됩니다. 옵션으로 clean() 메소드를 화면의 group에 추가해도 됩니다. 이것은 화면을 remove 하기 바로 전에 call 됩니다. clean() 메소드는 timer들을 정지시키고 Runtime listener를 remove 하기에 좋은 메소드 입니다. 아래 예제는 이 clean() 에소드가 포함된 경우 입니다.

template.lua (Director)

module(..., package.seeall)

--====================================================================--
-- SCENE: [NAME]
--====================================================================--

local cleanUp = function()

    -- stop timers, transitions, listeners, etc.

end

new = function () 
    ------------------
    -- Groups
    ------------------
  
    local localGroup = display.newGroup()
  
    ------------------
    -- Your code here
    ------------------
  
    --- CODE ---
  
    ------------------
    -- MUST return a display.newGroup()
    ------------------

    -- add clean method
    localGroup.clean = cleanUp
  
    return localGroup
end


Storyboard Scene Template

위의 코드를 스토리보드 API를 사용해서 구현하려면 어떻게 해야 되는지에 대한 예제가 아래에 있습니다.

scenetemplate.lua (Storyboard)

local storyboard = require "storyboard"
local scene = storyboard.newScene()

--------------------

function scene:createScene( event )
    local group = self.view

    --
    -- Create objects here (e.g. scene creation)
    --
end

--------------------

function scene:enterScene( event )

    --
    -- Manipulate objects here (e.g. scene logic)
    --
end

--------------------

function scene:exitScene( event )

    --
    -- Optional cleanup code here
    --
end

--------------------

scene:addEventListener( "createScene", scene )
scene:addEventListener( "enterScene", scene )
scene:addEventListener( "exitScene", scene )

return scene


디렉터 클래스의 new() 함수에 해당하는 스토리보드의 이벤트는 두가지가 있습니다. createScene과 enterScene 입니다. 사실 좀 더 있지만 일단 이 두가지를 보기로 하겠습니다.

스토리보드에서는  self.view 를 사용해서 그 화면의 view display group에 접근 할 수 있습니다. 디렉터 클래스에서 localGroup에 해당 화면의 모둔 객체들을 insert 했듯이요. 스토리보드에서도 그 화면의 모든 객체들을 self.view에 insert 하셔야 합니다. 이것을 하기에 가장 좋은 장소는 바로 createScene event listener 입니다.

위 예제에서 마지막에 있는 이벤트 리스너는 exitScene 이벤트 입니다. 이 부분은 디렉터 클래스의 clean() 메소드와 비슷합니다. 이 함수에서 타이머나 transition들을 정지시키고 Runtime listener들을 remove 시키는 등의 일을 하시면 됩니다.

스토리보드에서는 왜 이렇게 세분화 해서 나눴는지 궁금하실 겁니다. 나중에 설명 드리겠습니니다. 일단 왜 스토리보드에서는 createScene과 enterScene이 나눠졌는지를 알려드릴께요.

It has to do with scene “purging”.

디렉터 클래스와는 다르게 스토리보드에서 화면이 사라질때 그 화면은 자동적으로 remove 되지 않습니다. 그냥 화면 밖으로 사라져 버릴 뿐입니다. 여러분이 purge를 사용해서 그 scene을 따로 remove 시켜야 합니다. remove 되지 않는 다는 것은 그 화면의 객체들이 여전이 메모리에 있다는 얘기고 그러면 그 다음에 다시 그 화면을 불러 올 때 더 빨리 불러 올 수 있다는 얘기입니다. 그래서 자동적으로 remove 시키지 않고 개발자가 따로 함수를 사용해서 remove 시키도록 돼 있습니다.

Caveat : 만약 OS가 메모리가 부족하다는 경고를 보내면 최근에 접근된 화면이 purge 될 겁니다. 이 경우가 유일하게 스토리보드에서 화면이 자동적으로 remove 되는 상황입니다. 다른 경우에는 purge 나 remove 함수를 사용해서 특정 화면이나 이전의 전체 화면을 remove 시킬 수 있습니다. purge나 remove 같은 용어들의 정확한 의미를 아시려면 Storyboard Scene Events를 살펴 보세요.

조금 전으로 다시 돌아가서, 다른 화면으로 전환했는데 이전 화면은 화면에서만 사라지고 실제로는 메모리에 있는 상황을 가정합시다. 그 경우에 그 이전 화면이 다시 call 됐을 때 그 화면의 createScene event는 불려지지 않을 겁니다. (왜냐하면 이전에 이미 불려졌기 때문이죠). 이것이 createScene과 enterScene 이벤트가 둘로 분리된 가장 큰 이유입니다.

위 예제에 있는 것 말고도 여러분들이 사용할 수 있는  몇개의 Storyboard scene event들이 더 있습니다. 이것들을 모든 경우에 다 사용하셔야 된다는 것은 아닙니다. 필요한 경우에 사용하시면 됩니다.

   -  createScene
    - willEnterScene
    - enterScene
    - exitScene
    - didExitScene
    - destroyScene

위 이벤트들에 대한 좀 더 깊은 설명을 보려면 Storyboard Scene Events Explained 글을 봐 주세요. 그 글에는 각 이벤트들이 실행되는 순서를 보여주는 다이어그램도 있습니다. 그러니까 스토리모드의 위 이벤트들에 대해서 이해하시기 어려우시거나 좀 더 확실하게 사용하시려면 위 글을 봐 주세요. 


---- o ---- o ---- o ---- o ---- o ----


다음 글에서는 디렉터 클래스와 스토리보드 API 의 화면전환에 대해 비교해 보겠습니다.


반응형


반응형

얼마전 KOW님 질문에 대한 corona sdk 의 답변이었죠?


코로나로 개발하면서 안드로이드의 메뉴 버튼 클릭했을 때 이것을 콘트롤 할 수 있느냐는 거요.

대답은 event.keyName API를 보라는 거였는데요.


그 document를 아래 번역합니다.

예제 소스도 하나 만들었습니다.


event.keyName

Description:

"key" 리스너를 사용해서 눌려진 navigation key 의 이름을 스트링으로 얻습니다. key의 state (up,down)에 대한 사항은 event.phase를 보세요.

Note : home 하고 text 키들 (A-Z,0-9,punctuation)을 capture 될 수 없습니다.

** 안드로이드 디바이스에만 해당 됩니다.***


Syntax: keyName = event.keyName


Example:

-- Key listener
local function onKeyEvent( event )
        local phase = event.phase
        local keyName = event.keyName
        eventTxt.text = "("..phase.." , " .. keyName ..")"
 
        -- we handled the event, so return true.
        -- for default behavior, return false.
        return true
end
 
-- Add the key callback
Runtime:addEventListener( "key", onKeyEvent );


Note : keyEvent 리스너에서 false를 사용하면 해당 키의 디폴트 액션이 실행 됩니다.


Parameters: 없음


Returns: string


눌려진 navigation key의 이름이 return 됩니다 : "back", "search", "menu", "volumeUp", "volumeDown".

The D-Pad/Trackball key strings 는 "up", "down", "left", "right", "center" 가 return 됩니다

Note: home 키는 캡쳐 될 수 없습니다.


안드로이드 디바이스에서만 가능하고 코로나 SDK Build 2011.559 이상에서만 작동 합니다.

   

이상입니다.





위 소스를 조금 변경해서 아래 샘플 코드를 만들어 봤습니다.


-- Key listener
    _W = display.contentWidth;
    _H = display.contentHeight;
local txtPhase, txtKeyName, haveFun

txtPhase = display.newText( "Phase ", _W/2, _H/5, native.systemFont, 32 )
txtKeyName = display.newText( "KeyName : ", _W/2, _H/3, native.systemFont, 32 )
haveFun = display.newText( "Move", _W/8, _H/2, native.systemFont, 32 )

local function onKeyEvent( event )
        local phase = event.phase
        local keyName = event.keyName

        txtPhase.text = phase;
        txtKeyName.text = keyName;

        haveFun.x = haveFun.x + 50;
        if(haveFun.x > _W) then haveFun.x = 0 end
         -- we handled the event, so return true.
        -- for default behavior, return false.
        return true
end
 
-- Add the key callback
Runtime:addEventListener( "key", onKeyEvent );


main.lua에 이 소스를 붙여 넣고 실행하시면 화면에 phase와 keyName이 뜰겁니다.

제 디바이스에서 menu , back, search, volumeUp, volumeDown 등이 뜨는 거 확인 했어요.

마지막에 haveFun은 그냥 키가 눌려질 때 글자가 움직이도록 해 봤어요. 심심해서....


KOW님 덕분에 저도 몰랐던 사실을 알게 됬네요.


감사합니다.


반응형

Corona SDK로부터 받은 답변

2012. 4. 18. 07:35 | Posted by 솔웅


반응형

안녕하세요?

제가 이 블로그에서 받은 Corona SDK 와 관련된 질문 댓글 중 제 수준에서 답할 수 없는 것을 두건 Corona SDK에 문의 했었습니다.

오늘 아침 (4.17)에 보냈는데 오후에 답변이 왔네요.

feedback이 정말 좋네요. 고맙게도...


지금부터는 여러분들이 올리는 질문 (코로나 SDK에 대해) 에 더 성실히 답하고 모르는 건 이렇게 Corona SDK에 질문을 할 테니까 질문 많이 많이 올려 주세요.


오늘은 Kow님이 올리신 질문과 이상봉님께서 보내신 질문을 문의했었습니다.


오늘 온 답변 메일은 아래와 같습니다.





Changsoo,


Here are some answers to your questions from one of our team members:
아래 우리 팀원 중 한명이 당신이 보낸 질문에 대한 답변을 해 왔습니다.


1. 2012.03.28  KOW 
    Can I control 'MENU' Button on Android device with Corona SDK?  


You can override the Menu key by using Corona key listener as documented here...
Corona key 리스너를 사용해서 Menu를 오버라이드 할 수 있습니다. 문서는 아래에 있습니다.

 
2. 2012.03.26  Lee,Sangbong
    Regarding Image Sheets. If I use MASK on an object, screen becomes black except the object on Galaxy 2 LTE. There is no problem on other device. 



This sounds like the masking issue that was introduced in build 759 where textures are disappearing on devices with low-end graphics hardware.  It typically happens on devices with whose OpenGL max texture units are 2, the absolute minimum the OpenGL spec allows. We will work on this soon.

이 건은 빌드 759에서 나왔던 이슈 같습니다. low-end graphics 하드웨어에서 디바이스에서 texture가 사라지는 문제였는데요. 이 이슈는 특히  OpenGL max texture units 가 2인 디바이스에서 일어났습니다. 이 건에 대해서는 곧 해결하도록 하겠습니다.

You should be able to work-around this issue by reverting to build #758.

아마 빌드 758로 되돌아 가시면 이 현상은 일어나지 않을 겁니다.

이 상입니다.

이상봉님이 질문하신 내용은 빌드 759 이상에서 나오는 문제 같습니다. 오히려 그 이전 버전인 빌드 758로 돌아가면 그 문제가 없을 거라네요.

그리고 지금 그 버그를 수정중에 있다니까 조만간 그 정된 버전의 Corona SDK를  다운 받아 사용하실 수 있게 될 것 같습니다.

다른 분들도 질문이나 건의 또는 건설적인 의견이 있으면 댓글 달아 주세요.

Corona SDK 측에서 이렇게 확실히 신속하게 응답을 해 주니까 저도 여러분에게 좋은 답변을 드릴 수 있을 것 같습니다.

1번 KOW님의 질문에 대한 답변에서 보라고 했던 document는 제가 곧바로 번역해서 올리겠습니다.
혹시 테스트까지 하면 샘플을 올릴 수도 있겠죠?
아님 여러분 중에서 테스트 해 보신 후 성공하시면 샘플을 보내 주세요.

서로 공유하면서 필요한 자료를 share 하면 많은 도움이 될 것 같습니다.

감사합니다.



추천~~꾸욱~~


반응형


반응형

안녕하세요?


Corona SDK 명예 대사가 된 이후로 제대로 역할을 못하는 것 같네요.

여러분들의 많은 질문에도 답변 못하는 경우가 많구요.


일단 할 수 있는 것 부터 해야겠습니다.


여러분들이 Corona SDK 에 대해서 댓글로 질문 한 것 중 제가 답하기 어려운 것은 Corona SDK에 질문을 토스 하겠습니다.


그리고 답변을 받으면 이 블로그에 그 답변 내용을 올릴께요.


질문 이외에 코로나 SDK와 관련된 어떤 의견이나 제안사항도 마찬가자로 전달하겠습니다.


일단 이번에는 3월달에 올라온 질문 2가지를 Corona SDK CEO 인 Walter 하고 명예대사 담당자인 David 한테 보냈습니다.


아래 그 보낸 메일 내용입니다.


혹시 제가 빠뜨리거나 오래전에 올린 댓글 중에 제가 미처 답변 제대로 못 드린것도 있을 수 있습니다. 그 분들께는 죄송합니다. 제가 너무 일을 미루다가 발생한 일입니다.


지금부터는 정기적으로 질문 사항 정리해서 전달할 계획이니 질문사항이나 의견 있으시면 언제든지 댓글에 달아 주세요.





Dear Walter and David

I am Changsoo Park one of the Ambassador of Corona SDK.
I have blog http://coronasdk.tistory.com and I post Tutorial, DOC, Corona SDK News etc. on that blog in Korean.
Many people visit my blog and ask questions or suggest their opinion for Corona SDK.
I'd like to send you the questions and suggestions once a month and When I get back reply then I will let them know.

I am sending 2 questions at this time. 

Please check it out and reply soon .

1. 2012.03.28  KOW 
    Can I control 'MENU' Button on Android device with Corona SDK?  
2. 2012.03.26  Lee,Sangbong
    Regarding Image Sheets. If I use MASK on an object, screen becomes black except the object on Galaxy 2 LTE. There is no problem on other device. 

Best Regards

Changsoo (Douglas) Park


반응형


반응형

오늘은 Corona SDK 를 만든 회사인 Ansca의 CEO 강연을 하나 소개해 드리겠습니다.
얼마전 Carlos 공동 창업자가 2선으로 물러나면서 단독 CEO 가 된 Walter Luh 가 스탠포드 대학에서 한 강연입니다.

Corona SDK는 Lua 라는 Script Language를 사용하고 있는데요. 이 Lua 는 요즘 게임에 많이 사용되는 언어입니다.
앵그리버드도 이 Lua로 만든 겁니다.

이 Lua Language를 만든 사람이 Roberto Ierusalimschy 인데요. 스탠포드에서 교수로 있나 봅니다.
이 Roberto가 자신의 수업에 Walter를 초청해서 대신 수업을 진행한 화면입니다.

이 동영상을 보시면 Corona SDK에 대한 이해를 도울 수 있을 겁니다. 스탠포드 대학 학생들이 수업하는 분위기도 느낄 수 있구요.
한번 스탠포드 대학 수업에 같이 참여해 보시죠.





반응형


반응형

Using Components in Sencha Touch 2

What is a Component?

센차터치(Sencha touch)에서 눈에 보이는 부분을 담당하는 대부분의 클래스들은 컴포넌트(Component) 입니다. 센차터치의 모든 컴포는트는 Ext.Component의 서브클래스 입니다. 그 의미는 아래와 같다는 겁니다.

- templet을 사용하는 페이지에 자신들을 Render  한다.
- 어느 때든지 자신들을 보이도록 하거나 안보이도록 한다.
- 스크린에 자신들을 중앙에 위치 시킨다.
- Enable 하거나 Disable 하도록 할 수 있다.


이 컴포넌트들은 좀 더 진보된 것들을 할 수 있습니다.

- 다른 컴포넌트 위에서 떠 있는다. (윈도우, 메세지 박스와 overlay들)
- 애니메이션을 위해 스크린에서 사이즈와 포지션을 변경한다.
- 자신 내부에 다른 컴포넌트를 위치시킨다. (툴바에서 유용하게 사용함)
- 다른 컴포넌트들에 맞춰 정열한다. 자신들이 drag 될 수 있도록 한다. 자신들의 content를 스크롤 가능하게 한다. 등등


What is a Container?


여러분이 생성한 모든 컴포넌트는 위에 열거한 기능들을 모두 가지고 있습니다. 애플리케이션들은 수많은 컴포넌트들로 만들어 집니다. 대개 다른 컴포넌트 안에 다른 컴포넌트가 있고.. 하는 식으로 사용됩니다. 컨테이너도 컴포넌트와 마찬가지입니다. render하고 그 안에 child Component들이 있고 하는 그런 기능들이 마찬가지로 있는데 그 규모가 좀 다릅니다. 예를들어 메일앱에서 Viewport 컨테이너의 두 children 은 메세지 리스트와 이메일 미리보기 pane 이 필요할 겁니다. 

컨테이너는 다음과 같은 추가 기능들이 있습니다.

- 초기화 단계와 runtime 에서 child Component들을 add 할 수 있다.
- child Components 들을 remove 할 수 있다.
- Layout 을 지정할 수 있다.


Layout은 스크린에 child Component들을 어떻게 배치할 것인가를 결정하는 겁니다. 메일 앱 예제에서 우리는 HBox layout을 사용했습니다. 그래서 우리는 왼쪽에 이메일 리스트를 위치시키고 스크린의 부분에 preview pane 을 위치시킬 수 있었습니다. 센차 터치 2에는 몇가지 레이아웃이 있습니다. 모두 앱의 화면 구성을 정해 주는 겁니다. 레이아웃에 대한 좀 더 자세한 내용은 Layout guide를 참조하세요.

Instantiating Components


컴포넌트는 센차터치의 다른 모든 클래스들과 같은 방법으로 생성됩니다. Ext.create 를 사용합니다. 여기 어떻게 Panel 을 생성할 수 있는지 예제가 있습니다.

var panel = Ext.create('Ext.Panel', {
    html: 'This is my panel'
});


이렇게 하면 Panel instance가 생성될 겁니다. 그리고 아주 기본적인 HTML 이 있습니다. Panel은 HTML을 render 할 수 있는 간단한 컴포넌트 입니다. 그리고 다른 아이템들을 포함합니다. 이 경우에 우리는 Panel instance를 생성했지만 아직 스크린에 그 판넬이 보이지는 않을겁니다. 왜냐하면 아이템들은 instantiated 됐다고 그 즉시 render 되는것이 아니기 때문이죠. 이렇게 함으로서 우리는 어떤 컴포넌트들을 생성하고 rendering 하기 전에 움직여서 배치할 수 있습니다. rendering 한 다음에 움직이는 것보다 훨씬 빠른 방법이죠.

이 패널을 스크린에 보이도록 하려면 이것을 global Viewport 에 add 하기만 하면 됩니다.

Ext.Viewport.add(panel);

패널도 또한 컨테이너 입니다. 그러므로 다른 컴포넌트들을 포함할 수 있습니다. 그리고 layout을 통해서 정열 시킬 수도 있죠. 위의 예제를 고쳐보겠습니다. 이번에는 패널을 두개의 child 컴포넌트와 hbox 레이아웃으로 만들어 보겠습니다.

var panel = Ext.create('Ext.Panel', {
    layout: 'hbox',

    items: [
        {
            xtype: 'panel',
            flex: 1,
            html: 'Left Panel, 1/3rd of total size',
            style: 'background-color: #5E99CC;'
        },
        {
            xtype: 'panel',
            flex: 2,
            html: 'Right Panel, 2/3rds of total size',
            style: 'background-color: #759E60;'
        }
    ]
});

Ext.Viewport.add(panel);


이 예제에서 우리는 3개의 panel을 생성했습니다. 첫번째는 저 위의 예제에서와 같이 생성했구요 그 안에 두개의 또 다른 패널들을 생성했습니다. 패널 안의 패널은 xtype을 사용해서 정의했습니다. Xtype은 Ext.create 를 사용하고 전체 클래스 이름을 넣어서 컴포넌트를 만들 필요 없이 간편하게 컴포넌트를 생성할 수 있는 방법입니다. 단지 그 객체 안의 클래스에서 xtype을 넣어주면 됩니다. 그러면 그 프레임워크가 여러분을 위해 컴포넌트를 만들어 드릴 겁니다.

또한 top level 패널에서 레이아웃을 설정할 수 있습니다. 위 예제의 경우는 hbox를 설정했습니다. hbox는 parent 패널의 horizontal 방향으로 화면을 나눕니다. 각 child 들은 flex로 그 크기가 규정됩니다. 예를 들어 parent 패널의 너비가 300픽셀이면 첫번째 child는 100px을 차지할 것이고 두번째 child는 200px을 차지할 겁니다. 왜냐하면 첫번째는 flex: 1 이라고 했고 두번째는 flex:2라고 했으니까요.

Configuring Components

새 컴포넌트를 생성할 때는 configuration option들을 pass 할 수 있습니다. Component에서 사용할 수 있는 configuration들은 해당 class docs page의 "Config options" 섹션에 그 리스트들이 있습니다. 여러분이 컴포넌트를 instantiate 할 때 이 configuration option들을 원하는대로 사용하실 수 있습니다. 그리고 그 이후에 어느때든지 필요하면 그 내용을 수정하실 수도 있습니다. 예를 들어 html content를 생성한 이후 그 내용을 쉽게 수정할 수 있습니다.

//we can configure the HTML when we instantiate the Component
var panel = Ext.create('Ext.Panel', {
    fullscreen: true,
    html: 'This is a Panel'
});

//we can update the HTML later using the setHtml method:
panel.setHtml('Some new HTML');

//we can retrieve the current HTML using the getHtml method:
alert(panel.getHtml()); //alerts "Some new HTML"


모든 config들은 getter 메소드와 setter 메소드가 있습니다. 이 메소드들은 자동적으로 generate 되고 항상 같은 패턴을 유지합니다. 예를 들어 html 이라는 config는 getHtml과 setHtml 메소드를 받습니다. degaultType이라는 config가 있다면 getDefaultType 과 setDefaultType 메소드를 받을 겁니다.

Using xtype

xtype은 full class name 을 사용하지 않고 Component를 생성할 수 있도록 합니다. 특히 child 컴포넌트들을 포함한 컨테이너를 생성할 때 효과적입니다. xtype은 컴포넌트를 specifying 하는 간단한 방법입니다. 예를들어 Ext.panel.Panel 을 타입하는 대신 xtype: 'panel" 이라고 타입 하시면 됩니다.

Sample usage:

Ext.create('Ext.Container', {
    fullscreen: true,
    layout: 'fit',

    items: [
        {
            xtype: 'panel',
            html: 'This panel is created by xtype'
        },
        {
            xtype: 'toolbar',
            title: 'So is the toolbar',
            dock: 'top'
        }
    ]
});


List of xtypes

아래 내용들은 센차 터치 2에서 가능한 모든 xtype들 입니다.

xtype                   Class
-----------------       ---------------------
actionsheet             Ext.ActionSheet
audio                   Ext.Audio
button                  Ext.Button
component               Ext.Component
container               Ext.Container
image                   Ext.Img
label                   Ext.Label
loadmask                Ext.LoadMask
map                     Ext.Map
mask                    Ext.Mask
media                   Ext.Media
panel                   Ext.Panel
segmentedbutton         Ext.SegmentedButton
sheet                   Ext.Sheet
spacer                  Ext.Spacer
title                   Ext.Title
titlebar                Ext.TitleBar
toolbar                 Ext.Toolbar
video                   Ext.Video
carousel                Ext.carousel.Carousel
carouselindicator       Ext.carousel.Indicator
navigationview          Ext.navigation.View
datepicker              Ext.picker.Date
picker                  Ext.picker.Picker
pickerslot              Ext.picker.Slot
slider                  Ext.slider.Slider
thumb                   Ext.slider.Thumb
tabbar                  Ext.tab.Bar
tabpanel                Ext.tab.Panel
tab                     Ext.tab.Tab
viewport                Ext.viewport.Default

DataView Components
---------------------------------------------
dataview                Ext.dataview.DataView
list                    Ext.dataview.List
listitemheader          Ext.dataview.ListItemHeader
nestedlist              Ext.dataview.NestedList
dataitem                Ext.dataview.component.DataItem

Form Components
---------------------------------------------
checkboxfield           Ext.field.Checkbox
datepickerfield         Ext.field.DatePicker
emailfield              Ext.field.Email
field                   Ext.field.Field
hiddenfield             Ext.field.Hidden
input                   Ext.field.Input
numberfield             Ext.field.Number
passwordfield           Ext.field.Password
radiofield              Ext.field.Radio
searchfield             Ext.field.Search
selectfield             Ext.field.Select
sliderfield             Ext.field.Slider
spinnerfield            Ext.field.Spinner
textfield               Ext.field.Text
textareafield           Ext.field.TextArea
textareainput           Ext.field.TextAreaInput
togglefield             Ext.field.Toggle
urlfield                Ext.field.Url
fieldset                Ext.form.FieldSet
formpanel               Ext.form.Panel



Adding Components to Containers

위에서 언급했듯이 컨테이너는 Layout으로 정렬되는 child 컴포넌트를 가질 수 있는 특별한 컴포넌트입니다. 위의 예제에서 이미 1개의 패널 안에 2개의 child 패널을 만드는 방법에 대해서 보여 드렸습니다. 그리고 이 코드를 run time 중에 일어나게 할 수도 있습니다.

//this is the Panel we'll be adding below
var aboutPanel = Ext.create('Ext.Panel', {
    html: 'About this app'
});

//this is the Panel we'll be adding to
var mainPanel = Ext.create('Ext.Panel', {
    fullscreen: true,

    layout: 'hbox',
    defaults: {
        flex: 1
    },

    items: {
        html: 'First Panel',
        style: 'background-color: #5E99CC;'
    }
});

//now we add the first panel inside the second
mainPanel.add(aboutPanel);


이 예제에서는 총 3개의 패널을 생성했습니다. 첫번째로 aboutPanel을 만들었습니다. 이것은 유저에게 앱에 대한 설명을 하는데 사용할 겁니다. 그 다음에 우리는 mainPanel을 생성했습니다. 그리고 마지막으로 이 mainPanel 안에 add 메소드를 사용해서 첫번째 패널인 aboutPanel에 넣었습니다.

이 경우 mainPane을 다른 hbox 레이아웃에 넣었습니다. 그리고 디폴트도 사용했습니다. 모든 아이템들은 패널에 추가 됐습니다. 그러므로 이 경우에는 mainPanel에 있는 모든 child가 flex: 1 configuration을 가지게 됩니다. 그 결과 스크린에 첫번째로 render 되는 것은 현재 mainPanel 입니다. 그러므로 그 child는 full width를 차지하게 될 겁니다. mainPanel.add 라인이 call 될 때 그 안에 aboutPanel 이 render 될 것입니다. 이것은 또한 flex 1이 될 겁니다.

이와 같은 방법으로 컨테이너로부터 아이템들을 remove 하는 것도 아주 쉽습니다.

mainPanel.remove(aboutPanel);

이 코드 이 후는 aboutPanel이 없어져서 display 될 겁니다. 첫번째 child panel이 mainPanel의 전체를 차지하게 되겠죠.

Showing and Hiding Components

센차터치의 모든 컴포넌트는 간단한 API를 사용해서 보이게 하거나 또는 안보이게 할 수 있습니다. 위의 mainPanel 예제를 계속 사용해서 어떻게 안보이게 할 수 있는지를 보여드리겠습니다.

mainPanel.hide();

이렇게 하면 mainPanel이 안 보이게 될 겁니다. 그러면 mainPanel의 안에 있는 모든 child 컴포넌트들도 안보이게 될 겁니다. 아 컴포넌트를 다시 보이게 하는 것도 아주 쉽습니다.

mainPanel.show();

이렇게 하면 다시 mainPanel이 보이게 될 겁니다. 물론 그 안에 있는 컴포넌트들도요.

Events


모든 컴포넌트들은 이벤트를 발생합니다. 여러분들은 이 이벤트를 listen 하고 그 이벤트가 일어나면 특정 action을 하도록 할 수 있습니다 예를 들어 Text field 가 type 될때마다 이 Text field 는 change 이벤트를 발생합니다. 여러분은 리스너의 config 부분을 설정함으로서 간단히 이 이벤트를 listen 할 수 있습니다.

Ext.create('Ext.form.Text', {
    label: 'Name',
    listeners: {
        change: function(field, newValue, oldValue) {
            myStore.filter('name', newValue);
        }
    }
});


이 text field 의 값이 바뀔 때마다 change 이벤트가 발생하고 그러면 지정한 함수를 call 하게 됩니다. 이 경우에는 name에 새로운 값을 저장하게 될 겁니다. 저장하는 것 말고 다른 원하는 동작들을 얼마든지 코딩해 넣을 수 있습니다.

센차터치 컴포넌트들은 수많은 이벤트들을 발생합니다. 여러분은 어플리케이션에서 구현할 필요가 있으면 언제든지 쉽게 그 이벤트들을 catch 해서 이를 핸들링 할 수 있습니다. 이러한 것들은 그 컴포넌트를 생성하고 난 이후에 설정할 수 있습니다.

예를 들어 실시간으로 업데이트 하는 여론조사용 dashboard 가 있다고 합시다. 그런데 이 dashboard가 visible 하지 않을 때는 이 여론조사를 하고 싶지가 않습니다. 여러분은 이 dashboard의 show 와 hide 이벤트를 catch 해서 원하는 기능을 넣으실 수 있을 겁니다.

dashboard.on({
    hide: MyApp.stopPolling,
    show: MyApp.startPolling
});


이렇게 어떤 이벤트를 catch (hook) 하는 방법은 아주 쉽습니다. 더 자세한 사항은 아래 링크를 클릭해서 보세요.


각 컴포넌트들의 class docs 안에 그들이 발생하는 모든 이벤트 리스트들이 있습니다.

Docking


센차터치에는 다른 컨테이너 안에 Component들을 dock 할 수 있는 기능이 있습니다. 예를 들어 hbox layout을 사용하고 윗부분에 banner를 단다고 합시다. 아것을 다른 컨테이너 안에 또 다른 nest 컨테이너를 사용하지 않고 아래와 같이 쉽게 구현할 수 있습니다.




Layout Guide 를 보시면 이 docking에 대한 자세한 설명이 있고 또 다른 layout option들에 대한 설명도 보실 수 있습니다.

Destroying Components

모바일 디바이스의 메모리는 제한된 메모리를 가지고 있습니다. 그래서 컴포넌트들을 더이상 필요로 하지 않게 될 경우 그 컴포넌트들을 destory 시킬 필요가 있습니다. 이 작업은 그 컴포넌트를 생성할 때 할 수 있는 작업은 아니죠. 나중에 기능들이 완료 되고 난 후 필요한 부분에서 예를 들어 앱을 최적화 하는 단계에서 구현하셔야 하는 기능입니다. 컴포넌트를 destroy 하는 방법은 쉽습니다.

mainPanel.destroy();

이렇게 하면 DOM으로부터 mainPanel이 remove 될 겁니다. 그리고 특정 DOM elements 에서 셋업된 이 컴포넌트의 이벤트 리스너들도 remove 될 겁니다. 그리고 이 패널이 내부적으로 사용한 인스턴스들도 destroy 할 겁니다. 그리고 또한 모든 child 컴포넌트들도 destroy 될 겁니다. 이 컴포넌트가 destroy 된 후 그 컴포넌트의 모든 children도 사라지게 되는 것이죠. 그것들은 더이상 DOM에 존재하지 않을겁니다. 그리고 더이상 그 컴포넌트들을 사용할 수 없게 됩니다.


반응형


반응형

코로나에서 이번에 업데이트된 Daily build 2012.782, Daily build 2012.783 에서 몇가지 API를 변경 했습니다.

아래 그 변경된 내용을 소개해 드리겠습니다.



Storyboard, Network Changes, and More!


최근의 Daily Builds 를 눈여겨 보시지 않으신 분들께 안내 말씀 드리겠습니다. 몇가지 API 가 바꿘것들에 대해 소개합니다. 실제로 바뀐 내용들은 많이 있지만 이 글에서 다룰 수 있는 내용만 다루겠습니다. 유료 고객이시면 Daily Builds summary 를 보시면 변경된 사항을 자세히 보실 수 있을 겁니다.

Network API Changes

build 2012.782 에서는  network.request()network.download() 에 새로운 HTTP 메소드 지원을 하도록 기능을 확장했습니다.  (PUT,DELETE,HEAD - 기존의 POST와 GET은 여전히 사용가능 합니다. -)

이 기능 확장으로 코로나의 네트워킹 기능이 REST API에 좀 더 어울릴 수 있도록 함으로서 웹상의 여러 개발 API들을 더 많이 활용해서 코로나 앱을 개발 할 수 있도록 했습니다.


media.show() + Android = Better

buils 2012.783 에서 media.show() API가 코로나 internal camera 기능말고도 안드로이드 디바이스의 디폴트 카메라 앱을 사용할 수 있도록 확장됐습니다. 이를 위해서는 "WRITE_EXTERNAL_STORAGE" 퍼미션이 필요합니다. 물론 그 디바이스에는 Enternal storage 가 있어야 겠죠.

안드로이드의 디바이스 카메라를 사용해서 안드로이드 앱을 개발하려고 하시는 분들에게는 아주 좋은 뉴스가 되겠죠? 

Storyboard API Changes

Storyboard API에 몇가지 변경된 사항들이 있습니다. 큰 것은 아니지만 아주 유용한 추가 기능도 있구요.

“willEnterScene” and “didExitScene”

스토리보드 이벤트 이름이 바뀌었습니다. enterBegan 이 willEnterScene으로 바뀌었고 exitEnded 가 didExitScene으로 바뀌었습니다.  이전의 이름은 해당 기능에 대해 딱 맞는 이름이 아니었습니다. 그리고 다른 이벤트와도 이름이 너무 비슷했구요.  Storyboard Scene Events Explained  document 에도 이 바뀐 내용이 적용되었습니다.


New Storyboard Functions


스토리보드에 두개의 새로운 function이 추기 됐습니다. storyboard.loadScene(), storyboard.reloadScene(), 과 storyboard.getCurrentSceneName()      

두 함수인데요. 자세한 설명은 위 함수를 클릭하시면 보실 수 있습니다.


storyboard.loadScene()은 어떤 scene으로 화면전환을 하지 않은 채 그 scene을 load 해야 할 경우 사용할 수 있습니다. (전체 scene을 로드할 수도 있고 특정 모듈을 로드할 수도 있습니다. 설명서를 보시면 그 방법을 자세히 아실 수 있습니다.)  이 기능은 아주 heavy한 scene을 로드할 경우 미리 로드함으로서 화면전환을 자연스럽게 하고자 할 때 사용 하시면 유용하실 겁니다.

Storyboard 변경사항은 build 2012.782 버전 이상에서만 적용됩니다.


이 사항들은 최근의 Daily Build에서 바뀐 내용들의 일부분일 뿐입니다. 새로운 API를 사용해서 sprite들을 trim 하는 기능도 있구요. 그리고 다른 작은 추가되는 사항들과 변경되는 사항들이 있습니다.


이 기능들은 최근의 daily build 에서 사용 가능하시구요. 이 버전은 유료 사용자만이 사용하실 수 있읍니다.


반응형

Moving On and Thanks (Carlos icaza)

2012. 4. 15. 11:05 | Posted by 솔웅


반응형

4월 13일 Corona SDK 를 공동 창업했던 Carlos icaza 가 일선에서 물러나서 고문역할을 하게 됐습니다.


중국계 개발자인 Walter Luh 와 Carlos icaza는 2008년에 공동으로 Ansca를 창업해서 Corona SDK 를 배포하기 시작했는데요. (원래는 Adobe - 어도비 -  사의  Flash 개발 팀에 있었다고 합니다.)

짧은 4년 간동안 Corona SDK 를 아주 성공적으로 이끌어 왔는데요.

이제 일선에서 물러나서 Ansca (Corona SDK)는 Walter Luh 중심으로 운영이 될 것 같습니다.


작년에 작은 질문을 Carlos에게  메일로 보냈더니 금방 답장이 와서 놀랐었거든요. 덕분에 저도 더 관심을 갖고 공부하게 됐었습니다.


얼마전까지 홍길동처럼 여기저기 미국 전역을 다니면서 meetup 을 진행하던 아주 의욕적이고 활동적인 모습이 기억 나네요.


Carlos 가 떠나면서 남긴 편지를 소개해 드릴께요.




Moving On and Thanks


Saying goodbye is always hard, but I have decided this is the right time for me to move on from Ansca’s day-to-day operations. Now I don’t want you all to get worked up. This is sudden, but it’s for personal reasons. And I’ll still be around as an advisor to the company – which is as strong as it has ever been.


이별인사를 하는 것은 언제나 힘듭니다. 하지만 지금이 Ansca의 일선에서 물러나야할 바로 그 시간이라고 마음 먹었습니다. 동요하지는 마세요. 개인적인 일로 갑작스럽게 결정 된 겁니다. 그리고 앞으로도 계속 회사의 고문으로서 열심히 도움을 줄 것입니다.


When we started on this crazy journey of ours 4 years ago, no one knew who we were. Walter and I were just two individuals interested in mobile who decided to start a company in mid-2008 to create apps for our own.


4년동안의 이 미친 여정을 시작할 때 우리가 누군지 아무도 몰랐습니다. 월터와 나 이렇게 단 둘이 모바일에 관심을 가졌고 오리의 기술로 앱을 개발하기 위해 2008년 중반 쯤 회사를 창업하기로 결정했습니다.


I had no clue where the idea of making mobile apps would take us, but it has taken us where we are today. And I am very proud of what we have become, and, like I always say, “The Journey Is The Reward”, and this has been one hell of a fulfilling journey. It is truly the reward.


처음에는 모바일 앱을 만든다는 것 자체가 막막했지만 그 일을 시작함으로서 지금의 우리가 있을 수 있었습니다. 그리고 저는 지금까지 우리가 한 일에 대해서 아주 긍지를 가집니다. 제가 항상 얘기하듯이 "그 과정이 바로 그 성과자체이다" 라고 생각합니다. 이 여정은 풍요로운 성취의 여정이었고 그것이 진정한 우리의 성과입니다.


To the Corona community, thank you for being so incredibly passionate and supportive, don’t worry, I’ll be around on twitter, and other venues.

To the previous and current Ansca team members, continue to change the world one developer at a time, and continue to change the world of the developer.


코로나 커뮤니티에 말씀 드리고 싶습니다. 그동안 열정적으로 성원해 주심에 진심으로 감사드립니다. 염려 마세요. 저는 트위터를 통해서 그리고 다른 곳에서도 계속 만나실 수 있을 겁니다. 이전의 그리고 현재의 Ansca 팀 멤버들에게 말씀드리고 싶습니다. 계속해서 세상을 바꿔주세요. 한번에 한 개발자 씩. 그리고 계속 개발자의 세상을 바꿔주세요.

Carlos


반응형

Sencha Touch 2 Tutorial - MVC -

2012. 4. 14. 20:44 | Posted by 솔웅


반응형

Managing Dependencies with MVC

센차터치 2 앱에서는 종속적인 관계가 정의될 수 있는 곳이 두 군데 있습니다. 한군데는 application 이고요 다른 곳은 application class 입니다. 이 가이드에서는 앱내에서 어디에 어떻게 종속적인 관계를 정의하는지에 대해 설명 드리겠습니다.

Application Dependencies

MVC 어플리케이션을 생성할 때 Ext.application 에 손쉽게 models, views, controllers, stores, profiles 를 지정할 수 있도록 해 줍니다. 아래 예제가 있습니다.

Ext.application({
    name: 'MyApp',

    views: ['Login'],
    models: ['User'],
    controllers: ['Users'],
    stores: ['Products'],
    profiles: ['Phone', 'Tablet']
});


위 예제에 있는 5개의 configuration option 들은 애플리케이션이 주로 models, views, controllers, stores, profiles 로 구성되는데요 그 각각을 별도의 파일로 만들고 그 만든 파일을 로드할 수 있도록 해 줍니다. 위 예제를 실행하면 센차터치는 아래 경로의 파일들을 로드하게 될 겁니다.

app/view/Login.js
app/model/User.js
app/controller/Users.js
app/store/Products.js
app/profile/Phone.js
app/profile/Tablet.js


위 예제는 아래처럼 Ext.requre를 해서 로드할 수도 있습니다.

Ext.require([
    'MyApp.view.Login',
    'MyApp.model.User',
    'MyApp.controller.Users',
    'MyApp.store.Products',
    'MyApp.profile.Phone',
    'MyApp.profile.Tablet'
]);


애플리케이션에 클래스가 추가되면 추가될 수록 처음의 configurations 방법이 전체 클래스이름을 쓸 필요 없이 파일 이름만 쓰면 되므로 점점 더 효율적이 될 겁니다. 이 방법은 단지 파일을 로딩하는 것 이외에 아래와 같은 일도 추가적으로 하게 됩니다.

* profiles - 각 프로파일들의 instantiate 과 active 여부 판별. active 여부가 판별 되면 해당 프로파일을 로드 함
* controllers - 로딩 후 각 Controller instantiate 함
* stores - 각 Store들 instantiate 하고 아무것도 지정된 것이 없으면 디폴트 store ID 를 세팅함


위 기능들을 이용하기 원하시면 첫번째 configuration options 를 사용하시면 좋습니다.





Profile-specific Dependencies

Device Profile을 사용한다면 특정 디바이스에서만 사용되는 clsss 들이 있을겁니다. 예를 들어 태블릿에서는 폰 보다는 좀 더 많은 기능이 들어갈 겁니다. 그 얘기는 곧 태블릿쪽이 좀 더 많은 클래스를 로드해야 한다는 것이죠. 이 필요한 클래스들은 각각의 프로파일 내에서 정의할 수 있습니다.

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

    config: {
        views: ['SpecialView'],
        controllers: ['Main'],
        models: ['MyApp.model.SuperUser']
    },

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


이렇게 하면 위 프로파일이 active 되면 config에서 설정한 클래스들이 로드되게 됩니다. 위 태블릿 프로파일이 아니라 폰 프로파일이 active 되면 이 클래스들은 로드되지 않고 폰 프로파일에서 설정한 config에 있는 클래스들이 로드 되겠죠.

이렇게 각 디바이스 별로 프로파일을 만들고 그 프로파일 내에서 필요한 클래스들을 로드 하도록 함으로서 여러분들이 만든 애플리케이션이 특정한 디바이스가 아니라 여러 디바이스에서 사용할 수 있게 됩니다. 앱이 시작할 때 각 프로파일을 체크하고 그 프로파일에 필요한 클래스를 로드하기 때문이죠.

만약 앱의 용량이 아주 클 경우에는 이 방법을 사용해서 처음 앱이 실행될 때 그 앱이 실행된 디바이스에 필요한 클래스들만 다운로드 하도록 만들어서 용량을 줄일 수도 있을겁니다.

Nested Dependencies

규모가 큰 앱에서는 models, views, controllers를 subfolder들로 분리해서 프로젝트를 organize 하는것이 일반적입니다. 특히 views 부분이 더 그런데요. 큰 규모의 앱에서는 수백개의 view 클래스가 있는 것이 흔한일입니다. 그래서 그 클래스들을 더 간단하게 관리할 수 있도록 폴더별로 관리하는 것 입니다.

subfolders로 관리하게 되면 코드상에서 그 경로를 . 로 연결해서 사용하면 됩니다.

Ext.application({
    name: 'MyApp',

    controllers: ['Users', 'nested.MyController'],
    views: ['products.Show', 'products.Edit', 'user.Login']
});


이 5개의 파일들은 아래와 같은 경로에서 로드될 겁니다.

app/controller/Users.js
app/controller/nested/MyController.js
app/view/products/Show.js
app/view/products/Edit.js
app/view/user/Login.js


여기서 각각의 configuration 에서 서로 혼합하거나 match 할 수 있습니다. model, view, controller, profile, store 에 대해 클래스 이름의 마지막 부분을 사용하거나(directory convention을 따르고 있다면) 또느 전체 클래스 이름을 사용할 수 있습니다.

External Dependencies

우리는 앱 외부에 있는 클래스를 로드할 수도 있습니다. 이를 위해 사용하는 일반적인 방법은 여러 어플리케이션 사이에서 authentication(인증) 로직을 공유하는 방법이 있습니다. 아마 여러분의 여러개의 앱이 공동의 유저 데이터베이스에 로그할 필요가 있을 수 있을겁니다. 그럴 경우 그 앱들 사이에서 공통으로 인증 로직을 사용해서 접근하면 됩니다. 이를 위한 쉬운 방법은 폴더를 앱 폴더와 따로 만드는 것입니다. 그리고 여러분의 앱에서 이 폴더에 dependency를 주시면 됩니다.

예를 들어 login controller,유저 모델과 로그인 폼 뷰를 포함한 로그인 코드의 경우를 봅시다.  이 모든것을 어플리케이션 안에서 사용하기를 원합니다.

Ext.Loader.setPath({
    'Auth': 'Auth'
});

Ext.application({
    views: ['Auth.view.LoginForm', 'Welcome'],
    controllers: ['Auth.controller.Sessions', 'Main'],
    models: ['Auth.model.User']
});


이럴 경우 아래 파일들을 로드할 겁니다.

Auth/view/LoginForm.js
Auth/controller/Sessions.js
Auth/model/User.js
app/view/Welcome.js
app/controller/Main.js


처음 나오는 세개의 파일이 어플리케이션 밖에 있는 파일을 로드하는 것입니다. 나머지 두개는 앱 내에 있는 파일이구요. 이렇게 함으로서 어플리케이션 파일과 외부의 독립된 파일을 서로 mix하고 match 해서 사용 할 수도 있습니다.

외부 파일을 로드할 수 있도록 하려면 그 파일이 어디에 있는지를 Loader 에게 알려주면 됩니다. 이것은 위 예제에서 Ext.Loader.setPath 에서 한 일입니다. 이 경우 Auth 폴더 안의 Auth namespace로 시작되는 모든 파일을 Loader에게 찾으라고 지시하게 되는 겁니다. 이렇게 함으로서 Auth 코드를 애플리케이션 외부에 따로 떨어뜨려서 관리할 수 있고 그렇게 함으로서 전체 framework이 모든 필요한 것들을 load 하게 됩니다.

Where Each Dependency Belongs


각각의 dependency를 정의하는 장소를 정할 때의 일반적인 룰은 여러분의 클래스들을 완전하게 self-contained 하도록 유지하는 것입니다. 예를 들어 몇개의 다른 뷰를 가지고 있는 한개의 뷰가 있다고 했을 때 그 dependency들은 어플리케이션이 아니라 그 뷰 클래스 안에서 정의해야 합니다.

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

    requires: [
        'MyApp.view.Navigation',
        'MyApp.view.MainList'
    ],

    config: {
        items: [
            {
                xtype: 'navigation'
            },
            {
                xtype: 'mainlist'
            }
        ]
    }
});


app.js 에서는 아래와 같이 해 줍니다.

Ext.application({
    views: ['Main']
});


두가지 이유 때문에 이렇게 dependency들을 정의하는것이 가장 좋은 방법이라고 할 수 있습니다. 첫번째는 MyApp.view.Main을 불러옴으로서 여러분의 app.js 는 간단 명료하게 유지할 수 있고 이러한 dependency들을 이미 다 만족하도록 만들었다는 것을 확인 할 수 있습니다.

//this is bad
Ext.application({
    views: ['Main', 'Navigation', 'MainList']
});


간단하게 생각하면 app.js 안에는 단지 top-level 뷰들만 넣으시면 됩니다. 만약 여러분 앱에 Ext.create('MyApp.view.SomeView')를 사용한다면 그 뷰는 top-level일 겁니다. 한 뷰가 다른 뷰의 sub-view라면 (위 예제에서 MyApp.view.Navigation 과 MyApp.view.MainList 같은) 이 뷰는 app.js에 있을 필요가 없습니다.

Changes since 1.x

센차터치 1 (Sencha Touch 1)에서는 Ext.application call 과 같이 콘트롤러 안에서도 사용되어졌었습니다. 이 방법이 편리한 측면이 있지만 Controller 가 너무 뷰,모델, 스토어들을 통제하는 면이 있기도 합니다. 1.x 에서는 아래와 같이 사용할 수 있습니다.

//1.x code, deprecated
Ext.regController('SomeController', {
    views: ['Login'],
    models: ['User'],
    stores: ['Products']
});

이 방법은 Ext.application에서 뷰,모델,스토어를 정의하는 것과 동일합니다. 콘트롤러에서 이 클래스들에 접근하는데에는 편리합니다. 1.x 는 getLoginView()와 getUsermodel() 두개의 함수를 generate 합니다. 그리고 이 콘트롤러에서 정의한 Stores 에 대한 reference를 return 하는 getStore() 함수를 노출시킵니다. 2.x 에서는 이러한 함수들을 사용하지 않습니다. 두가지를 동시에 사용할 수도 잇습니다.

//creating a view - 2.x uses the standardized Ext.create
this.getLoginView().create();
Ext.create('MyApp.view.Login');

//getting a Model - just type out the Model name (it's shorter and faster)
this.getUserModel();
MyApp.model.User;

//Ext.getStore can access any Store whereas the old this.getStore only
//accessed those Stores listed in your Controller
this.getStore('Products');
Ext.getStore('Products');


이 함수들을 없애면 앱을 처음 시작할 때 로딩 시간을 줄일 수 있습니다. 왜냐하면 framework 이 각 콘트롤러에서 정의한 각 모델,뷰에 대한 함수들을 generate 할 필요가 없기 때문입니다. 또한 이러한 함수들을 사용하지 않으면 MVC 모델에 더 부합하는 설계를 할 수가 있습니다.


반응형