# Redis를 떠나 SolidQueue로 옮기는 이유

> Clean Markdown view of GeekNews topic #25849. Use the original source for factual precision when an external source URL is present.

## Metadata

- GeekNews HTML: [https://news.hada.io/topic?id=25849](https://news.hada.io/topic?id=25849)
- GeekNews Markdown: [https://news.hada.io/topic/25849.md](https://news.hada.io/topic/25849.md)
- Type: GN+
- Author: [xguru](https://news.hada.io/@xguru)
- Published: 2026-01-15T23:58:13+09:00
- Updated: 2026-01-15T23:58:13+09:00
- Original source: [simplethread.com](https://www.simplethread.com/redis-solidqueue/)
- Points: 16
- Comments: 2

## Summary

Rails 8은 **Redis 의존성을 제거**하고, 모든 백그라운드 작업을 **SolidQueue·SolidCache·SolidCable**을 통해 **PostgreSQL 기반**으로 처리하도록 전환합니다. SolidQueue는 `FOR UPDATE SKIP LOCKED`를 활용해 경쟁 없는 병렬 처리를 구현하며, **주기적 작업·동시성 제어·모니터링 대시보드**까지 기본 제공해 Redis+Sidekiq의 유료 기능을 대체합니다. 대부분의 Rails 애플리케이션은 이 단일 DB 스택만으로 충분히 운영 가능하며, 초고속 실시간 처리가 필요한 일부 경우에만 Redis가 유지하는 것을 권장합니다.

## Topic Body

- **Rails 8**은 기본 스택에서 **Redis 의존성을 제거**하고, **SolidQueue·SolidCache·SolidCable**을 통해 모든 작업을 **관계형 데이터베이스(RDB)** 위에서 처리하도록 전환  
- Redis는 빠르고 안정적이지만, **설정·보안·클러스터 관리·백업 등 운영 복잡성**을 초래함  
- **SolidQueue**는 PostgreSQL의 **`FOR UPDATE SKIP LOCKED`** 기능을 활용해 **경쟁 없는 병렬 작업 처리**를 구현  
- **주기적 작업, 동시성 제어, 모니터링 대시보드(Mission Control)** 등 Redis+Sidekiq 유료 기능을 **무료로 제공**  
- 대부분의 Rails 애플리케이션은 SolidQueue로 충분하며, **초고속·실시간 처리**가 필요한 일부 경우만 Redis 유지 필요  

---

### Redis의 숨은 비용
- Redis는 단순한 호스팅 비용 외에도 **설치·유지보수·보안 구성·HA 클러스터 관리** 등 지속적 관리 부담이 존재  
  - Rails와 Redis 간 **네트워크 연결 및 방화벽 설정**, **클라이언트 인증**, **Sidekiq 프로세스 오케스트레이션** 필요  
- 장애 발생 시 **Redis와 RDBMS 두 시스템을 동시에 디버깅**해야 하며, **이중 백업 전략**도 요구됨  
- 반면 Redis 없는 Rails 스택에서는 **PostgreSQL 하나만 관리**하면 되어 단순화 가능  

### SolidQueue의 동작 원리
- PostgreSQL의 **`FOR UPDATE SKIP LOCKED`** 기능을 이용해 **잠금 충돌(lock contention)** 없이 여러 워커가 동시에 작업을 가져감  
- 주요 테이블 구조  
  1. `solid_queue_jobs`: 작업 메타데이터 저장  
  2. `solid_queue_scheduled_executions`: 예약된 작업 대기  
  3. `solid_queue_ready_executions`: 실행 준비된 작업 큐  
- **워커·디스패처·스케줄러·슈퍼바이저** 프로세스가 각기 다른 테이블을 주기적으로 폴링하며 협력  
- PostgreSQL의 **MVCC 설계와 autovacuum** 덕분에 대량의 삽입·삭제 작업도 안정적으로 처리  

### 반복 작업 스케줄링
- SolidQueue는 **cron 스타일의 반복 작업**을 기본 제공하며, `config/recurring.yml` 파일로 설정  
- 스케줄러는 실행 시점이 된 작업을 큐에 넣고, **다음 실행 시점을 자동 예약**  
- **Fugit** 라이브러리로 자연어 스케줄을 파싱하고, **Concurrent::ScheduledTask**로 스레드를 생성  
- **GoodJob**의 결정적(deterministic) 스케줄링 방식을 차용해 **프로세스 재시작에도 일정 유지**  

### 동시성 제어 기능
- SolidQueue는 **POSIX 세마포어 패턴**을 사용해 **작업 단위별 동시 실행 제한**을 지원  
  - 예: `limits_concurrency to: 1, key: ->(user) { user.id }` 설정 시 사용자별 1개 작업만 실행  
- 세마포어 만료(`duration`)를 지정해 **작업 충돌·데드락 방지**  
- 관련 테이블  
  - `solid_queue_semaphores`: 동시성 제한 추적  
  - `solid_queue_blocked_executions`: 대기 중인 작업 저장  

### Mission Control을 통한 모니터링
- **Mission Control Jobs**는 Rails 8용 무료 오픈소스 대시보드로, `/jobs` 경로에 간단히 마운트 가능  
- 주요 기능  
  - 실시간 큐 상태, 실패 작업 추적, 재시도/폐기 제어  
  - 예약·반복 작업 타임라인 시각화  
  - 큐별 처리량 및 메트릭 그래프  
- SQL 기반 조회를 지원해 **추가 도구 없이 데이터베이스에서 직접 분석 가능**  

### Sidekiq에서 SolidQueue로의 마이그레이션
- **1단계:** `config.active_job.queue_adapter = :solid_queue` 설정  
- **2단계:** `bundle add solid_queue` 후 `rails solid_queue:install` 및 `db:migrate` 실행  
- **3단계:** `sidekiq.yml`의 cron 스케줄을 `recurring.yml`로 변환  
- **4단계:** `Procfile`에 `jobs: bundle exec rake solid_queue:start` 추가  
- **5단계:** Redis·Sidekiq 관련 gem 삭제  
- 기존 ActiveJob 코드는 수정 없이 그대로 작동  

### Redis가 여전히 필요한 경우
- **초당 수천 건 이상의 지속적 작업 처리**  
- **1ms 미만 지연(latency)** 이 필수인 실시간 시스템  
- **복잡한 pub/sub 구조** 또는 **정교한 rate limiting·카운터 연산** 필요  
- 예시로 Shopify는 초당 833 요청, 1,172 워커 프로세스를 운영하며 Redis 인프라를 사용  

### 실제 구현 가이드
- Rails 8 신규 앱 생성 시 SolidQueue·SolidCache·SolidCable 자동 구성  
- `config/database.yml`에 **별도 queue 데이터베이스 연결** 설정 권장  
- Mission Control 인증 추가 및 `/jobs` 라우트 마운트  
- `Procfile.dev`에 `jobs: bundle exec rake solid_queue:start` 추가 후 `bin/dev` 실행으로 전체 구동  
- 테스트 작업 생성 후 Mission Control에서 상태 확인 가능  

### 자주 발생하는 문제와 해결
- **단일 데이터베이스 구성**도 가능하지만, 운영 유연성 저하  
- **프로덕션 환경 Mission Control**에는 반드시 인증 추가 필요  
- **폴링 간격** 기본값은 예약 1초, 즉시 작업 0.2초로 대부분의 앱에 적합  
- **ActionCable/Turbo Streams** 사용 시 `SolidCable`을 별도 DB 연결로 설정해야 함  

### 확장성과 성능
- SolidQueue는 대부분의 Rails 앱에서 충분히 확장 가능  
- PostgreSQL 기반으로 **초당 200~300 작업 처리** 가능하며, **37signals는 하루 2천만 작업**을 Redis 없이 처리  
- 비교표  
  | 항목 | Redis + Sidekiq | SolidQueue |
  | --- | --- | --- |
  | 설정 복잡도 | 별도 서비스 필요 | 내장 DB 사용 |
  | 쿼리 언어 | Redis 명령어 | SQL |
  | 모니터링 | 별도 대시보드 | Mission Control |
  | 장애 시나리오 | 6개 이상 | 2개 |
  | 처리량 | 수천 건/초 | 200–300건/초 |
  | 적합 대상 | 99.9% 앱 | 95% 앱 |

### 결론
- Redis와 Sidekiq는 뛰어난 기술이지만, **대부분의 Rails 애플리케이션에는 과도한 복잡성과 비용**을 초래  
- **SolidQueue**는 단일 데이터베이스 기반으로 **운영 단순화·비용 절감·유지보수 효율화**를 실현  
- Rails 8 시대의 기본 선택지로 **SolidQueue 전환**이 권장됨

## Comments



### Comment 49386

- Author: kaydash
- Created: 2026-01-17T18:20:40+09:00
- Points: 1

레디스좋은데.

### Comment 49279

- Author: neo
- Created: 2026-01-15T23:58:13+09:00
- Points: 1

###### [Hacker News 의견들](https://news.ycombinator.com/item?id=46614037) 
- 모든 **오픈소스 저자**는 자신의 프로젝트 범위를 통제할 권리가 있다고 생각함  
  하지만 우리 팀이 [good_job](https://github.com/bensheldon/good_job)에서 SolidQueue로 바꾼 건 후회 중임  
  Basecamp은 MySQL 중심이라 **RDBMS 엔진 특화 쿼리**를 받지 않음. GitHub 이슈를 보면 MySQL 성능에만 집중하는 걸 볼 수 있음  
  또한 아직 **배치 작업 지원**이 없음 ([관련 PR](https://github.com/rails/solid_queue/pull/142))  
  - 최악의 조합처럼 들림. 우리도 MySQL을 쓰지만, 엔진 특화 쿼리 없이는 못 살겠음  
    복잡한 JOIN에서 MySQL이 쿼리 플랜을 잘못 짜는 경우가 많아서, 나는 **STRAIGHT_JOIN**으로 순서를 강제함. 미래 대비용임  
  - MySQL에 그렇게 깊게 묶여 있다면, **MySQL 전용 기능**을 쓰는 게 논리적이지 않음? 뭔가 빠진 것 같음  
  - GoodJob을 SolidQueue보다 추천하는 이유를 좀 더 구체적으로 듣고 싶음  
    나는 resque에서 옮길 후보로 두 개를 비교 중임. GoodJob은 **pg 전용 기능** 때문에 pgbouncer transaction 모드와 호환이 안 됨  
    세션 지속이 필요해서 귀찮지만, 성능 향상은 대부분의 규모에서 큰 의미가 없음  
    그래도 GoodJob의 **개발 모델과 코드 가독성**은 훨씬 신뢰감 있음  
  - 동의함. good_job은 **Postgres 기반 큐**로는 이상적인 접근임  
  - SolidQueue는 아직 잘 모르겠지만, good_job은 써보니 정말 즐거움. 잘 작동함  

- 프로덕션 환경이 단순해질 수 있다면 언제나 좋은 일임  
  Rails에서 이상적인 상황은 Redis로 **간단히 전환할 수 있는 구조**라고 생각함  
  SolidQueue로 시작했다가 확장성 한계에 부딪히면 Redis로 옮길 수 있으면 좋겠음  
  대부분의 Rails 앱은 트래픽이 크지 않으니, 두 시스템을 유지하는 게 오히려 복잡함  
  - Rails는 Active Job이라는 **추상화된 API**를 제공해서 Redis로 전환이 꽤 쉬움  
    물론 특정 큐 구현에 의존하는 앱도 있지만, 일반적인 경우 설정만 바꾸면 됨  
  - [Redis AOF 모드](https://redis.io/docs/latest/operate/oss_and_stack/management/persistence/)가 WAL처럼 모든 변경을 기록하는지 궁금함  
    로그가 너무 커지는 걸 막기 위해 스냅샷도 병행하는지, 그리고 이게 **분산 모드**에서도 작동하는지 알고 싶음  
  - 트랜잭션에 너무 의존하면 마이그레이션이 어려워짐  
    특히 작업 생성이 다른 DB 변경과 함께 일어나는 경우, 그 보장성을 잃는 게 문제임  
  - Rails는 백그라운드 작업 프로세서를 **프로덕션 DB와 분리**하지 않아서 혼란스러움  
    Redis는 이 점에서 가볍고 독립적인 상태 저장소로 유리했음  
    SolidQueue는 이런 분리를 명확히 하지 않는 것 같음 ([riverqueue.com](https://riverqueue.com/))  

- 내 사이드 프로젝트에서 SolidQueue를 실험해봤음  
  결론은, **Sidekiq에 문제가 없다면 굳이 바꿀 이유가 없음**  
  Redis 인프라를 없애고 싶을 때만 고려할 만함  
  새 프로젝트라면 GoodJob 쪽이 더 성숙하고 커뮤니티도 좋음  
  SolidQueue는 **UI가 너무 단순**해서 불편했음. 인덱스 최적화가 안 되어 데이터가 많아지면 페이지가 멈췄음  
  RDBMS를 쓰면 **커넥션 풀 관리 비용**이 추가된다는 점도 고려해야 함  

- 확장성 걱정하는 사람들을 위해, Elixir의 [Oban](https://oban.pro/articles/one-million-jobs-a-minute-with-oban) 벤치마크를 보면  
  단일 노드에서 분당 백만 개의 작업을 처리함. 대부분의 앱은 그보다 훨씬 적은 작업량임  
  - 우리 회사도 Oban을 쓰는데, Oban은 **Redis를 notifier로 사용**하거나 폴링을 권장함 ([scaling 문서](https://hexdocs.pm/oban/scaling.html))  
  - 하지만 그 벤치마크는 실제 앱과는 거리가 큼  
    5000개 작업을 한 번에 배치로 넣는 구조라 TPS는 실제로 200 정도임  
    배치 없이 개별 작업을 넣으면 **SQL 트랜잭션 부하**가 훨씬 커짐  

- 우리는 SolidQueue 이전부터 **DB에 작업을 저장**해왔음  
  장점은 프로덕션 상태를 그대로 개발 환경으로 **스냅샷**할 수 있다는 점임  
  다만 **rate limiter**는 Redis에 두고 있음. DB 부하 방지를 위해서임  

- DB 기반 큐의 한계는 **대용량 payload**임  
  큰 JSON을 큐에 넣으면 DB 쓰기 오버헤드로 비효율적임  
  Redis(Sidekiq)가 이런 경우 훨씬 빠름  
  SolidQueue+SQLite는 단순히 **primary key 전달용**으로는 괜찮음  
  하지만 다수의 워커가 같은 DB를 폴링하면 금방 병목이 생김  
  - 실제로는 작업 파라미터를 **ID 한두 개만** 전달하는 게 일반적임. 그 이상은 비효율적임  
  - Redis도 메모리 한계 때문에 큰 payload에는 부적합함  
    큰 데이터는 **S3 같은 외부 스토리지**에 두고 참조만 전달하는 게 낫다고 생각함  
  - 어차피 시스템의 다른 부분에서도 스토리지가 필요하니, S3나 garage 같은 **임시 저장소**를 쓰는 게 현실적임  
    혹시 벤치마크 결과를 정리한 자료가 있는지 궁금함  
  - Sidekiq 문서에서도 **식별자만 전달**하라고 권장함  
  - Redis에 큰 payload를 저장하는 건 **나쁜 관행**임. 메모리가 한정되어 있기 때문임  

- SolidQueue에서 **SKIP LOCKED**를 언급하지만, 15분짜리 작업을 트랜잭션으로 유지하는 건 위험함  
  장시간 열린 트랜잭션은 DB 성능을 망치고, 네트워크 끊김에도 취약함  
  이런 구조는 **안티패턴**으로 이어질 수 있음. 나중에 보니 lease 방식인 듯함  

- [Postgres for everything](https://www.amazingcto.com/postgres-for-everything/) 철학에 공감함  
  단순하게 **PostgreSQL 하나로 통합**하는 게 좋다고 생각함  
  - 나도 PG 올인 아이디어를 좋아하지만, “망치만 있으면 모든 게 못처럼 보인다”는 말을 자주 듣음  
    이 비유에 어떻게 반박해야 할지 모르겠음  
  - 요즘은 **NVMe 스토리지**가 너무 빨라서 Redis의 이점이 줄었다고 느낌  
    복잡성을 늘리면서까지 Redis를 쓸 이유가 있을까 싶음  

- “1ms 미만의 **지연 시간**이 중요한 비즈니스”라니, Rails로 HFT를 한다는 말인가?  
  - 물론 아님. 그 회사는 [SimpleThread 사례](https://www.simplethread.com/case-studies/)를 보면 HFT와는 거리가 멂  
  - 거래 엔진은 Rails로 안 돌겠지만, **거래 모니터링 UI**는 Rails로 만들 수도 있음  

- **Postgres가 세상을 먹을 것임**  
  - 나도 동의함. 언젠가 **pg_kernel 확장**이 나오면 Linux를 지워버릴지도 모름  
  - 하지만 몇 년 뒤엔 “Postgres for everything”도 “MongoDB for everything”처럼 **과한 유행**이었다는 걸 깨달을 수도 있음  
  - 그래도 MySQL은 유지보수도 쉽고 **성능도 준수**함 (나는 Postgres 유저임에도 그렇게 느낌)  
  - 지금은 PGQM과 PG_CRON을 쓰는데, 예전의 **MySQL + Redis + AWS 조합**보다 훨씬 깔끔함  
  - 결국 중요한 건 **기능 세트**임. RDBMS가 세상을 먹을 것임
