바로신고

바로신고 다산콜센터(120), 경찰청(112), 소방서(119)에 문자 기반 긴급 신고를 빠르고 간편하게 할 수 있는 앱입니다. 주요 기능 신고 대상 선택 — 다산콜센터, 경찰청, 소방서 중 선택 간편한 신고 작성 — 상황 설명 입력 + 사진 첨부 신고 이력 관리 — 접수완료, 처리중 등 상태 실시간 확인 알림 기능 — 신고 접수 및 처리 완료 푸시 알림 기술 스택 영역 기술 Backend Rails 8 + Turbo iOS Hotwire Native 1.2.2 (Swift, XcodeGen) Android Hotwire Native 1.2.5 (Kotlin) 호스팅 Render 다운로드 App Store (심사 중) Google Play (준비 중) 지원 문의: theqwe2000@naver.com ...

2026-03-07 · 1분 소요 · Seunghan

Rails 앱을 Hotwire Native로 iOS 앱 만들어 TestFlight 올리기까지의 삽질 기록

Rails 8로 만든 긴급 신고 웹앱 바로신고를 Hotwire Native으로 iOS 앱으로 감싸서 TestFlight에 올리기까지의 과정을 정리합니다. 기술 스택 Backend: Rails 8 + Turbo iOS: Hotwire Native 1.2.2 + XcodeGen 빌드: Makefile 자동화 프로젝트 구조 ios/ ├── project.yml # XcodeGen 설정 ├── ExportOptions.plist # App Store 내보내기 ├── Makefile # 빌드 자동화 └── BaroSingo/ ├── AppDelegate.swift ├── SceneController.swift ├── AppTab.swift ├── Bridge/ │ ├── FormComponent.swift │ ├── HapticComponent.swift │ └── ShareComponent.swift └── Resources/ ├── Assets.xcassets/ └── path-configuration.json 삽질 1: Hotwire Native API 변경 Hotwire.config.userAgent — 읽기 전용 // ❌ 컴파일 에러: 'userAgent' is a get-only property Hotwire.config.userAgent = "BaroSingo iOS" // ✅ 해결: makeCustomWebView 사용 Hotwire.config.makeCustomWebView = { configuration in let webView = WKWebView(frame: .zero, configuration: configuration) webView.customUserAgent = "BaroSingo iOS/1.0 Turbo Native" return webView } Hotwire.loadPathConfiguration — 존재하지 않는 API // ❌ 컴파일 에러: no member 'loadPathConfiguration' Hotwire.loadPathConfiguration(from: [source]) // ✅ 해결: config.pathConfiguration.sources 직접 설정 Hotwire.config.pathConfiguration.sources = [ .file(Bundle.main.url(forResource: "path-configuration", withExtension: "json")!), .server(URL(string: "\(baseURL)/api/hotwire/path-configuration")!) ] Bridge Component에서 ViewController 접근 // ❌ 컴파일 에러: optional type must be unwrapped delegate.webView?.findViewController() // ✅ 해결: delegate?.destination 사용 guard let viewController = delegate?.destination as? UIViewController else { return } 교훈: Hotwire Native는 버전별 API 변경이 잦다. 공식 소스코드와 실제 동작하는 프로젝트를 참고하는 게 가장 확실하다. ...

2026-03-07 · 4분 소요 · Seunghan
Render Deploy Debugging

Render 배포 실패 디버깅 — DB 업그레이드부터 Gemfile 누락까지 10개 에러 연속 격파

오늘 Rails 앱 배포가 build_failed로 떨어졌다. 처음엔 단순한 에러 하나겠지 싶었는데, 고칠 때마다 새 에러가 튀어나왔다. 결국 10개의 에러를 순서대로 해결하고 나서야 live 상태가 됐다. 연속 디버깅의 기록을 남긴다. 배경 Render에서 Rails 8 + Inertia.js + Svelte 5 조합 웹 서비스를 운영 중이다. 어느 날 대시보드를 보니 최신 배포가 build_failed 상태. 로그를 열었다. 에러 1: DB 연결 실패 — ActiveRecord::ConnectionNotEstablished bin/rails aborted! ActiveRecord::ConnectionNotEstablished: connection to server at "10.x.x.x", port 5432 failed: Connection refused Tasks: TOP => db:migrate 빌드 스크립트에서 db:migrate를 실행하는 순간 PostgreSQL 연결이 거부됐다. 트리거를 보니 service_resumed — 서비스가 재개(resume)된 것이었다. ...

2026-03-07 · 5분 소요 · Seunghan
Uxui Review And Fix Svelte Rails

Rails + Svelte 앱 UX/UI 전수 점검 및 개선 기록

Rails 8 + Inertia.js + Svelte 5 조합으로 만든 웹앱을 운영하다가, 기능은 돌아가는데 세부 UX가 들쭉날쭉하다는 걸 느꼈다. 이번 글은 전수 점검 후 우선순위 높은 4가지를 직접 고친 기록이다. 문제 발견: 같은 기능인데 UI가 다르다 가장 먼저 눈에 띈 건 시작일 입력 UI가 화면마다 다르게 동작하는 문제였다. 앱에는 할일을 만들 수 있는 진입점이 4곳이다. 대시보드 빠른 추가 모달(생성) 전체 페이지 생성 모달(수정) 위치 시작일 동작 대시보드 빠른추가 피커가 항상 노출 + + 시작일 버튼도 따로 존재 생성 모달 마감일 설정 후 + 시작일 추가 버튼 클릭 시 피커 표시 전체 페이지 피커 항상 노출 수정 모달 피커 항상 노출 생성 모달만 UX가 깔끔했고, 나머지 3곳은 피커가 항상 보여서 폼이 불필요하게 복잡해 보였다. + 시작일 버튼이 있는데 피커도 이미 떠 있으니 버튼의 의미가 모호했다. ...

2026-03-06 · 4분 소요 · Seunghan
Render Multi Service Error Fix Deploy

Render 6개 서비스 에러 일괄 점검 & 수정 — Stoplight, FK 제약, Puma 7, Solid Stack 삽질 기록

Render에 올려둔 Rails 서비스 6개가 전부 각자 다른 에러를 토해내고 있었다. 하나씩 로그를 까보니 공통 패턴도 있고, 프로젝트마다 고유한 문제도 있었다. 한 세션에서 전부 수정하고 배포까지 마친 과정을 정리한다. 전체 상황 Render API로 서비스 6개의 로그를 일괄 조회했다. 결과: 서비스 주요 에러 서비스 A ERB 문법 에러로 500 (이미 커밋됐지만 미배포) 서비스 B Stoplight Light#run 블록 에러 + Telegram 파싱 에러 서비스 C solid_cache_entries 테이블 누락 서비스 D PG::UndefinedColumn + solid_cache 누락 서비스 E PG::DuplicateTable sessions + Sentry 초기화 에러 서비스 F TaskCleanupJob FK 위반 + Puma deprecated 경고 공통 패턴: Rails 8의 Solid Stack (SolidCache, SolidQueue, SolidCable) 초기 설정 문제가 여러 프로젝트에서 반복됐다. ...

2026-02-24 · 6분 소요 · Seunghan
Rails8 Cross Project Patterns And Improvements

Rails 8 프로젝트 간 패턴 교차 적용 — rack-attack, PWA 배너, Sentry, FCM 멀티디바이스

두 개의 Rails 8 프로젝트를 병렬로 운영하다 보면 한쪽에서 공들여 만든 패턴이 다른 쪽에는 빠져있는 경우가 자주 생긴다. 기능을 구현할 때는 당장의 요구사항에 집중하다 보니 다른 프로젝트의 좋은 구현을 챙기지 못하는 것이다. 이번에 두 프로젝트를 나란히 놓고 비교하면서 빠진 부분을 서로 채워주는 작업을 했다. 주로 보안, PWA 경험, 에러 추적, 푸시 알림 인프라에 관한 내용이다. 비교 분석 방법 두 프로젝트의 주요 파일을 나열하고 대조했다. 확인 항목 ├── Gemfile (gem 목록) ├── config/initializers/ (설정 파일) ├── app/javascript/controllers/ (Stimulus 컨트롤러) ├── app/views/layouts/application.html.erb (레이아웃) ├── db/schema.rb (DB 스키마) └── ios/ (iOS 네이티브 설정) 결과적으로 아래 6가지를 양방향으로 이식했다. ...

2026-02-20 · 6분 소요 · Seunghan
Rails Sso Universal Links Hotwire Native

Rails 간 SSO 구현 + iOS Universal Links로 앱 자동 전환까지

두 개의 Rails 8 서비스가 있다. 하나는 메인 앱(IdP 역할), 다른 하나는 연동 서비스(RP 역할). 연동 서비스 로그인 페이지에 “메인 앱으로 로그인” 버튼을 넣고, SSO로 인증 후 돌아오는 플로우를 구현했다. 거기에 iOS Hotwire Native 앱이 설치돼 있으면, 브라우저 대신 네이티브 앱에서 인증이 진행되도록 Universal Links까지 붙였다. 목표 플로우 [연동 서비스] "메인 앱으로 로그인" 클릭 → 메인 앱 /auth/sso/authorize 로 리다이렉트 → (앱 설치 시) iOS Universal Link → 네이티브 앱 열림 → (미설치 시) 브라우저에서 로그인 → 이미 로그인 상태면 바로 토큰 발급 → 미로그인이면 OTP 로그인 → 토큰 발급 → "인증 완료" 페이지 (2초 대기) → 콜백 URL로 리다이렉트 → 연동 서비스가 토큰 검증 → 로그인 완료 삽질 1: SSO 파라미터가 로그인 과정에서 유실됨 문제 SSO authorize 엔드포인트에 before_action :require_authentication을 걸어놨더니: ...

2026-02-17 · 7분 소요 · Seunghan
Rails Sso Turbo Drive Debugging

Rails SSO 구현 중 Turbo Drive가 유발한 두 가지 버그 디버깅

Rails 앱 간 SSO(Single Sign-On)를 HMAC 기반으로 구현하던 중 예상치 못한 두 가지 버그를 만났다. 둘 다 Turbo Drive와 ERB의 동작 방식에서 비롯된 문제였다. 구현 개요 구조 IdP (Identity Provider): 사용자 인증을 담당하는 Rails 앱 (OTP 로그인) SP (Service Provider): IdP에서 인증받아 로그인하는 Rails 앱 플로우 SP 로그인 버튼 클릭 → SP: state 생성 후 세션 저장, IdP /authorize로 리다이렉트 → IdP: 로그인 확인 후 One-Time Token 발급 → IdP: authorize_complete 페이지 표시 (2초 후 SP callback으로 자동 리다이렉트) → SP callback: state 검증 + token 검증 → 로그인 완료 핵심 보안 요소 CSRF 방지: SP에서 생성한 state를 세션에 저장하고 callback에서 검증 HMAC 서명: SP가 IdP의 /verify 엔드포인트에 서명된 요청으로 token 검증 One-Time Token: 한 번 사용하면 무효화되는 토큰 버그 1: “state mismatch” — Turbo Drive prefetch가 세션을 덮어쓴다 증상 SP의 “SSO 로그인” 버튼을 클릭하면 IdP에서 인증 완료 페이지까지 잘 가는데, SP callback에서 항상 state mismatch 에러가 발생했다. ...

2026-02-13 · 4분 소요 · Seunghan
Rails Sso One Time Token Between Services

Rails 서비스 간 SSO 직접 구현하기: One-Time Token + HMAC 방식

두 개의 Rails 앱이 있다. 하나는 내부 직원용 앱(OTP 로그인, 특정 도메인 전용), 다른 하나는 심사/관리 시스템으로 Devise + JWT 기반이다. 내부 직원이 심사 시스템에도 접근해야 하는데, 계정을 따로 만들어 관리하기 싫었다. “이미 내부 앱에 로그인돼 있으면, 심사 시스템에서 버튼 하나로 자동 로그인되면 안 되나?” OAuth2를 붙이면 정석이지만, Doorkeeper 설정하고 scope 관리하고… 내부 서비스 두 개 사이에 그게 과할 수 있다. 더 단순한 방법을 택했다. 구조 선택: One-Time Token + HMAC 이미 두 서비스 사이에 webhook 연동이 있었다. ITSM 이벤트를 다른 서비스에 전달할 때 HMAC-SHA256으로 서명하는 패턴이 있었고, 이걸 SSO에도 그대로 쓰기로 했다. ...

2026-02-10 · 4분 소요 · Seunghan
Rails Rfc3161 Tsa Blockchain Merkle Debugging

RFC 3161 TSA 타임스탬프 + 블록체인 Merkle 앵커링: Rails에서 삽질 기록

전자계약 보관 시스템에 법적 증거력을 부여하기 위해 두 가지를 동시에 구현해야 했다: 블록체인 Merkle Tree 앵커링 — 계약 해시들을 모아 Merkle Root를 L2 체인에 기록 RFC 3161 TSA 타임스탬프 — 신뢰할 수 있는 제3자 시간 증명 간단해 보였는데, 삽질의 연속이었다. 1. RFC 3161 TSA란? RFC 3161은 Time-Stamp Authority(TSA) 프로토콜로, 특정 데이터가 특정 시점에 존재했음을 제3자가 증명해주는 표준이다. 흐름은 간단하다: 클라이언트 → SHA-256 해시 생성 → TSA 서버에 요청 → 서명된 타임스탬프 토큰 수신 무료 TSA 서버들: ...

2026-02-06 · 4분 소요 · Seunghan
개인정보처리방침 문의