웹뷰와 하이브리드, 그리고 네이티브 앱에서는 책임 분리가 중요하다.
웹뷰는 어떤 점들을 책임져야 할까?
먼저 URL state를 잘 설계해야 한다. 그래야 외부나 네이티브에서 들어오는 딥링크가 정확한 화면으로 타겟팅될 수 있다.
또한 네이티브의 Pull to Refresh 동작이 일어났을 때도 적절한 상태를 유지할 수 있어야 한다. 새로고침 한 번으로 사용자가 보고 있던 화면의 맥락이 깨지면 안 되기 때문이다. URL만으로도 현재 화면과 주요 상태를 어느 정도 복원할 수 있어야, 웹뷰와 네이티브 사이의 연결도 훨씬 예측 가능해진다.
웹뷰 리소스에 대한 캐싱 전략이나 빌드 시 번들링 전략도 중요하다.
유저가 앱을 껐다 켤 때마다 모든 리소스를 다시 다운로드받는 것만큼 비효율적인 일은 없을 것이다. 그렇다고 모든 리소스를 무조건 길게 캐싱할 수도 없다. 새로 배포한 코드가 앱 안에서 제때 반영되지 않으면 그것도 문제이기 때문이다.
그래서 어떤 리소스는 오래 캐싱하고, 어떤 리소스는 빠르게 갱신할지 나눠서 봐야 한다. 예를 들면 해시가 붙은 JS, CSS 같은 정적 리소스는 길게 캐싱할 수 있지만, 진입점이 되는 HTML이나 설정성 데이터는 비교적 짧게 가져가야 할 수 있다.
빌드 시 번들링 전략도 마찬가지다. 앱을 켤 때 당장 필요하지 않은 코드까지 한 번에 모두 내려받게 만들면 초기 진입이 무거워진다. 화면 단위로 적절히 나누고, 자주 바뀌는 코드와 잘 바뀌지 않는 코드를 분리해두면 웹뷰에서도 훨씬 안정적인 로딩 경험을 만들 수 있다.
여기까지 어느 정도 정리가 되었다면, 배포 시 버전 관리 전략도 중요하다. 현재 유저의 기기에서 실행 중인 웹뷰 버전이 최신인지 확인할 수 있어야 한다.
확인이 가능하다면 semver 원칙 등에 따라 현재 버전과 최신 버전을 비교하고, 새로고침을 유도하는 스낵바를 보여주는 등의 적절한 조치를 취할 수 있어야 한다.
다만 여기서 새로고침 동작은 네이티브에게 위임하는 방법이 좋을 수도 있다.
자 그렇다면, 모든 화면을 네이티브에서 만들 것인가? 웹뷰를 어느 정도 사용할 것인가? 이것도 생각해볼 만한 문제이다.
이건 결국 개발팀의 생산성과 속도에 대한 트레이드 오프를 챙겨야 하는 문제다. 만약 특정 화면은 웹뷰가 가져간다고 치자. 그렇다면 네이티브로 짠 화면과 동떨어진 느낌이 들면 안 된다. 최대한 유저는 몰라야 한다. 이 화면이 웹뷰인지, 네이티브인지.
또한 당연하지만 웹뷰와 네이티브 간의 브릿지 통신은 예상 가능한 구조로 짜여 있어야 한다.
나 스스로가 웹뷰와 네이티브 개발을 모두 책임질 수도 있고, 나는 웹뷰를 맡고 상대방은 네이티브를 맡는 구조로 갈 수도 있다. 어느 쪽이든 중요한 건, 서로의 책임이 어디까지인지 명확해야 한다는 것이다.
네이티브는 어떤 책임이 있을까?
기본적으로 네이티브는 웹뷰의 안정성을 항상 의심하는 게 좋다. 웹뷰가 항상 정상적으로 동작하지 않을 수 있다는 전제를 깔고 가야 한다.
웹뷰 로드는 성공적으로 되었다고 하는데, 정작 유저가 보는 화면은 빈 하얀 화면인 경우라면 네이티브는 어떻게 해줄 것인가?
다만 이런 고민들은 지금 만드는 앱이 모바일 앱인지, 키오스크 앱인지에 따라 달라질 수 있다. 모바일 앱이라면 사용자가 직접 다시 시도하거나 앱을 재실행할 여지가 있지만, 키오스크라면 상황이 조금 다르다. 사용자가 기기 앞에서 바로 행동해야 하는 환경이기 때문에, 빈 화면이나 로딩 실패를 그대로 방치하면 곧바로 운영 이슈로 이어질 수 있다.
그래서 네이티브는 웹뷰가 실패할 수 있다는 전제를 깔고, 최소한의 복구 흐름을 가지고 있어야 한다. 예를 들면 재로드 버튼을 보여주거나, 일정 시간 이상 화면이 정상적으로 표시되지 않으면 자동으로 새로고침하거나, 네트워크 상태나 장애 화면을 네이티브 레벨에서 보여주는 식이다. 중요한 건 웹뷰가 깨졌을 때 네이티브도 같이 무력해지면 안 된다는 점이다.
이런 상황까지 고려했을 때, 하이브리드 앱에서 중요한 건 단순히 “웹뷰로 화면을 띄운다”가 아니라, 웹뷰와 네이티브가 각각 어디까지 책임질 것인지 명확하게 나누는 일이라고 생각한다.
이런저런 생각을 하다 보니, 모든 생각을 다 적을 수는 없지만 그래도 중요하다고 느낀 부분들은 글로 남겨봐야겠다는 생각이 들어 이렇게 정리해본다.