Hotwire와 StimulusJS를 활용한 Rails 블로그 텍스트 하이라이트 및 노트 기능 구현

Adding Text Highlights and Notes in Rails with Hotwire

작성자
발행일
2025년 09월 02일

핵심 요약

  • 1 Hotwire와 StimulusJS를 사용하여 Rails 블로그에 텍스트 하이라이트 및 노트 생성 기능을 구현하는 방법을 상세히 설명합니다.
  • 2 사용자가 선택한 텍스트의 시작 및 끝 오프셋을 정확히 계산하고, 이를 기반으로 노트 생성 다이얼로그를 동적으로 표시합니다.
  • 3 `<mark>` 태그와 `turbo-frame`을 활용하여 하이라이트된 텍스트와 마우스 오버 시 노트를 동적으로 표시하는 기법을 소개합니다.

도입

본 문서는 블로그 애플리케이션에서 사용자가 기사 내 텍스트를 하이라이트하고 해당 하이라이트에 노트를 첨부할 수 있는 기능을 구축하는 방법을 다룹니다. 사용자가 텍스트를 선택하면 하이라이트 색상과 노트를 입력하는 다이얼로그가 나타나고, 나중에 하이라이트된 텍스트에 마우스를 올리면 해당 노트가 표시됩니다. 이 기능은 Hotwire와 StimulusJS를 활용하여 구현되며, `Article` 및 `Note` 모델을 설정하는 것부터 시작합니다. `Article` 모델은 제목과 본문을 포함하고, `Note` 모델은 `article_id`, `body`, `start_offset`, `end_offset`, `color`를 저장하여 하이라이트 정보를 관리합니다.

이 기능은 Hotwire와 StimulusJS를 중심으로 구축됩니다.### 텍스트 선택 및 노트 생성 다이얼로그* StimulusJS 컨트롤러: app/views/articles/show.html.erb<p> 요소에 notes Stimulus 컨트롤러를 연결하고, mouseup 이벤트를 notes#newNote 액션에 바인딩합니다. article_id는 데이터 값으로 전달됩니다.* 오프셋 계산: notes_controller.js#selectionOffsets 게터는 선택된 텍스트의 시작 및 끝 오프셋을 계산합니다. 이는 HTML 태그로 인해 텍스트 노드가 분할될 수 있는 복잡한 상황을 document.createTreeWalker를 사용하여 처리합니다.* 다이얼로그 표시: newNote 액션은 계산된 오프셋을 사용하여 #showNoteDialog를 호출하고, 이는 /notes/new 경로로 GET 요청을 보냅니다. 이때 responseKind: "turbo-stream"을 지정하여 Turbo Stream 응답을 기대합니다.* 노트 폼 렌더링: NotesController#new 액션은 전달된 파라미터로 Note 객체를 초기화하고, new.turbo_stream.erb 뷰는 turbo_stream.append_all "body"를 통해 노트 생성 폼이 포함된 <dialog>를 페이지에 동적으로 추가합니다. 폼에는 article_id, start_offset, end_offset이 숨겨진 필드로 포함됩니다.### 노트 저장 및 하이라이트 표시* 노트 저장: 사용자가 폼을 제출하면 NotesController#create 액션이 호출되어 노트를 저장하고, 성공 시 해당 기사 페이지로 리디렉션합니다.* 텍스트 하이라이트: highlighted_text 헬퍼 메서드는 article.body에 저장된 노트를 순회하며 <mark> 태그를 삽입합니다. 이때 start_offset을 기준으로 정렬하여 올바른 순서로 하이라이트가 적용되도록 합니다. offset 변수를 사용하여 삽입으로 인한 문자열 길이 변화를 보정하고, style='background-color: #{note.color}'를 통해 각 노트의 색상을 반영합니다.### 마우스 오버 시 노트 표시* Turbo Frame 삽입: highlighted_text 헬퍼는 각 <mark> 태그 내부에 turbo-frame을 추가합니다. 이 turbo-framesrc 속성을 통해 note_path(note)를 가리키며 loading='lazy'로 설정됩니다.* CSS 제어: CSS 규칙을 사용하여 mark 요소 내의 turbo-frame은 기본적으로 display: none으로 숨겨져 있다가, mark:hoverdisplay: block으로 변경되어 노트 내용을 표시합니다.

결론

Hotwire와 StimulusJS를 활용한 이 접근 방식은 복잡한 텍스트 하이라이트 및 노트 기능을 Rails 애플리케이션에 효율적으로 통합할 수 있음을 보여줍니다. 특히, 텍스트 선택 오프셋을 정확히 계산하고, Turbo Streams를 통해 동적으로 UI를 업데이트하며, `<mark>` 태그와 `turbo-frame`을 조합하여 인터랙티브한 사용자 경험을 제공하는 방식은 Hotwire의 강력함을 잘 드러냅니다. 이 구현은 서버 측 렌더링의 장점을 유지하면서 클라이언트 측의 풍부한 상호작용을 가능하게 하여, 개발 효율성과 사용자 만족도를 동시에 높이는 실용적인 해결책을 제시합니다.

댓글 0

댓글 작성

0/1000
정중하고 건설적인 댓글을 작성해 주세요.

아직 댓글이 없습니다

첫 번째 댓글을 작성해보세요!