[Rust] crate에 features 분기 설정하기

Rust는 결코 컴파일이 빠른 편에 속하지는 않는 언어다.

그래서 풍부하고 다양한 기능을 가진 crate를 만들 때는 필요한 기능만을 활성화해서 쓰도록 conditional compile을 구성해놓는 관례가 있다.

이런 디펜던시를 가지는 범용 캐시 모듈이 있다고 가정해보겠다.

이 모듈은 redis, dynamo를 이용한 캐시 기능을 동일한 인터페이스로 제공한다.
근데 사실, 이건 굳이 동시에 써야만 하는 기능은 아니다. 보통은 하나만 골라서 쓸 것이다. 이럴때 conditional compile을 응용하면 된다.




features 구성

crate를 좀 갖다써봤다면, 디펜던시를 Cargo.toml에 추가할때 features라는 세부필드로 기능을 명시한 기억이 있을 것이다. 이게 그거다.

Cargo.toml에 이런 느낌으로 기능 목록을 추가해준다. 계층적으로 정의된다.

default는 아무것도 지정하지 않았을때 기본으로 적용되는 feature를 넣는 부분이다. 빈 배열로 둔 dynamo와 redis는 leaf feature다. 저게 하나하나의 feature 단위가 될 것이다.

그리고 full이라는 상위 feature를 통해서 모든 기능을 한번에 사용하고 싶은 경우도 충족하도록 했다. 저건 없어도 된다.

그리고 관련된 코드들이, 저 feature가 들어왔을 때만 컴파일되도록 유도한다.

cfg는 사실상의 매크로다. cfg 표현식이 true로 평가되지 않으면 아예 코드에서 제거된다.




feature에 따른 디펜던시 구성

근데 이것만으로는 충분하지 않다. 보통은 코드 자체보단 그 디펜던시에서 빌드타임을 다 잡아먹기 때문이다.

각 기능에 종속적인 디펜던시에 optional이란 속성을 먼저 활성화해준다.

그리고 각 말단 feature에, 저 feature가 활성화되면 optional로 설정했던 디펜던시를 활성화하도록 설정했다.

이러면 dynamo feature가 활성화될때만 aws-config과 aws-sdk-dynamodb 디펜던시가 활성화된다.




사용

그럼 이제 사용할때 features 플래그로 필요한 기능만을 넣어서 사용하면 된다.

redis를 넣으면 redis 관련 디펜던시와 코드만 컴파일될 것이고


dynamo를 넣으면 dynamo 디펜던시와 코드만 컴파일될 것이다.

이렇게 써먹으면 된다.


참조
https://doc.rust-lang.org/cargo/reference/features.html