Resque에서 Solid Queue로의 전환 배경
37signals 팀이 Resque에서 Solid Queue로 전환하게 된 주된 이유는 Resque 설정의 복잡성이었습니다. 수년간 Resque를 사용하면서 여러 사용자 정의 코드, 포크된 젬, 그리고 다양한 문제를 해결하기 위한 복잡한 설정이 축적되었습니다. 특히 새로운 애플리케이션에 작업을 설정하려 했을 때, 기존 시스템의 복잡성을 인지하고 ActiveJob의 기능을 활용하며 데이터베이스를 백엔드로 사용하는 더 간단한 시스템의 필요성을 느꼈습니다. 이는 David Heinemeier Hansson의 제안에 따라 Solid Queue 개발로 이어졌습니다.
Solid Queue의 설계 및 마이그레이션
Solid Queue는 Resque 사용 중 직면했던 모든 요구사항과 문제점을 염두에 두고 설계되었습니다. 특히 Redis 대신 데이터베이스를 백엔드로 사용하여 트랜잭션 무결성을 확보하고 ActiveJob의 리트라이, 오류 처리, 직렬화와 같은 내장 기능을 활용하는 데 중점을 두었습니다. 초기에는 애플리케이션과 동일한 데이터베이스를 공유하는 방식으로 시작했으나, 쓰기 부하 문제로 인해 결국 별도의 데이터베이스를 사용하는 것으로 변경되었습니다. 이는 Solid Queue의 현재 기본 권장 사항이 되었습니다.
마이그레이션은 기존 애플리케이션인 Hey.com에서 시작되었습니다. 이는 새로운 애플리케이션에서 시작하는 것보다 실제 환경에서의 문제점과 작업 볼륨을 더 잘 파악할 수 있기 때문입니다. ActiveJob의 queue_adapter
기능을 활용하여 사용자에게 영향이 적은 작업부터 Solid Queue로 점진적으로 전환했습니다. 예를 들어, 데이터 영구 삭제와 같은 작업은 지연되어도 큰 문제가 없으므로 우선적으로 마이그레이션되었습니다. Kamal로의 마이그레이션과 겹쳐 작업이 일시 중단되기도 했지만, Kamal 덕분에 Resque와 Solid Queue를 동시에 실행하는 것이 매우 간단해졌습니다. 미래에 예약된 작업들은 수동으로 Solid Queue로 옮겨졌으며, 이는 Resque의 API를 통해 작업을 추출하고 Solid Queue에 대량으로 삽입하는 방식으로 이루어졌습니다.
디버깅 및 작업 패턴
Solid Queue의 가장 큰 장점 중 하나는 작업 상태(대기 중, 예약됨, 실행 중, 실패)의 투명성입니다. 모든 작업 상태가 데이터베이스에 저장되므로 Mission Control과 같은 도구를 통해 쉽게 디버깅하고 모니터링할 수 있습니다. 이는 Redis 기반 시스템에서 특정 클래스의 작업을 검색하기 어려운 Resque와 비교할 때 훨씬 간편합니다.
작업 패턴에 있어서 37signals 팀은 가능한 한 작업을 작고 독립적으로 유지하는 것을 선호합니다. 이는 오류 발생 시 재시도 및 문제 해결을 용이하게 합니다. 작업 시스템을 오케스트레이터로 사용하는 것을 피하고, 대신 코드 내에서 비즈니스 로직을 관리하며 단일 작업이 많은 작업을 처리하는 경우에도 재개 가능한 형태로 구현하는 것을 선호합니다. 재시도 및 실패 처리는 ActiveJob의 기능을 활용하며, 수동 개입이 필요한 경우 Mission Control을 사용합니다.
반복적인 작업(예: 매일 보고서 생성 또는 데이터 삭제)의 경우, 팀은 Unix Cron과 유사한 Solid Queue의 내장 반복 작업 기능을 선호합니다. 이는 작업이 스스로 다음 실행을 예약하는 방식보다 훨씬 안정적이며, 특정 시점에 작업이 누락되더라도 다음 실행 시 처리될 수 있도록 보장합니다. 또한, 장기 실행 작업(예: 데이터 내보내기)의 경우, Kamal 배포 중 중단될 수 있으므로, 작업 상태를 데이터베이스에 저장하고 특정 서버에 작업을 고정하여 중단된 지점부터 재개할 수 있도록 구현했습니다.
테스트 및 코드 관리
37signals 팀은 배경 작업 테스트에 대해 독특한 접근 방식을 가지고 있습니다. 작업 자체에는 거의 비즈니스 로직을 포함하지 않고, 모든 로직을 모델에 넣어 모델에서 테스트합니다. ActiveJob이 제공하는 헬퍼를 사용하여 작업이 올바른 인수로 대기열에 추가되었는지, 지연이 예상대로 적용되었는지 등을 확인합니다. 또한 Stephen Marihain의 Acidic Job 및 Chaotic Job과 같은 젬을 통해 다양한 시나리오를 시뮬레이션하고 무작위 오류를 주입하여 작업을 테스트하는 가능성을 언급했습니다.
코드 관리 측면에서 팀은 사용되지 않는 코드를 적극적으로 삭제하는 경향이 있습니다. 특히 Resque에서 Solid Queue로의 마이그레이션 후 Resque 관련 코드를 완전히 제거한 것은 큰 만족감을 주었습니다. 이는 프로젝트의 히스토리에 기록되어 필요할 경우 참조할 수 있도록 합니다. 이는 불필요한 코드가 애플리케이션의 복잡성을 증가시키고 유지보수를 어렵게 만든다는 믿음에 기반합니다.