Rails에서 Turbo Frames와 네이티브 <dialog> 요소를 활용한 비동기 모달 구현은 다음과 같은 단계로 진행됩니다.
1. 레이아웃에 컨테이너 추가
메인 레이아웃 파일의 <body> 태그 내에 모달 콘텐츠를 로드할 turbo_frame_tag를 추가합니다. 이는 모달이 비동기적으로 로드될 위치를 정의합니다.
```html
<%= turbo_frame_tag :modal %>```
2. 모달을 여는 링크 구성
모달을 트리거하는 링크를 생성합니다. data: { turbo_frame: :modal } 속성을 통해 클릭 시 해당 turbo_frame_tag로 콘텐츠가 비동기적으로 로드되도록 설정합니다.
erb
<%= link_to "Sign In", login_path, data: { turbo_frame: :modal } %>
3. 폼을 turbo_frame으로 감싸기
로그인 폼 뷰에서 해당 콘텐츠를 turbo_frame_tag :modal로 감싸고, 그 안에 네이티브 <dialog> 요소를 포함시킵니다. <dialog> 요소에는 Stimulus 컨트롤러(data-controller="modal")를 연결하여 모달의 동작을 제어합니다. 유효성 검사 또는 모달 내 탐색 시 모달이 깜빡이는 것을 방지하기 위해 추가적인 turbo_frame_tag :modalContent로 내부 콘텐츠를 감싸는 것이 중요합니다.
```erb <%= turbo_frame_tag :modal do %>
<% end %> ```
4. Stimulus 컨트롤러 생성
모달 창의 생명주기를 관리하는 Stimulus 컨트롤러를 구현합니다.
-
connect(): 요소가 DOM에 연결될 때this.element.showModal()을 호출하여 모달을 열고, 배경 클릭 시 모달을 닫는 이벤트 리스너를 추가합니다. -
disconnect(): 요소가 DOM에서 제거될 때 이벤트 리스너를 제거하고close()메서드를 호출하여 모달을 닫습니다. -
close():this.element.close()를 통해 모달을 닫고,ModalController.turboFrame.src = null로turbo-frame의src를 초기화하며,this.element.remove()를 통해 모달 요소를 DOM에서 제거하여 다음 모달이 열릴 때 이전 콘텐츠가 깜빡이는 것을 방지합니다. -
#closeOnBackdropClick(event): 배경을 클릭했을 때만 모달이 닫히도록 처리합니다.
작동 원리
-
링크 클릭 시, Turbo는 요청을 보내
turbo_frame_tag :modal로 콘텐츠를 로드합니다. -
콘텐츠가 로드되면 Stimulus 컨트롤러의
connect()메서드가 실행되어showModal()을 통해<dialog>를 열고 배경 클릭 리스너를 설정합니다. -
모달이 닫히면 (
close()메서드),turbo-frame의src를 초기화하고 모달 요소를 DOM에서 제거하여 깔끔하게 정리합니다.
이 접근 방식의 이점
-
네이티브
<dialog>요소 활용 -
비동기 콘텐츠 로딩
-
자동 포커스 관리 및 접근성
-
Rails 및 Turbo와의 간편한 통합
-
닫힌 후 DOM 오염 방지