IT Life

안드로이드 앱, 제대로 한번 만들어 보자!

2015.10.15 09:41


이전 글들에서 계속 나왔던 주제, 바로 좋은 코드입니다. 이번에는 좋은 코드에서 더 나아가 좋은 애플리케이션을 만들기 위해 필요한 전략들을 알아 볼텐데요. 먼저 안드로이드 앱에 대해 알아보겠습니다. 여러분이 이미 안드로이드 앱개발을 해봤으며, 기본 위젯(widget[각주:1])들을 사용해봤다는 가정하에 설명드리겠습니다.


안드로이드 프로젝트를 처음 만들어 보면 여러 폴더들이 나옵니다. 그 중 Android Studio의 경우 기본으로 프로젝트를 만들면 『/app/src/main/java/』 폴더 아래 java 파일들이 안드로이드 애플리케이션의 비즈니스 로직을 담당하고 있습니다. 아시다시피 java 파일들은 각각의 특성에 따라 프로그래머가 그룹을 지을 수 있습니다. 바로 java에서 패키지라 불리죠. 


순환 참조란 A패키지에서 B패키지의 클래스에 있는 메서드를 호출하고 B패키지에서도 A패키지의 클래스에 있는 메서드를 호출하는 경우를 말합니다. 즉 서로 상대방의 메서드를 호출 하고 있는 상황 입니다. 이는 패키지뿐만 아니라 클래스에도 적용할 수 있습니다. 같은 패키지에서도 서로 다른 클래스가 상대방의 메서드를 참조하는 경우 순환 참조하고 있다고 얘기할 수 있습니다.


순환 참조는 대부분 좋은 코드를 지향하는데 방해가 됩니다. 유명한 정적(static) 분석 툴인 소나 큐브(Sonar Qube)에서는 “아키텍처에서 최우선적으로 고려해야 할 것은 의도치 않은 순환 참조를 제거하는 것” 이라고 강조합니다. 순환 참조가 왜 좋지 않은 걸까요? 한쪽의 패키지를 수정했을 경우 얽혀있는 다른 패키지의 코드도 수정될 확률이 높기 때문입니다.

순환 참조를 제거하기 위해서 어떻게 해야 할까요? 비슷한 속성끼리 패키지를 구성해야 하는데, 예를 들어 보겠습니다. 

카드를 관리하는 기능을 갖고 있는 앱을 두 가지 방식으로 만들어 보았습니다. 즉 두 프로젝트는 같은 기능을 하는 앱인 것이죠. 아래 프로젝트 A와 B의 상황을 살펴 볼까요?



프로젝트 A에서는 안드로이드 기능 관점에서 패키지들을 그룹화 했습니다. 즉 ‘activity’ 패키지는 화면을 구성하는 안드로이드 Activity 클래스들이 모여있고, ‘adapter’는 데이터를 관리하고 View 객체(패키지가 아닌 안드로이드 View 클래스)에게 데이터를 넘겨주는 역할을 담당하고 있는 클래스들이 모여있습니다. 


이처럼 안드로이드 관점의 기능 별로 묶으면 패키지 이름들만 봐서는 카드를 관리하는 앱인지 알 수 없습니다. 또한 카드의 결제 기능을 하나 수정해야 한다고 가정해봅시다. 그러면 화면에 해당하는 ‘activity’ 패키지에서 관련 클래스를 하나 수정해야 하고 또 Ativity 클래스 안에 배치 될 수 있는 화면 단위인 ‘fragment’ 패키지의 클래스도 수정하고 관련된 ‘services’, ‘adapter’… 모든 패키지가 다 수정될 수도 있습니다.


이렇게 다 수정을 했는데 최종 테스트 단계에서 에러가 났을 때는 어떻게 해야 할까요? 어디서 에러가 났는지 지금까지 수정한 패키지 별로 클래스를 하나씩 다시 테스트 해봐야 합니다. 여러 패키지들의 클래스를 수정했으므로 어디가 잘못되었는지 알기 힘들기 때문입니다.





프로젝트 B는 어떨까요? 업무별, 즉 해당 앱이 역할을 하는 기능을 중심으로 묶었습니다. ‘billing’에는 결제 관련 클래스들이 들어갈 것이고, ‘delete’는 카드 해제 및 삭제, ‘input’은 카드 등록 기능을 수행하겠죠. 기능별로 패키지를 구성한 것입니다. 이때 결제 관련 모듈을 수정한다고 하였을 때, 대부분의 경우 ‘billing’ 패키지에 있는 클래스들만 수정하면 될 것입니다. 그렇다면 다른 패키지의 클래스들은 손을 대지 않았기 때문에 이전과 마찬가지로 잘 돌아간다고 보장할 수 있죠. 그리고 수정 후 테스트에서 에러가 난다면 ‘billing’에서 수정한 코드가 잘못되었다고 판단할 수 있습니다. 프로젝트 A의 경우처럼 에디터에서 복잡하게 스크롤을 넘겨가며 여러 클래스를 수정할 필요가 없는 것이죠!



물론 상황에 따라 패키지를 구성하는 전략은 달라질 수도 있습니다. 하지만 명심해야 할 것은 앱을 만들 때 패키지 구성부터 충분히 신경 써야 하고 의도하지 않은 순환 참조는 피해야 한다는 것입니다. 

매일 매일 쏟아지는 앱 홍수 속에 경쟁은 점점 치열해지고 있습니다. 경쟁에서 살아남기 위해 앱들의 품질은 점점 올려가고 있고, 디자인도 마찬가지 입니다. 점점 그래픽이 화려해지고 동적(dynamic)인 것을 지향하고 있죠. 구글을 예로 들면 ‘머티리얼(Material)’이라는 디자인 컨셉까지 만들 정도로 디자인의 중요성이 커지고 있다는 것을 알 수 있습니다.


안드로이드에서 제공하는 기본 위젯들 만으로도 충분히 앱을 만들 수 있습니다. 하지만 좀 더 멋지고 화려한 앱을 만드려면 기본 위젯 말고도 안드로이드에서 제공하는 그래픽 API나 오픈 소스를 활용해야 합니다. 오픈 소스를 활용하면 빠르고 싶게 원하는 UI를 구성할 수도 있습니다. 하지만 기본 API에는 무엇이 있고 어떻게 작동하는 지 안다면 응용력도 길러지고 내게 맞는 오픈 소스들도 잘 활용할 수 있을 것입니다. 그러면 안드로이드 그래픽 처리가 어떻게 이루어지는지 간단히 살펴 보겠습니다.


안드로이드 그래픽 처리에서 가장 기본이 되는 것이 바로 비트맵입니다. 안드로이드에서 화면에 보여지는 것은 전부 비트맵 형식입니다. 비트맵 형식은 화면에 보이는 이미지 정보를 픽셀들의 집합으로 표시하고 있으며, 여러 비트[각주:2]의 조합으로 하나의 픽셀에 대한 색 정보를 담고 있습니다. 한 픽셀에 비트를 많이 할당할수록 다양한 색상을 표현할 수 있죠.


비트맵을 다룰 수 있다면 화면에 그림을 그리거나 글을 표시 할 수 있습니다. Bitmap이라는 클래스를 통해 메모리에 비트맵 형식으로 저장되어 있는 이미지 정보를 수정하거나 생성하는 것이죠.


아래와 같은 코드를 통해 Bitmap 객체를 생성하고 픽셀들을 색칠할 수 있습니다.



위의 Bitmap 객체는 넓이 300, 높이 300의 픽셀 배열이며, 한 픽셀의 정보를 Alpha(8bit), Red(8bit), Green(8bit), Blue(8bit) 총 32bit로 저장하고 있습니다. 두 번째 라인의 코드는 모든 픽셀을 파란 색으로 전부 칠하는 것입니다. 이렇게 하면 메모리에 ‘bitmap’ 변수로 참조하고 있는 Bitmap 객체를 화면에 표시할 준비가 된 것입니다. 이제 어떻게 표시하면 될까요?


이는 ImageView 클래스를 통해 간단히 표시할 수 있습니다. 두 번째 라인의 setImageBitmap() 메서드를 통해 메모리에 있던 비트맵 정보들이 화면에 자동으로 표시되는 것이죠.



위 방법은 픽셀 단위로 세세한 작업을 할 때는 유용하지만, 원을 그린다거나 선을 긋고 글을 쓸 때는 픽셀들을 일일이 조작하기 힘들기 때문에 매우 지루한 작업입니다. 그래서 안드로이드에서는 고수준의 작업할 수 있도록 Canvas라는 클래스를 제공하고 있습니다. Bitmap을 도화지에 비유한다면 Canvas는 모형자 정도로 생각하시면 됩니다. 여러 도형을 쉽게 그릴 수 있죠. 하지만 모형자만으로 그림을 그릴 수 없기 때문에 여러 색이나 두께의 펜이 필요하겠죠? 바로 이 역할을 하는 것이 Paint 클래스입니다.



위 코드에서처럼 Canvas 객체의 ‘draw~’로 시작하는 메서드를 통해 여러 도형을 그릴 수 있습니다. 먼저 도형을 그리기 전에 3번 라인에서 Paint 객체를 생성한 후 앞으로 그릴 도형의 색과 선의 넓이를 설정해 줍니다. 그 후 7번 라인의 drawLine()을 통해 선을 그립니다. 이 메서드가 없다면 점을 여러 개 붙여 선을 만들어야겠죠? 하지만 이 메서드를 사용하면 편리하게 선을 그릴 수 있습니다. 인자로 들어간 네 개의 숫자 0, 5, 100, 5는 좌표 (0, 5) 에서 (100, 5)로 선을 그리라는 뜻입니다. 마지막으로 스타일을 정의한 Paint 객체를 넘겨주는데요. 다른 도형을 그릴 때 색이나 스타일을 변경하고 싶으면 Paint 객체를 변경 후 다시 그리면 됩니다. 8 ~ 11라인이 그리기 전에 색을 변경한 경우입니다.


이와 같은 과정을 응용하면 Animation 효과도 만들 수 있습니다. 특정 시간 간격으로 그렸던 그림을 지우고 좌표를 이동시켜 다시 그린다면 마치 움직이는 것 같은 효과를 볼 수 있습니다. 


낮은 수준의 그래픽 API를 살펴 보았는데요. 이를 응용하면 나만의 화려한 동작을 가진 Custom View 클래스와 같은 다양한 활용이 가능합니다. 또한 어떤 오픈 소스를 선택하는 것이 현재 프로젝트에 적합한지 분석할 때도 유용합니다.


데이터를 저장하고 불러오는 것은 앱의 가장 기본적인 기능 중 하나입니다. 데이터를 저장하는 수단은 여러 가지 지만, 많은 데이터를 저장할 때는 데이터끼리 관계를 맺을 수 있는 데이터베이스가 좋습니다. 저는 초기에 기본 API만 사용해서 데이터를 관리했었는데, 데이터가 많아지니 코드가 너무 복잡해 지는 것이 문제였습니다. 이때 도움이 되는 것이 ORM(Object Relational Mapping) 기술인데요, ORM을 구현한 라이브러리를 이용하면 코드가 매우 간단해집니다.


OrmLite(http://ormlite.com/)라는 라이브러리를 예로 들겠습니다. 테이블과 클래스를 직접 매핑 시켜주는 라이브러리로, 기본 API로 수십 줄이 필요한 코드를 OrmLite를 통해 10줄 이내로 줄일 수 있습니다. 또한 테이블을 하나의 클래스로 매핑시키고 그 클래스를 객체화하여 반환해주기 때문에 훨씬 직관적입니다. 


예를 들면 아래와 같이 여러 줄에 걸친 코드가



다음처럼 간단해 질 수 있습니다.



학생 정보를 저장해 놓은 테이블을 Student 클래스에 자동으로 매핑시켜 주기 때문에 getName() 메서드를 통해 간단히 값을 불러올 수 있습니다. 코딩 할 때 훨씬 직관적이죠.


OrmLite와 같은 라이브러리를 자유자재로 사용하기 위해서는 많은 샘플과 개발 문서를 보면서 익혀야 합니다. 하지만 스트레스 받을 필요는 없습니다. 개발자를 힘들게 하려고 나온 라이브러리가 아니고 개발을 더 쉽게 도와주려고 나온 라이브러리니까요. DB 로직은 라이브러리에 맡기고 비즈니스 로직에만 신경 쓸 수 있다는 것을 말씀 드리고 싶었습니다. 


이와 같이 앞으로도 새로운 기술이나 라이브러리가 나올 때 번거롭다고 생각할 것이 아니라, 잘 분석해보고 고민해 보는 것이 중요합니다. 프로젝트에 잘만 사용한다면 개발 생산성을 많이 끌어 올릴 수 있을 테니까요!


마지막으로 『이것이 안드로이드다』 라는 책으로도 유명한 박성근님이 운영하시는 ‘슈퍼드로이드’(http://cafe.daum.net/superdroid)라는 카페를 소개해 드립니다. 안드로이드 개발에 유용한 많은 정보가 있으니 참고하시기 바랍니다. 그럼 즐겁게 안드로이드 개발에 푹~ 빠져볼까요?


글 ㅣ LG CNS 의료솔루션2팀 



<’초보 프로그래머를 위한 코딩 꿀팁’ 연재 현황 및 향후 계획>


● 사람이 읽기 쉬운 코드 :  http://blog.lgcns.com/841

● 어려운 코딩, 생각하고 관찰하고 쪼개라! : http://blog.lgcns.com/872

● 인터넷 보다 책! : http://blog.lgcns.com/899

● 안드로이드 제대로 알고 코딩 하기 : http://blog.lgcns.com/931

● 웹 맨땅에 헤딩하지 않기 : http://blog.lgcns.com/959



  1. android.widget 패키지에 있는 UI 요소들을 얘기함 [본문으로]
  2. 컴퓨터에서 정보를 저장하는 최소 단위 [본문으로]
Posted by IT로 만드는 새로운 미래를 열어갑니다 LG CNS

댓글을 달아 주세요

위로