1. Turbo Frames와 외부 폼의 상호작용 개요
Turbo Frames는 페이지의 일부분을 독립적인 컨텍스트로 격리하여 SPA(Single Page Application)와 유사한 부드러운 사용자 경험을 제공합니다. 그러나 검색 필터링이나 정렬 기능처럼 여러 UI 요소가 하나의 HTTP 요청에 포함되어야 하는 경우, 요소들이 서로 다른 프레임에 위치하거나 폼 태그의 외부에 존재하면 데이터 수집이 까다로워질 수 있습니다. 일반적으로 폼 제출 시에는 해당 <form> 태그 내부에 포함된 입력 요소의 값만 전송되기 때문입니다.
2. 문제 상황: 분산된 입력 요소와 상태 관리
본 예제에서는 도서 검색 시스템을 구축하며, 기존의 패싯 검색 기능에 ‘출판 연도’, ‘저자 이름’, ‘제목’ 기준의 정렬 기능을 추가하는 상황을 가정합니다. 여기서 발생하는 주요 챌린지는 다음과 같습니다.
- UI 구조적 제약: 정렬용 드롭다운(Select Box)은 검색 결과를 표시하는 Turbo Frame 내부에 위치하여 결과와 함께 업데이트되어야 하지만, 실제 검색을 수행하는 메인 <form> 태그는 프레임 외부에 존재합니다.
- 코드 유지보수: 기존에 작성된 Stimulus 컨트롤러의 로직을 수정하지 않고, 단순히 새로운 쿼리 파라미터(sort)를 기존 검색 요청에 추가해야 합니다.
- 데이터 무결성: 사용자가 선택한 정렬 기준이 검색어 및 다른 필터 조건과 함께 서버로 전달되어야 정확한 결과를 얻을 수 있습니다.
3. 핵심 해결책: HTML5 form 속성의 활용
이 문제의 가장 우아한 해결책은 HTML5 표준인 form 속성을 사용하는 것입니다. <select>, <input>, <button> 등의 폼 관련 요소에 form="target-form-id" 속성을 부여하면, 해당 요소가 DOM 트리 상에서 물리적으로 <form> 태그 내부에 있지 않더라도 지정된 ID를 가진 폼의 논리적인 일부로 동작하게 됩니다.
구현 세부 사항:
- 연결 방식: 메인 검색 폼에
id="search-form"을 부여하고, Turbo Frame 내부에 위치한 정렬 드롭다운에form="search-form"속성을 추가합니다. - 이벤트 트리거: Stimulus 컨트롤러가 폼 제출을 트리거하면, 브라우저는 자동으로 폼 내부의 요소뿐만 아니라
form속성으로 연결된 외부의 정렬 드롭다운 값까지 취합하여 서버로 전송합니다. - 서버 측 처리: Rails 컨트롤러(또는 예제의 NodeJS 서버)는 전달받은
sort파라미터(예:name_asc,title_desc)를 해석하여 데이터베이스 쿼리의 정렬 순서를 결정하고, 업데이트된 Turbo Frame 콘텐츠를 응답합니다.
4. 이 방식의 장점과 실무적 가치
이러한 접근 방식은 다음과 같은 여러 가지 이점을 제공합니다. - 자바스크립트 최소화: 별도의 데이터 수집 로직이나 상태 동기화 코드를 작성할 필요가 없어 JavaScript 번들 크기를 줄이고 버그 발생 가능성을 낮춥니다. - 컴포넌트 재사용성: 정렬 기능이 포함된 Turbo Frame을 다양한 페이지에서 재사용할 수 있습니다. 각 페이지의 메인 폼 ID만 일치시키면 별도의 설정 없이 즉시 연동됩니다. - 웹 표준 준수: 특정 프레임워크에 종속된 기능이 아닌 브라우저 고유의 기능을 활용하므로 장기적인 유지보수 측면에서 유리합니다. - 유연한 레이아웃: 디자인 요구사항에 따라 입력 요소들을 페이지의 어디에든 자유롭게 배치할 수 있으며, 논리적인 폼 구조를 유지할 수 있습니다.