JavaScript 없이 모던 브라우저 기능으로 아름다운 확인 대화 상자 구축하기

Beautiful Rails confirmation dialogs (with zero JavaScript) | Boring Rails: Skip the bullshit and ship fast

작성자
jeff
발행일
2025년 12월 15일

핵심 요약

  • 1 최신 브라우저의 Invoker Commands, @starting-style, allow-discrete를 활용하여 JavaScript 없이 선언적으로 스타일링된 확인 대화 상자를 구현할 수 있습니다.
  • 2 HTML의 commandfor, command, closedby 속성을 통해 대화 상자의 열기/닫기, 접근성 및 애니메이션을 순수 HTML/CSS로 제어합니다.
  • 3 Turbo의 Turbo.config.forms.confirm을 사용하여 기존 data-turbo-confirm 기능을 사용자 지정된 모던 대화 상자와 통합하고, returnValue로 사용자 응답을 효율적으로 처리합니다.

도입

기존 웹 애플리케이션에서 사용자에게 확인을 요청하는 `confirm()` 대화 상자는 그 기능적 유용성에도 불구하고 시대에 뒤떨어진 외형과 제한적인 커스터마이징으로 인해 UI/UX 측면에서 아쉬움을 남겼습니다. 이로 인해 많은 개발자가 Stimulus 컨트롤러와 같은 JavaScript 기반 솔루션을 통해 스타일링된 대화 상자를 구현했으나, 이는 코드 복잡성을 증가시키는 요인이었습니다. 그러나 최근 Chrome 131+, Safari 18.4+ 등 주요 브라우저에 Invoker Commands가 도입되면서, JavaScript 코드 없이도 선언적인 방식으로 아름답고 기능적인 대화 상자를 구축할 수 있는 새로운 가능성이 열렸습니다.

이 글에서는 모던 브라우저 기능을 활용하여 JavaScript를 최소화하거나 전혀 사용하지 않고 확인 대화 상자를 구현하는 방법을 상세히 다룹니다. 핵심적인 기능은 다음과 같습니다.

1. 선언적 대화 상자 제어

  • command="show-modal": <button> 요소에 이 속성을 추가하고 commandfor="[dialog-id]"로 대상 <dialog> 요소를 지정하면, 버튼 클릭 시 showModal() 메서드가 호출되어 대화 상자가 열립니다.

  • command="close": 취소 버튼에 이 속성을 사용하면 대화 상자의 close() 메서드가 호출됩니다.

  • closedby="any": <dialog> 요소에 이 속성을 추가하면 대화 상자 외부 영역(backdrop)을 클릭해도 대화 상자가 닫히는 ‘라이트 디스미스’ 기능을 제공합니다.

  • Escape 키: showModal()로 열린 대화 상자는 Escape 키 입력 시 자동으로 닫히는 브라우저 기본 동작을 지원합니다.

2. 접근성 (Accessibility)

  • role="alertdialog": 대화 상자가 사용자 응답이 필요한 중요한 메시지를 전달하는 확인 창임을 스크린 리더에 알립니다.

  • aria-labelledby, aria-describedby: 대화 상자의 제목과 설명을 연결하여 스크린 리더 사용자가 전체 맥락을 파악할 수 있도록 돕습니다.

3. 애니메이션 추가 (@starting-style)

  • @starting-style: 요소가 처음 나타날 때의 초기 상태를 정의하여 자연스러운 진입 애니메이션을 구현합니다. 예를 들어, opacity: 0; scale: 0.95에서 opacity: 1; scale: 1로 전환될 수 있습니다.

  • allow-discrete: displayoverlay와 같은 이산(discrete) 속성에도 전환 효과를 적용할 수 있게 합니다. 이를 통해 대화 상자가 닫힐 때 사라지는 애니메이션을 부드럽게 처리할 수 있습니다.

css dialog { opacity: 1; scale: 1; transition: opacity 0.2s ease-out, scale 0.2s ease-out, overlay 0.2s ease-out allow-discrete, display 0.2s ease-out allow-discrete; @starting-style { opacity: 0; scale: 0.95; } } dialog:not([open]) { opacity: 0; scale: 0.95; }

4. Turbo Confirm 시스템과의 통합

  • Turbo.config.forms.confirm: Turbo에서 제공하는 이 설정을 통해 기본 confirm() 프롬프트 대신 사용자 정의된 <dialog>를 활용할 수 있습니다.

  • 대화 상자 템플릿: application.html.erb<dialog id="turbo-confirm-dialog"> 템플릿을 추가하고, 확인 버튼은 <form method="dialog"> 내의 type="submit" 버튼으로 설정하여 returnValue를 통해 어떤 버튼이 클릭되었는지 감지합니다.

  • JavaScript 설정: 메시지 텍스트 설정, data-turbo-confirm-button을 통한 버튼 텍스트 커스터마이징, 대화 상자 열기 등 최소한의 JavaScript만으로 Turbo의 data-turbo-confirm 기능을 지원합니다.

  • 스크롤 방지: body:has(dialog:modal) { overflow: hidden; } CSS 규칙을 사용하여 모달 대화 상자가 열려 있는 동안 페이지 스크롤을 방지할 수 있습니다.

결론

이 글에서 소개된 접근 방식은 최신 브라우저의 Invoker Commands 및 CSS 기능을 적극 활용하여, 이전에는 많은 JavaScript를 필요로 했던 복잡한 UI 요소를 순수 HTML과 CSS만으로 구현할 수 있음을 보여줍니다. 특히 Turbo와 같은 프레임워크와의 통합은 기존 Rails 애플리케이션에서도 이러한 현대적인 기능을 손쉽게 도입할 수 있게 하여 개발 효율성을 높이고 유지보수를 간소화합니다. JavaScript 의존도를 줄이고 플랫폼의 내장 기능을 최대한 활용함으로써, 더욱 견고하고 접근성 높은 웹 애플리케이션을 구축하는 데 기여할 것입니다. Safari의 `closedby` 지원 등 일부 브라우저 호환성 문제는 폴리필로 해결 가능합니다.

댓글 0

로그인이 필요합니다

댓글을 작성하거나 대화에 참여하려면 로그인이 필요합니다.

로그인 하러 가기

아직 댓글이 없습니다

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