Shim Won

January 22, 2015 4:5 pm

번역 루비에 블록이 있는 이유

루비의 블록은 대부분의 뉴비에게 언어를 배울면서 가장 큰 장애물이 되기 쉽습니다. 다른언어에서 몇년의 경험이 있다고 해도, 그 컨샙은 처음엔 알기 어려운 것일 수 있죠.

제 의견입니다만, 블록이 이해하기 어려운 것은 설명 방식의 문제일 수도 있습니다. Parley에 쓰인 글에서 시작된 이 글에서는 다른 언어에서 사용했던 실용적인 요약(pragmatic shortcut)처럼 블록에 대해 설명하려고 합니다.

루비는 다른 언어처럼, 넘길수 있고 실행할 수 있는 작은 익명 코드를 만들 수 있습니다. 이걸 표현하는 방법은 많습니다만, 이 글의 목적을 위해 한가지 방법(proc)만 있다고 가정합시다.

code = proc do |name|
  puts "hello, #{name}"
end
code.call("Avdi")
# >> hello, Avdi

proc은 데이터 대신 행동을 메소드에 넘길 수 있게 하기에 편리합니다.

(익숙한 걸로..)예를 들어 파일을 열 때, 파일이 열린 동안 실행 될 코드를 proc으로 넘길 수 있습니다. 그리고 proc이 끝나면 파일이 자동으로 닫히게 될 겁니다.

code = proc do
  # ...
end
open("myfile", "w", :while_open_do => code)

proc의 형태로 메소드에 전달한 이 행동은 대부분 일회성 코드입니다. 로컬 변수에 할당할 이유가 없죠. 그래서 대게, 밑에 보이는 것 처럼 묶어서 넘기게 됩니다.

open("myfile", "w", :while_open_do => proc do
  # ...
end)

데이터 인자 처럼, 행동 인자를 사용하는 메소드를 좀 더 만들다보면, 이런걸 깨닫게 됩니다. 90%의 경우, 메소드는 하나의 행동 인자만 받습니다.

작은 메소드에는 단일 책임(외부에서 파악하기 위해 하나의 행동만을 해야한다)의 원칙이 있습니다.^1

그래서 관례(convention)를 사용하기 시작합니다. 메소드가 행동을 파라메터화 할 필요가 있을때는 항상 끝에 인자를 “block of code”나 “block”으로 만들어 줄입시다.

def open(filename, mode, block)
  # ...
end
open("myfile", "w", proc do
  # ...
end)

이는 매우 일반적인 경우에 우리의 코드를 훨씬 간결하게 합니다. 하지만, 이 이야기는 아직 끝나지 않았는데, 조금 이견이 있기 때문입니다.

  1. 이제 어디서든 proc 키워드를 보게 됩니다. 조금 눈에 거슬리기 시작하죠.
  2. 이제 인수로 행동을 전달해, 새로운 언어 구조처럼 보이게 할 수 있다는걸 깨닫게 됩니다. 하지만, 때문에 항상 proc이 있고 닫는 괄호가 끝에 있어 그리 많이 새로워 지진 않죠.

사실, 닫는 괄호는 우리가 평소에 괄호를 필요로하지 않기에 언어에서 특히 크게 거슬립니다.

“한 인자는 코드 블록”를 위한 관례를 만들기 위해 언어를 수정한다고 하면 어떻게 해야 할까요? 코드 블록을 나타내는 특수 기호를 사용할 수 있습니다. 그리고선, 인자 목록의 바로 오른쪽에 블록을 시작하게 해서, 닫기 괄호를 신경쓰지 않게 할 수 있습니다. 그리고, 언어 문법을 만드는 중이기 때문에, 지금은 특별히 proc 키워드를 없엘 수 있습니다.

def open(filename, mode, &block)
  # ...
end
open "myfile", "w" do
  # ...
end

이런, 하는 김에, 명시적으로 파라메터로 선언하지 않았어도 코드 블록을 실행하는 방법을 만들어 봅시다. yield를 “넘겼다고 가정하는 코드를 제어”를 의미하도록 사용하겠습니다.

def open(filename, mode)
  # ...
  yield
  # ...
end

이제 루비블록을 만들었습니다. 여기서 기억해야할 중요한 것은, 이건 그냥 매우 일반적인 경우(넘겨지는 파라메터 중 하나가 코드 블록인 메소드)를 위한 신텍스 슈가라는 사실입니다.

(경험많은 루비프로그레머라면, 블록이 제어 흐름에서 다른 문법적 특성이 있다는 것을 알 것입니다. 하지만 그것이 블록은 사실 단축이라는 핵심 전재를 변경하리라 생각하지 않습니다.)

마지막으로 한마디 하겠습니다. 이 글은 짧지만 이 글이 좋았다면 아마도 RubyTapas도 좋아할 겁니다. RubyTapas에서는 일주일에 커피 두잔의 값으로 루비 지식을 레벨업 시킬 수 있습니다.

1: 제가 재대로 이해 못했으니 아마도 오역일 겁니다. 원문은: There’s something about small methods with single responsibilities that causes them to only have one piece of behavior that needs to be specified from outside.