라이브러리 가이드라인

라이브러리 가이드라인

이 문서는 Elixir 라이브러리를 만들고 배포하려는 개발자들을 위한 일반적인 가이드라인을 정리해요. 다른 개발자들이 가져다 쓸 라이브러리를 쓸 때 어떻게 구성하고, 어떻게 게시하고, 의존성을 어떻게 다루면 좋은지 설명합니다.

출처: Library guidelines

본문

시작하기

새 Elixir 라이브러리는 mix new 명령으로 만들 수 있어요.

$ mix new my_library

프로젝트 이름은 모든 글자가 소문자이고 단어를 밑줄로 구분하는 snake_case 관례를 따라요. 이는 Elixir의 변수·함수명·아톰이 쓰는 규칙과 같은 거예요. 자세한 내용은 Naming Conventions 문서를 참고하세요.

모든 프로젝트에는 빌드·컴파일·테스트 실행 방법 등을 담은 mix.exs 파일이 있어요. 라이브러리는 보통 Elixir 소스 코드를 담는 lib 디렉터리와 test 디렉터리가 있고, Erlang 소스용 src 디렉터리도 있을 수 있어요.

mix new--sup 옵션을 쓰면 감독 트리(supervision tree)를 바로 갖춘 프로젝트를 만들 수도 있어요. 프로젝트 실행에 대한 더 자세한 내용은 공식 Mix & OTP guideMix 문서를 확인하세요.

배포(Publishing)

코드를 쓰는 것은 패키지를 배포하는 여러 단계 중 첫걸음일 뿐이에요. 다음을 강력히 권장해요.

  • 버전 스키마 선택 — Elixir는 MAJOR.MINOR.PATCH 형식의 버전을 요구하지만 각 숫자의 의미는 여러분이 정해요. 대부분 Semantic Versioning을 선택해요.
  • 라이선스 선택 — Elixir 커뮤니티에서 가장 흔한 라이선스는 MIT LicenseApache License 2.0. 후자는 Elixir 자체가 쓰는 라이선스예요.
  • 코드 포매터 실행mix format은 커뮤니티 전체가 공유하는 일관된 스타일로 코드를 정리해 주어, 다른 개발자가 코드를 이해하고 기여하기 쉬워져요.
  • 테스트 작성 — Elixir에는 ExUnit 테스트 프레임워크가 딸려 있어요. mix new가 만든 프로젝트에는 샘플 테스트와 doctest가 포함돼요.
  • 문서 작성 — Elixir 커뮤니티는 문서를 일급 시민으로 대우해요. 모듈·타입·함수에 대한 완전한 API 문서와 예시를 제공하는 라이브러리가 표준을 만들어요. ExDoc로 문서에서 HTML·EPUB을 생성할 수 있고, 지금 읽고 있는 이 페이지 같은 "extra pages"도 지원해요.
  • 모범 사례 준수 — Elixir 프로젝트는 코드에서 피해야 할 안티 패턴을 문서화하고 있어요. 특히 프로세스 관련·메타 프로그래밍 관련 안티 패턴은 라이브러리 작성자에게 특히 중요해요.

프로젝트는 주로 Hex 패키지로 배포되어 다른 개발자들이 쓸 수 있게 돼요. Hex는 조직용 비공개 패키지도 지원해요. ExDoc을 Mix 프로젝트에 설정했다면, Hex에 패키지를 게시할 때 생성된 문서가 HexDocs에도 자동으로 게시돼요.

의존성 처리

여러분의 라이브러리가 의존성으로 쓰일 때 기본적으로 :prod 환경에서 실행돼요. 따라서 개발·테스트에만 필요한 의존성은 :only 옵션으로 지정해야 해요. 또한 사용자에게 강제하지 않는 :optional 의존성을 지정할 수도 있어요. 이 경우 테스트 환경에서 mix compile --no-optional-deps --warnings-as-errors로 빌드해서 선택적 의존성이 없어도 경고 없이 컴파일되는지 확인해 보는 걸 고려하세요.

mix.lock(락파일)은 호스트 프로젝트에서 무시된다는 점을 기억하세요. 호스트 프로젝트에서 mix deps.get을 실행하면 mix.exsdeps 요구사항에 따라 최신 버전을 가져오려 해요. 반면 라이브러리의 기여자들은 결정적(deterministic) 빌드가 필요하므로 VCS(예: git)에 mix.lock이 있어야 해요.

두 시나리오를 모두 검증하려면 mix.lock을 버전 관리에 포함하고, 하나는 mix.lock에 의존하는 결정적 빌드용, 다른 하나는 mix deps.unlock --all부터 시작해 항상 최신 의존성으로 컴파일하고 테스트하는 두 가지 CI 워크플로를 돌리는 걸 권해요. 후자는 밤마다 돌려 의존성 업데이트 관련 문제를 미리 알 수도 있어요.

의존성 버전 요구사항

의존성 버전 요구사항은 결국 여러분이 정해요. 하지만 너무 엄격한 요구사항이 라이브러리 사용자에게 미치는 영향을 고려해야 해요. 예를 들어 {:some_dep, "== 0.2.3"}은 그 특정 버전만 쓰게 만들기 때문에 버그 수정 업그레이드를 받을 수 없어요. 애매하면 "~> x.y" 형식의 의존성을 쓰세요. 이는 메이저 버전은 올리지 못하게 하지만, 버그 수정과 비파괴 개선이 담긴 마이너·패치 업그레이드는 허용해요.

예외는 1.0 이전 라이브러리예요. Semantic Versioning을 쓰는 1.0 이전 라이브러리는 버전 간 무엇이 바뀔지 보장하지 않으므로, 이 경우 전체 패치 버전, 즉 "~> 0.1.2"가 더 나은 기본값이에요.

흔한 실수는 "~> x.y.z"를 "x.y.z보다 큰 버전"이라는 뜻으로 쓰는 거예요. 예를 들어 "~> 1.2"에 의존하는데 라이브러리 다음 버전에 필요한 수정이 1.2.1로 나왔다고 해요. 이를 "~> 1.2.1"로 표현하면 사용자가 "1.3.0" 이상으로 올리지 못해요! 대신 "~> 1.2 and >= 1.2.1"을 버전 요구사항으로 써야 해요. 그러면 사용자는 2.0 미만이면서 1.2.1 초과인 어떤 버전이든 쓸 수 있어요.

더 알아보기

  • mix new: 새 라이브러리 프로젝트 생성
  • Mix 모듈: 빌드·의존성·컴파일 설정 전반
  • ExUnit: Elixir 기본 테스트 프레임워크
  • Hex: 패키지 배포 및 접근 권한 문서