학습
Ruby 블록과 프로시저 (Blocks and Procs)
Ruby 블록과 프로시저 (Blocks and Procs) — 초급
블록과 프로시저 (Blocks and Procs)
1. 도입 (왜 배워야 하는가)
루비에서 블록과 프로시저는 매우 중요한 개념입니다. 이 두 가지는 코드의 재사용성과 가독성을 높여주며, 특히 콜백(callback)이나 이벤트 기반 프로그래밍을 할 때 유용합니다. 현업에서는 데이터 처리나 비동기 작업에서 이러한 기능이 자주 사용됩니다. 예를 들어, 쇼핑몰에서 사용자가 장바구니에 상품을 추가할 때마다 특정 작업(예: 총 가격 계산)을 자동으로 수행해야 할 때 블록이나 프로시저를 사용하면 코드가 더욱 효율적이고 깨끗해집니다.
블록과 프로시저를 모르면 코드를 중복해서 작성하게 되고, 이는 유지보수의 어려움으로 이어집니다. 따라서 이 개념을 이해하고 활용하는 것은 프로그래밍 실력을 높이는 데 필수적입니다.
2. 핵심 개념 설명
- 블록 (Block): 루비에서 블록은 코드의 집합으로, 메서드에 인자로 전달되어 실행됩니다. 블록은
{}또는do...end로 정의됩니다. - 프로시저 (Proc): 프로시저는 블록을 객체로 만들어 저장할 수 있게 해주는 클래스입니다. 블록을 프로시저로 변환하면 나중에 재사용할 수 있습니다.
비유하자면, 블록은 요리의 레시피와 같습니다. 요리사가 레시피를 보고 요리를 하듯이, 메서드는 블록을 보고 특정 작업을 수행합니다. 반면 프로시저는 미리 만들어 놓은 요리입니다. 언제든지 꺼내 먹을 수 있는 거죠.
| 용어 | 설명 |
|---|---|
| 블록 | 메서드에 전달되는 코드의 집합 |
| 프로시저 | 블록을 객체로 만들어 재사용 가능하게 한 것 |
3. 기본 코드 예제
블록을 사용하는 간단한 예제입니다.
def greet(&block)
puts "안녕하세요!"
block.call if block_given?
end
greet { puts "반갑습니다!" }
실행 결과
안녕하세요!
반갑습니다!
def greet(&block): greet라는 메서드를 정의하고, 블록을 인자로 받기 위해 &block을 사용합니다.puts "안녕하세요!": 메서드가 호출되면 먼저 "안녕하세요!"를 출력합니다.block.call if block_given?: 블록이 주어졌을 경우, block.call로 블록을 실행합니다.greet { puts "반갑습니다!" }: greet 메서드를 호출하며 블록을 전달합니다. 블록 안의 코드는 block.call에 의해 실행됩니다.4. 실전 활용 예제
- 장바구니 총 가격 계산: 쇼핑몰에서 사용자가 장바구니에 상품을 추가할 때마다 총 가격을 계산할 수 있습니다.
- 비동기 작업 처리: 웹 애플리케이션에서 비동기 요청 후 특정 작업을 수행할 수 있습니다.
- 블록의 유효성 검사: 블록을 호출하기 전에
block_given?으로 블록이 전달되었는지 확인해야 합니다. 그렇지 않으면 에러가 발생합니다. - 프로시저를 잊지 않기: 프로시저를 잘못 사용하면 의도한 대로 동작하지 않을 수 있습니다. 프로시저를 정의하고 사용 시에는 항상
Proc.new혹은proc을 사용하여 정의해야 합니다. - 블록은 메서드에 전달되는 코드의 집합이며, 프로시저는 블록을 객체로 만들어 재사용할 수 있게 해줍니다.
- 블록과 프로시저를 사용하면 코드의 재사용성과 가독성을 높일 수 있습니다.
- 블록 사용 시
block_given?으로 블록의 유효성을 검사하는 것이 중요합니다. - 다음에 학습하면 좋은 주제는 "람다(lambda)"와 "고급 블록 패턴"입니다.
class ShoppingCart
def initialize
@items = []
end
def add_item(item, &block)
@items << item
block.call(@items) if block_given?
end
def total_price
@items.sum
end
end
cart = ShoppingCart.new
cart.add_item(100) { |items| puts "현재 장바구니: #{items}, 총 가격: #{cart.total_price}" }
cart.add_item(200) { |items| puts "현재 장바구니: #{items}, 총 가격: #{cart.total_price}" }
실행 결과
현재 장바구니: [100], 총 가격: 100
현재 장바구니: [100, 200], 총 가격: 300
def fetch_data(&block)
puts "데이터를 가져오는 중..."
sleep(2) # 데이터 가져오는 시간 시뮬레이션
block.call("데이터 수신 완료!") if block_given?
end
fetch_data { |result| puts result }
실행 결과
데이터를 가져오는 중...
(2초 대기)
데이터 수신 완료!
5. 흔한 실수와 주의사항
# 잘못된 코드
def greet
puts "안녕하세요!"
block.call # 에러 발생
end
# 올바른 코드
def greet(&block)
puts "안녕하세요!"
block.call if block_given? # 블록이 있을 때만 호출
end
# 잘못된 코드
my_proc = proc { puts "Hello" }
my_proc.call # 정상 동작
# 올바른 코드
my_proc = Proc.new { puts "Hello" }
my_proc.call # 정상 동작