Ruby로 만드는 DSL의 기초

[27M07] The basis of making DSL with Ruby (ja) / Yasuko Ohba (Everyleaf Corporation)

작성자
RubyKaigi
발행일
2025년 10월 05일

핵심 요약

  • 1 Ruby는 DSL 구현에 매우 적합하며, 이는 특별한 기술이 아닌 코드 가독성과 유지보수성을 향상시키는 일상적인 코딩 기법입니다.
  • 2 DSL스러운 코드를 작성하는 핵심적인 세 가지 방법은 선언적 기술, 블록의 적극적인 활용, 그리고 특정 개념을 명확히 나타내는 메서드 생성입니다.
  • 3 선언적 기술은 '무엇을 할지'보다 '무엇이다'라는 상태나 성질을 기술하며, 모듈 인클루드와 클래스 메서드를 활용하여 구현할 수 있습니다.

도입

본 세션은 Ruby 개발자인 오바야시 야스코(大林安子) 씨가 Ruby를 활용한 DSL(Domain-Specific Language) 구현의 기초에 대해 발표한 내용입니다. 발표자는 자신의 대표작인 웹 가계부 '코즈치(小槌)'와 번역서 'JLB on Rails 실천 가이드' 등을 소개하며, Ruby가 DSL에 적합한 언어임을 강조했습니다. DSL은 도메인 특화 언어로, 특정 분야의 지식을 이해하기 쉬운 형태로 표현하는 것을 목표로 하며, 본 세션에서는 Ruby 내부에 구현되는 '언어 내 DSL'에 초점을 맞춰 설명합니다.

DSL스러운 코딩을 위한 세 가지 핵심 전략

발표자는 DSL을 단순히 ‘대단한 사람들이 만드는 것’이 아닌, Ruby 개발자들이 일상적으로 활용하여 코드의 가독성과 유지보수성을 높일 수 있는 코딩 기술의 하나로 제시하며, DSL스러운 코드를 작성하는 구체적인 세 가지 방법을 소개했습니다.

1. 선언적 기술 (Declarative Description)

  • 개념: ‘무엇을 해라’는 명령형 방식 대신, ‘무엇이다’와 같이 객체의 상태나 성질을 기술하는 방식입니다. Rails의 validates_presence_of :name이나 before_filter :find_group, has_many :children 등이 대표적인 예시입니다.

  • 특징: 리시버(self)를 생략하고 괄호를 사용하지 않아 프로그램 코드보다는 전용 언어처럼 보이게 합니다.

  • 구현: 클래스 내에서 해당 클래스의 성질을 나타내는 메서드(클래스 메서드)를 정의하여 구현합니다. 예를 들어, self.money = 0 대신 poor라는 선언적 메서드를 사용하거나, include Product 대신 acts_as_product와 같은 메서드를 정의하여 모듈을 포함하는 방식을 활용합니다.
    • acts_as_product와 같은 클래스 메서드는 일반적으로 Object 클래스 또는 상위 클래스에 정의하여 모든 하위 클래스에서 호출 가능하게 합니다. 이는 Rails의 이니셜라이저 등을 통해 애플리케이션 로드 초기에 실행되어야 합니다.
  • 명명 규칙: 선언적 기술에는 형용사나 과거분사(attached, recorded) 또는 3인칭 단수 현재형(has, is, validates)을 사용하고, 일반 메서드에는 동사 원형(have, use, validate)을 사용하는 것이 좋습니다.

2. 블록의 활용 (Utilizing Blocks)

  • 개념: Ruby의 블록은 복잡한 데이터 구조를 표현하거나, 블록 내부에 작성된 코드에 특정 스코프를 적용하는 데 유용합니다. Rake의 태스크 정의나 Rails 폼 헬퍼 등이 블록을 활용하는 대표적인 사례입니다.

  • 구현: 특정 개념을 나타내는 최상위 메서드(예: game)를 정의하고, 이 메서드가 블록을 인수로 받아 내부에서 객체를 생성한 후 블록에 전달하여 실행합니다. 이를 통해 블록 내부에서 해당 객체의 메서드(예: uses, deals)를 호출할 수 있게 합니다.

  • 고급 활용: yield 대신 instance_exec를 사용하면 블록에 인수를 명시적으로 전달하지 않고도, 블록이 특정 객체의 컨텍스트에서 실행되도록 하여 더욱 DSL스러운 표현을 가능하게 합니다.

3. 특정 개념을 나타내는 메서드 (Methods Representing Specific Concepts)

  • 개념: 명사 대용 메서드나 다른 언어의 개념에 직접 대응하는 메서드를 활용하여 코드의 의미를 명확하게 만듭니다. Rails의 url 헬퍼나 HTML 태그를 나타내는 submit, RJS의 assert 등이 이에 해당합니다.

  • 고려사항: 실용성과 타당성 사이의 균형을 유지하는 것이 중요하며, 지나치게 영어처럼 보이게 하려는 시도는 지양해야 합니다.

일반적인 DSL 코딩 팁

  • 인수에 기본값을 설정하여 인수를 생략할 수 있도록 합니다.

  • 해시를 사용하여 호출 코드의 가독성을 높입니다.

  • 심볼을 적극적으로 활용하여 의미를 명확히 합니다.

  • 메서드 이름을 단순히 처리 내용 대신 반환 값이나 스코프를 나타내는 방식으로 고안합니다.

결론

결론적으로, DSL은 Ruby 개발자에게 결코 특별하거나 접근하기 어려운 존재가 아닙니다. 오히려 Ruby의 유연한 특징을 활용하여 코드의 가독성, 작성 용이성, 코드량 감소, 그리고 궁극적으로 유지보수성을 크게 향상시킬 수 있는 실용적인 코딩 기술입니다. 선언적 기술, 블록 활용, 특정 개념 메서드와 같은 기법들을 의식적으로 적용하고, 기존의 잘 만들어진 코드를 분석하며 학습하는 것이 DSL 구현 능력을 향상시키는 중요한 방법입니다. 이를 통해 개발자들은 더욱 아름답고 효율적인 Ruby 코드를 작성할 수 있을 것입니다.

댓글 0

로그인이 필요합니다

댓글을 작성하거나 대화에 참여하려면 로그인이 필요합니다.

로그인 하러 가기

아직 댓글이 없습니다

첫 번째 댓글을 작성해보세요!