Files
ruby-examples/docs/03_메서드와 블록.md

5.3 KiB

Ruby 메서드와 블록

Ruby는 간결하고 유연한 문법을 제공하는 언어로, 메서드와 블록을 활용하면 가독성이 뛰어나고 재사용 가능한 코드를 작성할 수 있다. 이번 글에서는 메서드블록을 중심으로 설명하겠다.


1. Ruby 메서드(Method)

Ruby에서 메서드는 특정 동작을 수행하는 코드의 묶음이다. 다른 프로그래밍 언어에서 함수(function)와 비슷하지만, Ruby에서는 모든 것이 객체이므로 메서드 역시 객체에 속한다.

1.1. 메서드 정의와 호출

메서드는 def 키워드를 사용하여 정의하며, end로 닫는다.

def say_hello
  puts "Hello, Ruby!"
end

say_hello  # 메서드 호출

매개변수가 있는 메서드

def greet(name)
  puts "안녕하세요, #{name}님!"
end

greet("Alice")  # "안녕하세요, Alice님!"

기본값을 갖는 매개변수

def greet(name = "Ruby")
  puts "안녕하세요, #{name}님!"
end

greet  # "안녕하세요, Ruby님!"
greet("Alice")  # "안녕하세요, Alice님!"

여러 개의 인수 받기 (가변 인수, splat 연산자 *)

def sum(*numbers)
  numbers.sum
end

puts sum(1, 2, 3, 4, 5)  # 15
puts sum(10, 20, 30)  # 60

*numbers는 가변 길이의 인수를 배열로 변환하여 처리한다.


1.2. 반환값(Return Value)

Ruby의 메서드는 기본적으로 마지막 실행된 표현식의 결과를 반환한다.

def add(a, b)
  a + b  # 마지막 줄이 반환값
end

puts add(3, 7)  # 10

return 키워드를 사용하면 명시적으로 값을 반환할 수 있다.

def add(a, b)
  return a + b
end

하지만, Ruby에서는 return을 생략하는 것이 일반적이다.


1.3. 키워드 인수(Keyword Arguments)

Ruby 2.0부터 키워드 인수를 지원하여 가독성이 높아졌다.

def introduce(name:, age:)
  puts "이름: #{name}, 나이: #{age}"
end

introduce(name: "Alice", age: 25)

기본값을 설정할 수도 있다.

def introduce(name: "홍길동", age: 20)
  puts "이름: #{name}, 나이: #{age}"
end

introduce  # "이름: 홍길동, 나이: 20"
introduce(name: "Bob")  # "이름: Bob, 나이: 20"

2. 블록(Block)과 반복문

블록은 {} 또는 do...end로 감싸는 코드 덩어리다. 특정 메서드에서 실행할 코드를 블록으로 전달할 수 있다.

3.times { puts "Ruby!" }
3.times do
  puts "Ruby!"
end

위 두 코드는 동일한 결과를 출력한다.


2.1. 블록을 사용하는 메서드

블록을 전달받는 대표적인 메서드로 each가 있다.

[1, 2, 3].each { |num| puts num }
[1, 2, 3].each do |num|
  puts num
end

2.2. 블록을 명시적으로 호출 (yield)

Ruby에서는 yield를 사용하여 블록을 실행할 수 있다.

def with_greeting
  puts "안녕하세요!"
  yield  # 블록 실행
  puts "좋은 하루 되세요!"
end

with_greeting { puts "블록 내부 실행!" }

출력 결과:

안녕하세요!
블록 내부 실행!
좋은 하루 되세요!

블록에 값 전달

def twice
  yield 1
  yield 2
end

twice { |num| puts "숫자: #{num}" }

출력 결과:

숫자: 1
숫자: 2

2.3. 블록을 매개변수로 받기 (&block)

블록을 명시적으로 매개변수로 받으려면 &block을 사용한다.

def repeat(n, &block)
  n.times { block.call }
end

repeat(3) { puts "블록 실행!" }

출력 결과:

블록 실행!
블록 실행!
블록 실행!

블록이 주어지지 않은 경우의 예외 처리는 block_given?을 사용한다.

def optional_block
  if block_given?
    yield
  else
    puts "블록이 없습니다!"
  end
end

optional_block  # "블록이 없습니다!"
optional_block { puts "블록이 실행됨!" }

2.4. ProcLambda

Ruby에서는 블록을 Proc 또는 Lambda 객체로 저장할 수도 있다.

Proc 객체

say_hello = Proc.new { puts "Hello!" }
say_hello.call  # "Hello!"

Lambda 객체

greet = ->(name) { puts "안녕하세요, #{name}님!" }
greet.call("Alice")

ProcLambda의 차이점은 return 동작 방식과 매개변수 처리 방식에 있다.

def test_proc
  p = Proc.new { return "Proc 리턴" }
  p.call
  "메서드 종료"
end

puts test_proc  # "Proc 리턴" (Proc의 return이 메서드까지 종료)

def test_lambda
  l = -> { return "Lambda 리턴" }
  l.call
  "메서드 종료"
end

puts test_lambda  # "메서드 종료" (Lambda의 return은 람다 내부만 종료)

3. 마무리

Ruby에서 메서드와 블록을 활용하면 가독성과 재사용성이 높은 코드를 작성할 수 있다.

  • 메서드def로 정의하며, 매개변수를 가질 수 있다.
  • 블록{} 또는 do...end로 감싸며, yield 또는 &block을 사용해 실행할 수 있다.
  • Proc과 Lambda를 사용하면 블록을 객체로 다룰 수 있다.

이제 Ruby의 메서드와 블록을 활용하여 더 유연한 프로그램을 만들어보자!