WebView 화면에서 앱 기능이 필요할 때 Native Bridge를 직접 호출하는 방식은 처음에는 가장 단순해 보입니다.

앱에서 제공하는 함수 이름과 파라미터를 확인하고 화면에서 호출하면 됩니다. 토스트 메시지, 앱 화면 이동, WebView 닫기처럼 작은 기능은 이 방식만으로도 빠르게 연결할 수 있습니다.

하지만 화면이 늘면서 직접 호출 방식이 조금씩 부담으로 바뀌기 시작했습니다.

화면마다 앱 환경을 알아야 했습니다

Bridge를 직접 사용하는 화면은 앱에서 제공하는 함수 이름과 파라미터 구조를 알아야 합니다.

브라우저에서 단독으로 실행하면 해당 함수가 없기 때문에 예외 처리도 필요합니다. 앱 버전에 따라 지원 여부가 다르다면 버전 확인과 대체 동작까지 화면에서 판단해야 합니다.

비슷한 기능인데도 화면마다 호출 방식이나 오류 처리가 달라질 가능성이 생겼습니다. 앱의 인터페이스가 바뀌면 여러 화면을 함께 수정해야 하는 문제도 있었습니다.

중요한 것은 Bridge를 호출할 수 있느냐가 아니라, 웹서비스 안에서 Bridge를 어떤 기준으로 사용할 것인가였습니다.

공통 Wrapper를 두기로 했습니다

이번 프로젝트에서는 화면과 Native Bridge 사이에 공통 Wrapper를 두었습니다.

화면은 앱의 실제 함수 이름보다 웹서비스에서 정의한 공통 기능을 사용합니다. Wrapper는 현재 앱 환경인지 확인하고, 필요한 파라미터를 구성한 뒤 Bridge를 호출합니다.

브라우저에서 실행할 때는 기능별 fallback을 제공합니다. 단순 메시지는 웹 토스트로 대체하고, 앱 화면 이동처럼 브라우저에서 수행할 수 없는 기능은 안전하게 종료하거나 개발자가 확인할 수 있는 방식으로 처리합니다.

앱 버전별 지원 여부와 공통 오류 처리도 Wrapper에 모았습니다. 화면 개발자는 앱 내부 구현보다 자신이 요청하는 기능과 결과에 집중할 수 있게 됩니다.

Wrapper가 모든 차이를 숨기지는 않습니다

공통 모듈을 만들었다고 앱과 웹의 차이가 사라지는 것은 아닙니다.

전자서명이나 로그인처럼 사용자 흐름과 보안 검증이 중요한 기능은 단순한 함수 호출로 추상화하기 어렵습니다. 호출 결과뿐 아니라 취소, 실패, 중복 호출, 화면 복귀까지 계약으로 정의해야 합니다.

그래서 Wrapper의 목적을 앱 기능을 무조건 같은 모습으로 만드는 것으로 두지 않았습니다. 화면마다 반복하지 않아도 될 환경 판단과 호출 규칙을 모으고, 중요한 차이는 명시적인 인터페이스로 드러내는 쪽에 가깝습니다.

브릿지를 연결하는 일에서 기준을 제공하는 일로

Native Bridge는 앱과 웹을 이어주는 통로입니다.

통로가 있다는 사실만으로 웹서비스가 일관되게 동작하는 것은 아니었습니다. 어떤 기능을 공통화하고, 지원하지 않는 환경에서 어떻게 행동하며, 오류를 어디까지 화면에 전달할지 함께 정해야 했습니다.

Bridge Wrapper는 단순한 유틸리티보다 앱과 웹이 합의한 사용 기준에 가까웠습니다.

화면 개발자가 앱 연동 방식이 아니라 고객에게 제공할 업무 흐름에 집중할 수 있게 하는 것. 그것이 이번 프로젝트에서 Wrapper를 만든 가장 큰 이유였습니다.