[Project] Carpool App 회고록
Carpool App
저희 팀이 개발한 카풀앱은 22.12.16 ~ 23.02.11 동안 개발하여 마무리 되었습니다. 저희의 카풀서비스는 대학생을 대상으로 드라이버와 패신저가 자유롭게 매칭할 수 있는 환경을 제공해주는 앱 입니다. 드라이버는 수익을 얻을 수 있고, 패신저는 빠르고 편안하게 등교를 할 수 있는 환경을 제공해주기 위해 개발을 시작했습니다.
기획담당 PO분들이 2~3명, 백엔드 2명, FE에서는 AOS 2명, IOS 1명, 디자이너가 2명 정도 계셨지만 마지막엔 모두 나가셔서 프로젝트가 더이상 진행될 수 없는 환경이 되어서 종료되었습니다.
Learned About
이 프로젝트는 사이드 프로젝트를 위한 서비스를 제공해주는 ‘렛플’ 에서 알게되어 참여했었습니다. 저에게 첫 프로젝트 였고, 재학중에 수행했던 프로젝트와는 엄연히 Quality가 다른 환경이었습니다. 직장인분들도 계셨고, 학생이지만 저보다 훨씬 뛰어나신 분들이 계셔서 정말 많은걸 배울 수 있는 환경이었습니다.
저는 api를 연결하여 데이터를 요청하고 응답받는 경험은 이전까지 공공데이터 포털에서 1~2개의 기능만을 구현해보았었고 잘알지 못하던 상황이었습니다.
프로젝트를 수행하면서 Retrofit2와 OkHttp3 라이브러리를 활용하여 서버로 부터 JWT 토큰을 받아서 api 통신을 할때마다 header에 삽입하여 사용자의 유효성을 인증받고, HTTP Method( GET/ POST/ PUT/ DELETE ) 를 여러가지로 사용해보면서 Http Uri 방식을 이해할 수 있게 되었습니다.
Domain Layer인 추상화된 RepositoryImpl 에서 Data layer에서 api 를 fetch 하여 널러블 하게 받은 Response 값을 캡슐화 하여 ViewModel로 전달하고, 전달받은 Domain Model (Entity)을 ViewModel에서 View가 필요한 정보만을 캡슐화 하여 State 객체(Item) 로 만들어 화면을 StateFlow로 갱신하여 보여주었습니다.
이러한 MVVM 디자인 패턴에 대해서 공부하게 되었고 정말 MVVM을 100% 이해하지는 못했지만, 나름대로 MVVM 구조로 만들면서 얻는 이득들에 대해서 학습하는 시간도 가졌습니다.
저희프로젝트는 여러번 수정작업을 해야하는 상황들이 빈번했지만, 내부적으로는 계층단위로 나누어져 있어서 api가 수정되었다고 한들 Response 클래스를 변경만 해주면 그 여파가 Data Layer 까지만 미치고 Domain Layer 로 전파되지 않는 것을 보면서 왜 이렇게 나누어야 했는지 수정작업을 해보면서 느꼇습니다.
또한, 이전에는 Domain Layer의 RepositoryImpl에서 ViewModel의 이벤트를 알고 여기서 Item 객체로 캡슐화하여 전달하거나 Http Exception을 검출하는등 ViewModel이 해야하는 로직들을 수행했었습니다.
하지만 프로젝트를 진행하면서 받은 코드리뷰로 Repository 에서는 local 경로의 Database인 Room 혹은 DataStore 또는 서버로부터 fetch 하여 얻는 결과물을 단순히 캡슐화 하여 필요한 정보들만을 전달하는 역할만 수행하면 된다는것을 배웠습니다.
RepositoryImpl은 어떤 ViewModel에서 호출될지 모르기 때문에 Request를 위한 입력 파라미터는 변수값 하나하나로 받던지, Domain 객체로 받는다면 내부의 필드값들을 모두 사용하는 형태 이어야만 합니다.
ViewModel 에서는 View에서 필요한 형태로 전달받은 Domain Model을 캡슐화하여 Item 객체로 만들어서 내부에 저장합니다. 이때 Kotlin의 Data Class의 장점인 .copy() 메소드를 통해 깊은복사를 하여 내부의 UiState의 값을 update 해주는 패턴을 이용했습니다.
기존 프로젝트 에서나 Carpool 프로젝트 초반에는 명령형 UI 패러다임인 layout.xml에 LiveData와 Databinding 을 이용하는 형식으로 진행을 했었지만, 중간에 들어오신 안드로이드 개발자님이 신규작업들은 Compose와 Flow로 해보는게 어떻겠느냐고 제안해주셨고 저는 그게 어떤것들인지는 알고있었지만 학습할 기회가 없었어서 너무 반가운 마음에 좋다고 진행하자고 했었습니다.
진행하면서 Compose는 기존의 Jetpack 라이브러리와 호환은 되지만 사용법이 모두달라져서 학습하는 시간이 좀걸렸었습니다. 하지만 Compose로 익숙해 지기 시작할때쯤 기존의 명령형 방식으로 작업할 때 보다 속도가 훨씬 빨라졌습니다.
빈번하게 layout으로 가서 작업을 하고 BindingAdapter에 재사용될만한 로직들을 작성하고 ViewModel로 이동해서 비즈니스 로직을 구성하고 이러한 반복되는 형태에서 헷갈릴때도 생기고 속도가 상대적으로 느렸던 반면, Compose는 composable 함수내에서 view의 작업이 모두 수행되는 형태인것 뿐만아니라 RecyclerView Adapter를 만들지 않아도 되서 너무 편했습니다.
Compose는 databinding을 하는 방식이 달라서 State Hositing 구조로 State를 사용하는 끝까지 내리고, state를 update 하는 로직은 callback 형태로 state가 존재하는 곳까지 최대한 끌어올려서 구현해야 하는법을 학습했습니다.
ViewModel 에서는 전달받은 Domain Model 로 MutableStateFlow인 uiState값을 update 하여 View에서 collect 하여 화면을 갱신하는 형태로 구현했고, flow의 cold stream은 collect를 하기 시작해야 data가 전달되며 observer pattern 으로 전달받은 data를 자동으로 화면에 갱신시켜 주기 위해 Hot stream인 StateFlow를 이용 해야 한다는 점을 학습했습니다.
Communication
처음 프로젝트에서 api에서 장애가 발생해서 백엔드 개발자님께 여쭤보았는데, 백엔드 개발자님이 저의 말을 이해를 못하셨습니다.
그때, 같은 안드로이드 팀원분이 저에게 피드백을 해주셨는데 항상 다른 팀원과 소통할때는 정확한 상황설명과, 요약을 잘해서 말씀해달라고 해주셨습니다.
어떤 상황속에서, 어떤 api가 어떤 input을 넣었더니, 어떤 장애가 발생했고 그때의 ouput 값은 어떻게 나왔으며 장애의 Exception Message를 요약해서 말씀드려야 한다는 점을 이때 배웠습니다.
프로젝트 초기인원은 위와 같이 시작했지만, 프로젝트를 진행하는 과정에서 중심이 되는 PO님의 소통이 원활하지 못했습니다. 중간에 나가는 사람이 발생해도 나머지 사람들에게 언급을 해주지 않아서 매주 Meeting 날에 가서야 그분이 나갔는지 알게됬습니다.
또한, 기획서와 피그마의 디자인부분이 다르거나 기획서의 페이지마다 디자인이 달라서 어느게 진짜 디자인인지 알 수가없어 매번 여쭤봐야 했고 여쭤본다고 답이 금방 돌아오지 않아 기다려야 했고.. 기다리는 시간이 아까워서 다음 작업을 하다가 답장을 받았을 때는 연계되는 내용들이 물거품이 되어서 다시 전부 작업해야하는 상황이 빈번하게 일어났습니다.
실질적으로 개발한 기간은 약3개월이라는 시간이 걸렸지만, 중간에 프로젝트가 2번 엎어졌고 개발한 기간의 70퍼센트의 시간이 수정작업을 하는게 걸리는 시간 이어야만 했습니다.
이러한 부분들을 PO님과 어떻게 소통하고 대화로 잘 풀어나갈 수 있을까 고민과 고민을 더해 소통해보려 했으나 원활하게 되지는 못했습니다.
결국 마지막 까지 그래도 마무리는 해보자고 의기투양 해주셧던 백엔드 개발자님 까지 나가시게 되면서 프로젝트는 완성하지 못한체 종료되어 너무 아쉬운 마음이 컸습니다만 이프로젝트에서 배운점이 많았고 성장할 수 있어서 기분은 좋았습니다.
다만, 저의 소통능력이 부족하지는 않았는지 곱씹어 보기도 했고 좀더 PO님이 이 프로젝트에 열정적으로 활동하실 수 있게끔 더 소통을 많이 했다면 다른 구성원들도 남아계시면서 프로젝트가 완성되지 않았을까 하는 아쉬움도 컸습니다.
첫 프로젝트 였던만큼 꼭 성공적으로 앱을 완성하고 마켓에 런칭해서 유저의 피드백도 받아보고 싶은 마음이 컸습니다. 이렇게 되서 아쉽지만 다음 프로젝트에서는 더성장한 모습으로 성공적으로 완수할 수 있도록 노력해야 겠다는 다짐을 했습니다.
댓글남기기