#10장 람다를 이용한 도메인 전용 언어

Raoul-Gabriel Urma 저, 우정은 역 「Modern Java in Action, 2019」를 읽고 정리하였습니다.

10장 요약

  • DSL은 개발자와 도메인 전문가 사이의 간격을 좁힌다.

  • DSL은 외부적 또는 내부적 DSL 나눠진다.

  • JVM에서 이용가능한 스칼라, 그루비 언어도 다중 DSL 을 개발할 수 있다. 이 언어들은 자바보다 유연하지만, 자바와 통합하려면 빌드과정이 복잡해진다.

  • 자바의 장황함과 문법적 엄격함으로 DSL을 개발하는 언어로 보통 적합하지 않지만, (자바 8) 람다식 메서드 참조와 같은 도입덕분에 개선되었다.

  • 자바는 자체 API에 작은 DSL을 제공한다. 이는 특히 컬렉션 데이터의 정렬, 필터링, 변환, 그룹화에 유용하다.

  • 자바로 DSL 구현시, 3가지 패턴 (메서드체인, 중첨함수, 함수시퀀싱)이 사용된다.

  • 많은 자바 프레임워크와 라이브러리를 DSL을 통해 이용할 수 있다. jOOQ (SQL 매핑 도구), BDD 프레임워크 Cucumber, 엔터프라이즈 통합 패턴을 구현한 Spring Integration을 살펴봤다.

다룰 내용

  • DSL (도메인 전용 언어)란?

  • DSL을 API에 추가시 장단점

  • JVM에서 활용할 수 있는 자바 기반 DSL을 깔끔하게 만드는 대안

  • 최신 자바 interface와 class에 적용된 DSL에 대한 배움

  • 효과적인 자바 기반 DSL을 구현하는 패턴과 기법

  • 이들 패턴을 자바 라이브러리와 도구에서 얼마나 자주 사용되는지 확인

10.1 도메인 전용 언어

  • DSL의 장점

    • 간결함 : API는 비즈니스 로직을 간편하게 캡슐화하므로 반복을 피할 수 있고 코드를 간결하게 만들 수 있다.

    • 가독성 : 도메인 영역의 용어를 사용하므로 비 도메인 전문가도 코드를 쉽게 이해할 수 있다. 결과적으로 다양한 조직 구성원 간에 코드와 도메인 영역이 공유될 수 있다.

    • 유지보수 : 잘 설계된 DSL로 구현한 코드는 쉽게 유지 보수하고 바꿀 수 있다.

    • 높은 수준의 추상화 : DSL은 도메인과 같은 추상화 수준에서 동작하므로 도메인의 문제와 직접적으로 관련되지 않은 세부 사항을 숨긴다.

    • 집중 : 비즈니스 도메인의 규칙을 표현할 목적으로 설계된 언어이므로 프로그래머가 특정 코드에 집중할 수 있다. 결과적으로 생산성이 좋아진다.

    • 관심사 분리 : 지정된 언어로 비즈니스 로직을 표현함으로 애플리케이션의 인프라구조와 관련된 문제와 독립적으로 비즈니스 관련된 코드에서 집중하기가 용이하다.

  • DSL의 단점

    • DSL 설계의 어려움 : 간결하게 제한적인 언어에 도메인 지식을 담는 것이 쉬운 작업은 아니다.

    • 개발 비용 : 코드에 DSL을 추가하는 작업은 초기 프로젝트에 많은 비용과 시간이 소모된다. 또한 DSL 유지보수와 변경은 프로젝트에 부담을 주는 요소다.

    • 추가 우회 계층 : DSL은 추가적인 계층으로 도메인 모델을 감싸며 이때 계층을 최대한 작게 만들어 성능 문제를 회피한다.

    • 새로 배워야 하는 언어 : DSL을 프로젝트에 추가하면서 팀이 배워야 하는 언어가 한 개 더 늘어난다는 부담이 있다.

    • 호스팅 언어 한계 : 일부 자바 같은 범용 프로그래밍 언어는 장황하고 엄격한 문법을 가졌다. 이런 언어로는 사용자 친화적 DSL을 만들기가 힘들다.

  • DSL의 카테고리: 내부 DSL, 외부 DSL, 다중 DSL

    • 내부는 순수 자바 코드 같은 기존 호스팅 언어를 기반하고 외부는 독립적으로 자체의 문법을 가진다.

    • 다중 DSL는 JVM 특성에 의해 생겨났다.

내부 DSL

다중 DSL

장점

  • 같은 자바 바이트코드를 사용하는 JVM 기반 프로그래밍 언어를 이용하여 DSL을 만들 수 있다.

  • 문법적 잡음이 없으며 개발자가 아닌 사람도 코드를 쉽게 이해할 수 있다.

  • 자바 언어가 가지는 한계를 넘을 수 있다 (스칼라 - 커링, 임의 변환 등 DSL 개발에 필요한 여러 특성을 갖춤)

단점

  • 누군가가 해당 언어에 대해 고급 기술을 사용할 수 있을 정도의 충분한 지식을 가지고 있어야 한다.

  • 두 개 이상의 언어가 혼재하므로 여러 컴파일러로 소스를 빌드하도록 빌드 과정을 개선해야 한다.

  • 호환성 문제를 고려해야한다

외부 DSL

  • 자신만의 문법과 구문으로 새로운 언어를 설계해야 한다는 단점

  • 우리에게 필요한 특성을 완벽하게 제공하는 언어를 설계할 수 있다는

  • JVM에서 실행되는 언어는 100개가 넘는다. (스칼라, 그루비 포함)

10.2 최신 자바 API의 작은 DSL

  • 자바의 새로운 기능의 장점을 적용한 첫 API는 네이티브 자바 API 자신이다.

  • 람다 표현식과 메소드 참조를 이용해 DSL의 가독성, 재사용성, 결합성이 높아졌다.

스트림 API는 컬렉션을 조작하는 DSL

  • Stream 인터페이스는 네이티브 자바 API에 작은 내부 DSL을 적용한 좋은 예시

  • 스트림 API의 fluent style인 메서드 체인은 잘 설계된 DSL의 또 다른 특징

데이터를 수집하는 DSL인 Collectors

10.3 자바로 DSL을 만드는 패턴과 기법

  • 메서드 체인: 플루언트 스타일의 메서드 체인을 이용하여 DSL을 만든다.

    • DSL 가독성을 개선. 노이즈 최소화.

  • 중첩된 함수 이용: 다른 함수 안에 함수를 이용해 도메인 모델을 만든다.

    • 메서드 체인에 비해 함수의 중첩 방식이 도메인 객체 계층 구조에 그대로 반영된다.

  • 람다 표현식을 이용한 함수 시퀀싱

  • 3개 조합하기

  • DSL에 메서드 참조 사용하기

10.4 실생활의 자바8 DSL

  • jOOQ(java Object Oriented Querying): SQL을 구현하는 내부적 DSL, 자바에 직접 내장된 형식 안전 언어

  • Cucumber: 동작 주도 개발(BDD, Behavior-driven development) 프레임워크

  • Spring Integration: 엔터프라이즈 통합패턴을 지원할 수 있도록 의존성 주입에 기반한 스프링 프로그래밍 모델을 확장

Last updated