2012년 5월 17일 목요일

안드로이드 intent flag


안드로이드 엑티비티에 대해 이해하기 위해 필요한 지식은 3가지 정도가 아닐까 생각합니다. 바로 Activity Lifecycle, Task, Intent 입니다. 모두 어느정도 이해를 하시고 계신 상태라고 생각하고 글을 적어보겠습니다.

인텐트를 이용하여 새로운 엑티비티를 띄우기 위해서는 일반적으로 다음과 같은 방법으로 새로운 엑티비티를 실행하게 됩니다.

Intent intent = new Intent(this, MyActivity.class);
startActivity(intent);


위의 코드는 다음과 같은 순서로 실행이 됩니다.

1. 새로운 MyActivity 인스턴스가 생성됩니다.
2. 이 인스턴스가 현재 태스크 스택의 최상단에 푸시가 됩니다.
3. 엑티비티가 시작되며(onStart) 포그라운드로 가져옵니다.

하지만 위와 같은 인텐트 생성에 관련된 기본적인 실행 방법을 인텐트 플래그를 사용하여 임의로 조정할 수 있습니다.

intent.addFlag(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);


위와 같은 방법을 통해 특정한 플래그 옵션값을 startActivity(intent)가 수행될때 같이 넘겨줄 수 있습니다. 지금부터 이러한 플래그 옵션값들을 좀더 상세기 적어보도록 하겠습니다.

FLAG_ACTIVITY_BROUGHT_TO_FRONT

이 플래그는 사용자가 설정하는것이 아닌 시스템에 의해 설정되는 값입니다. 엑티비티의 실행모드가 singleTask이고 이미 엑티비티스택에 존재하고 있는 상태라고 가정을 할 때 다시 그 엑티비티가 호출되고 재활용 되었을 경우 자동으로 설정이 됩니다.


FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET
이 플래그를 사용하면 태스크가 리셋될때 플래그가 사용된 엑티비티부터 최상단의 엑티비티까지 모두를 삭제합니다. 리셋은 FLAG_ACTIVITY_RESET_TASK_IF_NEEDED 플래그에 의해 실행이 되는데 시스템에 의해 홈스크린에서 사용자에 의해 백그라운드에 있던 태스크가 포그라운드로 전환될때에 항상 붙게 됩니다. 

위의 그림에서 볼 수 있듯이 백그라운드와 포그라운드 전환관계에서CLEAR_WHEN_TASK_RESET 플래그가 설정된 엑티비티와 이후의 엑티비티 모두가 삭제되는것을 알 수 있습니다. 백그라운드로 넘어갔을때 유지를 안해도 될 일회성 엑티비티들은 해당 플래그를 사용하면 도움이 될것이라 봅니다.


FLAG_ACTIVITY_RESET_TASK_IF_NEEDED

이 플래그는 인텐트를 이용하여 새로운 태스크를 생성하거나 존재하고 있는 태스크를 포그라운드로 가져오는 경우가 아닌경우에는 사용하여도 아무런 효과가 없습니다. 적절한 경우라면 태스크를 리셋 합니다. 이때에 태스크의 affinity 설정에 맞추어 리셋이 일어나게 되며FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET과 같은 플래그 설정에 맞추어진 특정 처리가 일어나게 됩니다.


FLAG_ACTIVITY_CLEAR_TOP
만약에 엑티비티스택에 호출하려는 엑티비티의 인스턴스가 이미 존재하고 있을 경우에 새로운 인스턴스를 생성하는 것 대신에 존재하고 있는 엑티비티를 포그라운드로 가져옵니다. 그리고 엑티비티스택의 최상단 엑티비티부터 포그라운드로 가져올 엑티비티까지의 모든 엑티비티를 삭제합니다.

예를 들면 현재 ABCDE순서로 엑티비티가 스택에 들어있다고 할때 엑티비티E에서 C를 호출하게 되면 D와 E는 스택에서 삭제되고 ABC만이 남아있게 됩니다. 여기서 AB 역시 남는다는 것을 이해하셔야 합니다.


FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS

엑티비티가 새로운 태스크안에서 실행될때에 일반적으로 타겟 엑티비티는 '최근 실행된 엑티비티' 목록에 표시가 됩니다. (이 목록은 홈버튼을 꾹 누르고 있으면 뜹니다) 이 플래그를 사용하여 실행된 엑티비티는 최근실행된엑티비티 목록에서 나타나지 않습니다.



FLAG_ACTIVITY_FORWARD_RESULT


기본적으로 엑티비티A가 엑티비티B를 호출하였다고 할 경우 startActivity(intent) 대신에startActivityForResult(intent) 메서드를 이용하여 호출을 함으로써 엑티비티B의 결과값을 엑티비티A로 전달할 수 있습니다.

엑티비티B에서는 setResult(int resultCode)를 정의한 뒤에 종료를 하게 되며 엑티비티B를 호출하였던 엑티비티A는 콜백메서드인 onActivityResult()를 통해 결과값을 전달받게 됩니다.
이제 엑티비티B가 또다른 엑티비티C를 호출하였다고 가정해 봅시다. 그리고 이렇게 호출된 엑티비티C에서 엑티비티A까지 전달할 결과값을 정의하였습니다. 이 결과값을 B에서 A로 또다른 코드를 통해서 프로그래머의 코드를 통해서 값을 전달하는 번거로움을 피하기 위해 안드로이드에서는 이 인텐트 플래그값을 제공합니다.

위에 나와있는 그림의 예를 통해 보면 엑티비티B가 엑티비티C를 호출하기위해 단순히startActivity()를 이용하는 것을 알 수 있습니다. 그리고 지금 설명중인 플래그를 붙이도록 합니다. 이후에 엑티비티C에서는 setResult()를 통해 결과값을 정의를 한후에 finish()를 통해 엑티비티를 종료하도록 합니다.

엑티비티B에서는 단순히 마찬가지로 finish()를 통해 엑티비티를 종료하시기만 하면 됩니다. 이후에 startActivityForResult()를 통해 엑티비티B를 호출했던 엑티비티A는 onActivityResult() 콜백 메서드로 결과값을 받아보시면 엑티비티C에서 정의한 값을 받을 수 있다는것을 알 수 있습니다.


FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY

이 엑티비티 플래그는 시스템에 의하여 자동으로 설정되는 플래그입니다. 홈스크린화면에서 홈버튼을 롱클릭함으로써 뜨게 되는 "최근실행목록"을 통해 실행되었을 경우 자동으로 설정됩니다.


FLAG_ACTIVITY_MULTIPLE_TASK

이 엑티비티 플래그는 FLAG_ACTIVITY_NEW_TASK와 함께 사용하지 않으면 아무런 효과가 없는 플래그입니다. 두개의 플래그를 동시에 사용할 경우 새로운 태스크는 재활용되지 않고 무조건 새로 생성되며 피호출되는 엑티비티는 이 새로운 태스트의 최상위 엑티비티가 됩니다. (당연히 하나밖에 없을테니-_-a)


FLAG_ACTIVITY_NEW_TASK

이 엑티비티 플래그를 사용하여 엑티비티를 호출하게 되면 새로운 태스크를 생성하여 그 태스크안에 엑티비티를 추가하게 됩니다. 단, 기존에 존재하는 태스크들중에 생성하려는 엑티비티와 동일한 affinity를 가지고 있는 태스크가 있다면 그곳으로 새 엑티비티가 들어가게됩니다.

하나의 어플리케이션안에서는 모든 엑티비티가 기본 affinity를 가지고 같은 태스크안에서 동작하는것이 기본적(물론 변경이 가능합니다)이지만 FLAG_ACTIVITY_MULTIPLE_TASK 플래그와 함께 사용하지 않을경우 무조건적으로 태스크가 새로 생성되는것은 아님을 주의하셔야 합니다.


FLAG_ACTIVITY_NO_ANIMATION

안드로이드 OS가 2.0으로 올라오면서 새로 추가된 엑티비티 플래그입니다. 이 플래그를 사용할 경우 엑티비티가 스크린에 등장할시에 사용될 수 있는 다양한 애니메이션 효과를 사용하지 않습니다.


FLAG_ACTIVITY_NO_HISTORY

이 플래그를 사용할 경우 새로 생성되는 엑티비티는 어떤 태스크에도 보존되지 않게 됩니다. 예를 들면 로딩화면과 같이 다시 돌아오는것이 의미가 없는 화면이라면 이 플래그를 사용하여 태스크에 남기지 않고 자동적으로 화면이 넘어감과 동시에 제거할 수 있습니다.


FLAG_ACTIVITY_NO_USER_ACTION

이 플래그가 설정되면 자동적으로 엑티비티가 호출될 경우에 자동 호출되는onUserLeaveHint()가 실행되는것을 차단합니다. onUserLeaveHint() 콜백 메서드는 어플리케이션 사용중에 전화가 온다거나 하는등의 사용자의 액션없이 엑티비티가 실행/전환되는 경우에 호출되는 메서드입니다.


FLAG_ACTIVITY_REORDER_TO_FRONT
호출하려던 엑티비티가 이미 엑티비티 스택에 존재하고 있다면 이 플래그를 사용하여 스택에 존재하는 엑티비티를 최상위로 끌어올려줍니다. 결과적으로 엑티비티 스택의 순서가 재정렬되는 효과를 가집니다. 위의 예를 볼 경우에 엑티비티E가 C를 호출하게 됨으로써 엑티비티C가 최상단으로 이동하는 결과를 확인하실 수 있습니다.


FLAG_ACTIVITY_SINGLE_TOP

이 플래그는 말그대로 하나의 탑(?)을 의미하는 설정입니다. 엑티비티를 호출할 경우 호출된 엑티비티가 현재 태스크의 최상단에 존재하고 있었다면 새로운 인스턴스를 생성하지 않습니다. 예를 들어 ABC가 엑티비티 스택에 존재하는 상태에서 C를 호출하였다면 여전히 ABC가 존재하게 됩니다.

2012년 5월 5일 토요일

안드로이드 글꼴 적용 방법 1


1. 글꼴
      안드로이드는 기본적으로 몇 가지 글꼴이 포함돼있으며, 원하는 글꼴을 따로 추가할 수 있다.
      1.1 기본 포함 글꼴
           안드로이드는 기본적으로 'sans', 'serif', 'monospace'의 세 가지 글꼴이 내장돼 있다. 세 가지 글꼴 모두 어센터(Ascender)에서 오픈 핸드셋 얼라이언스(Open Handset Alliance)에 제공한 드로이드 글꼴이다.
           - 드로이드 글꼴을 사용하려면 XML 레이아웃 파일에서 해당 글꼴을 바로 참조하면 된다.

<?xml version="1.0" encoding="utf-8"?>
<TableLayout
       xmlns:android="http://schemas.android.com/apk/res/android"
       android:layout_width="fill_parent"
       android:layout_height="fill_parent"
       android:stretchColumns="1">
       <TableRow>
             <TextView
                   android:text="sans:"
                   android:layout_marginRight="4px"
                   android:textSize="20sp"
             />
            <TextView
                  android:id="@+id/sans"
                  android:text="Hello, world!"
                  android:typeface="sans"                  android:textSize="20sp"
            />
      </TableRow>
      <TableRow>
           <TextView
                 android:text="serif:"
                 android:layout_marginRight="4px"
                 android:textSize="20sp"
            />
           <TextView
                android:id="@+id/serif"
                android:text="Hello, world!"
                android:typeface="serif"                android:textSize="20sp"
            />
       </TableRow>
       <TableRow>
          <TextView
              android:text="monospace:"
              android:layout_marginRight="4px"
              android:textSize="20sp"
         />
        <TextView
              android:id="@+id/monospace"
              android:text="Hello, world!"
              android:typeface="monospace"              android:textSize="20sp"
        />
    </TableRow>
    <TableRow>
       <TextView
             android:text="Custom:"
             android:layout_marginRight="4px"
             android:textSize="20sp"
       />
      <TextView
             android:id="@+id/custom"
             android:text="Hello, world!"
             android:textSize="20sp"
      />
   </TableRow>
</TableLayout>
          원하는 외부 글꼴을 사용하는 방법
           - 홈디렉토리에 assets/라는 디렉토리를 생성
           - assets/fonts 등의 디렉토리를 생성하여 관리하는 것이 깔끔
           - 트루타입 글꼴 파일(TTF 파일)을 assets/ 디렉토리에 넣어둔다.
           - 자바코드에서 외부 글꼴 지정하도록 코딩
import android.app.Activity;
import android.graphics.Typeface;
import android.os.Bundle;
import android.widget.TextView;
public class FontSampler extends Activity {
      @Override
      public void onCreate(Bundle icicle) {
             super.onCreate(icicle);
             setContentView(R.layout.main);
 
             TextView tv=(TextView)findViewById(R.id.custom);
             Typeface face=Typeface.createFromAsset(getAssets(),
                                                                 "fonts/HandmadeTypewriter.ttf");
 
             tv.setTypeface(face);

      }
}
          예외사항
          - 트루타입 글꼴 가운데에도 간혹 안드로이드가 읽어들일 수 없는 글꼴이 있다. 만약 안드로이드가 읽지 못하는 글꼴을 사용하려 한다면 Exception을 띄우기보다는 그냥 'sans' 글꼴을 대체해서 사용한다.
          - 글꼴을 제대로 적용한 것 같은데 계속해서 'sans' 글꼴로 나타난다면, 이는 안드로이드와 호환되지 않는 글꼴일 가능성도 있다.
          - 투루타입 글꼴은 유니코드 글자 가운데 어느 정도 충분한 양을 표현하려면 파일 크기가 상당히 커진다. 따라서 너무 많은 공간을 차지할 수 있으니 꼭 필요한 글꼴만 추가해 사용하는 것이 좋다.

스마트폰 기본 폰트



모바일에서 사용되는 기본폰트

>>>>>>>>>>>>>>>>>>>아이폰
LockClock.ttf
Helvetica.ttc
AppleGothicRegular.ttf


>>>>>>>>>>>>>>>>>>>안드로이드
Clockopia.ttf
DroidSans.ttf
DroidSans-Bold.ttf
DroidSansFallback.ttf

안드로이드 폰트



개발Q&A 에 어떤분이 올리신 질문중에
"보낸이" 가 " 보냰이" 로 나온다고 하신 분이 계서서...

http://www.androidside.com/bbs/board.php?bo_table=B49&wr_id=6088&page=2

말이 나온김에 폰트에 관련된 이야기를 나누어 볼까 합니다.

먼저 폰트의 종류부터 알아보죠

비트맵 폰트 
아주 옛날^^ 8비트 컴퓨터 시절 쓰이던 폰트죠
화면에 뿌려주는 처리속도는 매우 빠르지만 글씨의 크기가 변경 될때 이쁘게 보이질 않게 되죠
이미 크기가 정해져 비트맵으로 저장 되어 있기 때문인데요
c:\windows\fonts 에 보시면


이런 폰트들이 있으실텐데요 로 표시된 폰트가 비티맵 폰트입니다.




글씨가 커질수록 안 예쁘게 보여지는 단점이 있습니다.

외곽선 폰트 
컴퓨팅 기술이 발전하면서 폰트도 이쁘게 표현할 필요가 생겼는데요
벡터 그래픽이나 베지어 곡선을 폰트에 적용하면서 외곽선 폰트 형태가 생겼습니다.
이 폰트는 크기에 상관 없이 일정한 품질의 출력을 하는 장점이 있습니다.
포스트 스크립트, 트루타입, 오픈타입 폰트등이 이에 속합니다.



포스트스크립트 (Postscript)
어도비사가 개발한 포스트스크립트 폰트는 Type1,2,3 등 다양한 포맷이 있는데요 Flash 에 적용되어
있던 벡터 개념을 폰트에도 적용하여 만든 것입니다 주로 프린터에 많이 사용됩니다.

TrueType 폰트 
베지에 3차곡선을 사용하는 Type1과는 달리 베지에 2차곡선을 사용하지만 이에대한 폰트의
품질 향상은 미비하지만 속도는 빠른 장점 때문에 windows 에서 많이 사용되고 있습니다.
위 그림중 "T" 자로 되어 있는 폰트입니다.

오픈타입 폰트 
어도비는 M$ 와 손잡고 오픈타입 폰트라는것을 제작 하게 되는데요.
true type 폰트와 postscript 폰트를 합친 새로운 형식입니다.
유니코드에 바탕을둔 truetype 에 opentype 공통의 헤더 정보를 더하여 확장시킨 포멧입니다.
유니코드이기 때문에 안드로이드에서 이 폰트를 사용하고 있습니다.
위 그림중 "O" 자로 되어 있는 폰트입니다.


서론이 너무 길었나요?
그럼 먼저 안드로이드 기본폰트에 대해 알아보죠

1. 기본폰트 사용하기



안드로이드 기본 폰트는 위 그림과 같이 
Sans , Serif  두 종류가 있구요 mono 는 각 글자의 넓이가 일정한 폰트입니다. 

layout 파일에


typeface="sans"  또는 "serif"
하시면 끝

2. 사용자폰트 사용하기

위에서 말씀드린바와 같이 windwos\fonts 에서 "O" 형태의 폰트를 고르신 후



assets\fonts\ 에 붙여넣기 합니다.

Activity onCreate 부분에 



와 같이 하시면 됩니다.

실행 화면을 볼까요?





위 화면을 보신분 중 이러한 궁금증이 생기시는분이 분명 생기실껍니다.

"그럼 폰트를 일괄 적용은 못하나요?"

그래서 말씀 드리려구요.


3. Application 전체에 특정폰트 적용하기

res/values/styles.xml 에 위 내용을 입력합니다.





메니페스트 파일에 android:theme="@style/CustomTheme" 를 추가합니다.


"그러면.. Application 전체에 커스텀폰트를 적용하려면 어떻게 하나요?"
제가 알고 있는바에 따르면 현재 버전에선 불가능 한것으로 알고 있습니다. ^^;
(완전 불가능한건 아니죠 안드로이드 core 소스를 구해서
특정폰트로 교체한 후 빌드 하면 될테니까요)

2012년 4월 28일 토요일

안드로이드 activity flag 사용


[코딩] 안드로이드 유용한 Activity Flag들 안드로이드

일반적인 경우, 안드로이드 용 어플리케이션을 작성하게 되면 여러가지 Activity 들을 생성하게 됩니다. 이때, 가장 골치가 아픈 일 중 하나는 바로 Activity 와 Activity 간의 Flow 를 설계하고 이를 적절하게 구현하는 일입니다. (특히 안드로이드를 사용해보지도 않은 UX 팀과 함께 일하게 되는 경우라면 더욱 그러합니다...)

 기본적으로 안드로이드 플랫폼 상에서 Activity 는 또 다른 Activity 를 시작할 수 있고, 각각의 Activity 는 차곡 차곡 Task 라고 불리우는 Activity Stack 에 쌓이게 됩니다. 사용자는 일반적으로 Back 버튼을 이용해서 현재 화면상에 보이는 Activity 를 종료 시키고, 바로 직전에 사용된 Activity 로 돌아갈 수 있습니다. 안드로이드 펍의 회색님의 말을 빌리자면, 인터넷 브라우저를 통해 웹페이지를 검색하는 것과 유사한 방식입니다. 

 하지만 이러한 방법만으로는 효과적인 UX Flow 를 구축하는데 어려움이있습니다. 다행히, 구글에서는 Activity 를 호출할 때 사용되는 Intent 에 적절한 플래그 값을 설정해서 Activity Stack 을 제어할 수 있는 방법을 제공해 줍니다. 이 플래그들은  FLAG_ACTIVITY 라는 접두어를 갖고 있는데, 종류가 다양해 헷갈리는 수도 있는데, 개인적으로 제가 가장 요긴하게 사용하고 있는 FLAG_ACTIVITY 네 가지를 소개해 봅니다. 

 먼저 FLAG_ACTIVITY_SINGLE_TOP 입니다. 우선 간단하게 그림으로 표현해 보았습니다. A 와 B  두 가지 Activity 가 있는 데, A 라는 Activity 는 B 를 B 라는 Activity 는 다시 자기 자신인 B 를 호출 하는 경우라고 가정해 보겠습니다. 
< FLAG_ACTIVITY_SINGLE_TOP >

 호출하는 Activity B 가 이미 Task 의 가장 앞에 위치하는 경우, 또 하나의 B 를 생성하는 대신, 기존에 존재하는 B Activity 가 재활용됩니다. 이 때 B 가 재활용된다는 것을 개발자가 알아채고 새롭게 전달되는 Intent 를 사용할 수 있도록 B Activity 의 onPause() / onNewIntent() / onResume() 가 순차적으로 호출됩니다. 별 생각없이 동일한 Activity 를 여러번 생성하는 것은 메모리 사용량과 Activity 시작 속도 양쪽 모두에 악영향을 끼칠 수 있습니다. (특히 이미지가 덕지덕지 붙어 있는 Activity 라면). 이런 경우 FLAG_ACTIVITY_SINGLE_TOP 를 적절하게 활용하면 제법 큰 효과를 볼 수 있습니다.

 두 번째는, FLAG_ACTIVITY_NO_HISTORY 플래그입니다. 우선 간단하게 그림으로 표현해 보았습니다. A 와 B  두 가지 Activity 가 있는 데, A 라는 Activity 는 B 를 B 라는 Activity 는 A 를 호출한 후 에 (A->B->A) 사용자가 Back 키를 누르는 경우를 가정해 보겠습니다.
<FLAG_ACTIVITY_NO_HISTORY>

 말 그대로, FLAG_ACTIVITY_NO_HISTORY 로 설정된 Intent 로 시작된 Activity B 는 Task 에 그 흔적을 남기지 않게 됩니다. B 에서 또다른 A 를 시작한 후, Back 을 누르면 일반적인 경우 이전에 실행되었던 B 가 나타나지만, NO_HISTORY 를 사용하는 경우 맨 처음에 실행 되었던 A 가 화면에 표시됩니다. 몇 가지 주의할 점이 있습니다. 우선 NO_HISTORY 를 사용하게 되면 Task 에 해당 Intent 의 정보가 기록되지 않기 때문에, A->B 인 상황 (그림에서 두 번째 단계...) 에서 홈키등을 눌러 다른 Task 로 전환된 후, 다시 본 Task 로 돌아오게 되면, A Activity 가 화면에 표시됩니다. 또한, B Activity 의 onDestroy() 가 호출되는 시점이 조금 애매합니다.일반적인 예상과는 달리, B 에서 또다른 A Activity 를 호출하는 세 번째 단계에서는 onStop 까지만 호출되고, 이 후에 새롭게 호출된 A Activity 가 사라지는 순간 (네 번째 단계) 에서야 onDestroy() 가 호출 됩니다.

 FLAG_ACTIVITY_NO_HISTORY 는 여러가지로 쓸모가 있는데, 특히 특정한 이벤트에 대한 알람등을 위해 다이얼로그 형태로 화면에 표시되는 Activity 들에 적용하기에 편리합니다. (대게의 경우 팝업은 해당 시점에 한번만 보여주면 되니까.)

 다음으로 굉장히 유용한 플래그 두 가지를 동시에 설명해보고자 합니다.FLAG_ACTIVITY_REORDER_TO_FRONT 와 FLAG_ACTIVITY_CLEAR_TOP 플래그입니다. 우선 간략하게 그림으로 살펴 보겠습니다. A Activity 에서 B Activity 를 그리고 B 에서 A 를 호출하는 상황을 가정해보았습니다. (A->B->A)


 FLAG_ACTIVITY_REORDER_TO_FRONT 는 매우 특이하게도 Task 의 순서 자체를 뒤바꿔 줍니다. 이 플래그를 사용하면, 런치하고자 하는 Activity 가 이미 Task 상에 존재하는 경우 해당 Activity 를 새롭게 생성하는 대신, 아래쪽에 위치한 Activity 의 순서를 Task 의 가장 위로 끌어올려줍니다. 따라서 A->B->A 의 순서로 Activity 호출이 일어날때, 새로운 A 가 생성되는 대신 아래쪽에 위치한 A 가 위로 올라와 최종적으로 B->A 의 형태로 Task 가 구성되게 됩니다. 어떤 Activity 에서 특정 Activity 로 점프하는 형식의 Flow 를 구성해야하는 경우 요긴하게 사용될 수도 있지만, Task 의 순서를 뒤섞는 다는 점에서 사용에 주의를 기울일 필요가 있습니다.  (별 생각없이 남발하게 되면 Back 키가를 누를 때 엉뚱한 Activity 가 표시되어 사용자들이 굉장히 혼란스러워 하는 경우가 있습니다.) 

 마지막으로 소개해 드릴 플래그는 바로 FLAG_ACTIVITY_CLEAR_TOP 입니다. 제가 개인적으로 가장 사랑스럽게 생각하는 녀석입니다. 이 플래그가 사용되는 경우  
런치하고자 하는 Activity 가 이미 Task 상에 존재하는 경우, 해당 Activity 위에 존재하는 다른 Activity 를 모두 종료시켜 줍니다. 따라서 A->B->A 로 호출이 일어나는 경우, B Activity 가 종료 되고, A Activity 만 Task 에 남게 됩니다. (A->B->C->A 인 경우에도 마찬가지로 B와 C 가 종료되고 A 만 남게 됩니다.)

  이 Flag 는 특정 어플리케이션의 대쉬보드 (혹은 홈) Activity 를 호출할 때 굉장히 유용하게 사용될 수 있습니다. 즉 하나의 어플리케이션이 하나 혹은 두 가지의 주요한 Activity 와 그 외 특정 값을 선택하는등 단순한 일을 수행하기 위한 여러 개의 Sub-Activity 로 구성되어 있다면, 주요 Activity 를 호출하는데 이 Flag 를 사용함으로서 어플리케이션의 홈버튼등을 손쉽게 구현할 수 있습니다. 또 이 Flag 는 FLAG_ACTIVITY_REORDER_TO_FRONT 와는 달린 Task 의 순서를 뒤섞지 않음으로 사용자에게도 큰 혼란을 주지 않습니다. (사용을 적극 권장합니다.)

 한 가지 주의해야할 점은 A->B->A 형태로 Activity 를 호출 하고자 할 때, 단순히 FLAG_ACTIVITY_CLEAR_TOP 만을 사용하게 되면, 기존에 생성되었던 A Activity 가 종료된 후 (onDestroy() 가 호출됨) 새롭게 A 가 생성 (onCreate()) 됩니다. 만일 기존에 사용된 A Activity 가 계속 사용되기를 원한다면, SINGLE_TOP 플래그와 함께 사용해야 합니다.

 휴... 생각보다 내용이 길어졌네요. 대부분 SDK 문서를 읽어보면 잘 나와있는 내용이라 새로운 내용은 없습니다만... 문서 읽기를 게을리한 덕분에 한창을 고생했던 기억이 떠올라 (특히 CLEAR_TOP) 유용하게 사용한 Flag 를 정리하는 겸 작성해 보았습니다~

2012년 4월 1일 일요일


[블로터포럼] 새싹 CEO들의 고민은
by 도안구 | 2012. 04. 01
  
지난 2월 새싹찾기라는 꼭지에 등장했던 대표 세 분을 다시 만났다. 클라우드 기반 서비스와 앱을 제공하는 장선진 소프트웨어인라이프 대표와 교육용 앱 개발 회사인 신석현 형아소프트 대표, 배달통을 서비스하는 김상훈 스토니키즈 대표가 그 주인공들. ‘모바일’ 분야에 가능성을 보고 도전한 새내기 기업들이다.
이들을 다시 한번 만난 이유는 개별 인터뷰 때 물어보지 못했던 내용도 이 참에 물어보고, 서로 얼굴도 트는 자리를 마련하기 위해서였다. 블로터닷넷은 앞으로 새싹찾기에 등장했던 대표들을 이런 자리를 통해 꾸준히 만나 볼 계획이다.
새싹기업인만큼 세 대표들의 고민도 엇비슷했다. 투자를 받아야 하는 시점에 대한 고민과 매출 달성을 위해 어쩔 수 없이 수행해야 하는 외주 제작의 문제, 또 안드로이드의 다양한 버전 지원에 대한 기술적인 고민까지 술술 풀어놨다.사업 초기 월급을 주기 위해 제2금융권에서 대출을 받기도 했고, 아내의 적금을 맡기고 대출도 받아보고 했었다는 이야기는 많은 새싹 기업들의 현주소를 엿볼 수 있는 대목인 듯 해 마음이 울컷했다.
기술적인 부분에서는 안드로이드의 파편화 문제에 대한 대응이 공통된 고민이었다. 단순히 안드로이드 운영체제 버전의 차이만이 문제가 아니라 각 제조회사들마다 서로 다른 센서들의 성능이 정말 큰 문제라는 것. 이들은 “새싹기업 입장에서 시장에 출시되는 제조회사들의 스마트폰을 모두 지원하기란 현실적으로 힘들다”면서 “이 문제는 좀처럼 해결될 기미가 없어 보이는것이 정말 문제”라고 어려움을 토로했다.
자리에 일어나 출발선을 갓 출발한 이들의 고민 속으로 다시 한벌 들어가 귀를 기울여봤다.
  • 일시: 2012년 3월 21일
  • 장소: 양재동 블로터아카데미 회의실
  • 참석자: 장선진 소프트웨어인라이프 대표(사진 오른쪽), 신석현 형아소프트 대표(왼쪽), 김상훈 스토니키즈 대표(가운데), 도안구 블로터닷넷 기자
도안구 : 다시 한번 만나게 되어 반갑습니다. 바로 본론으로 들어가보죠. 대표로서 투자를 받는 문제에 대해 어떻게 생각하고 계신가요.
김상훈 스토니키즈 대표(이하 김상훈) : 게임회사 출신이라서 그런지 제 나름의 가치관이 있습니다. 넥슨처럼 회사를 키우고 싶다는 생각입니다. 내부의 건실한 수익 모델을 통해 외부 투자를 최소화하면서 회사를 키우겠다는 생각입니다. 될 수 있으면 자생력을 키워날 갈 수 있도록 하는 전략입니다. 투자도 부담이 될 수 있거든요. 투자는 각 회사 경영진들의 생각에 따라 많이 다르다고 봅니다. 사업 초기엔 제 2금융권을 이용하기도 했습니다. 지금은 웃으면서 이야기하지만 그 때는 그런 것들밖에 자금을 수혈받을 수 없었죠.
신석현 형아소프트 대표(이하 신석현) : – 사업 초기에는 투자에 대해서 별 생각이 없었습니다. 투자가 필요한 때가 될 때 받을 수 있으면 좋겠다는 생각을 해봤죠. 회사를 빠르게 키워가야 하는 시점이던가 아니면 자본의 힘으로 외형을 키울 필요가 있을 때 말입니다. 그런데 막상 사업을 하고 회사를 운영하면서 관점이 조금 달라졌습니다. 공모전 수상도 해보고 했지만 사업 하면서 대출도 받고, 현금서비스도 받고 아내의 예금을 담보로 대출도 받아 봤습니다.(웃음). 그런 고비를 넘기면서 많이 바뀌었습니다. 올해는 모바일 앱 관련 교육 플랫폼을 만드는 해라서 투자를 받아볼 까 합니다.
도안구 : 두 분 다 사업 초기 힘겨운 나날을 보내셨군요. 장선진 대표의 생각은 어떻습니까.
장선진 소프트웨어인라이프 대표(이하 장선진) : 다행히 저희는 카드를 긁어보지 않앗습니다. (웃음). 저는 사람을 키우는 회사를 만들고 싶십니다. 사람을 키우려면 분명히 돈이 필요합니다. 그래서 사업 초기부터 수익 위주로 일을 해 왔습니다. 저희는 B2C 분야의 게임과 클라우드 분야인 B2B 사업 모델을 가지고 있습니다. 구글앱엔진 프로젝트로 기업 대상으로 수익을 냈습니다. 외부 고객들의 프로젝트를 수주하면서도 내부 역량을 키울 수 있도록 노력했습니다. 투자는 당연히 받아도 좋다고 봅니다. 다만 단기적 이득을 얻기 위한 투자보다는 지속적으로 회사의 서비스와 인력들이 성장할 수 있는 투자였으면 하죠.
도안구 : 좋은 투자가들을 만나시길 바랍니다. 그럼 말이 나온 김에 외주 제작과 내부 제작에 대해서는 어떻게 조율해 나가는 지 궁금합니다. 배달통엔 상관없는 질문이기는 하지만요.
장선진 : 창업 초창기 그 문제로 내부에 이견이 있었습니다. 저희는 개인 대상 콘텐츠와 구글앱앤진이라는 클라우드 기반 B2B 사업 파트가 있었습니다. 전 초기에 게임 개발에 대해서는 좀 말렸습니다. 우리가 조금 더 성장하고 나서 콘텐츠 개발에 인력과 시간을 투자했으면 했죠. 그런 상황을 만들어 놓은 과정은 반드시 필요했다고 본 것이죠. 그런데 일단 게임을 만들어 보기로 했는데 판매가 잘 안되었습니다. 안타깝기는 하지만 그래도 좋은 경험이었죠.
외주를 해도 저희는 인력을 파견하지 않습니다. 그래서 시작도 못해보는 곳들이 물론 있죠.(웃음). 구글앱엔진 관련해서 그간 고객들을 많이 확산시키지 못한 이유 중에 하나이기는 하지만 이런 정책을 바꿀 생각은 없습니다. 우리가 관련 경험을 축적하고 내부 인력들이 관련 기술들을 쌓아갈 수 있는 상황을 유지하기란 쉽지 않지만 저희의 서비스 개발을 위해서도 이런 정책을 고수하려고 합니다.
신현석 : 저도 장선진 대표와 비슷한 생각을 가지고 있습니다. 저희는 교육 관련 앱을 선보이고 교육 관련 앱 위주로 외주 제작을 하고 있습니다. 전혀 생뚱맞은 영역의 용역은 회사와 내부 동료들의 기술 축적에 도움이 안됩니다. 생산성 향상을 위해서는 저희가 지향하는 앱 위주로 하는 것이 여러모로 좋습니다. 또 회사를 만든 이상 남이 시키는 대로 내부 인력들이 일하는 걸 보고 싶지도 않습니다. 얼마 전 외주 제품 때문에 직원들이 2박 3일 가량 철야를 하는데 차마 못보겠더라구요.
김상훈 : 저도 할 이야기가 있습니다.(웃음) 실은 저도 2년 정도는 게임 관련해서 외주 용역으로 일을 받아서 회사를 운영했습니다. 초기엔 선택의 문제는 아닌 것 같습니다. 회사를 유지하기 위해서는 외주 제작을 하는 게 현실적이죠. 그렇지만 회사가 외부의 영향력 아래 있다는 것이 문제긴 하죠. 2년 정도 하다가 문제가 발생해서 우리 자체 서비스를 만들어 보자고 생각을 했고 승부수를 띄웠습니다. 그게 운이 좋게 인기를 끈 것이죠.
신석현 : 서비스는 만들기는 쉽지 않지만 궤도에 올면 그렇게 부러울 수가 없죠. 용역 비즈니스는 너무 가변적입니다. 돈도 제 때 안들어오는 경우도 많죠. 참 불안한 모델입니다.
도안구 : 사업 모델과 수익 모델 확보는 기업의 영원한 숙제 같습니다. 이번엔 최근 자주 언급되고 있는 안드로이드 파편화 문제에 대해서 좀 말을 나눠보죠. 버전이 너무 다양하고 제조 회사들 기기들도 천차만별인데 어떤 기준으로 앱이나 서비스를 제공하시나요.
장선진 : 고민이 많은 분야입니다. 애플 아이폰은 시장도 좋고 유료 결재율도 높다는 건 다 알고 있죠. 그런데 안드로이드는 이야기 나온 것에 비해서 시장성 문제가 있죠. 가장 좋은 방법은 아이폰용 앱을 잘 개발하는 인력이 안드로이드 앱도 잘 개발할 수 있도록 교육시키는 것이 있고, 또 하나는 제이쿼리나 모바일 웹앱 프레임워크인 센차터치(Sench Touch)를 사용해 다양한 플랫폼에 손쉽게 대응할 수 있도록 하는 것이죠.
개발 인력 수급 문제까지 함게 고민해야 될 문제입니다. 최근엔 좋은 미들웨어가 많이 나오고 있어서 이걸 적극적으로 활용하는 데 주목하고 있습니다. 마이크로소프트의 윈도우폰 쪽은 파급력이 있을지 아직 모르겠지만 그래도 막연한 기대감은 있습니다. 클래스 플랫폼에 대한 고민은 모든 앱 개발사들이 느끼는 공통 문제라고 봅니다.
신석현 : 개인 고객들을 본다면 삼성전자의 갤럭시 제품군의 보급율이 가장 높습니다. 좀 상위기종이죠. 그런데 보급형 단말기들이 생각보다 많이 퍼지고 있습니다. 팬택, HTC, 모토로라와 같은 업체는 물론 삼성전자나 LG전자의 보급형 제품들이 많아 쏟아지고 있습니다. 문제는 안드로이드의 운영체제 버전 파편화보다 제조 회사들 마다 다른 수많은 센서들의 성능 차이, 드라이버 문제 등이 실제는 더 큰 고민이고 문제입니다. 어디는 되고 어디는 안되고 하는 문제가 많이 발생하죠. 같는 회사 제품인데도 부품이 달라서 또 손을 봐야 하는 경우도 비일비재합니다.
새로운 기기가 나오자 마자 바로 대응하기란 안드로이드 진영에서는 거의 불가능합니다. 물론 애플의 iOS도 버전이 바뀌면서 API가 갑자기 바뀌는 경우도 있기는 하죠. 그렇지만 하드웨어를 애플이 만드니 안드로이드 진영에서 느끼는 어려움이 상대적으로 덜한 상황일 뿐입니다.
김상훈 : 저희는 위치기반 서비스를 하고 있어서 그 부분에 대해 문제를 지적해보고 싶습니다. 안드로이든 쪽은 GPS 수신율이 기기마다 너무 다르고 아이폰에 비해서 수신 감도도 별도 좋지 않습니다. 이러다보니 저희는 상위 톱 5 앱만 우선 지원합니다. 기기마다 너무 분화돼 있어서 모두를 지원하기란 사실 불가능합니다. 그리고 판매 대수도 많지 않은 곳이 있습니다. 고객들에게는 정말 죄송한 일이지만 현실적으로 모든 기기를 지원할 여력이 없습니다.
도안구 : 그럼 삼성전자가 다양한 크기의 태블릿을 선보이는 데 그것도 고민이 많겠군요.
일동 : 네. 삼성전자가 너무 다양한 사이즈의 태블릿을 내놓는 게 이해가 안갑니다. 그거 다 지원하는 앱 개발회사들은 아마 없을 겁니다.
도안구 : 삼성전자가 가장 먼저 아이스크림 샌드위치에 대한 업그레이드 지원에 나섰습니다. 이건 박수받을 일이죠. 여러분 회사는 언제쯤 아이스크림 샌드위치에 맞게 업그레이드 할 계획이신가요.
신석현 : 우린 아직 지원을 안하고 있습니다. 지금 운영체제가 불안한 상황입니다. 게시판을 보면 나오잖아요. 아직 검증을 더 해봐야 합니다
정선진 : 너무 서두를 필요는 없어 보입니다. 모든 제조회사가 지원하는 것도 아니고 사용자들이 빠르게 아이스크림 샌드위치로 넘어가는 것도 아닙니다. 좀더 지켜봐야 합니다.
김상훈 : 아직 대응할 상황은 아니라고 봅니다. 지금 지원하고 있는 앱들도 지속적으로 최적화 시키고 있어서 개발자가 고생이 많습니다. 개발자 눈이 꼭 팬더처럼 되더라구요.
도안구 : 다크서클이 커져서 그렇다는 말인 듯 해 웃지도 못하겠다.
신석현 : 안드로이드 개발자들은 신형 폰이 출시된다고 하면 한숨부터 쉽니다. 그만큼 지원 문제가 쉽지 않죠. 또 개발자 입장에서 어떤 폰은 지원하고 어떤 폰은 지원하지 않으면 정말 찜찜하거든요. 마땅한 해법도 찾기가 쉽지 않습니다.
김상훈 : 고객 클레임에 민감할 수밖에 없는 서비스를 제공하다보니 한분 한불의 불만에 제대로 대응 못해 아쉬움이 큽니다. 개발자도 제대로 대응하지 못한다고 생각하고 풀이 죽어 있죠. 안드로이드 쪽은 이런 문제가 좀 심각합니다.
도안구 : 마이크로소프트의 윈도우폰에 대한 기대는 어떻습니까.
김상훈 : 저는 기대를 많이 하고 있습니다. 아이폰을 2년 쓰고 있지만 처음에는 앱들도 많이 다운받아보고 이것 저것 활용도 많이 했지만 지금은 자주 사용하는 것 몇개 위주로 사용합니다. 마이크로소프트 윈도우는 PC와 엑스박스, 스마트폰을 모두 연동해주는데 있어서 경쟁력이 있을 거라고 봅니다. 윈도우8이 출시되고 폰의 운영체제도 더 개선된다면 가능성이 아예 없는 건 아니라고 봅니다. 물론 윈도우폰7을 탑재한 폰의 경쟁력은 아직 멀었다는 생각입니다. 또 삼성전자가 제대로 된 윈도우폰을 만들어 주면 그 때 생각을 해보겠지만 말이죠.
장선진 : 스마트폰 운영체제 시장에서 마이크로소프트는 힘들어 보입니다. 고급폰은 애플의 아이폰이 확실히 틀어쥐고 있고 저가폰은 안드로이드가 장악했습니다. 그럼 마이크로소프트는 중간 지대로 치고 들어와야 하는데 이 시장은 아주 애매모호한 규모이기도 하고 틈새가 큰 것도 아니죠. 마이크로소프트가 콘텐츠를 많이 만들어 내고 협력을 하겠다고 하지만 쉽지는 않을 것 같습니다.
신석현 : 윈도우폰7 가지고는 희망이 없어 보입니다. 마이크로소프트는 스마트폰 시장에서 많은 기회를 잃은 것 같습니다. 물론 마이크로소프트를 지지하는 개발자들은 여전히 많이 있습니다. 개발 도구와 관련된 분야만 놓고 보면 마이크로소프트가 칭찬받을 만 한데 딱 거기까지입니다. 기업 내부에서 사무를 보는 용도로 도움을 주는 접근법은 여전히 가능성이 있어보이지만 개인 대상의 시장은 달리 생각해봐야 할 문제라고 봅니다.
(신석현 대표는 초기 마이크로소프트 윈도우 모바일 개발로 시장에 대응해왔었다. 그는 “시장이 있어야 하는 데 시장이 없다”라고 잘라 말했다. 많은 개발 우군을 가지고 있지만 정작 경쟁력 있는 폰이 고객들에게 널리 확산되지 않은 상황에서 윈도우폰을 지원하기 위해 지금 당장 인력과 시간을 투자할 곳은 거의 없다는 설명이었다.)
도안구 : 마지막으로 관련 생태계 관련한 제도 개선 분야에 대해서 한마디 한다면
장선진 : 클라우드 서비스 업체 입장에서는 개인정보보호법이 바뀌어야 합니다. 클라우드 시대에 특정 공간이나 지역에 정보를 저장하라는 건 너무 웃긴 것 같습니다. 기술 흐름이나 시장 변화와 동떨어져 있습니다.
김상진 : 인력 채용 문제와 관련한 제도가 너무 빡빡합니다. IT 전문 인력 지원금 제도라고 있었습니다. 100인 이상 회사에서 5년 정도 다니고 직급은 과장을 달았던 이가 이직할 때 채용 장려금을 해당 업체에 지원하도록 합니다. 근데 이 기준이 정말 너무 까다롭거든요. 4년 반 동안 100인 이상 회사 다니다가 그만둔 인력은 아예 기준에 못들죠. 과장 이상이라는 직급도 그렇구요. 제대로 바뀌면서 사실상 이를 활용할 수 있는 곳들은 많지 않아졌을 겁니다. 이러 부분이 좀 유연해졌으면 좋겠습니다.
신석현 : 최근엔 바빠서 정부 제도에 대해서 유심히 살펴볼 시간이 없었습니다.(웃음). 정부 과제에도 많은 기업들이 신청을 하는데 문턱이 높고 아주 좁습니다. 정부 과제를 수행할 수 있는 문턱도 낮출 필요가 있어 보입니다 .
도안구 : 바쁘신 시간 내주셔서 고맙습니다. 초심 잃지 않고 꾸준히 위기를 극복해 나가면서 지속적인 성장을 이뤄 냈으면 좋겠습니다. 그 여정 속에서 자주 인사드리도록 하겠습니다. 봄날인데 감기들 조심하세요.