hpack으로 더 나은 Haskell 패키지 만들기

ko생성일: 2025. 10. 13.

Cabal 파일의 번거로움 대신 YAML 기반 hpack을 사용해 보일러플레이트와 중복을 줄이고, 공통 작업을 단순화하며 Stack과의 통합까지 누리는 방법을 소개합니다.

Haskell 패키지를 작성하려면 패키지 메타데이터를 Cabal 파일에 넣어야 합니다. 안타깝게도 Cabal 파일 형식은 커스텀이고, 번거롭고, 장황합니다. Simon Hengel의 hpack 도구는 Haskell 패키지를 정의하는 더 나은 방법을 제공합니다. 그래서 제 Haskell 패키지 체크리스트는 hpack 사용을 권장합니다.

Cabal은 맞춤 파일 형식을 사용합니다. 제가 아는 한, Cabal 파일을 파싱하는 유일한 방법은 Haskell에서 Cabal 라이브러리를 사용하는 것입니다. 이 때문에 다른 언어에서는 일상적인 편집, 정보 추출, 예쁜 출력 등에 쓰기 어렵습니다. 비교하자면, hpack은 그냥 YAML입니다. 아마 여러분도, 사용하는 에디터도, 쓰는 다른 언어들도 이미 YAML에 익숙할 것입니다.

Cabal 파일 형식의 또 다른 문제는 불필요한 보일러플레이트가 많다는 것입니다. 예를 들어 패키지에 새 모듈을 만들면 exposed-modules 또는 other-modules에 반드시 추가해야 합니다. 그렇지 않으면 그 모듈을 사용할 수 없고 이상한 링크 오류가 납니다. hpack은 모듈을 자동으로 찾아서 공개해 주지만, 여전히 필요한 경우 특정 모듈을 숨길 수 있는 제어권도 제공합니다.

보일러플레이트를 없애는 것 외에도 hpack은 흔한 기능들을 위한 유용한 지름길을 제공합니다. 예컨대 패키지에 포함해야 하는 템플릿 파일 묶음이 있을 수 있습니다. Cabal에서는 그것들을 일일이 나열해야 하고, 추가/삭제할 때마다 목록을 계속 최신 상태로 유지해야 합니다. hpack에서는 extra-source-files: templates/* 같은 식으로 적고 잊어버리면 됩니다.

hpack은 중복도 대폭 줄여 줍니다. 하나의 패키지 안에서 라이브러리, 실행 파일, 테스트 스위트를 정의하고 모두가 같은 의존성을 필요로 하는 경우가 아주 흔합니다. Cabal은 각 섹션에 이 의존성을 반복해서 적게 만들어 패키지 파일의 크기를 손쉽게 세 배로 불려 버립니다. hpack은 의존성을 최상위에 적어 섹션 간에 공유할 수 있게 해 줍니다. (Cabal도 언젠가는 비슷한 기능을 제공할지 모르지만, 적어도 2012년부터 알려진 문제입니다.)

hpack은 설정 가능한 범위를 제한하지 않으면서 이런 유용한 기능들을 모두 제공합니다. Cabal에서 hpack으로 옮긴다고 해서 힘이나 표현력이 줄어드는 건 아닙니다. 실제로는 hpack-convert로 Cabal 파일을 기계적으로 hpack 형식으로 변환하는 것도 가능합니다.

Stack에는 hpack이 기본 내장되어 있습니다. 따라서 패키지를 빌드하는 데 Stack을 사용한다면(그리고 아마 그렇게 하는 편이 좋습니다) stack build 과정의 일부로 hpack을 공짜로 얻게 됩니다. 그리고 hpack이 Cabal 파일을 생성해 주기 때문에 어떤 이유로든 다시 Cabal을 써야 한다면 돌아가기도 쉽습니다.

요컨대, hpack을 사용해 Haskell 패키지 작성자로서의 삶을 더 편하게 만드세요.