Ruby Silver(루비 어소시에이션 인증 루비 프로그래머 실버)는 Ruby의 핵심 문법과 객체 지향 기초를 검증하는 공식 자격 시험입니다. 이 글은 출제 범위 전체를 코드 예제 중심으로 해설하고, 하단의 실전 문제 위젯으로 즉시 점검할 수 있도록 구성했습니다.
Ruby Silver 시험 개요
Ruby Silver는 선택지형 객관식 시험으로, 코드를 직접 작성하지 않습니다. 주어진 코드 스니펫의 실행 결과를 정확히 예측하거나, 특정 동작을 설명하는 문장을 고르는 방식입니다. 암기보다 "왜 그 결과가 나오는지" 이해가 핵심입니다.
1. 변수 타입과 스코프
Ruby에는 4가지 변수 타입이 있으며, 접두어로 구분합니다.
name— 지역 변수(local): 소문자 또는_시작, 현재 스코프에서만 유효@name— 인스턴스 변수: 해당 객체 안에서 공유, 초기화 전엔nil@@count— 클래스 변수: 클래스와 모든 인스턴스가 공유$var— 전역 변수: 어디서나 접근 가능, 남용 시 예측 어려운 버그 유발CONST— 상수: 대문자 시작, 재할당 시 경고 발생
def)는 새로운 스코프를 만들어 외부 지역 변수에 접근할 수 없지만, 블록(block)은 바깥 스코프의 지역 변수를 그대로 공유합니다.
x = 10
3.times { x += 1 } # 블록 → 외부 x 공유
puts x # => 13
def test
puts x # => NameError: undefined local variable (메서드는 새 스코프)
end
2. truthy와 falsy — Ruby의 가장 유명한 함정
Ruby에서 falsy 값은 false와 nil 단 두 가지입니다. 다른 언어와의 가장 큰 차이점으로, 시험에서 반드시 출제됩니다.
# 모두 truthy!
if 0 then puts "0 is truthy" end
if "" then puts "'' is truthy" end
if [] then puts "[] is truthy" end
if {} then puts "{} is truthy" end
# falsy
if nil then puts "never" end
if false then puts "never" end
JavaScript의 0, Python의 빈 컨테이너 등이 falsy인 것과 정반대라는 점을 기억하세요.
3. 문자열: 큰따옴표 vs 작은따옴표
문자열 보간(#{...})과 이스케이프 시퀀스(\n, \t)는 큰따옴표(") 문자열에서만 동작합니다.
name = "Ruby"
puts "Hello, #{name}!" # => Hello, Ruby!
puts 'Hello, #{name}!' # => Hello, #{name}! ← 보간 안 됨
puts "탭:\t끝" # => 탭: 끝
puts '탭:\t끝' # => 탭:\t끝 ← 이스케이프 안 됨
4. 컬렉션: Array, Hash, Range
주요 Enumerable 메서드 반환값 비교
arr = [1, 2, 3, 4, 5]
arr.each { |n| n * 2 } # => [1,2,3,4,5] 원본 반환
arr.map { |n| n * 2 } # => [2,4,6,8,10] 새 배열 반환
arr.select { |n| n > 3 } # => [4,5] 조건 참 요소
arr.reject { |n| n > 3 } # => [1,2,3] 조건 거짓 요소
arr.find { |n| n > 3 } # => 4 첫 매칭 요소 (없으면 nil)
arr.inject(0) { |sum, n| sum + n } # => 15 누적 계산
Hash 기본 조작
h = { name: "Alice", age: 30 }
h[:name] # => "Alice"
h[:missing] # => nil
h.fetch(:missing) # => KeyError 발생 (명시적 에러 처리)
h.fetch(:missing, "default") # => "default"
# 심볼 키와 문자열 키는 다름!
h[:name] # => "Alice"
h["name"] # => nil ← 다른 키로 취급
5. 블록(Block), Proc, lambda
블록은 메서드에 넘길 수 있는 코드 덩어리입니다. yield로 실행하고, block_given?으로 전달 여부를 확인합니다.
def greet(name)
if block_given?
yield name
else
"Hello, #{name}"
end
end
greet("Ruby") # => "Hello, Ruby"
greet("Ruby") { |n| n.upcase } # => "RUBY"
| Proc | lambda | |
|---|---|---|
| 인자 검사 | 느슨 (부족해도 nil) | 엄격 (ArgumentError) |
| return 동작 | 외부 메서드 탈출 | 람다 내부 종료만 |
| 생성 문법 | Proc.new { } | ->(x) { } |
6. OOP 기초: 클래스, 상속, 모듈
class Animal
attr_accessor :name # getter + setter 자동 생성
def initialize(name)
@name = name # 인스턴스 변수
end
def speak
"..."
end
end
class Dog < Animal # 상속
def speak
"Woof! I'm #{@name}"
end
end
module Swimmable
def swim
"#{name} is swimming"
end
end
Dog.include(Swimmable)
d = Dog.new("Rex")
d.speak # => "Woof! I'm Rex"
d.swim # => "Rex is swimming"
메서드 접근 제어자는 코드 위치(선언 위치 이후 메서드에 적용)에 주의하세요.
- public: 어디서나 수신 객체를 붙여 호출 가능 (기본값)
- private: 명시적 수신자 없이
self로만 호출 가능 (클래스 외부 불가) - protected: 같은 클래스 계열 객체끼리 수신 객체를 붙여 호출 가능
7. 예외 처리
begin
raise ArgumentError, "잘못된 인자"
rescue ArgumentError => e
puts "ArgumentError 잡힘: #{e.message}"
rescue StandardError => e
puts "일반 오류: #{e.message}" # 위에서 이미 잡혀 여기 오지 않음
ensure
puts "항상 실행" # 예외 유무 무관
end
ensure 안에 명시적 return을 쓰면 begin의 반환값을 덮어쓰는 함정이 있습니다.
학습 전략
- 코드를 보면 먼저 "이 스코프에서 어떤 변수가 보이는가"를 확인하세요.
- truthy/falsy 문제는 nil과 false만 falsy라는 규칙을 체화하세요.
- 메서드 반환값은 마지막 식 —
return을 생략해도 됩니다. - 틀린 문항은 "왜 오답이었는지" 1문장으로 오답 노트에 남기세요.
- 시험 3일 전에는 새 문제보다 오답 노트 2회전에 집중하세요.
실전 문제 풀기
아래 위젯에서 실제 시험과 동일한 코드 기반 객관식 문제를 풀어볼 수 있습니다. 각 문제는 정답 선택 후 상세 해설을 확인할 수 있으며, 앞으로 계속 추가될 예정입니다.