패키지, 크레이트, 모듈로 프로젝트 관리하기

프로그램의 규모가 커질수록 코드를 체계적으로 관리하는 일은 점점 더 중요해진다. 관련 기능을 그룹화하고 각 기능을 명확히 구분하면, 특정 기능을 구현한 코드를 쉽게 찾을 수 있고 기능의 동작을 수정할 위치도 명확해진다.

지금까지 작성한 프로그램은 하나의 파일에 하나의 모듈로 구성되어 있었다. 프로젝트가 커지면 코드를 여러 모듈로 나누고, 이를 다시 여러 파일로 분리해야 한다. 하나의 패키지는 여러 바이너리 크레이트를 포함할 수 있으며, 선택적으로 하나의 라이브러리 크레이트를 포함할 수 있다. 패키지가 커지면 일부를 분리해 외부 의존성으로 사용할 수 있다. 이 장에서는 이러한 기법을 모두 다룬다. 서로 연관된 패키지 집합으로 구성된 대규모 프로젝트의 경우, Cargo는 워크스페이스 기능을 제공한다. 이에 대해서는 14장 “Cargo 워크스페이스”에서 자세히 설명한다.

구현 세부 사항을 캡슐화하는 방법도 살펴본다. 이를 통해 코드를 더 높은 수준에서 재사용할 수 있다. 한 번 구현한 기능은 공개 인터페이스를 통해 다른 코드에서 호출할 수 있으며, 내부 구현 방식을 알 필요가 없다. 코드를 작성할 때 어떤 부분을 공개하고 어떤 부분을 비공개로 할지 결정할 수 있다. 이는 코드를 이해하고 관리해야 하는 세부 사항의 양을 줄이는 또 다른 방법이다.

관련 개념으로 스코프가 있다. 스코프는 코드가 작성된 중첩된 컨텍스트로, ’스코프 내’에 정의된 이름들의 집합을 의미한다. 코드를 읽고, 쓰고, 컴파일할 때 프로그래머와 컴파일러는 특정 위치의 이름이 변수, 함수, 구조체, 열거형, 모듈, 상수 등을 가리키는지, 그리고 그 의미가 무엇인지 알아야 한다. 스코프를 생성하고 어떤 이름이 스코프 내에 있는지 변경할 수 있다. 같은 스코프 내에서는 두 항목이 같은 이름을 가질 수 없으며, 이름 충돌을 해결하는 도구가 제공된다.

Rust는 코드의 조직화를 관리할 수 있는 여러 기능을 제공한다. 어떤 세부 사항을 공개할지, 어떤 부분을 비공개로 할지, 프로그램의 각 스코프에 어떤 이름이 있는지 등을 제어할 수 있다. 이러한 기능을 통칭하여 모듈 시스템 이라고 부르며, 다음과 같은 요소로 구성된다:

  • 패키지: 크레이트를 빌드, 테스트, 공유할 수 있는 Cargo 기능
  • 크레이트: 라이브러리나 실행 파일을 생성하는 모듈 트리
  • 모듈use: 경로의 조직화, 스코프, 접근 제어를 관리
  • 경로: 구조체, 함수, 모듈 등의 항목을 식별하는 방법

이 장에서는 이러한 기능을 모두 다루고, 각 기능이 어떻게 상호작용하는지 설명하며, 스코프를 관리하는 방법을 알아본다. 이 장을 마치면 모듈 시스템을 충분히 이해하고 스코프를 전문가처럼 다룰 수 있을 것이다.