Ruby에서 "yield"라는 단어는 정확히 무엇을 의미할까요? 그리고 실제로 어떤 역할을 할까요?
간단히 말하면…
yield는 키워드(즉, 언어의 핵심 구성 요소)로, 메서드 내부에서 블록을 호출하기 위해 사용됩니다.
꼭 알아야 할 핵심 사항은 다음과 같습니다:
- 블록을 호출하면 해당 블록 내부의 코드가 실행됩니다(메서드를 호출하는 것과 유사)
- yield는 블록에 원하는 만큼 인수를 전달할 수 있습니다
- 블록의 반환값이
yield의 반환값이 됩니다
이 내용을 제대로 이해하려면 먼저 블록 개념을 알아야 합니다.
블록은 이름 없는 메서드라고 생각하면 됩니다. 다른 메서드에 추가 인수처럼 전달할 수 있는 코드 덩어리죠.
예제를 살펴보겠습니다:
def make_salad
yield "lettuce"
yield "carrots"
yield "olive oil"
end
make_salad { |ingredient| puts "Adding #{ingredient} to salad!" }
이 코드는 블록을 3번 호출하며, 다음과 같은 출력 결과가 나옵니다:
Adding lettuce to salad! Adding carrots to salad! Adding olive oil to salad!
이것이 바로 yield의 본질입니다. 메서드를 호출하는 것과 비슷하지만, 대신 블록을 호출하는 것이죠.
블록에는 이름이 없기 때문에, 이 키워드가 그 역할을 대신해 줍니다.
자, 이제:
호출할 블록이 없는 경우에는 어떻게 되는지 살펴보겠습니다.
블록 없이 yield 호출 시 발생하는 에러
블록 없이 yield를 호출하면 에러가 발생합니다.
예제:
def write_code yield end write_code # LocalJumpError: no block given (yield)
이 에러 메시지는 아주 명확합니다. "no block given"은 write_code 메서드 호출 시 블록이 전달되지 않았다는 의미입니다.
그렇다면 이 에러를 어떻게 예방할 수 있을까요?
다음과 같이 하면 됩니다:
def write_code yield if block_given? end
block_given? 메서드는 블록이 존재하는지 확인하며, 블록이 있을 때만 yield를 실행하도록 해줍니다.
yield를 사용하는 이유
yield를 사용하면 블록 기능을 활용할 수 있습니다.
우리는 블록을 통해 메서드 호출의 일부로 코드 조각을 전달합니다.
다음과 같은 상황에서 특히 유용합니다:
- 코드 실행 시간을 측정해 로깅하는 범용 로깅 함수를 작성하고 싶을 때
- 메서드가 끝난 후 특정 코드를 실행하고 싶을 때(JavaScript의 "콜백"과 유사)
- 필요할 때만 실행되고 사용자가 커스터마이징할 수 있는 "지연 실행 코드(lazy code)"를 원할 때(예시는
Hash#fetch메서드 문서 참고)
아주 유용하죠!
yield_self – 무엇이 다를까?
yield_self라는 새로운 메서드를 보고 yield와 관련이 있다고 생각할 수 있습니다.
하지만 그렇지 않습니다.
yield(self)조차 다릅니다. 여기서 self는 현재 객체를 가리키기 때문입니다.
반면 Ruby 2.5에서 추가된 yield_self는 해당 메서드를 호출하는 객체 자체를 가리킵니다.
이 메서드의 좋은 활용 예는 무엇일까요?
메서드 체이닝을 하면서 yield_self를 호출한 객체로 무언가 작업을 수행하고 싶을 때 사용하면 됩니다.
원본 객체가 아니라 처리된 결과를 반환한다는 점이 핵심입니다.
예제:
n_squared = ->(n) { n ** 2 }
2
.yield_self(&n_squared)
.yield_self(&n_squared)
# 16
Ruby 2.6에서는 yield_self의 별칭인 then 메서드가 도입되었습니다.
하지만 일반적인 yield와 혼동해서는 안 됩니다.
알겠죠?
Rails에서의 yield 활용
Rails와 템플릿 엔진에서 yield가 사용되는 방식도 간단히 짚고 넘어가겠습니다.
레이아웃 파일 안에서 yield를 찾아볼 수 있습니다.
Rails는 이 부분을 렌더링 중인 뷰(view)의 내용으로 교체합니다.
yield가 없으면 빈 레이아웃만 남게 됩니다!
바로 이 방식으로 레이아웃과 뷰가 하나로 결합되는 것입니다.
정리
이번 글에서는 Ruby의 yield 키워드에 대해 배웠습니다! 정확히 무엇인지, 어떻게 동작하는지, 그리고 왜 중요한지까지 살펴보았습니다.
이제 직접 Ruby 코드에 적용해 보세요.
읽어주셔서 감사합니다! 🙂