본 문서는 Ruby on Rails 애플리케이션에서 기존 Rails UJS를 Hotwired Turbo로 전환하는 과정에서 발생할 수 있는 주요 변경 사항과 해결 방안을 제시합니다. 오래된 기술 스택으로 운영되던 내부 도구를 Rails 7 및 jsbundling-rails 환경으로 업데이트하며 겪은 경험을 바탕으로, 개발자들이 마이그레이션 시 직면할 수 있는 구체적인 문제점과 해결책을 상세히 설명합니다.
Rails UJS에서 Turbo로의 마이그레이션은 기본적으로 @rails-ujs
및 jquery-ujs
패키지를 제거하고 @hotwired/turbo-rails
를 설치하는 것에서 시작합니다. 이 과정에서 프로젝트가 yarn과 npm 중 어떤 패키지 매니저를 사용하는지 확인하고 일관성을 유지하는 것이 중요합니다. 또한, application.js
파일에서 Rails UJS import/require 구문을 제거하고 Turbo를 import/require하도록 수정해야 합니다.
핵심적인 코드 변경 사항은 다음과 같습니다. 첫째, RESTful HTTP 메서드(POST, PATCH, DELETE)를 사용하는 link_to
헬퍼는 method: :post
와 같은 인자 대신 data: { turbo_method: :post }
형태로 변경해야 합니다. 둘째, 링크 클릭 시 확인 대화 상자를 표시하는 data-confirm
속성은 data: { confirm: "..." }
에서 data: { turbo_confirm: "..." }
으로 수정해야 합니다. 셋째, 폼 제출 버튼의 중복 클릭 방지를 위한 disable_with
기능도 Turbo 방식에 맞춰 재구현해야 합니다.
인증 라이브러리인 Devise를 사용하는 경우, 에러 메시지가 올바르게 표시되도록 Devise 초기화 설정에서 config.responder.error_status
와 config.responder.redirect_status
를 :unprocessable_entity
와 :see_other
로 설정해야 할 수 있습니다. 또한, 컨트롤러에서 모델 저장 실패 시 폼과 함께 에러 메시지를 다시 렌더링하는 패턴을 사용하는 경우, render :new
호출에 status: :unprocessable_entity
옵션을 추가하여 Turbo가 에러 응답을 올바르게 처리하도록 해야 합니다.
Ajax 요청 처리 방식도 변경될 수 있습니다. Rails UJS의 Rails.ajax()
를 사용했다면, Turbo 환경에서는 Rails Request.js 라이브러리 사용이 권장됩니다. 외부 CDN에서 로드되는 JavaScript 라이브러리가 Turbo 페이지 전환 시 제대로 초기화되지 않는 문제를 경험했다면, 해당 라이브러리를 프로젝트 번들에 포함시키는 방식으로 해결할 수 있습니다.
가장 큰 변화 중 하나는 JavaScript 이벤트 핸들링입니다. 기존 jQuery의 $(document).ready()
또는 네이티브 DOMContentLoaded
, window.onload
이벤트에 의존하던 코드는 Turbo의 turbo:load
이벤트 리스너로 전환해야 합니다. turbo:load
이벤트는 페이지 탐색 시 여러 번 발생할 수 있으므로, 이벤트 핸들러 코드는 멱등성을 가져야 합니다. 또한, 특정 요소에 직접 이벤트 리스너를 등록하기보다는 이벤트 위임(event delegation) 패턴을 사용하여 document
나 window
에 리스너를 등록하고 이벤트 발생 시점에 대상 요소를 확인하는 방식이 Turbo 환경에 더 적합하며 권장됩니다. 이러한 복잡성을 해결하고 인터랙티브 동작을 구조적으로 관리하기 위해 Stimulus 프레임워크를 도입하는 것도 좋은 대안이 될 수 있습니다.
Rails UJS에서 Hotwired Turbo로의 마이그레이션은 단순히 라이브러리 교체를 넘어, 애플리케이션 전반에 걸친 코드 수정, 특히 프런트엔드 JavaScript 로딩 및 이벤트 처리 방식의 근본적인 변화를 요구합니다. 본 문서에서 제시된 주요 변경 사항들을 면밀히 검토하고 적용함으로써, 개발자는 Turbo의 장점을 활용하며 기존 기능의 정상 작동을 보장하는 원활한 전환을 달성할 수 있습니다.