문제점
기존 Turbo Frame은 내부 콘텐츠만 업데이트하므로, 사이드바 하이라이트와 같은 외부 UI 요소는 자동으로 변경되지 않습니다. 이를 해결하기 위해 프론트엔드 솔루션(예: Stimulus)을 사용할 수 있지만, 이 글에서는 모든 로직을 백엔드에서 처리하는 방법을 제안합니다.
해결책의 핵심 아이디어
전체 페이지 로드 시에는 사이드바 콘텐츠를 일반적인 위치에 렌더링하고, Turbo Frame 요청 시에는 프레임 내에서 렌더링된 Turbo Stream을 사용하여 사이드바를 업데이트하는 방식입니다.
구현 세부사항
- 레이아웃 (
application.html.erb): 사이드바를 위한 렌더링 슬롯을 정의합니다. ```html<%= yield %> ```
- 챕터 페이지 뷰 (
chapters/show.html.erb):turbo_frame_tag내부에 사이드바와 챕터 내용을 모두 렌더링합니다. ```erb <%= turbo_frame_tag :chapter_content do %> <%= render ‘sidebar’, chapters: @chapters, chapter: @chapter %>... <% end %> ```
- 사이드바 부분 뷰 (
_sidebar.html.erb):turbo_aware_content_for헬퍼를 사용하여 현재 챕터가 강조되도록 렌더링합니다. ```erb <%= turbo_aware_content_for :sidebar do %><% end %> ```
turbo_aware_content_for헬퍼:turbo_frame_request?일 경우,turbo_stream.replace(name, method: :morph, &block)를 사용하여name에 해당하는 HTML 요소를 새로운 내용으로 교체합니다.morph옵션은 부드러운 업데이트와 스크롤 위치 유지를 가능하게 합니다. 일반 요청일 경우,content_for(name, &block)를 사용하여 사이드바 슬롯에 콘텐츠를 삽입합니다.
중요 기술적 고려사항
-
사이드바는 Turbo Frame 내에서 렌더링되어야 Turbo Stream이 정상적으로 작동합니다.
-
헬퍼는
id가 일치하는 최상위 요소(예:<nav id="sidebar">)가 존재한다고 가정합니다.
이 접근 방식의 장점
이 기법은 외부 UI 변경 시 서버 사이드 렌더링 로직만 수정하면 되므로, 확장성이 뛰어납니다. 예를 들어, 사이드바에 부제목 목록을 추가하는 경우, 프론트엔드 솔루션에서는 복잡한 변경이 필요하지만, 이 방식에서는 사이드바 부분 뷰만 업데이트하면 모든 것이 자동으로 작동합니다. 또한, 전체 페이지 Turbo Morph와 달리, 페이지 간 이동 시에도 스크롤 위치를 보존하며, 콘텐츠는 교체하고 사이드바는 morph하는 ‘정보에 기반한’ 업데이트를 제공하여 성능과 사용자 경험을 최적화합니다.