프로젝트를 진행한 것이기에 학습 목차 대신, 공부한 것들, 사용한 것들을 시간순으로 정리해 보았습니다.
아키텍처 구조
- 클린 아키텍처를 참고했습니다.
- repository 패턴을 사용하였습니다. (android docs)
[Modules]
- app
- data
- dataSource, httpClient, localDatabase, model, repository
- di
- qualifier
- modules
- ui
- common
- dialog
- bindingAdapter
- animation
- 화면 단위의 패키지들 ...
- domain
- exception, model, repository
- support (주로 util이라 불리는 기능들. util이 app에 영향을 받지 않도록, 제공만 하도록 분리를 명확히한 것.)
- data (데이터 계층에서 사용하는 기능들. 현재는 에러 로그를 가져오는 메서드가 있다. 확장함수인데 왜 여기?)
- presentation
- event (Livedata 단일처리를 위한 Event)
- log (sentry와 같은 log를 출력하는 기능이 있다.)
- images (기기 이미지 uri)
- extentions, loginManager, naverMap, permission 등
Event
일회성 livedata 처리를 위한 방법입니다.
작성 완료, 제출과 같이 버튼이 클릭되었을 때 화면이 종료되어야 하는 경우가 이에 해당합니다.
해당 글을 참고해 event wrapper를 사용하였습니다. (관련 이슈)
Test
android에서는 기본적으로 junit5를 제공하지 않고 있습니다. junit4만 지원합니다.
하지만, Rule을 Extention으로 바꾸어 junit5를 사용할 수도 있습니다.
이렇게 할 경우 일부 안드로이드 의존성이 필요한 테스트에서 vintage engine 의존성을 추가해 junit4와 junit5 문법을 함께 사용해야 하기 때문에 혼동이 올 것이라 판단했습니다.
때문에 app module에서는 junit4를 사용하기로 결정했습니다. (관련 이슈)
Toolbar
툴바는 커스텀이 용이하지 않기 때문에 툴바 뷰를 만들어 include를 사용하고 있었습니다.
하지만, 이는 반복적인 많은 양의 파일을 만들었습니다. 때문에 더 나은 방법이 없을지 고민하였습니다.
AppBarLayout, AppBarLayout, MaterialToolbar 세 가지나 되었고, 이에 대해 알아보았습니다.
각 상황에 맞추어 AppBarLayout만 사용하거나, AppBarLayout와 MaterialToolbar을 함께 사용하는 등의 방식을 취하였습니다.
역시 가장 중요한 것은 기초! 기초를 활용하였습니다. (관련 이슈)
GeoCoder
구글에서 제공하는 주소나 위경도를 반환해 주는 기능입니다.
행정구역만 사용한다는 기획에 따라 이후에는 네이버 지오코더를 사용하기도 하였습니다.
구글에서 제공하는 지오코더를 사용하면 안드로이드에서 네트워크 통신 코드를 작성하지 않아도 된다는 장점이 있습니다.
하지만 이는 네트워크를 사용하지 않는다는 얘기는 아니며 이에 따라 비동기 작업이 필요했습니다.
이 과정에서 postValue, setValue의 차이점에 대해 알 수 있었습니다.
네이버에서 제공하는 지오코더를 사용하면 일반적으로 작성하는 네트워크 통신 코드가 필요합니다.
또한, 의존성이 추가되며 api 이용 신청도 필요합니다(map과는 다른 서비스).
하지만 구글은 국외기업이기 때문에 구글 지오코더는 국내 서비스에 적합하지 않았습니다(분단국가이기 때문에 국외에 지도 반출 금지).
구글 지오코더의 경우 대부분의 행정동에 대해 각 부분(서울시, 송파구, 방이동 등)을 개별로 불러올 수 없었습니다.
또한, 네트워크 상태에 따라서 다른 결과가 나오기도 하는 등 일관성이 없는 값을 받아야 했습니다.
여기서 추가 정보! 지오코딩은 주소로 변환하는 작업을 나타내고, 리버스 지오코딩은 위경도를 주소로 변환하는 작업을 나타냅니다.
(관련 이슈 1, 관련 이슈 2 - 네이버 지오코더로 변경)
Photo Picker
글 작성 화면에는 기기로부터 이미지를 가져오는 기능이 있었습니다.
기기의 미디어 파일에 접근할 때에는 권한이 필요했으나 Photo Picker를 사용할 경우 이 과정을 생략할 수 있다는 장점에 사용하였습니다.
하지만, 이를 사용하였을 때 api32 이하의 버전에서 ANR이 발생하기도 하였습니다.
api 33 이상 버전의 기기에서 가져온 이미지의 경로는 PhotoPicke에서 제공하는 임의의 경로였습니다.
하지만, api32 이하 버전의 기기에서 가져온 이미지 경로는 Content Provider를 이용해 가져온 임의의 경로인 Content Uri였습니다.
이를 직접적으로 사용하려고 했기 때문에 발생한 문제였습니다.
Content Resolver를 사용해 해당 문제를 해결하였습니다.
(관련 이슈 1, 관련 이슈 2 - api 32 이하에서의 ANR 문제 해결)
Image 처리 - 압축과 형식
요즘 핸드폰은 화질이 너무 좋습니다. 때문에 용량이 큽니다. 이미지 크기를 줄여 보관하기로 했습니다.
이미지의 가로 세로 모두가 720px이 넘을 경우 가로세로 비율을 유지하며 짧은 측면이 720px이 되도록 압축하였습니다.
예를 들면, 3000 x 4000 크기의 이미지가 있다면 720 x 960이 되도록 하였습니다.
촬영 후 이미지 형식은 jpg, png 모두 지원하지만 jpg를 기본으로 사용하도록 하였습니다.
png보다 일반적으로 압축이 잘 됩니다(용량이 더 적습니다).
또한, png는 이미지 투명도 조절이 되는 등 사진보다는 아이콘이나 일러스트레이이션과 같은 분야에 자주 이용되는 형식입니다.
여기서 추가 정보! jpg와 jpeg는 같은 형식입니다.
jpg는 옛날옛적 윈도우가 확장자명을 3글자로 제한해 만들어진 확장자명입니다.
3글자 제한이 풀린 후에는 jpeg로 표기하는 곳도 많아졌습니다.
MediatorLiveData
글 작성 화면에서는 글을 수정하고, 새로 작성하는 기능을 모두 사용할 수 있었습니다.
이에 따라 이미지를 가질 때 기기의 파일 위치를 알 수 있는 File 타입의 변수도 있었고, 서버로부터 가져온 uri를 가지는 변수도 있었습니다.
두 변수 중 하나라도 null이 아니라면 hasImage를 true로 설정해야 했습니다.
이는 매번 설정하기에는 코드가 일관성이 없고 복잡해지는 문제가 있었습니다.
MediatorLiveData를 사용해 각각의 변수에 변경사항이 있을 때 그에 맞춰 hasImage를 변경하도록 하였습니다. (관련 이슈)
어려웠던 점
처음으로 하는 팀 프로젝트였다. 처음부터 만들어나간다는 것이 참 어려웠다. 초반에 맞추었던 규칙은 진행하며 점차 구멍과 어려움이 있다는 것을 알았다. 이것을 느꼈을 때 기능만 추가하겠다고 우선 만들고 보는 것이 아니라 서로 조금 더 길게 얘기해봤으면 좋았을텐데 아쉽다. 4개월이라는 시간 동안 프로젝트의 구조는 점차 일관성을 일어갔다. 규칙이라는 것을 설립하고 이를 지키고 유지보수하는 과정이 아직은 익숙하지 않은 것 같다.
관련 링크
깃허브: https://github.com/woowacourse-teams/2023-trip-draw
블로그:https://tripdraw.blog/archive
플레이스토어: https://play.google.com/store/apps/details?id=com.teamtripdraw.android
'우아한테크코스 5기 > 정리' 카테고리의 다른 글
레벨 4 미션 정리 (0) | 2023.11.01 |
---|---|
우아한테크코스 5기 모바일 레벨2 총정리 (0) | 2023.06.18 |
우아한테크코스 5기 모바일 레벨1 총정리 (0) | 2023.04.08 |
[git] origin에 merge된 브랜치에서 추가로 진행된 commit 이동하기 (4) | 2023.02.27 |
[kotlin][JUnit5] TDD (Test Driven Development, 테스트 주도 개발) (0) | 2023.02.21 |
댓글