[서비스개선] firebase를 활용하여 실시간으로 배너 item 원격 교체
배경
앱 내 배너 기능이 있는데 안에 있는 컨텐츠를 교체해달라는 요청이 들어왔다. 기존에 팀원이 작성해놓은 코드는 local에 이미지나 연결되는 link를 저장해놓고 불러오는 식이라 컨텐츠를 변경하려면 코드 자체를 수정했어야 했다. 이러면 앞으로 교체 요청이 들어올 때마다 매번 코드를 수정해서 플레이스토어에 심사를 올려야하고 업데이트를 하지 않은 사용자들은 교체된 내용을 받아볼 수가 없다.
매번 업데이트를 올리고 받아야 하니 개발자, 유저 모두가 번거로워지는 상황이라 firebase를 활용해서 실시간, 원격으로 배너 item을 교체할 수 있게 리팩토링을 하기로 했다.
리팩토링
1) firebase 세팅
firebase 프로젝트를 생성해야 하는데 기존에 구글 클라우드 플랫폼에 프로젝트를 만들어놓은 게 있어서 연동을 시켜주었다. firestore에 배너에 담을 이미지를 올려놓고 웹으로 열어서 url을 얻은다음 이것을 cloud firestore에 추가해주었다.
addSnapshotListener 메서드를 사용하면 일회성 수신이 아닌, data에 변경사항이 생길 때마다 업데이트를 해준다. setPromotion()은 어댑터를 생성하고 submitList해주는 함수인데 data 수신이 비동기적으로 이루어짐에 따라 같은 scope 안에 넣어주어야 data 수신 후에 함수가 돌아간다. 바깥에 작성해주면 data가 다 세팅되기도 전에 함수가 돌아서 인덱스 에러가 뜬다.
submitList로 data를 전달받으면 Image가 바인딩 될 수 있게 했고, 각 뷰 터치 시 인터페이스를 활용해 터치된 item 정보를 그대로 넘겨줄 수 있게 했다. link를 안 달아주는 경우 firebase에서 값을 ""로 넣어주었기 때문에 값이 비어있지 않을 때만 웹뷰가 실행되게 했고, startWebView는 여러곳에서 편하게 사용할 수 있게 따로 확장함수를 만들어준 것이다.
처음엔 넘겨받은 item 정보를 식별하는 값으로 absoluteAdapterPosition을 사용하려고 했는데 배너가 무한으로 계속 돌아가게 logic이 짜여져있어서 1번째 배너가 처음엔 absoluteAdapterPosition 값으로 450을 가졌다면 다시 돌아왔을 땐 453이 돼있는 등 일정한 값을 가지지 않았다. 그래서 item 자체를 넘겨주었다.
여기까지 하면 배너 이미지와 링크를 원격에서 교체가 가능해진다.
2) repository를 활용하여 firebase 코드를 data layer로 분리
data를 받아오는 logic이니 뷰와 분리를 해주어야 한다. 따라서 위에서 작성한 data 수신 logic을 repository로 옮겨주고 viewModel에선 값을 받아 관리할 수 있게 했다. 이때 callbackFlow를 활용해서 data 수신이 온전히 완료된 후에 값을 넘길 수 있게 하였다.
3) data를 실시간으로 받아오는 거랑 화면이 갱신되는 것은 별개의 문제
우선 data를 실시간으로 받아오는 거랑 화면이 갱신되는 것은 별개의 문제다. 지금은 LiveData로 선언한 UiState를 활용하여 상태를 옵저빙하다가 받아온 data를 submitList 해주도록 구현을 해놨다.