Bridge Components는 웹 인터페이스가 네이티브 UI/코드에 접근해야 할 때 사용됩니다. 이는 웹 뷰만으로는 불가능한 특정 네이티브 기능(예: 카메라, 위치 서비스, 복잡한 UI 요소)을 통합할 때 특히 유용합니다. 핵심적인 작동 방식은 다음과 같습니다.
1. 웹 (Rails/JavaScript - Stimulus) 측면
- Stimulus Controller:
data-controller
및data-action
HTML 속성을 사용하여bridge_form_controller.js
와 같은 Stimulus 컨트롤러를 연결합니다. - 메시지 전송: Stimulus 컨트롤러의
send
함수는 JavaScript 브리지를 통해 Hotwire Native 앱으로 메시지(예:connect
,submit_disabled
,submit_enabled
)와 페이로드(데이터)를 전송합니다. - 이벤트 리스닝: Turbo.js의
turbo:submit-start
및turbo:submit-end
와 같은 이벤트를 수신하여 네이티브 컴포넌트의 상태(예: 버튼 활성화/비활성화)를 제어합니다.
2. 네이티브 (iOS - Swift) 측면
- BridgeComponent 상속:
form_component.swift
와 같은 네이티브 컴포넌트는BridgeComponent
를 상속받습니다. on_receive
함수: JavaScript 브리지에서 전송된 메시지를 수신하고, 메시지 이름(예:connect
)과 페이로드(예:submit_title
)에 따라 적절한handle
함수를 호출합니다.- UI 조작:
handle_connect
함수는 네이티브 내비게이션 바에 제출(Submit) 버튼을 추가하고,submit_title
페이로드를 사용하여 버튼 텍스트를 동적으로 설정합니다.handle_submit_disabled
및handle_submit_enabled
는 버튼의 활성화 상태를 변경합니다. - 웹 이벤트 트리거: 네이티브 버튼 클릭 시,
reply
함수를 통해 웹 측에 이벤트를 다시 전송하고, 웹의 JavaScript 콜백은submit_target.click()
을 호출하여 웹 폼 제출을 트리거합니다. 이는 Turbo.js의 기본 폼 처리 로직을 활용하여 폼 필드 비활성화 등의 기능을 자동으로 적용합니다.
3. 네이티브 (Android - Kotlin) 측면
- iOS와 유사한 원리로 작동하지만, Android API의 특성상 Kotlin 코드가 Swift보다 더 길고 복잡할 수 있습니다.
layout_inflater
를 사용하여 XML 레이아웃으로 정의된 버튼을 동적으로 생성하고 툴바에 추가합니다.- 활동 표시기(Activity Indicator)와 같은 Android 고유의 UI 요소를 활용하여 사용자 경험을 향상시킵니다.
4. 고급 예시: 메뉴 컴포넌트
- 동적 네이티브 메뉴: HTML
data-bridge-ios-image
및data-bridge-android-image
속성을 통해 SF Symbols(iOS)와 같은 네이티브 아이콘을 동적으로 표시하는 드롭다운 메뉴를 구현합니다. - 실시간 업데이트: HTML 속성만 변경하면 앱 재배포 없이 네이티브 메뉴 항목과 아이콘이 즉시 업데이트됩니다.
- 우아한 저하(Graceful Degradation): Hotwire Native 앱이 특정 Bridge Component를 등록하지 않은 경우, 해당 네이티브 UI 대신 웹 기반 HTML UI가 표시되어 기능 손실 없이 동작합니다.
5. 스타일링 및 재사용성
- CSS를 통한 숨김: Hotwire Native는
data-bridge-components
와 같은 속성을 HTML에 주입하여, CSS 선택자를 통해 네이티브 컴포넌트가 활성화될 때 웹 기반 UI 요소를 숨길 수 있도록 합니다. - ‘단순한’ 네이티브 컴포넌트: 네이티브 컴포넌트에는 최소한의 UI 로직만 포함하고, 비즈니스 로직은 Rails/Stimulus 측에서 처리하여 컴포넌트의 재사용성을 극대화합니다.