2013
마이크로소프트웨어

글: 김도균 | dokyun@dokyun.pe.kr / 2013-06


<COVER STORY 2>

성공적인 앱 개발을 위한 FAQ

안드로이드 기본 API 활용 노하우

안드로이드가 국내에 본격적으로 도입된 지도 약 3년의 시간이 흘렀다. 그동안 안드로이드의 버전이 빠르게 업데이트돼 현재 4.2 젤리빈 버전이 사용되고 있으며, 키 프라임 파이가 올해 공개될 것으로 예상된다. 그럼에도 SDK의 핵심은 크게 바뀌지 않고 있으므로 기본을 확실히 익혀 둔다면 버전이 계속 업그레이드되더라도 새로운 버전을 쉽게 이해할 수 있을 것이다. 지금부터는 안드로이드의 기본 API에 대해 살펴보자.



안드로이드 애플리케이션 동작 방식
안드로이드 디바이스에 설치된 .apk 파일은 자체 샌드박스 모델에 의해 동작된다. 안드로이드 운영체제는 각 응용프로그램에게 각각 다른 사용자 계정을 부여해 실행시키기 때문에 응용프로그램들은 각각 리눅스 사용자 ID를 가진다. 이 ID에 의해 각 응용프로그램들은 접근 권한과 파일 권한을 가진다. 안드로이드 응용프로그램들은 안드로이드 운영체제 상에서 각각 VM을 할당 받아 실행하게 되므로 각 응용프로그램들은 다른 프로그램들의 영향을 받지 않게 된다. 응용프로그램들은 기본적으로 필요한 시스템이 가지고 있는 구성요소에 대한 접근권한을 가지고 실행되고 권한이 부여되지 않으면 시스템이 가지고 있는 구성요소에 접근할 수 없다. 

안드로이드 운영체제의 자원 활용도를 높이기 위해서 리눅스 사용자 ID를 공유하도록 할 수도 있고, 서로 다른 시스템들끼리 동일 VM을 사용할 수 있도록 추천할 수도 있다. 또한 응용프로그램은 사용자의 연락처, 메시지, 카메라와 같은 기능에 접근하게 할 수 있도록 권한을 부여할 수 있다. 이러한 권한들은 응용프로그램 설치 시에 사용자에게 부여해야 한다.


안드로이드 애플리케이션의 구성요소 
안드로이드 응용프로그램은 총 네 가지의 요소로 구성된다. 첫 번째는 액티비티이다. 액티비티(Activity)는 사용자 인터페이스를 가진 화면을 나타낸다. 화면이 필요한 메시지 프로그램, 웹브라우저 프로그램들은 모두 액티비티를 이용해서 만들어졌다. 하나의 액티비티는 하나의 화면을 나타내기 때문에 여러 개의 화면으로 구성된 응용프로그램은 여러 개의 액티비티로 구성되어 있다고 볼 수 있다. 예를 들어 메시지를 주고받는 안드로이드 애플리케이션은 메시지의 목록을 조회하는 액티비티와 메시지의 상세내용을 조회하는 액티비티로 구성되어 있다.  

두 번째로는 서비스(Service) 구성요소를 가지고 있다. 서비스는 백그라운드에서 장기적으로 실행되기 위해 구현되는 구성 요소다. 서비스는 별도의 사용자 인터페이스를 제공하지는 않는다. 예를 들어 음악을 재생한다거나 네트워크를 이용해서 외부와 메시지를 계속 주고받는 작업 등을 할 수 있다. 

세 번째 구성요소는 콘텐트 제공자, 즉 콘텐트 프로바이더(Content Provider)이다. 우리가 만든 응용프로그램은 SQLite와 같은 영구 저장소에 데이터를 저장할 수 있다. 안드로이드 OS에서는 콘텐트 프로바이더를 이용해서 SQLite와 같은 데이터베이스에 접근할 수 있도록 하고 있다. 이뿐만 아니라 콘텐트 프로바이더를 통해 다른 응용프로그램에서 데이터를 읽거나 쓸 수 있다. 안드로이드 시스템에서는 기본적으로 몇 가지 응용프로그램에 대해 콘텐트 프로바이더가 준비돼 있다. 예를 들어 주소록이나 메모장 같은 경우가 될 수 있다. 

네 번째 구성요소는 브로드캐스트 리시버(Broadcast receiver)이다. 이 컴포넌트는 안드로이드 시스템 전체에서 오는 브로드캐스트 공지사항에 대해 응답하거나 공지사항을 전송할 수 있는 구성요소이다. 예를 들어 화면이 꺼졌다고 공지사항이 전송된다면 응용프로그램에서는 상응하는 작업을 수행할 수 있고, 응용프로그램이 어떤 작업을 할 경우 이 작업이 다른 응용프로그램에게 영향을 미친다면 이를 공지사항으로 전송할 수 있다. 브로드캐스트 리시버의 경우 사용자 인터페이스에 표시되지 않지만, 이벤트가 발생했을 경우에 사용자에게 알려주기 위해서 별도의 노티피케이션을 날릴 수 있다.


다른 애플리케이션 실행
안드로이드 응용프로그램에서는 다른 응용프로그램을 자신의 일부인 것처럼 실행시킬 수 있다. 예를 들어 우리가 만든 응용프로그램에서 카메라를 실행시킬 수도 있다. 응용프로그램에서 카메라를 실행시킬 때 카메라 응용프로그램을 직접 실행시키는 것이 아니라 카메라 액티비티를 우리가 만든 응용프로그램이 구동되는 VM으로 가지고 와서 실행시킨다. 즉 라이브러리 형태로 실행시킨다고 볼 수 있다. 안드로이드 프로그램은 자바의 static void main(String[] args) 메소드와 같이 진입지점을 가지고 있지 않다.  

안드로이드에서 액티비티나 서비스, 브로드캐스트 리시버는 인텐트(Intent)라는 비동기 메시지에 의해 활성화시킬 수 있다. 인텐트는 개별 컴포넌트를 실행 시점에 바인딩한다. 인텐트는 컴포넌트의 타입에 맞는 인텐트 객체를 통해 만들 수 있다. 액티비티 및 서비스에 대한 인텐트는 수행할 작업을 정의한다. 인텐트를 통해 액티비티를 수행하고 그 결과에 대한 반환 값을 받을 수 있다. 예를 들어 연락처 정보를 선택할 수 있도록 인텐트를 발행하고 이 인텐트를 가리키는 URI를 다른 응용프로그램에 전송할 수 있다. 다른 응용프로그램에서는 URI로 인텐트를 실행해 연락처 정보를 조회하거나 수정할 수 있다.  

인텐트를 이용해서 액티비티를 실행시킬 경우 실행된 액티비티에서 이전 액티비티로 돌아가야 할 경우, 안드로이드에서 제공하는 ‘last in, first out’ 구조의 스택을 이용해 수행할 수 있다. 

브로드캐스트 리시버의 경우에 인텐트를 간단히 정의할 수 있지만 콘텐트 프로바이더와 같은 경우에는 인텐트를 이용해서 활성화될 수 없고 콘텐트리졸버(ContentResolver)에 의해서 활성화될 수 있다. 콘텐트리졸버는 콘텐트 프로바이더와 직접적으로 트랜잭션하기 때문에 콘텐트 프로바이더와 트랜잭션하지 않고 콘텐트리졸버 객체를 통해 트랜잭션하면 된다.


안드로이드 메니페스트 파일과 리소스 
안드로이드 프로그램에서 필요한 것 중에 한 가지는 Android Manifest.xml 메니페스트 파일이다. 안드로이드 시스템이 응용프로그램을 구동시킬 때 이 프로그램이 어떤 컴포넌트들을 이용했는지 알아야 한다. 따라서 이 컴포넌트들에 대해 Android Manifest.xml에 기술한다. 이외에도 컴포넌트를 선언할 때 응용프로그램에서 요청하는 사용자 퍼미션들을 설정할 수 있다. 응용프로그램이 실행될 수 있는 최소한의 API Level을 지정할 수도 있고 응용프로그램에서 요구하는 하드웨어 소프트웨어 기능을 선언할 수도 있다. 안드로이드 응용프로그램은 소스 코드와 이미지, 오디오 파일, 비디오 파일 등이 분리돼 있다. 리소스 파일의 수정은 응용프로그램의 수정 없이도 간단히 할 수 있다. 이미지와 같은 리소스 파일을 바꾸어 주는 것만으로도 쉽게 변경할 수 있다. 이렇게 리소스를 분리해서 관리하기 때문에 다른 대체 리소스의 사용이 가능하다. 예를 들어 소스 코드 수정 없이 이미지를 해상도별로 지정해 관리할 수 있다. 안드로이드에서는 다양한 한정자를 지원해주기 때문에 디바이스, 해상도, 통신사별로 다양한 리소스를 지정해 관리할 수 있다.


<FAQ>


Q. 안드로이드를 학습할 때 가장 먼저 공부해야 할 부분은? 
안드로이드에서 가장 공부하기 쉬운 부분은 안드로이드 UI이다. UI를 공부하면서 안드로이드의 동작방식을 이해한 후에 다른 주제로 이해의 폭을 넓히는 것이 좋다. 안드로이드 UI에서 가장 먼저 살펴볼 부분은 레이아웃이다. 레이아웃은 화면의 구성요소를 화면에 배치하는 역할을 한다. 안드로이드에서는 리니어 레이아웃, 상대 레이아웃, 프레임 레이아웃, 그리드 레이아웃과 같은 다양한 레이아웃을 제공하고 있다. 통상 1개 이상의 레이아웃을 섞어서 사용한다. 레이아웃은 사전에 XML에 지정해 사용하기도 하지만, 런타임 시에 레이아웃을 임시로 만들어서 사용할 수도 있다. 레이아웃은 ViewGroup 객체를 상속 받았기 때문에 소스 코드 내에서 레이아웃을 생성할 수 있다.  

안드로이드에서 레이아웃과 화면의 모든 컴포넌트들은 모두 View와 ViewGroup을 상속 받는다. 예를 들어 버튼, 텍스트 에디트, 이미지 뷰와 같은 컴포넌트들은 모두 View를 상속 받는다. 뷰(View) 객체는 아이디, 포지션, 패딩, 레이아웃, 이벤트 핸들링과 같은 기본적인 속성을 가진다. 뷰를 상속 받은 모든 화면 컴포넌트들은 동일한 속성을 가지고 있다. 예를 들어 뷰 객체를 상속받는 모든 컴포넌트들은 클릭 이벤트 리스너를 가질 수 있다. 보통 레이아웃 XML에 레이아웃과 컴포넌트의 객체를 사전에 지정해 사용하는데, 이 컴포넌트들은 모두 findViewById() 메소드를 이용해 추출하고 객체로 변환할 수 있다. 변환된 객체를 이용해 이벤트와 같은 부가적인 기능을 부여할 수도 있다. 안드로이드에서는 기본적으로 버튼(Button), 이미지 버튼(Image Button), 체크박스(CheckBox), 라디오 버튼(RadioButton), 토글 버튼(Toggle Button) 등의 기본 위젯을 제공해준다. 뿐만 아니라 안드로이드가 제공해주는 위젯이 마음에 들지 않는 경우에는 우리가 자체적으로 위젯을 만들어 사용할 수도 있다. 


Q. 안드로이드에서 이벤트 처리는 어떤 방식으로 이루어지는가?
안드로이드는 다양한 이벤트 처리방식을 제공한다. 안드로이드에서는 클릭 이벤트, 키 이벤트, 터치 이벤트, 롱 클릭 및 포커스 이벤트 등의 이벤트가 처리되며, 이벤트 처리 절차는 모든 이벤트가 동일하다. 안드로이드 이벤트 처리 절차는 <그림 1>과 같다. 



<그림 1> 안드로이드 이벤트 처리 절차


개발자가 실제 이벤트를 등록하기 위해서는 버튼 객체에 OnTouchListener를 등록하고 OnTouchListener의 OnTouch() 메소드에서 수행해야 할 로직을 넣어 주기만 하면 이벤트 처리를 위한 작업이 모두 끝난다.

이벤트 처리를 위해서는 OnClickListener와 같은 리스너 인터페이스를 구현해야 한다. 이를 구현할 때 주의할 점은 너무 과도한 중첩 클래스를 사용하지 말아야 한다는 것이다. 하나의 액티비티에서 여러 개의 위젯에서 클릭 이벤트를 처리한다고 가정할 경우, 이를 OnClickListener를 구현한 하나의 클래스에서 위젯의 ID별로 나누어 이벤트를 처리하는 방식으로 이벤트 처리 로직을 한 군데 모으는 것이 좋다. 중첩 클래스를 남발하는 경우에는 코드의 가독성을 저해할 수 있다. 

이벤트 처리를 위해 메소드 내부에 들어간 중첩 클래스를 사용할 경우에는 중첩 클래스에서 참조하는 메소드의 로컬 변수는 final로 선언해야 함을 명심하자. 중첩 클래스에서 로컬 변수를 참조할 경우 중첩 클래스가 생성되는 시점에 참조되는 값이 고정돼 있어야 하기 때문이다.


Q. 안드로이드의 다이얼로그와 노티피케이션의 종류가 궁금하다. 그리고 만드는 방법도 알고 싶다. 
안드로이드에서 제공되는 다이얼로그에는 알림 다이얼로그, 프로그레스 다이얼로그, 커스텀 다이얼로그 등이 있다. 프래그먼트 개념이 추가되면서 다이얼로그 프래그먼트도 제공된다. 알림 다이얼로그는 화면 내비게이션 중간에 사용자에게 상태나 선택을 위한 메시지를 알려주는 목적이다. 프로그레스 다이얼로그는 진행 상태나 진행 바를 표시하는 다이얼로그이며 알림 다이얼로그의 확장개념이다. 데이터 피커 다이얼로그, 타임 피커 다이얼로그는 날짜와 시간 선택을 위한 다이얼로그이다. 

구글에서는 다이얼로그 디자인 가이드라인을 제시하고 있다. 다이얼로그는 총 3개의 영역으로 이루어져 있다. 타이틀 영역, 콘텐츠 영역, 버튼 영역 세 가지로 구분되고 콘텐츠 영역에서는 사용자의 의사결정을 받기 위한 텍스트와 슬라이드, 버튼, 체크박스 등을 넣을 수 있다. 물론 타이틀의 경우에는 반드시 다이얼로그에 넣어야 하는 것은 아니다. 하지만 타이틀이 있는 다이얼로그의 경우에는 좀더 심각한 상황의 경고를 위해 사용될 수 있다. 

안드로이드에서 컴포넌트를 생성할 때 점점 빌더(Builder) 패턴을 많이 활용하는 추세다. 다이얼로그도 마찬가지로 AlertDialog.Builder와 같이 별도의 Builder 클래스를 통해서 객체를 생성하고 설정할 수 있도록 하고 있다. 덕분에 간결하게 다이얼로그를 만들 수 있다.  

알림 다이얼로그는 콘텐츠 영역에 들어가는 내용에 따라 리스트형, 라디오 버튼을 가진 리스트형, 체크박스를 가진 리스트형으로 구분할 수 있다. 이들은 리스트가 선택됐거나 라디오 버튼이 선택될 경우에 이벤트가 발생한다. 이 이벤트를 받아서 필요한 로직을 수행하면 된다. 이 이벤트는 앞서 공부했던 View 객체의 이벤트가 아니라 DialogInterface. OnClickListener()와 같이 DialogInteface 하위의 OnClick Listener를 구현해야 한다. DialogInteface의 OnClickListener의 onClick 메소드의 인자로는 DialogInteface 객체와 선택된 아이템의 번호가 인자로 전달된다.


프로그레스 다이얼로그의 경우에는 진행 상황을 표시해줄 목적으로 사용된다. 프로그레스 다이얼로그 자체는 <리스트 1>의 코드와 같이 간단히 만들 수 있다.



하지만 실제로 이를 사용하려면 스레드와 같은 별도의 진행률 업데이트 방식과 같이 사용된다. 안드로이드에서는 사용자가 만든 화면을 다이얼로그로 만들 수 있는 방법을 제공하고 있다. View 객체를 만들고 이를 다이얼로그 Builder 객체의 setView() 메소드를 이용해서 추가할 수 있다. View 객체를 꾸미기 위해서는 기존의 레이아웃을 인플레이터한 뒤에 수정해서 사용할 수도 있고 ViewGroup으로 직접 꾸밀 수도 있다. 

노티피케이션의 목적은 다이얼로그와 마찬가지로 사용자에게 어떤 메시지를 알려주는 것인데, 다이얼로그는 사용자에게 의사결정을 요청하는 반면에 노티피케이션은 단지 정보를 보여주는 역할만 수행한다. 안드로이드에서의 노티피케이션에는 토스트 노티피케이션, 상태바 노티피케이션, 커스텀 노티피케이션, 리치 노티피케이션 등이 있다. 토스트 노티피케이션은 간단하게 사용자에게 단문 메시지를 출력해주기에 효과적이다.


Toast toast = Toast.makeText(context, text, duration);
toast.show();


위의 코드와 같이 간단하게 만들 수 있다. 간단한 디버깅 용도로도 Toast 메시지는 효과적이다. 상태바 노티피케이션의 경우 너무 자주 사용하게 되면 사용자들이 불쾌감을 느낄 수도 있다. 구글의 경우 노티피케이션은 반드시 시간에 민감하게 관련된 이벤트에만 사용돼야 하고 반드시 사람과 같은 대상을 포함시켜야 한다고 가이드한다. 사람을 포함시킨다는 의미는 예를 들어 다른 사람으로부터 온 메시지를 노티피케이션하거나, 사람과의 약속처럼 다른 사람과 상호작용하는 경우에 주로 노티피케이션을 사용해야 한다는 의미다. 가능하면 상태바 노티피케이션은 주의 깊게 사용해서 사용자들이 우리가 만든 앱을 지우지 않도록 하는 것도 중요하다. 상태바 노티피케이션을 만들기 위해서는 NotificationManager를 getSystemService를 통해 가지고 와서 미리 만들어 놓은 Notification을 NotificationManager에 등록해야 한다. 

커스텀 노티피케이션의 경우에는 커스텀 다이얼로그와 마찬가지로 별도의 RemoteViews 객체를 만들고 이를 Notification의 setView() 메소드의 인자에 입력해 만들 수 있다.


Q. 프래그먼트란 무엇인가?
안드로이드는 버전 3.0부터 좀더 역동적이고 유연한 UI의 구성을 위해서 프래그먼트를 등장시켰다. 간단하게 말하면 미니 액티비티라고 생각할 수 있다. 태블릿의 경우는 화면이 크기 때문에 일반적인 안드로이드폰의 개발과는 UI 디자인 및 UI의 흐름이 달라질 수밖에 없다. 

프래그먼트는 개발자가 간단하게 액티비티의 화면을 분할해서 내용을 구성할 수 있게 한다. <그림 2>는 프래그먼트의 개념도이다.



<그림 2> 태블릿과 휴대폰의 프래그먼트 개념도


<그림 2>와 같이 만들어진 프래그먼트는 태블릿에서는 하나의 액티비티 안에서 사용되며 스마트폰의 경우에는 액티비티에서 프래그먼트가 사용된다. 프래그먼트를 구현할 경우 반드시 onCreate(), onCreateView(), onPause() 메소드를 구현해야 한다. 안드로이드에서 제공하는 프래그먼트의 종류는 Dialog Fragment, ListFragment, PreferenceFragement 등이 있다. 프래그먼트는 다음의 코드처럼 Fragment 클래스를 상속 받아야 한다.


public class TestFragment extends Fragment


프래그먼트를 액티비티에 추가하기 위해서는 xml에 fragment 태그를 이용해 추가할 수도 있고, 액티비티 실행 도중에 <리스트 2>의 코드와 같이 FragmentManager를 통해 추가할 수도 있다.



Q. 허니콤 이후 버전에서는 메뉴 버튼이 없는데, 메뉴를 어떻게 처리해야 하는가?
안드로이드 허니콤 이후 버전부터는 액션바 개념이 도입됐다. 이전 버전의 하드웨어에서는 물리적으로 메뉴 버튼이 존재했다. 하지만 아이스크림 샌드위치 버전 이후의 레퍼런스폰에서는 메뉴 버튼이 제거됐다. 대신 구글에서는 액션바에 메뉴 기능을 추가하도록 가이드하고 있다. 그러므로 허니콤 이전 버전을 타겟으로 하는 경우에는 메뉴를 사용해도 좋지만 이후 버전이 타겟인 경우에는 액션바를 이용해야 한다. 액션바를 이용하는 경우에는 액션 오버플로우를 고민해야 한다. 화면의 해상도나 디바이스에 따라 어떤 액션들은 가려져 있고 어떤 액션들은 노출되게 된다. 따라서 반드시 노출돼야 하는 액션과 가려져도 되는 액션들에 대한 충분한 고민이 필요하다. 

액션바를 사용하기 위해서는 minSdkVersion이 11 이상으로 설정돼 있어야 한다. 메뉴 리소스 xml의 메뉴 아이템에 android:showAsAction=“ifRoom”과 같이 설정하면 화면에 여유가 있을 경우에는 메뉴가 나타나지만 여유가 없는 경우에는 오버플로우 메뉴로 들어가게 된다. 액션바에는 자주 사용되는 메뉴, 중요한 메뉴, 일반적인 메뉴 순으로 메뉴를 넣어줘야 한다. 액션바를 만들기 위해서는 menu.xml에 메뉴 아이템으로 메뉴를 등록해주면 된다. 

또한 액션바에 액션 뷰를 추가할 수 있다. 액션 뷰는 menu. xml의 메뉴 아이템에 android:actionViewClass 속성을 정의함으로써 추가 가능하다. actionViewClass에 해당하는 클래스는 별도로 만들어 액션 뷰의 행위를 정의할 수 있다.
액션바를 이용해서 탭을 구현할 수도 있다. ActionBar. TabListener 인터페이스를 구현하게 되면 탭에서 터치 이벤트가 발생했을 때, 터치 이벤트를 받을 수 있다. 터치 이벤트가 발생하면 ActionBar.TabListener 인터페이스의 콜백 메소드가 호출된다. 콜백 메소드에서 해당 프래그먼트로 바꿀 수 있다.


Q. 안드로이드에서 드래그 앤 드롭은 어떤 방식으로 동작하는가?
안드로이드에서는 클립보드 프레임워크를 통해 응용프로그램 간 또는 응용프로그램 내에서 복사와 붙여넣기 기능을 지원해주고 있다. 클립보드 프레임워크에서 복사와 붙여넣기를 지원해주는 대상은 일반 텍스트 문자열, URI 그리고 인텐트(Intent)이다. 안드로이드의 클립보드 프레이워크에서 사용되는 클래스는 ClipboardManager, CliepData, ClipData.Item, ClipDescription이 있다. ClipboardManager 클래스는 안드로이드 시스템에서 제공해주는 getSystem Service(CLIPBOARD _SERVICE)를 이용해서 얻을 수 있다. 클립보드의 데이터를 추가하기 위해서는 ClipData 객체를 만들어야 한다. 이 ClipData에는 데이터와 데이터를 위한 설명 정보가 같이 담겨 있다. 클립보드는 한 번에 1개씩의 ClipData 데이터를 가질 수 있다. ClipData는 Clip Description 객체를 가지고 있고 1개 이상의 ClipData.Item 객체를 가지고 있다. <그림 3>은 안드로이드에서 제공하고 있는 클립보드 프레임워크의 동작 방식이다.



<그림 3> 클립보드 프레임워크의 동작 방식


데이터를 복사하기 위해서 애플리케이션은 ClipData 객체를 전역 클립보드인 ClipboardManager 객체에 넣는다. ClipData는 1개 이상의 ClipData.Item 객체와 ClipDescription 객체를 가지고 있다. 데이터를 붙여넣기 위해서 애플리케이션은 ClipData에서 데이터를 가져오고 ClipDescription에서 MIME 타입을 가지고 온다. 그리고 ClipData.Item에서 데이터를 가지고 오든가 ClipData.Item에서 참조된 콘텐트 프로바이더에서 데이터를 가져온다.

지금까지 안드로이드 프레임워크에서 제공되는 필수 구성요소와 구조에 대해 살펴봤다. 안드로이드가 동작하는 방식을 정확히 이해하고 응용프로그램을 만들어야 강건한 애플리케이션을 만들 수 있다. 안드로이드는 버전별로 내용들이 계속 바뀌기 때문에 구글 안드로이드 API를 꾸준히 살펴보고 공부하는 것이 좋다. 여의치 않을 경우에는 관련 블로그나 최신 API를 다루는 서적을 살펴보는 것도 바람직하다.



/필/자/소/개/

김도균dokyun@dokyun.pe.kr (프리지아 랩)

마이크로소프트 공인 강사(MCT)이자 MVP(Exchange)이며 IT 전문 번역가와 컬럼니스트로 활동하고 있다. 스마트 라이프를 추구하는 라이프 스타일 이노베이터며 사소하고 일상적인 것에 새로운 가치를 부여하는 일을 즐긴다. 기술 전문가 집단 GoDev(www. godev.kr)의 기술 창의성 리더로, 최근에는 <나홀로 개발자를 위한 안드로이드 프로그래밍의 모든 것>을 출간했으며 그간 20여권의 번역서를 낸 바 있다.




※ 본 내용은 (주)마소인터렉티브(http://www.imaso.co.kr/)의 저작권 동의에 의해 공유되고 있습니다.
    Copyright ⓒ Maso Interactive Corp. 무단전재 및 재배포 금지

맨 위로
맨 위로