Rails 8에서 Devise 걷어내기 — has_secure_password로 마이그레이션한 실전 기록

Devise가 Inertia.js와 싸우기 시작했다 Rails 8 + Inertia.js + Svelte 5 스택으로 운영하던 프로젝트에서 로그인이 안 되는 버그가 터졌다. 에러 메시지도 없고, 401만 돌아왔다. 로그를 보니 Warden의 database_authenticatable strategy가 valid_for_params_auth? = false를 찍고 있었다. 쿼리가 0개 — DB에 접근조차 안 한 것이다. 원인은 Devise의 Warden 미들웨어가 request.params[:user]를 읽는데, Inertia.js는 {email, password}를 flat하게 보내서 Rails의 ParamsWrapper가 session 키로 감싸버리는 구조적 충돌이었다. # Inertia.js가 보내는 것 { email: "user@example.com", password: "secret" } # Rails ParamsWrapper가 변환한 것 { email: "...", password: "...", session: { email: "...", password: "..." } } # Devise/Warden이 찾는 것 { user: { email: "...", password: "..." } } # ← 이게 없다 normalize_sign_in_params라는 핵으로 params[:user]를 세팅했지만, Warden은 ActionController의 params가 아니라 **Rack 레벨의 request.params**를 따로 읽었다. 두 객체는 완전히 별개다. ...

2026-03-31 · 7분 소요 · Seunghan
Rails Sso One Time Token Between Services

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

두 개의 Rails 앱이 있다. 하나는 내부 직원용 앱(OTP 로그인, 특정 도메인 전용), 다른 하나는 심사/관리 시스템으로 Devise + JWT 기반이다. 내부 직원이 심사 시스템에도 접근해야 하는데, 계정을 따로 만들어 관리하기 싫었다. “이미 내부 앱에 로그인돼 있으면, 심사 시스템에서 버튼 하나로 자동 로그인되면 안 되나?” OAuth2를 붙이면 정석이지만, Doorkeeper 설정하고 scope 관리하고… 내부 서비스 두 개 사이에 그게 과할 수 있다. 더 단순한 방법을 택했다. OAuth2를 안 쓴 이유 OAuth2는 서드파티 클라이언트 지원, 세밀한 권한 범위(scope) 관리, 토큰 갱신 흐름, 공개 API 연동이 필요할 때 올바른 선택이다. 하지만 같은 팀이 운영하는 두 내부 서비스 사이에서 OAuth2를 도입하면 다음을 감수해야 한다. ...

2026-02-10 · 6분 소요 · 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
개인정보처리방침 이용약관 면책조항 문의