본문으로 건너뛰기

Active Record의 진화: Rails 애플리케이션의 복원력 향상

Hartley McGuire - Active Record 8: Resilient by Default

작성자
Ruby on Rails Youtube
발행일
2025년 09월 16일

핵심 요약

  • 1 Active Record는 연결 검증 및 재시도 가능한 쿼리 도입을 통해 데이터베이스 연결 오류에 대한 복원력을 지속적으로 강화해왔습니다.
  • 2 Rails 7.1부터 8.1에 이르기까지, 연결 검증 방식의 최적화와 쿼리 재시도 가능성 확장을 통해 애플리케이션의 안정성이 크게 향상되었습니다.
  • 3 특히 Rails 8.1은 내부적으로 더 많은 쿼리를 재시도 가능하게 하고 개발자가 안전한 SQL 리터럴을 명시적으로 표시할 수 있는 도구를 제공하여 역대 가장 복원력 있는 Active Record 버전을 제시합니다.

도입

Rails World에서 발표된 이 강연은 새로운 기능보다는 Rails의 '마법'과 같은 내부 컴포넌트 개선에 초점을 맞춥니다. Shopify의 Kate SQL 팀에서 근무하며 데이터베이스 오류의 중요성을 체감한 연사는, Active Record가 수년간 어떻게 발전하여 애플리케이션의 복원력을 높여왔는지 설명합니다. 특히 일시적인(transient) 데이터베이스 오류가 고객 경험에 미치는 영향을 강조하며, Rails 업그레이드가 이러한 문제를 해결하는 데 핵심적인 역할을 한다고 서론을 엽니다.

Active Record의 복원력 향상은 크게 세 가지 영역에서 이루어졌습니다.

1. 연결 검증 (Connection Verification)의 발전

  • 초기 방식 (Rails 1.1 이전): 쿼리 실행 후 실패 시에만 연결을 재설정하여, 쿼리 재시도 가능성이라는 복잡한 문제를 야기했습니다.

  • Rails 1.1 도입: 쿼리 실행 전 연결을 핑(ping)하여 검증하는 verify before checkout 패턴을 도입, 연결 오류 가능성을 현저히 줄였습니다. 이 방식은 추가적인 왕복 시간을 필요로 하지만, 안정성을 높이는 합리적인 트레이드오프로 간주되었습니다.

  • Rails 7.1의 혁신: Matthew의 대규모 리팩토링을 통해 쿼리를 재시도 가능(retriable)으로 표시하는 기능이 추가되었습니다.

    • 예시: BEGIN 트랜잭션 시작 쿼리는 안전하게 재시도 가능하므로, 초기 연결 검증 핑을 생략하여 지연 시간을 줄일 수 있게 되었습니다. 이는 복원력 향상의 중요한 기반을 마련했습니다.

2. 연결 고정 (Connection Pinning)의 변화

  • 기존 방식 (Rails 7.1까지): 한 요청 처리 스레드가 연결을 체크아웃하면, 해당 연결은 요청이 끝날 때까지 스레드에 고정(pinned)되었습니다. 이는 동일한 연결이 여러 쿼리에 사용되도록 보장했지만, 연결 풀 크기에 제약을 주었습니다.

  • Rails 7.2의 세분화된 체크아웃 (Granular Connection Checkouts): Jean은 연결이 쿼리 사용 후 바로 풀로 반환되도록 Active Record를 리팩토링했습니다.
    • 장점: 요청이 쿼리 외 다른 작업을 하는 시간이 길 경우, 필요한 총 연결 수를 줄일 수 있습니다.
    • 문제점: 각 쿼리마다 연결을 체크아웃하고 재검증하는 과정에서 불필요한 지연 시간이 발생할 수 있었습니다.
  • Rails 8.0.2의 개선: Matthew는 검증 핑이 마지막 성공적인 쿼리 이후 2초 이상 경과했을 때만 발생하도록 시간 기반 로직을 추가하여, 세분화된 체크아웃의 성능 저하를 해결하고 7.1의 효율적인 검증 동작을 복원했습니다.

3. 쿼리 재시도 가능성 (Query Retriability)의 확장

  • 재시도 기준: Active Record는 기본적으로 멱등성(idempotent)을 가지는 쿼리(여러 번 실행해도 안전한 쿼리)만 자동으로 재시도해야 합니다. SELECT 쿼리가 이에 해당하지만, 데이터베이스를 수정할 수 있는 함수나 서브쿼리를 포함할 경우 멱등성이 깨질 수 있습니다.

  • Rails 7.2의 자동 재시도 가능한 SELECT 쿼리: Adriana의 기여로, Active Record는 쿼리 빌드 과정에서 SQL literal과 같이 재시도 불가능한 요소를 감지하여 해당 쿼리를 자동으로 재시도 불가능으로 표시합니다. 이는 대부분의 SELECT 쿼리를 재시도 가능하게 하여 연결 오류로부터의 복구 가능성을 크게 높였습니다.

  • Rails 8.1의 추가 개선: 연사는 Active Record 내부적으로 사용되는 SQL literal (예: 1 as 1)이 쿼리를 재시도 불가능하게 만드는 문제를 발견했습니다.

    • 해결책: Arel.sql(sql_string, retriable: true) 옵션을 통해 개발자가 알려진 안전한(known safe) SQL 문자열에 대해 명시적으로 재시도 가능하다고 표시할 수 있게 했습니다. 이는 Rails 7.2부터 사용 가능하며, Rails 8.1에서 더욱 개선되어 기본적으로 더 많은 쿼리가 재시도 가능하도록 내부 수정이 이루어졌습니다.

결론

Rails 7.1에서 시작된 연결 검증 및 재시도 가능 쿼리 도입은 Rails 애플리케이션의 복원력 향상을 위한 강력한 기반을 마련했습니다. Rails 7.2는 세분화된 연결 체크아웃과 자동 재시도 가능한 SELECT 쿼리를 통해 이 기반을 더욱 공고히 했으며, Rails 8.0.2는 성능 회귀를 해결했습니다. 궁극적으로 Rails 8.1은 기본적으로 더 많은 쿼리를 자동으로 재시도하고, 개발자에게 재시도 불가능한 쿼리를 식별하고 수정할 수 있는 도구를 제공함으로써 역대 가장 복원력 있는 Active Record 버전을 제공합니다. 이러한 개선 사항들은 애플리케이션 코드 변경 없이 Rails 업그레이드만으로 '무료'로 제공되어, 개발자들이 더욱 안정적인 서비스를 구축할 수 있도록 돕습니다.

댓글 0

댓글 작성

댓글 삭제 시 비밀번호가 필요합니다.

이미 계정이 있으신가요? 로그인 후 댓글을 작성하세요.

0/1000
정중하고 건설적인 댓글을 작성해 주세요.