문제점 및 초기 접근
초기에는 웹 애플리케이션에서 친구 추가 버튼 클릭 시 Bootstrap을 이용하여 모달을 띄웠습니다. 이는 다음과 같은 data
속성을 버튼에 추가하여 구현됩니다.
data-turbo-frame="modal"
data-bs-toggle="modal"
data-bs-target="#modal"
웹에서는 이 방식이 깔끔하게 작동하지만, Hotwire Native iOS 앱에서 동일한 웹 기반 모달을 사용하면 네이티브 앱의 일관성을 해치고 부자연스럽게 보였습니다.
Hotwire Native의 기본 동작
웹 기반 모달 관련 data
속성을 제거했을 때, Hotwire Native iOS 앱에서는 /new
로 끝나는 경로에 대해 자동으로 네이티브 모달 컨텍스트로 렌더링하는 기능이 있습니다. 이는 iOS 앱의 경로 설정(path configuration
)에서 /new
패턴에 context: modal
을 부여했기 때문입니다. 이 덕분에 웹 기반 속성을 제거하면 iOS 앱에서는 네이티브 모달이 올바르게 나타났습니다.
최종 해결책: 조건부 Ruby 헬퍼
그러나 웹 기반 모달 속성을 제거하면 웹에서는 더 이상 모달이 작동하지 않는 문제가 발생했습니다. 이를 해결하기 위해 Hotwire Native 앱 여부를 판별하여 조건부로 모달 속성을 적용하는 Ruby 헬퍼를 구현했습니다.
헬퍼 구현
ModalsHelper
모듈 내에 modal_data
메서드를 정의합니다. 이 메서드는 hotwire_native_app?
헬퍼 메서드를 사용하여 현재 요청이 Hotwire Native 앱에서 왔는지 확인합니다.
ruby
# app/helpers/modals_helper.rb
module ModalsHelper
def modal_data
if hotwire_native_app?
{}
else
{ data: { turbo_frame: 'modal', bs_toggle: 'modal', bs_target: '#modal' } }
end
end
end
이 헬퍼는 뷰에서 다음과 같이 사용됩니다:
html+erb
<%= link_to '친구 추가', new_profile_friend_path(@profile), modal_data %>
결과
이 조건부 헬퍼를 적용한 결과, 동일한 HTML 마크업으로 세 가지 다른 플랫폼에서 최적화된 모달 경험을 제공할 수 있게 되었습니다.
- 웹: Bootstrap을 활용한 웹 기반 모달이 정상적으로 표시됩니다.
- iOS: Hotwire Native의 설정에 따라 네이티브 모달이 자연스럽게 나타납니다.
- Android: 하프 시트(half-sheet) 형태의 네이티브 모달이 구현됩니다.
이를 통해 플랫폼별 사용자 경험을 해치지 않으면서도 코드의 재사용성을 높일 수 있습니다.