춤추는 개발자

[안드로이드] 우산 챙겨주는 알람시계 본문

Developer's_til/프로젝트 요약

[안드로이드] 우산 챙겨주는 알람시계

Heon_9u 2021. 8. 6. 18:54
728x90
반응형

💻 프로젝트 페이지와 구조

서비스 페이지
날씨에 따라 다른 알람해제 UI

 

📚 개발 도구

  • Android Studio
  • Room
  • Java
  • XML
  • Open API

 

🧑 전체적인 개발 과정

  • 기존 MVC패턴으로 작성한 코드 리팩토링
  • MVVM 패턴과 LiveData 활용, observer패턴으로 최신 데이터 유지
  • DataBinding으로 데이터와 View를 매핑 및 Java 코드 간결화
  • 비동기 처리로 사용한 AsyncTaskRxJava로 교체, API 30이상부터 AsyncTask deprecated.
  • 백그라운드에서 멀티 스레드동기화(synchronized) 작업을 통해 알람 기능 구현
  • 알림음 설정 시, 내장 벨소리와 외부 저장소의 노래 목록을 Fragment로 구현
  • 구글 광고(Admob) 템플릿을 커스터마이징하여 'Native 고급 광고' 배치
  • 날씨에 따라 다른 알림음과 알람해제 UI 제공

 

✅ 아쉬웠던 점

  • MVVM으로 역할을 분리했지만, 여전히 하나의 컴포넌트에 많은 코드가 존재
  • 오늘의 날씨와 함께 미세먼지 정보까지 제공하는 기능
  • 국내 주소만 사용할 수 있기 때문에 해외에서는 사용 불가
  • 알림음 설정할 때, 원하는 노래를 하나씩 찾아야함
  • Dto에 Getter/Setter 메서드가 많아서 복잡함
  • 오늘의 날씨뿐만 아니라, 일기 예보 기능을 추가하여 주 단위 날씨 제공하기 

 

🛠 개선해야할 사항

  • Domain 패키지로 비즈니스 로직을 처리하여 계층 간의 역할 철저히 분리하기
  • 공공데이터의 미세먼지 api와 tmX, tmY 좌표계 측정하여 미세먼지 정보 제공하기
  • 구글 지도와 연동하거나 현재 위치 주소 불러오는 기능 추가하기
  • 알림음 설정 페이지에 검색 기능(문자열 탐색 알고리즘) 추가하기
  • @lombok 활용하기

 

💡 발생했던 이슈

  1. 알람 실행 시, 변수에 데이터가 저장되기 전에 다른 스레드가 참조하며 NPE 발생
  2. API 29이상의 스마트폰에 다크모드를 적용하면 어플의 글씨가 사라지는 현상 발견
  3. 스마트폰 재부팅 시, 알람이 재등록되는 기능에서 ANR 발생
  4. 객체 리스트에 최신 데이터를 반영하기 위해 전체 리스트를 갱신해야함, 이를 개선할 수 있는 방안 찾기

 

🔑 해결책

  1. 처음에는 while문과 boolean 타입의 flag로 해결했지만, 성능(변수의 추가, 반복문으로 시간 지연)적인 측면에 아쉬움이 있었다. 해결 방법을 고민하던 중, 정보처리기사를 공부하면서 봤던 스레드의 동기화가 생각났다. 참고 자료를 찾아가며 동기화 작업을 진행, 동기화 블록 키워드인 synchronized상태 제어 함수 stop(), notify() 활용하여 Thread-safety를 지켰다.
  2. 테마를 담당하고있는 XML 코드가 모드별로 분기되어있지 않음을 발견했다. 테마를 라이트다크모드로 분기하여 해결했다.
  3. 메인 스레드에서 실행되는 Receiver에 많은 작업을 처리하면서 발생한 문제임을 파악, 알람이 재등록되는 Service와 스레드를 생성하여 ANR 문제를 해결했다.
  4. RecyclerView에 데이터를 바인딩시켜주는 Adapter를 개선, RecyclerView.Holder 대신 ListAdapter를 상속하여 DiffUtil을 반환하는 DIFF_CALLBACK 구현, 전체 리스트 중 변경된 Item만 갱신하며 성능 개선

 

🙋‍♂️ 느낀점

 처음으로 도전했던 모바일 어플리케이션 개발로 배운 점이 많은 만큼 이슈도 많았다. 특히, 컴포넌트의 특징들을 간과하며 ANR이 자주 발생했다. 해당 이슈를 해결하면서 모바일 앱은 스레드 관리가 생명이라는 것을 느꼈다.

 

 메인 스레드에서만 UI를 관리하기 때문에 메인 스레드에 너무 많은 작업이 몰릴 경우 ANR이 발생, 더이상 사용자와 어플이 상호작용할 수 없어서 어플은 비정상 종료된다. 그렇기 때문에 백그라운드에서 작업할 업무들은 새로운 Task로 처리하며 멀티 스레드 환경에서 개발하는 것이다.

 하지만, 무지성으로 스레드를 사용하면 안된다. 스레드가 너무 많아지면 그만큼 배터리 소모단말기 발열로 인해 사용자는 불편함을 느낄 것이다. 게다가 Thread-safety를 지키기 위해 동기화 작업을 신경써야 한다. 이런 이유들 때문에 모바일 어플리케이션의 스레드 관리는 매우매우매우 중요한 것이다.

 

 게다가, 단말기의 환경을 생각하며 개발하는 과정도 쉽지 않았다. 안드로이드 버전별 권한 설정메서드 호출을 분기할 뿐만 아니라, 디스플레이 크기에 따라 View의 배치를 비율적으로 진행해야했다.

 

 이외에도 화면에 따라 UI를 어떻게 설계하고 배치할지 고민을 많이 했다. UI는 IT서비스의 첫인상이자 얼굴이기 때문에 사용자의 경험을 높이기 위해서 많은 신경을 썼다.

 

  • 한 페이지에 2개 이상의 레이아웃을 적용하여 스크롤해도 움직이지 않는 View들을 배치
  • 사람들이 주로 터치하는데 쓰는 엄지손가락의 범위를 고려하며 버튼 배치.
  • 특정 Item이나 버튼을 클릭할 때마다 터치 효과를 적용
  • 직관적인 아이콘 적용
  • 레이아웃 커스터마이징
  • Swipe 버튼과 FragmentPager 활용
  • 오픈 소스를 찾아보며 무료 이미지, 아이콘 사용

 

 마지막으로 약 3개월간 유지보수하며 사용자의 피드백이 개발의 원동력이 될 수 있음을 느꼈다. 예상하지 못한 이슈를 발견하기도 하였지만, 가장 기억에 남는 피드백은 나의 개발 의도와는 다르게 사용자에게 혼란을 줬던 점이다.

 처음에는 [구글 광고 템플릿]을 커스터마이징해서 메인 화면에 배치했다. 하지만 사용자 입장에서는 이게 광고인지, 버튼인지 헷갈린다는 것이다. 해당 의견을 받아들여 템플릿 색깔과 메인 화면의 배경색을 다르게 하였고, 템플릿에 광고를 뜻하는 단어인 'AD'를 삽입했다.

 해당 피드백을 접하면서 개발자의 의도를 사용자가 어떻게 받아들일지 항상 고민할 필요가 있음을 느꼈다. 나중에 많은 사용자가 있는 IT서비스를 개발할 기회가 생긴다면 고객 관점에서 개발하며 완성한 기능도 다시 보는 습관들 들여야 겠다.

728x90
반응형