싱글턴 깨기: Ruby 싱글턴 인스턴스를 다시 로드하는 방법

Breaking the Singleton: How to Reload Ruby Singleton Instance

작성자
발행일
2025년 07월 04일

핵심 요약

  • 1 Ruby의 Singleton 패턴은 애플리케이션 수명 주기 동안 단 하나의 인스턴스만 보장하지만, 특정 상황에서 인스턴스 재설정이 필요할 수 있습니다.
  • 2 테스트 환경에서 Singleton 인스턴스의 상태가 전체 테스트 스위트에 영향을 미치는 문제를 해결하기 위해 `Singleton.__init__` 메서드를 활용하여 인스턴스를 초기화할 수 있습니다.
  • 3 `Singleton.__init__(MyClass)`는 기존 싱글턴 인스턴스를 재설정하여 새 인스턴스를 생성하게 하며, `MyClass.clone`은 새로운 익명 싱글턴 클래스를 반환하여 상태를 분리합니다.

도입

Ruby의 `Singleton` 모듈은 애플리케이션 수명 주기 동안 특정 클래스의 단일 인스턴스만 존재하도록 보장하는 디자인 패턴을 구현합니다. 이는 설정, 로깅, 또는 전역 클라이언트 등에 활용됩니다. `new` 및 `allocate` 메서드를 숨기고 `clone`, `dup`을 제한하여 단일 인스턴스를 유지합니다. `instance` 메서드 첫 호출 시 인스턴스가 생성되어 저장되며, 이후 동일한 인스턴스를 반환합니다. 하지만 특정 상황에서 이 단일 인스턴스를 재설정해야 할 필요가 생길 수 있습니다.

작성자는 Rails 애플리케이션에서 Singleton 패턴을 사용하는 클라이언트 라이브러리 마이그레이션 중 테스트 환경에서 Singleton 인스턴스 상태 관리 문제에 직면했습니다. 전체 테스트 스위트 실행 시, 첫 번째 테스트에서 설정된 Singleton 인스턴스의 상태가 이후 모든 테스트에 전파되어 예측 불가능한 결과를 초래했습니다. 이 문제를 해결하기 위해 Ruby Singleton 모듈의 소스 코드를 분석했고, 비공개 메서드인 __init__를 발견했습니다.

Singleton.__init__를 이용한 인스턴스 재설정

Singleton.__init__(클래스명) 메서드는 해당 Singleton 클래스의 인스턴스를 nil로 설정하고 새로운 뮤텍스를 생성하여 스레드 안전성을 유지하며 클래스 상태를 재설정합니다. 이 메서드를 호출하면 다음 instance 호출 시 완전히 새로운 Singleton 인스턴스가 생성됩니다.

작성자는 이 기법을 활용하여 Rails.env를 스텁하고 테스트 전후로 Singleton 인스턴스를 재설정함으로써, 각 테스트가 독립적인 환경에서 실행되도록 했습니다. RSpec 테스트 코드 예시는 다음과 같습니다.

ruby RSpec.describe "Clients migration" do before { setup_env('production') } after { setup_env('test') } it 'generates the correct URL for client instance' do # ... end def setup_env(env) Rails.env = env Singleton.__init__(MyClient) Singleton.__init__(AnotherClient) # ... end end

clone 메서드의 다른 동작

Singleton 모듈의 클래스 레벨 clone 메서드는 내부적으로 __init__를 호출하지만, 기존 Singleton 클래스를 재설정하는 대신 새로운 익명 Singleton 클래스를 반환합니다. 이는 기존 인스턴스에 영향을 주지 않고 독립적인 상태를 가진 새로운 Singleton 인스턴스를 얻고자 할 때 유용합니다. Timer 클래스 예시는 다음과 같습니다.

ruby class Timer include Singleton attr_reader :timestamp def initialize @timestamp = Time.now end end Timer.instance.timestamp Timer.clone.instance.timestamp Singleton.__init__(Timer).instance.timestamp 이러한 방법들을 통해 Singleton 인스턴스의 상태를 효과적으로 관리하고 테스트의 독립성을 확보할 수 있습니다.

결론

Ruby의 Singleton 패턴은 유용하지만, 테스트 환경에서 인스턴스 상태 재설정 필요성이 종종 발생합니다. 본문은 `Singleton` 모듈의 비공개 `__init__` 메서드를 활용하여 기존 Singleton 인스턴스를 효과적으로 재설정하는 방법을 제시했습니다. 더불어 `clone` 클래스 메서드가 기존 인스턴스 재설정 대신 새로운 익명 Singleton 클래스를 생성하여 상태를 분리하는 대안적 동작을 설명했습니다. 이러한 기법들은 Singleton 인스턴스의 예측 가능한 동작을 보장하고, 복잡한 테스트 스위트에서 발생할 수 있는 상태 의존성 문제를 해결하는 데 핵심적입니다.

댓글 0

로그인이 필요합니다

댓글을 작성하거나 대화에 참여하려면 로그인이 필요합니다.

로그인 하러 가기

아직 댓글이 없습니다

첫 번째 댓글을 작성해보세요!