Ruby: 참조값에 의한 전달

발행: (2025년 12월 26일 오후 06:33 GMT+9)
3 min read
원문: Dev.to

Source: Dev.to

대부분의 Ruby 개발자는 흔히 “pass‑by‑reference‑value”라고 불리는 개념에 익숙합니다.
가변 객체(예: String)를 다른 변수에 할당하면 두 변수 모두 같은 객체를 참조합니다. 하나의 참조를 통해 객체를 변형하면 다른 변수에서도 그 변형이 반영됩니다.

Simple Assignment Example

var1 = "Hello, World"
var2 = var1
var2.gsub!("World", "Ruby")
puts var1   # => Hello, Ruby

Service Class Example

class DummyClass
  attr_accessor :value

  def initialize(value)
    @value = value
  end
end

dummy = DummyClass.new("Hello, World!")

puts "Before service action:"
puts dummy.value   # => Hello, World!

class ServiceClass
  def initialize(value)
    @value = value
  end

  def perform_action
    local_value = @value
    local_value.gsub!("World", "Ruby")
  end
end

ServiceClass.new(dummy.value).perform_action

puts "After service action:"
puts dummy.value   # => Hello, Ruby!

Real‑World Pitfall

실제 운영 코드베이스에서는 같은 동작이 은밀한 버그가 될 수 있습니다. 문자열 속성을 가진 ActiveRecord 모델이 템플릿 문자열 안의 플레이스홀더(예: %%BRAND%%)를 대체하는 서비스에 전달된다고 가정해 보세요:

# Hypothetical usage
Interpolator.custom_interpolate(source, brand_name)

메서드 이름 custom_interpolate는 새로운 문자열을 반환한다는 인상을 주지만, 구현이 source 객체에 gsub! 같은 변형 메서드를 사용한다면 레코드가 저장되기 전에 모델의 속성이 메모리 상에서 수정됩니다. 이러한 부수 효과는 애플리케이션 전반에 걸쳐 예상치 못한 데이터 변화를 초래할 수 있습니다.

Best Practices

  • 변형되지 않는 메서드(gsub 대신 gsub!)를 사용해 변환된 값만 필요할 때는 변형 메서드를 피합니다.

  • 입력을 복제하여 원본 객체를 보호합니다:

    def safe_interpolate(str, replacements)
      str = str.dup
      # perform non‑mutating transformations
      str.gsub!("%BRAND%", replacements[:brand])
      str
    end
  • 메서드가 의도적으로 인자를 변형한다면 부수 효과를 명확히 문서화합니다.

  • 서비스 호출 후 객체가 의도치 않게 변경되지 않았는지 테스트를 작성합니다.

변형 가능성에 대해 명시적이고 방어적인 복사를 사용하면 Ruby의 pass‑by‑reference‑value 특성으로 인한 미묘한 버그를 피할 수 있습니다.

Back to Blog

관련 글

더 보기 »

Git이란 무엇인가?

왜 Git이 필요한가? 많은 개발자에게 pendrive는 오래된 프로젝트나 파일을 저장하고 꺼내는 장소에 불과합니다. 하지만 폴더가 너무 많아지고 중복 파일이 …

애자일 | 스크럼 & 칸반 프레임워크

Agile란 무엇인가? 이전 모듈에서 Agile이라는 용어는 DevOps 문화의 핵심 측면을 설명했으며, 고객의 요구와 피드백에 빠르게 대응하는 능력을 의미했습니다. Agil...