dry-struct의 핵심은 간단한 DSL을 통해 속성(attribute)을 정의하고 이에 대한 리더(reader)를 자동 생성하는 능력에 있습니다. 예를 들어, attribute :name, Types.String.optional
과 같이 타입을 명시하여, 런타임 시 발생할 수 있는 타입 관련 오류를 줄이고 코드의 견고성을 높일 수 있습니다. Types.Coercible::Integer
와 같은 타입을 통해 입력 값의 강제 변환도 가능하여 유연한 데이터 처리를 지원합니다. 이전 버전의 Dry::Struct::Value
는 깊은 불변성을 제공했으나, 현재 Dry::Struct
자체가 불변 객체의 특성을 가지므로 더 이상 권장되지 않습니다. 이는 dry-struct
가 본질적으로 데이터 객체로서의 역할에 충실하도록 설계되었음을 보여줍니다.
dry-struct는 입력 해시(hash) 처리를 위해 dry-types의 해시 스키마를 활용합니다. transform_keys
나 transform_types
와 같은 기능을 통해 입력 키를 심볼로 변환하거나 특정 타입으로 변환하는 전처리 작업을 수행할 수 있으며, 이러한 변환 기능은 상속과도 잘 연동되어 공통적인 입력 변환 로직을 재사용할 수 있게 합니다. 중요한 점은 dry-struct가 데이터 유효성 검사(validation)를 위한 도구가 아니라는 것입니다. dry-struct는 유효하다고 가정된 입력 데이터를 처리하는 데 최적화되어 있으며, 상세한 오류 메시지 생성과 같은 복잡한 유효성 검사는 dry-validation
과 같은 전용 라이브러리를 통해 수행하는 것이 권장됩니다.
dry-struct는 Virtus와 유사하지만 몇 가지 주요 차이점을 가집니다. 첫째, 속성 라이터(attribute writer)를 제공하지 않고 오직 “데이터 객체”로만 사용됩니다. 이는 객체의 상태 변경을 제한하여 예측 가능한 동작을 보장합니다. 둘째, 속성 값 및 해시 처리가 dry-types의 독립적인 타입 객체와 해시 스키마를 통해 이루어져 훨씬 강력하고 유연한 기능을 제공합니다. 셋째, 특정 사용 사례에 맞는 다양한 생성자 유형을 제공하며, 범용적인 “스위스 아미 나이프” 방식이 아닌 명확한 목적성을 가집니다. 마지막으로, dry-struct 클래스는 dry-types처럼 동작하여 해시 스키마 내에서 사용되거나, 배열의 멤버로 활용되거나, 다른 타입과 합쳐지는 등 dry-types 생태계 내에서 높은 호환성을 가집니다.