외주업체에서 말한 접근 방법이 백엔드가 존재한다면 일반적인 솔루션이 될 겁니다. 왜냐하면 어차피 어떤 이벤트에 푸쉬 메세지를 보내야할 지는 백엔드의 몫이 거든요. 파이어베이스는 다만 푸쉬기능을 디바이스에 전해주는 역할을 하는 플랫폼일 뿐이므로, 거기에 종속되지 않도록 하려면, 백엔드에서 파이어베이스를 연결하는 인터페이스를 만들고 카프카같은 메세지큐에 넣어서 동작하도록 하는 것이 훨씬 유연한 솔루션입니다. 만약 백엔드가 바로 파이어베이스에 물려 사용한다면, 추후에 회사에서 더 적합한 푸쉬시스템이 있어서 바꾸기로 한다면, 마이그레이션하는데 상당한 수고가 따를 것입니다. 푸쉬시스템이 실제적으로 어떤 벤더를 사용하는지 상관하지 않고 메세지큐와 인터페이스 형태로 만든다면, 변경사항을 최소화될 수 있겠죠. 그렇기 때문에 어떤 라이브러이던, 의존된 플랫폼이던 간에, 그것이 third party 라면 wrapping해서 사용하는 것이 좋습니다. 이건 안드로이드도 마찬가지죠. 예를 들면 이미지 로딩 라이브러리를 피카소를 사용하고 있었다면, 이걸 wrapping하지 않고 사용했다면, 나중에 Glide로 변경한다고 하면, 소스 여기저기를 손대야 할 겁니다. 하지만
interface ImageLoader {
fun loadImageTo(View: ImageView, url: String)
}
class PicassoImageLoader : ImageLoader {
}
class GlideImageLoader: ImageLoader {
}
object DependencyInjector {
fun getImageLoader(): ImageLoader [
return PicassoImageLoader();
//만약 Glide로 교체한다면,
// return new GlideImageLoader();
}
}
class MyActivity ... {
private val ImageLoader = DependencyInjector.getImageLoader();
ImageLoader.loadImageTo( imageView, "http://blablabla")
}
이런식으로 인터페이스를 만들고 실제 구현은 라이브러리에 따라 하게 되면, 앱에서는 ImageLoader 인터페이스만 사용하기 때문에, 변경에 따른 임팩트는 최소화할 수 있게 됩니다.
그리고, 다른 중요한 이유 중의 하나는 FCM은 일반적인 유즈케이스를 고려한 시스템이므로, 비즈니스의 요구사항을 수용하기 쉽도록 하려면, 중간에 이것을 수용할 시스템이 필요합니다. FCM이 님의 회사 비지니스 룰을 반영해주지는 않으니까요. 따라서 별도의 백엔드가 FCM을 중계하는 것을 올바른 선택이라고 보여집니다.