📦

변수와 타입 — Ruby의 동적 타이핑이 그리워지는 순간

duck typing이 사라진 세계에서 살아남기

Ruby에서 변수를 만들 때 타입을 신경 쓴 적이 있는가? 없다. name = "hello"하면 알아서 String이다. name = 42로 바꿔도 아무도 뭐라 안 한다. 런타임이 알아서 처리한다.

Go는 다르다. var name string = "hello" — 타입을 명시한다. 짧게 쓰면 name := "hello"인데, 이래도 Go 컴파일러가 타입을 추론해서 고정한다. 한번 string이면 영원히 string이다. name = 42 하면 컴파일 에러.

:= 가 Ruby의 = 과 다른 점

Ruby의 =는 아무 값이나 재할당 가능하다. Go의 :=는 선언+초기화를 한 번에 하지만, 이후 타입이 바뀔 수 없다. Ruby에서 x = []; x = {}가 되는 건 Go에서는 불가능하다.

제로값(Zero Value) — nil 대신

Ruby에서 초기화 안 한 변수는 nil이다. Go에서는 타입별 제로값이 정해져 있다. int는 0, string은 "", bool은 false, 포인터는 nil. Ruby의 nil 하나로 통일되는 세계가 오히려 단순해 보일 수 있다.

타입 변환이 자동이 아니다

Ruby에서 "count: " + 42.to_s.to_s 붙이면 된다. Go에서는 "count: " + strconv.Itoa(42) — 명시적 변환 필수. int와 float64 사이도 자동 변환 안 된다. var a int = 1; var b float64 = float64(a) 이렇게 해야 한다.

귀찮은가? 귀찮다. 근데 Ruby에서 "5" + 3이 TypeError 나는 걸 프로덕션에서 겪어본 사람은 Go의 엄격함이 오히려 편하게 느껴질 거다.

Ruby에서 Go로

1

Ruby: 동적 타이핑, 변수에 아무 값이나 재할당 가능 → Go: 정적 타이핑, 한번 정한 타입은 변경 불가

2

Ruby: nil 하나로 통일 → Go: 타입별 제로값 (int=0, string="", bool=false)

3

Ruby: .to_s, .to_i로 간편 변환 → Go: strconv 패키지로 명시적 변환 필수

4

:= 는 선언+초기화 단축. 함수 안에서만 사용 가능 (패키지 레벨은 var 필수)

장점

  • 컴파일 타임에 타입 에러를 전부 잡아준다 — Ruby의 "프로덕션에서 발견" 패턴이 사라짐
  • := 단축 문법으로 타입 명시 없이도 사용 가능 — 생각보다 덜 귀찮다

단점

  • 타입 변환이 전부 명시적 — Ruby의 .to_s 한 방에 비하면 코드가 길어진다
  • Generic이 1.18에서야 추가됨 — 타입 시스템이 성숙하지 않은 부분이 있다

사용 사례

Ruby의 동적 타이핑에서 발생하는 런타임 타입 에러를 컴파일 타임에 잡고 싶을 때 JSON API 응답의 타입을 struct로 명시하여 안전하게 파싱하고 싶을 때