Turbo의 폼 제출 처리 과정
Turbo는 document에 submit 이벤트 리스너를 등록하여 폼 제출을 가로챕니다. 이후 브라우저의 기본 제출 동작을 preventDefault()로 막고, fetch API를 통해 서버로 데이터를 전송합니다. 이때 Accept 요청 헤더에 text/vnd.turbo-stream.html을 추가하여 서버에 Turbo Stream 응답을 요청합니다.
서버는 이 헤더를 인식하여 Content-Type: text/vnd.turbo-stream.html과 함께 Turbo Stream 요소로 응답할 수 있습니다. 만약 성공적인 제출 후 Turbo Stream 대신 일반 HTML 응답을 원한다면, 서버는 반드시 리다이렉션을 발행해야 합니다. 그렇지 않을 경우 Turbo는 오류를 발생시키며, 유효성 검사 오류와 같은 경우 일반 HTML을 직접 렌더링할 수 있습니다.
Turbo의 Turbo Stream 응답 처리 과정
Turbo는 turbo:before-fetch-response 이벤트에 리스너(`StreamObserver
inspectFetchResponse)를 연결합니다. fetch 요청 후 응답이 도착하면 이 이벤트가 디스패치되고, 리스너는 응답의 Content-Type이 text/vnd.turbo-stream.html`인지 확인합니다.
Turbo Stream 응답으로 확인되면, 해당 내용을 DOM에 추가합니다. DOM에 <turbo-stream> 요소가 추가되는 순간, 각 요소에 정의된 action (예: append, prepend, remove)에 따라 커스텀 JavaScript 코드가 실행되어 실제 DOM 변경이 발생합니다. 서버는 단일 응답으로 여러 <turbo-stream> 요소를 보낼 수 있으며, 모든 액션은 순차적으로 처리됩니다.
일반 fetch 요청 시에도 Accept 헤더를 text/vnd.turbo-stream.html로 설정하여 Turbo Stream을 요청할 수 있으며, @rails/request.js 라이브러리의 responseKind: "turbo-stream" 옵션을 통해 편리하게 구현 가능합니다.