Rails Turbo Actioncable 500 Debug

Rails Turbo Stream 500 에러 3종 세트 디버깅 — broadcast, SolidCable, Telegram Markdown

Rails 8 + Hotwire(Turbo) 기반 앱을 운영하다 보면 broadcast_append_to 계열 콜백이 조용히 500을 내뱉는 경우가 있다. 거기에 SolidCable 초기 설정 문제와 Telegram Bot 메시지 파싱 오류가 겹치면 로그 해석도 헷갈린다. 이번에 세 가지가 한꺼번에 터져서 순서대로 해결한 과정을 정리한다. 문제 1: No unique index found for id — broadcast 콜백 500 현상 메시지나 알림을 생성할 때 컨트롤러에서 500이 발생한다. 로그를 보면: MessagesController#create error: No unique index found for id 원인 Rails after_create_commit 콜백 안에서 broadcast_append_to 를 호출할 때, 내부적으로 ActionCable 채널을 통해 메시지를 전달하는 과정에서 예외가 발생한다. SolidCable을 쓰는 경우 특히 초기 설정이 완전하지 않으면 이 에러가 자주 나온다. ...

2026-01-09 · 4분 소요 · Seunghan
Rails Solidqueue Render Manual Assignment

Rails 8 + SolidQueue Render 배포 삽질 3연타 — 테이블 누락, AI 담당자, 수동 배정

오늘 Rails 8 기반 ITSM 시스템을 Render에 배포하면서 연속으로 삽질을 했다. 각각 원인이 달랐지만 사슬처럼 연결된 문제들이었다. 삽질 1 — Application exited early with SolidQueue 증상 Render 배포 로그에 빌드는 성공인데 실행하자마자 죽는다. ==> Build successful 🎉 ==> Deploying... ==> Running 'bundle exec puma -C config/puma.rb' [87] Puma starting in cluster mode... [87] * Preloading application ==> Application exited early 원인 찾기 Render 로그를 자세히 보면 스택 트레이스가 있다. from solid_queue-1.3.1/lib/solid_queue/configuration.rb in 'recurring_tasks' from solid_queue-1.3.1/lib/solid_queue/supervisor.rb:15 in 'start' from solid_queue-1.3.1/lib/puma/plugin/solid_queue.rb:81 in 'start_solid_queue' ... [69] Detected Solid Queue has gone away, stopping Puma... SolidQueue::RecurringTask.from_configuration 내부에서 load_schema!가 호출되고, SchemaCache#columns에서 터진다. 즉 solid_queue_recurring_tasks 테이블이 DB에 없다. ...

2026-01-06 · 4분 소요 · Seunghan
Rails Ruby3 Kwargs Dispatch Integration Debug

하루 종일 삽질한 것들 — Ruby 3.0 kwargs, Docker env, NAS 크론, SSH 특수문자

AI 에이전트가 Rails API 서버를 호출해서 티켓을 자동 배정하는 디스패처를 만들었다. 로직 자체는 간단한데 붙이는 과정에서 예상치 못한 곳에서 계속 막혔다. 겪은 것들을 기록해 둔다. 1. Ruby 3.0 kwargs 분리 — render_success(key: val) 가 왜 터지나 가장 오래 고생한 것. Rails 컨트롤러에서 응답 헬퍼를 이렇게 호출했다: render_success(tickets: tickets_list, pagination: pagination_data) 서버 로그에 찍힌 에러: ArgumentError - unknown keywords: :tickets, :pagination 헬퍼 정의는 이렇다: def render_success(data, status: :ok) render json: { success: true, data: data }, status: status end Ruby 2.x에서는 render_success(tickets: ..., pagination: ...) 호출 시 {tickets: ..., pagination: ...} 해시가 data에 들어갔다. ...

2026-01-02 · 5분 소요 · Seunghan
Hotwire Native Ios Tab Bar Patterns

Hotwire Native iOS 탭바 앱 구축 — HotwireTabBarController 적용기와 삽질 모음

Rails 앱을 Hotwire Native로 래핑할 때 단일 Navigator 대신 HotwireTabBarController 패턴으로 전환하면서 생긴 문제들을 정리한다. 시뮬레이터에서는 안 보이던 버그가 TestFlight에서 터지고, 로컬 개발 환경 설정이 꼬이는 등 여러 지점에서 시간을 날렸다. 1. HotwireTabBarController 기본 구조 단일 Navigator 대신 탭별로 독립적인 Navigator와 WKWebView를 갖는 구조다. // AppTab.swift enum AppTab: String, CaseIterable { case home, ai, request var systemImage: String { switch self { case .home: return "house" case .ai: return "message" case .request: return "checkmark.circle" } } var selectedSystemImage: String { switch self { case .home: return "house.fill" case .ai: return "message.fill" case .request: return "checkmark.circle.fill" } } var url: URL { let base = AppDelegate.baseURL switch self { case .home: return base.appendingPathComponent("dashboard") case .ai: return base.appendingPathComponent("conversations") case .request: return base.appendingPathComponent("service_requests") } } var hotwireTab: HotwireTab { HotwireTab( title: "", image: UIImage(systemName: systemImage)!, selectedImage: UIImage(systemName: selectedSystemImage)!, url: url ) } } // SceneController.swift 핵심 부분 private lazy var tabBarController: HotwireTabBarController = { let controller = HotwireTabBarController(navigatorDelegate: self) controller.load(AppTab.allCases.map(\.hotwireTab)) // 탭 아이콘만 표시, 텍스트 제거 controller.viewControllers?.forEach { vc in vc.tabBarItem.title = nil vc.tabBarItem.imageInsets = UIEdgeInsets(top: 6, left: 0, bottom: -6, right: 0) (vc as? UINavigationController)?.delegate = self } return controller }() 탭 제목을 없애고 아이콘만 남기려면 tabBarItem.title = nil과 imageInsets 조정이 같이 필요하다. title만 nil로 하면 아이콘 위치가 내려가지 않아서 어색하게 보인다. ...

2025-12-26 · 5분 소요 · Seunghan
Rails Devise Multistep Signup Resend Email

Rails 8 + Devise 다단계 회원가입 & Resend 이메일 삽질 기록

Rails 8 + Inertia.js + Svelte 5 스택에서 역할별 다단계 회원가입과 Resend 이메일 서비스를 연동하면서 겪은 문제들을 정리한다. 1. 역할별 조건부 다단계 회원가입 폼 요구사항 사용자 역할이 두 종류인 서비스에서 회원가입 플로우를 다르게 가져가야 했다. 역할 A: 기본 정보 → 업무 선택 → 소속 정보 (3단계) 역할 B: 기본 정보 → 업무 선택 (2단계, 소속 정보 불필요) Svelte 5 Runes로 조건부 스텝 구현 $derived로 역할에 따라 전체 스텝 수와 버튼 동작을 동적으로 처리했다. ...

2025-12-20 · 4분 소요 · Seunghan
Rails Denormalized Cache Vs Count Query

Rails 비정규화 캐시 컬럼과 COUNT 쿼리 불일치: 씨드 데이터가 0%를 만들었을 때

Rails 앱에 데모용 씨드 데이터를 직접 삽입했는데, 화면에서 모든 퍼센트가 0% 로 표시되는 상황을 만났다. 서버 로그도 깨끗하고, 데이터는 DB에 분명히 들어가 있는데, 숫자만 안 나온다. 상황 투표 기능이 있는 Rails 앱이다. 선택지(Choice)마다 득표 수를 보여주는 화면이 있고, 전체 투표수 대비 퍼센트를 계산해서 프로그레스 바와 숫자로 표시한다. 데모를 보여줘야 해서 외부 API에서 실시간 데이터를 가져와 씨드 데이터로 넣었다. 방식은 간단했다. # 씨드 데이터: 컬럼을 직접 업데이트 choice.update_column(:vote_count, 4712) pick.update_column(:total_votes, 6536) DB를 직접 조회하면 숫자가 잘 들어가 있다. 그런데 화면에서는: ...

2025-12-16 · 4분 소요 · Seunghan
Mcp Flutter Rails System Category Debug

MCP 도구 연동부터 Flutter 설정 토글까지 — 삽질 기록

MCP 도구로 서버 사이드에 카테고리를 생성했다. 그런데 모바일 앱에서 새 카테고리가 보이지 않았다. 간단해 보이는 문제였는데, 파고들수록 여러 레이어가 얽혀 있었다. 문제의 시작: MCP로 만든 카테고리가 앱에 안 보인다 MCP 도구를 통해 dev/, memory 같은 시스템 카테고리를 서버에 생성했다. API를 직접 호출하면 데이터가 있다. 앱을 리프레시해도 나타나지 않는다. 첫 번째 가설: 앱이 캐시를 사용하는 건가? → 아니다. PapersLoadRequested + PaperCategoriesLoadRequested 이벤트를 순서대로 디스패치하고 있었고, 서버에서 정상 응답이 오고 있었다. 두 번째 가설: API가 필터링하고 있나? → Rails 컨트롤러를 봤다. 필터 없음. 전체 반환 중. ...

2025-12-13 · 5분 소요 · Seunghan
Hotwire Native Webview 8 Fixes

Hotwire Native WebView 삽질 모음 — 네이티브 앱에 Rails WebView 래핑할 때 자주 겪는 8가지 문제

Rails 앱을 Hotwire Native(Turbo Native)로 래핑해서 iOS/Android 네이티브 앱을 만들다 보면, 브라우저에서는 멀쩡한데 WebView에서만 이상하게 동작하는 것들이 꽤 많다. 실제로 작업하면서 겪은 문제와 적용한 수정을 한 곳에 정리해 둔다. 대부분 CSS 몇 줄 또는 path configuration JSON 한 줄로 끝난다. 1. 더블탭 줌 / 300ms 클릭 딜레이 증상 버튼을 빠르게 두 번 탭하면 화면이 확대된다. 단순 탭에도 눌렸다는 느낌이 살짝 늦다 (약 300ms). 원인 iOS WKWebView는 더블탭 줌 제스처를 감지하기 위해 첫 번째 탭 이벤트를 ~300ms 동안 잡아둔다. user-scalable=yes(viewport 기본값) 상태에서는 핀치 줌과 더블탭 줌이 활성화되어 있다. ...

2025-11-25 · 4분 소요 · Seunghan
Rails Stimulus Controllers Lookbook Debug

Rails + Stimulus 컨트롤러 11개 구현기: 스크롤·캐러셀·텍스트 애니메이션

Rails + ViewComponent + Lookbook 조합으로 컴포넌트 라이브러리를 만들 때, Stimulus 컨트롤러가 전부 스텁(빈 껍데기) 상태로 남아있는 상황을 맞닥뜨렸다. 13개 컨트롤러 중 3개만 동작하고 나머지 10개는 connect() {} 한 줄짜리였다. 이걸 전부 구현하면서 겪은 삽질을 정리한다. 구현 대상 총 11개 컨트롤러를 4단계로 나눠서 구현했다. Wave 컨트롤러 핵심 기술 1 TagInput, FileDropzone, CategoryTab DOM 조작, 드래그 이벤트 2 ScrollReveal, ScrollScale, VideoScrubbing, HorizontalScroll RAF 쓰로틀, IntersectionObserver, ResizeObserver 3 ScrambleText, RandomReveal RAF 애니메이션 루프, Fisher-Yates 셔플 4 ImageCarousel, CarouselContainer 드래그/터치, translateX 트랜지션 삽질 1: Lookbook 프리뷰에서 Stimulus가 아예 안 됨 가장 크게 막혔던 부분이다. 컨트롤러를 다 구현하고 Lookbook을 열었는데 아무 동작도 하지 않는다. 크롬 DevTools를 열어보니 data-controller 속성은 붙어있는데 Stimulus가 연결이 안 된 상태였다. ...

2025-11-18 · 6분 소요 · Seunghan
Rails Inertia Svelte Pet Avatar Image Color

Rails + Inertia + Svelte 5: 아바타 이미지/색상 선택 기능 구현에서 삽질한 것들

Rails 8 + Inertia.js + Svelte 5 스택으로 펫(반려동물) 프로필 아바타를 이미지 또는 색상으로 선택하는 기능을 구현하면서 겪은 문제들을 정리한다. 문제 1: 색상이 DB에 저장되지 않았다 증상 처음 코드를 보니 펫 카드에 색상을 표시할 때 이런 식으로 되어 있었다. const PET_COLORS = ['#f3caa1', '#b7ddf9', '#d3c8ff', '#c5d5f4', '#ffd9aa'] function petColor(index: number): string { return PET_COLORS[index % PET_COLORS.length] } 펫을 생성한 순서(인덱스) 로 색상을 결정하는 구조였다. 색상을 DB에 아예 저장하지 않았으니, 사용자가 색상을 바꿔도 새로고침하면 원래 색상으로 돌아왔다. 해결 마이그레이션으로 avatar_color 컬럼을 추가하고 기본값을 지정했다. ...

2025-11-15 · 4분 소요 · Seunghan
개인정보처리방침 이용약관 면책조항 문의