Inertia.js와 Ruby on Rails를 활용한 드로어 컴포넌트의 낙관적 UI 업데이트

Optimistic Drawer UI with Inertia.js and Rails

작성자
발행일
2025년 10월 14일

핵심 요약

  • 1 Inertia.js와 Ruby on Rails를 사용하여 URL 쿼리 파라미터로 드로어 컴포넌트의 상태를 관리하고, 즉각적인 사용자 피드백을 위한 낙관적 UI 업데이트를 구현합니다.
  • 2 Rails 컨트롤러 컨선(concern)을 통해 외부 API에서 데이터를 비동기적으로 로드하고, Inertia.js의 `inertia_share`를 활용하여 페이지 프롭(props)으로 데이터를 공유하는 패턴을 소개합니다.
  • 3 로딩 스피너 및 오류 메시지 표시를 포함한 사용자 경험 개선과, UI 로직과 데이터 로딩 로직의 명확한 분리를 통한 유지보수성 향상 방법을 설명합니다.

도입

본 영상은 Inertia.js와 Ruby on Rails 환경에서 드로어(drawer) 컴포넌트의 상태 관리 및 낙관적 UI 업데이트(Optimistic UI Update) 구현 방안을 다룹니다. Inertia.js Rails 어댑터의 공동 저자이자 관리자인 Brian Nolles는 이전 영상에서 다룬 낙관적 UI 업데이트 패턴을 NBA 경기 목록 데모 애플리케이션의 드로어 컴포넌트에 적용하는 과정을 시연합니다. 특히, 실제 애플리케이션에서 적용 가능한 좀 더 복잡한 시나리오를 통해 Inertia.js의 강력한 기능을 보여주는 데 중점을 둡니다.

드로어 컴포넌트 구현 전략

Inertia.js에서 모달(modal) 또는 드로어를 구현하는 세 가지 주요 전략이 있습니다. 첫째, 일반적인 로컬 상태(local state)를 통해 관리하는 방법입니다. 둘째, Inertia UI 라이브러리를 활용하는 방법으로, 모달/드로어를 별도의 페이지처럼 취급하여 고유한 URL과 페이지 객체를 가질 수 있습니다. 셋째, 본 영상에서 중점적으로 다루는 방법으로, 쿼리 파라미터와 Rails 컨트롤러 컨선(concern)을 사용하여 드로어의 상태를 관리하는 방식입니다.

쿼리 파라미터를 활용한 상태 관리

  • 링크 클릭 및 쿼리 파라미터 추가: NBA 경기 목록에서 점수 링크를 클릭하면, Inertia.js는 해당 요청을 가로채어 URL에 detailed_game_id라는 쿼리 파라미터를 추가합니다. 이는 일반적인 HTML 앵커 태그처럼 동작하며, Inertia.js가 서버 요청을 처리하고 페이지 응답을 클라이언트 앱에 병합합니다.

  • 장점: 쿼리 파라미터 방식은 드로어의 상태를 URL에 반영하여, 해당 URL을 새 탭에서 열거나 공유할 때 드로어가 올바른 상태로 열리도록 합니다. 이는 HTML 프로토콜의 기본 원칙을 따르면서 풍부한 클라이언트 측 경험을 제공합니다.

  • Rails 컨트롤러 컨선(GameDetailable): 서버 측에서는 BaseControllerGameDetailable 컨선을 포함합니다. 이 컨선은 detailed_game_id 쿼리 파라미터의 존재 여부를 확인하고, 존재할 경우 외부 API에서 실제 경기 상세 데이터를 가져옵니다. inertia_share를 사용하여 이 데이터를 페이지 프롭(page props)으로 공유하며, 쿼리 파라미터 자체도 클라이언트로 다시 전달하여 편의성을 높입니다.

  • 드로어 컴포넌트 렌더링: 클라이언트 측의 GameDetailsDrawer 컴포넌트는 페이지 프롭에서 detailed_game_id의 존재 여부를 확인하여 드로어의 열림/닫힘 상태(isDrawerOpen)를 제어합니다. 드로어를 닫을 때는 detailed_game_id 파라미터 없이 페이지를 다시 로드하여 드로어가 닫히도록 합니다.

낙관적 UI 업데이트 및 사용자 경험 개선

  • 문제점: 네트워크 지연(latency)이 발생할 경우, 드로어가 열리거나 닫히는 데 시간이 걸려 사용자 경험이 저하됩니다.

  • 낙관적 업데이트 적용: Inertia.js 2.0의 클라이언트 측 방문(client-side visit) 기능을 활용하여, 서버 요청을 보내기 전에 클라이언트에서 페이지 프롭에 detailed_game_id를 낙관적으로 추가합니다. 이를 통해 드로어가 즉시 열리고, 닫을 때도 즉시 닫히는 것처럼 보이게 하여 사용자에게 즉각적인 피드백을 제공합니다. 서버 응답은 백그라운드에서 처리됩니다.

  • 로딩 상태 표시: 드로어가 열렸지만 아직 상세 데이터가 로드되지 않았을 때(즉, detailed_game_id는 있지만 detailed_game 객체는 없을 때) 로딩 스피너를 표시하여 사용자에게 진행 상황을 시각적으로 알립니다.

  • 오류 처리: 외부 API 호출 시 발생할 수 있는 타임아웃 오류를 시뮬레이션하고, begin rescue 블록으로 이를 처리합니다. 오류 발생 시 detailed_game_error라는 새로운 프롭을 클라이언트로 전송하고, 드로어 컴포넌트에서는 이 오류 프롭의 존재 여부를 확인하여 적절한 오류 메시지를 표시합니다.

관심사의 분리 (Separation of Concerns)

이 패턴의 핵심은 각 컴포넌트와 로직이 명확한 책임을 갖는다는 것입니다.

  • GameRow (링크): 단순히 detailed_game_id 쿼리 파라미터를 서버로 전송하여 “이 게임에 대해 더 알고 싶다”는 의도를 전달할 뿐, UI가 어떻게 반응해야 하는지에 대한 지식은 없습니다.

  • Concern (데이터 로딩): detailed_game_id의 존재 여부를 확인하고, 해당 ID를 기반으로 데이터를 로드하거나 오류를 반환합니다. UI에 대한 어떠한 가정도 하지 않습니다.

  • GameDetailsDrawer (UI 렌더링): 서버에서 전달된 데이터나 오류를 해석하여 드로어의 열림/닫힘, 로딩 상태, 오류 메시지 표시 등을 결정합니다. 또한, 드로어를 닫는 방법을 스스로 알고 있습니다.

이러한 분리 덕분에, 예를 들어 드로어를 모달이나 페이지 내의 다른 컴포넌트로 변경하더라도 GameRowConcern의 코드는 전혀 수정할 필요가 없습니다.

결론

본 영상에서 제시된 Inertia.js와 Ruby on Rails를 활용한 드로어 컴포넌트 패턴은 낙관적 UI 업데이트를 통해 사용자에게 즉각적이고 반응성 높은 경험을 제공합니다. 쿼리 파라미터를 통한 상태 관리, 로딩 및 오류 처리, 그리고 명확한 관심사 분리는 코드의 유지보수성과 유연성을 크게 향상시킵니다. 특히, UI 로직과 서버 측 데이터 로딩 로직이 독립적으로 작동하면서도 긴밀하게 연동되는 구조는 현대 웹 애플리케이션 개발에서 매우 효과적인 접근 방식임을 보여줍니다. 이는 Inertia.js가 풍부한 클라이언트 측 프레임워크의 장점을 활용하면서도 기본적인 HTML 프로토콜의 장점을 유지하는 강력한 도구임을 입증합니다.

댓글 0

댓글 작성

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

아직 댓글이 없습니다

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