Hotwire Native의 핵심 이점
Hotwire Native의 주요 목표는 기존 웹 화면을 iOS, Android, 웹 세 플랫폼에서 재사용하여 개발 노력을 최소화하는 것입니다. 이를 통해 네이티브 iOS 및 Android 개발자 없이 단일 프레임워크로 앱을 유지보수하고 배포할 수 있으며, Ruby로 작성된 Rails 비즈니스 로직을 그대로 활용하여 개발 시간과 비용을 크게 줄일 수 있습니다. 또한, Hotwire Native 앱은 웹 뷰를 통해 Rails 서버에 접속하므로, 서버 변경 사항이 다음 페이지 로드 시 앱에 즉시 반영되어 앱 스토어 검토 없이 빠른 업데이트가 가능합니다. 필요한 경우 프로그레시브 인핸스먼트를 통해 전체 화면이나 부분 요소를 네이티브 기능(예: 지도, 연락처 목록, 네이티브 버튼)으로 전환할 수 있습니다. Basecamp와 HEY와 같은 수백만 사용자 앱에서 이미 사용되고 있어 프로덕션 환경에서의 안정성과 강력함이 입증되었습니다.
iOS 및 Android 앱 구축 실습
워크숍에서는 Xcode를 사용하여 iOS 앱을, Android Studio를 사용하여 Android 앱을 처음부터 구축하는 과정을 시연했습니다.
iOS 앱 구축
- 새 iOS 앱 프로젝트를 생성하고, 인터페이스는 Storyboard, 언어는 Swift를 선택합니다.
- Swift Package Manager를 통해
hotwire-native-ios
라이브러리를 추가합니다. SceneDelegate
에서Hotwire.Native.Navigator
를Configuration
과 함께 초기화하고,rootURL
을localhost:3000/posts
로 설정합니다.- Rails 블로그 데모 앱을 로컬에서 실행하여 iOS 앱이 웹 콘텐츠를 로드하고 네이티브와 유사한 화면 전환, 풀투리프레시, Rails 리다이렉트 처리 등을 보여줍니다.
Android 앱 구축
- 새 Android 앱 프로젝트를 생성하고, Empty Views Activity, 언어는 Kotlin을 선택합니다.
build.gradle.kts
파일에dev.hotwire:core
와dev.hotwire:navigation-fragments
의존성을 추가합니다.AndroidManifest.xml
에 인터넷 접근 권한과usesCleartextTraffic
설정을 추가하여localhost
대신10.0.2.2:3000
으로 로컬 서버에 접속합니다.activity_main.xml
에FragmentContainerView
를 사용하여NavigatorHost
를 정의하고,MainActivity.kt
에서HotwireActivity
를 상속받아Navigator.Config
를 설정합니다.
네이티브 경험 개선 및 기능 추가
웹 인터페이스 개선
- 조건부 CSS(예:
if hotwire_native_app?
)를 사용하여 네이티브 앱에서만 특정 웹 요소를 숨겨(예: 웹 내비게이션 바, 제목) 더 네이티브처럼 보이게 합니다. - HTML의
<title>
태그 내용을 네이티브 내비게이션 바의 제목으로 자동 반영하여 웹과 네이티브 간의 일관성을 유지합니다. 네이티브 UI 요소를 CSS로 복제하지 말고, 웹 요소를 네이티브 요소와 자연스럽게 어우러지도록 디자인하는 것이 중요합니다.
네이티브 탭 바 추가 (iOS)
SceneDelegate
에서Navigator
대신HotwireTabbarController
를 사용하도록 변경합니다.Hotwire.Tab
객체 배열을 생성하여 각 탭의 제목,UIImage(systemName:)
(SF Symbols) 아이콘, 시작 URL을 정의합니다.AppDelegate
에서UITabBarAppearance
를 설정하여 탭 바의 배경을 불투명하게 만듭니다. 탭 바는 자체적인 내비게이션 스택을 가지며, 동적으로 탭 구성을 서버에서 가져올 수도 있습니다.
브릿지 컴포넌트 활용
- 웹(Stimulus 컨트롤러)과 네이티브(iOS/Android) 간의 통신을 위한 브릿지 컴포넌트를 소개합니다.
@hotwired/hotwire-native-bridge
라이브러리를importmap
에 추가하고,bin/rails g stimulus bridge/confirm
으로 브릿지 컴포넌트 스켈레톤을 생성합니다.- JavaScript의
BridgeComponent
에서send()
메서드를 사용하여 네이티브로 메시지를 보내고, Swift의BridgeComponent
서브클래스에서onReceive()
메서드를 통해 메시지를 처리합니다. AppDelegate
에 브릿지 컴포넌트를 등록하여 네이티브 앱이 해당 컴포넌트를 처리할 수 있음을 알립니다. Safari/Chrome 개발자 도구를 통해 웹 뷰의 콘솔 로그를 확인하고data-bridge-components
속성을 통해 등록 여부를 확인할 수 있습니다.- 동적인 네이티브
UIAlertController
를 웹에서 트리거하는 예제를 통해, JavaScript에서 데이터(예:title
)를 보내고 Swift에서Decodable
구조체를 사용하여 이를 디코딩하는 과정을 시연합니다. 이를 통해 네이티브 코드에서 웹으로부터 받은 데이터를 기반으로 유연하게 UI를 구성할 수 있습니다. - 브릿지 컴포넌트는
confirm
,alert
,location
등과 같이 가능한 한 범용적인 네이티브 API에 매핑되도록 설계하는 것이 좋습니다.bridgecomponents.dev
에서 다양한 사전 구축된 브릿지 컴포넌트를 제공합니다.