안드로이드 개발 가이드라인
아래는 <Imagine + Engineer> 시리즈 목차이자 첫 글
모바일 애플리케이션 개발은 변화 속도가 매우 빠르다. 물론 웹 개발 쪽도 정말 변화 속도가 빠르지만, 비교하자면 안드로이드나 iOS는 각각 구글과 애플이 주도해서 변화를 이끌어나간다면 웹 쪽은 각지에서 새로운 패러다임을 들고 나와서 "내가 최고가 될 거야!"라고 소리치는 느낌이랄까.
한국에서는 그간 안드로이드가 모바일 앱 시장을 주도해왔다. 얼마 전까지만 하더라도 거의 한국 스마트폰 사용자의 대다수가 안드로이드 기기를 사용했기 때문인데, 아이폰6 출시 이후 아이폰 판매가 한때 30%를 넘어서면서 안드로이드의 인기가 주춤하기도 했다.
그래도 여전히 한국에서 안드로이드의 인기는 여전하고, 특히 중장년층의 변함없는 애정으로 한국에서 '스마트폰 앱을 출시한다면 안드로이드부터'가 아직도 특별한 조건이 붙지 않는다면 정석으로 불린다. 한편 개발자의 관점에서는 안드로이드는 개발을 처음 입문하는 사람이 접근하기에 가장 쉬운 분야인데, 간단한 앱을 만들기 위해서는 상대적으로 알아야 하는 배경지식이 적기 때문이다.
위의 지난 글에서 웹프그래밍을 하기 위해서 알아야 되는 부분을 살펴봤다. HTML, CSS, Javascript 도 해야 되고, Database를 통해 데이터를 조작하려면 SQL도 알아야 한다. 그 뿐만 아니라 자바스크립트 기반인 Nodejs를 사용하지 않을 거라면 프로그래밍 언어 하나와 그 언어로 구현된 웹 프레임워크도 공부해야 한다. 그리고 실제 사용되는 서비스로 만들려면 서버도 구축해서 직접 세팅도 다 해야 된다. 보통은 개인 학습용이나 작은 프로젝트는 리눅스 기반으로 작업하는 경우가 많으니까 리눅스라는 새로운 OS도 공부해야 된다.
그런데 안드로이드는 서버와 연결이 필요하지 않은 계산기 같은 단순한 앱이라면 정말 손쉽게 만들어서 구글 플레이에 등록할 수 있다. 그래서 많은 시니어 개발자분들이 '안드로이드로 개발 배워서 백엔드 프로그래밍도 할 줄 모르는 이상한 애'가 들어왔다고 탄식하기도 하지만, 나는 개발을 처음 배우는 과정에서 안드로이드를 선택하는 것은 나쁘지 않다고 생각한다. 사실 최근 자바의 트렌드는 안드로이드가 주도하고 있다고 해도 과언이 아닌데, 아직 안드로이드에 자바 버전 7까지 밖에 지원하지 않는 탓에 자바 8의 람다를 사용하지 못해서 안드로이드에서는 RetroLambda라는 라이브러리를 통해서 RxJava 등 다양한 기술의 접목이 일어나고 있다.
무엇보다 우리는 매일 생활하면서 거의 모든 시간을 스마트폰과 함께 하는데, 그 스마트폰에 넣어서 사용할 수 있는 앱을 내 손으로 직접 만들어 본다는 것은 정말 큰 즐거움을 주기 때문이다. 즐겁지 않은 개발로는 몰입할 수 없다. 몰입하지 않고서는 절대로 전문가가 될 수 없고. 자, 그럼 이제 안드로이드 개발자가 되기 위해서 무엇을 공부해야 하는지 알아보자. 순서는 자바 기초 > 안드로이드 기초 > 자바 중급 > 안드로이드 중급 > 자바 고급 > 안드로이드 고급 순으로 구성하였다. 고급에 해당하는 내용은 따로 설명하지 않고 목록만 적어놓는데, 궁금하면 찾아보면 되겠다.
우선 자바를 하지 않고서는 안드로이드 개발을 시작할 수 없다. 자료형, 연산자와 변수, 자료구조(리스트, 해시 맵, 해시 셋), 메소드, 클래스, 인터페이스 순서로 공부하자. 프로그래밍을 처음 공부하는 사람이 하기 쉬운 착각이 책에 나오는 모든 내용을 외워버려야겠다고 생각하는 것이다. 물론 클래스 안에 들어있는 메소드 이름 같은 것은 프로그래밍을 하다 보면 자연스레 외워지는데, 기억이 안 나면 구글 형이 다 알려주신다. 자바를 공부하는 목표는 결코 모든 것을 이해하고 외우는 것이 아니라, 어떤 요소들이 있고 각각의 역할이 무엇인지를 파악하자. 이후에 안드로이드를 직접 만들다 보면 자바에 대한 이해가 더 높아진다.
- XML
웹에 HTML이 있다면, 안드로이드 앱에는 XML이 있다. 사용자에게 전달하기 위한 프로그래밍을 할 때 자바 코드로만 작업을 한다면 변경사항을 파악하기 위해서는 매번 새롭게 실행하는 과정을 거쳐야 한다. 이 과정을 compile이라고 부르는데, 안드로이드는 이 실행 시간이 길기로 매우 유명하다. 화면에 배치된 요소의 위치를 조금 옮길 때마다 다시 앱을 실행시켜야 한다면, 프로그래밍하는 시간보다 실행시키는 시간이 더 많이 잡아먹을 정도다. XML을 이용하면 훨씬 직관적으로 시각적인 요소를 파악할 수 있다.
<View>
<ImageView />
</View>
위의 XML을 보자. 실제 안드로이드에서 사용되는 XML을 굉장히 간소화해서 가져와 봤는데, View 태그 안에 ImageView가 있다는 것을 알 수 있다!
View view = new View()
ImageView imageView = new ImageView()
view.addView(imageView)
위의 XML을 자바 코드로 바꾸면 아래와 같이 쓸 수 있는데 일단 훨씬 복잡하고 직관적이지 않다. 한 마디로 한 눈에 안들어온다. 그리고 이미지를 담고 있는 ImageView나 그 ImageView를 담고 있는 View는 각자 다양한 조건들을 갖고 있기 때문에 UI가 복잡해질수록 XML을 쓰는 것이 훨씬 유리하다.
- Activity/Fragment
액티비티는 안드로이드의 각 화면을 나타낸다. 앱을 쓰다 보면 버튼을 누르면 다른 화면으로 덮이는 것을 볼 수 있다. 다른 액티비티를 호출한 것이다. 프래그먼트는 액티비티 안에서 좌우로 넘기는 페이지를 처리한다든지 하는 세부적인 기능을 수행한다.
액티비티는 안드로이드의 가장 기본 단위고 생명주기를 가지고 있다. 즉, 생성되고 난 다음에 사용되고, 종료되는 일련의 과정에 각각 세팅을 해줄 수 있고, 앱이 복잡할수록 이런 부분들을 잘 처리해주어야 한다. 안드로이드 신입 개발자를 뽑을 때 자주 물어보는 1번 질문쯤 되지 않을까 싶다.
- Intent
인텐트는 액티비티 간에 화면 전환이 이루어질 때 기존의 액티비티에서 갖고 있는 데이터를 다른 액티비티로 전송할 때 사용한다.
- List/RecyclerView
모바일 애플리케이션은 데스크톱에 비해 좁은 화면 특성상 길게 이어지는 리스트 형태의 UI가 많이 사용된다. 당연히 기본적으로 리스트를 처리하는 방법을 배워야 한다.
- 로컬 데이터베이스(SQLite, Realm)
모바일 애플리케이션도 원래 다 프로그램이라서 꺼지면 데이터가 몽땅 날아간다. 그런데 카카오톡은 껐다 켜도 대화 내용이 살아있다! 이게 다 내 휴대폰에 데이터를 저장해놓기 때문이다. 그래서 오랫동안 지우지 않고 쓰다 보면 엄청난 용량을 자랑하는 카카오톡을 볼 수 있다. 이런 기능을 하기 위한 것이 기존에 SQLite가 있었는데, 최근에는 Realm이 핫한 듯하다.
- 애니메이션
애플리케이션도 이제 디자인이 너무나 중요해졌고, 버튼을 눌렀을 때나 화면 간 전환도 매우 중요한 요소가 되었다.
하단 메뉴
- 안드로이드에는 뒤로 가기 버튼과 메뉴 버튼이 있으니, 각 화면 별로 버튼을 눌렀을 때 동작을 처리해줘야 한다. 뭐든 그냥 되는 게 없다.
- Null check
안드로이드 앱을 쓰다가 자꾸 꺼진다. 물론 다양한 이유가 있을 수 있겠지만, NullPointerException은 자바 개발자의 영원한 친구다. 확신이 없는 경우에는 반드시 방어적으로 코딩하는 것이 좋다. 특히 서버와 통신하는 비동기 프로그래밍의 경우 이런 처리가 중요해진다.
- Callback
안드로이드 코딩을 하다 보면 자꾸 무슨 콜백 메소드를 넣으라고 한다. 안드로이드를 처음 배우기 시작할 때부터 알 필요는 없지만, 콜백이 어떻게 구현되는지 알아두면 좋다.
- HTTP API(Retrofit)
다른 사람과 데이터를 함께 공유하고 싶다면 결국에는 서버가 있어야 한다. 무슨 말인지 모르겠다면, 내가 쓴 글 혹은 채팅이 다른 사람이 볼 수 있다면 서버랑 연결되어야 한다고 보면 된다. 로그인, 로그아웃 기능도 마찬가지다. 모바일 애플리케이션은 휴대폰에 저장되는 형태이기 때문에 거의 대부분이 리버스 엔지니어링을 통해서 코드 복원이 가능하다. 따라서 데이터베이스와 직접 연결할 경우 해커에게 '제 서비스의 모든 정보를 다 가져가세요.'라고 하는 거랑 마찬가지다. 결국엔 서버 프로그래밍을 할 수 있어야 하는데, 이 글에서는 누군가 서버 쪽 작업을 하는 사람이 있다고 가정하자. 하지만 결국 안드로이드 개발을 하다 보면 서버 쪽에 관심이 갈 수밖에 없다.
일반적으로 서버와 모바일 기기의 데이터 전송은 REST API를 통해서 이뤄지고, 이것을 쉽게 도와주는 것이 Retrofit이다.
- Image(Picasso/Glide)
위의 Retrofit을 통해서 데이터를 받아왔는데, 사용자 프로필 사진의 url(온라인 상의 주소)가 따라왔다면? 이제 이 이미지를 안드로이드 기기로 다운로드하여서 보여 주어야 한다. 그런데 리스트라 이미지가 너무 많다면? 앱 전체에 이미지 사용이 많아서 메모리 관리가 필요하다면? 그럴 때 쓰는 게 Picasso나 Glide라는 라이브러리다. 다른 부분을 신경 쓰지 않고 이미지를 손쉽게 가져올 수 있게 해준다.
- Cache
위에 소개한 이미지 처리 라이브러리의 경우 일정 부분 이미지를 캐싱 처리해준다. 캐싱이란 결국 메모리에 이미지를 올려놓고 쉽게 꺼내 쓰는 것을 말한다.(물론 메모리만 캐싱을 할 수 있는 것은 아니다.) 왜냐면 같은 이미지를 매번 다운로드한다면 앱 전체 속도가 늦어질 수밖에 없고, 자주 사용하는 이미지는 캐싱 처리해서 메모리에 올려놓고 사용하는 것이 좋다.
캐싱은 이미지에만 사용하는 것은 아니고 자주 호출하는 데이터에서도 사용 가능하다. 물론 서버 쪽 캐싱 작업도 존재한다.
- Thread/Handler/Looper
모바일 앱을 쓰다가 갑자기 화면이 멈췄다가 움직이는 것을 본 적이 있다면 바로 '스레드' 처리를 잘 해주지 않았기 때문이다. A와 B라는 작업이 있을 때 보통은 A를 완료한 다음 B를 작동해도 무관하다. 그런데 그러면 안 되는 경우가 있다. 바로 앱에서 버튼을 눌렀을 때와 같은 상황인데, 다른 작업을 하기 위해서 화면이 잠시 멈추면 사용자는 '앱이 죽었다.'라고 느끼게 된다. 내가 이런 불편을 매일 같이 느끼는 앱은 '네이버 웹툰'인데 제발 고쳐주면 좋겠다. 이런 앱의 경우 '서버에 데이터를 요청하고 기다리는' 작업을 수행하면서 '화면을 움직이는' 작업을 쉬고 있는 것이다.
- SparseIntArray
- WeakReference
- 테스트 및 성능 관리
Crashlytics
Roboletics
메모리 관리(설정)
화면 수직/수평 전환 테스트
- 주요 라이브러리
Retrolambda/RxJava
Gson/Jackson
Roboguice/Dagger
Proguard
Picasso/Glide(위에서 언급)
Retrofit(위에서 언급)
- 다른 프로그래밍 언어
자바가 좋은 언어라는 것은 분명하지만 가장 편리한 언어가 아닌 것도 확실하다. 자바는 JVM이라는 가상 머신 위에서 돌아가는데, 같은 가상 머신 위에서 돌아가는 Scala, Kotlin 같은 언어를 통해서도 안드로이드 프로그래밍이 가능하다. 특히 Kotlin의 경우 최근 iOS 개발이 가능한 Swift와 비슷한 문법으로 주목받고 있다.
- 하이브리드 앱
안드로이드를 처음 배우면서 하이브리드 앱으로 시작하는 것은 권하지 않는다. 하이브리드 앱은 결국 안드로이드 본연의 기능을 제대로 알고 있어야 사용하기 쉽기 때문이다. 하지만 하이브리드의 장점은 한 번의 작업으로 iOS와 Android 앱을 찍어낼 수 있다는 점이다. 특히 웹뷰를 사용한 페이지의 경우 앱을 구글 플레이에 올려놓고 다시 올리는 작업 없이 수시로 화면을 변경할 수 있어서, 사용자가 적은 초기 앱에 적용하면 좋다. 물론 안드로이드 본연의 기능을 사용하는 네이티브 앱에 비해 성능은 떨어지는 것이 사실이다. React Native, Ionic, Xamarin와 같은 프레임워크들이 있다.
- 소셜 로그인
사람들은 일일이 이메일을 넣고 가입하는 것을 싫어하기 때문에 페이스북이나 카카오톡을 통해서 간편하게 가입하고 싶어 한다. 각각의 개발자 페이지에 들어가서 문서를 보고 해당 내용을 붙여야 한다.
- 지도
구글맵이나 네이버 지도, 다음 지도 등의 API를 이용한다. 휴대폰의 위치 정보를 통해서 주소를 불러온다든지 하는 작업이 가능하다.
- 동영상 & 음악
동영상이나 음악 등의 멀티미디어를 재생하는 부분도 익혀두면 좋다. 요즘은 바야흐로 동영상의 시대이니까.
- Bluetooth, Beacon, NFC
IoT의 선구자 같은 기술들이다. 일반적인 네트워크를 통하는 것이 아니라 안드로이드 기기 내장 센서를 통해서 작동한다.