커져 가는 프로젝트를 패키지, 크레이트, 모듈로 관리하기

거대한 프로그램을 작성할 때는 코드의 구조화가 무척 중요해집니다. 코드에서 연관된 기능을 묶고 서로 다른 기능을 분리해 두면 이후 특정 기능을 구현하는 코드를 찾거나 변경할 때 헤매지 않게 됩니다.

앞서 작성한 프로그램들은 하나의 모듈, 하나의 파일로 이루어져 있었지만, 프로젝트 규모가 커지면 코드를 여러 모듈, 여러 파일로 나누어 관리해야 합니다. 한 패키지에는 여러 개의 바이너리 크레이트와 (원할 경우) 라이브러리 크레이트가 포함될 수 있으므로, 커진 프로젝트의 각 부분을 크레이트로 나눠서 외부 라이브러리처럼 쓸 수 있습니다. 이번 장에서 배워 볼 것은 이러한 기법들입니다. 상호연관된 패키지들로 이루어진 대규모 프로젝트의 경우에는 14장 ‘카고 작업공간’ 절에서 다룰 예정인, 카고에서 제공하는 작업공간 (workspace) 기능을 이용합니다.

또한 세부 구현을 캡슐화하면 더 고수준에서 코드를 재사용할 수 있는 방법에 대해서도 설명합니다. 일단 어떤 연산을 구현하면 그 구현체의 작동 방식을 몰라도 다른 코드에서 공개 인터페이스를 통해 해당 코드를 호출할 수 있습니다. 코드를 작성하는 방식에 따라 다른 코드가 사용할 수 있는 공개 부분과 변경 권한을 작성자에게 남겨두는 비공개 구현 세부 사항이 정의됩니다. 이는 머릿속에 기억해 둬야 하는 세부 사항의 양을 제한하는 또 다른 방법입니다.

스코프 개념도 관련되어 있습니다. 중첩된 컨텍스트에 작성한 코드는 ‘스코프 내에’ 정의된 다양한 이름들이 사용됩니다. 프로그래머나 컴파일러가 코드를 읽고, 쓰고, 컴파일할 때는 특정 위치의 특정 이름이 무엇을 의미하는지 알아야 합니다. 해당 이름이 변수인지, 함수인지, 열거형인지, 모듈인지, 상수인지, 그 외 아이템인지 말이죠. 스코프를 생성하고 스코프 안 혹은 바깥에 있는 이름을 변경할 수 있습니다. 동일한 스코프 내에는 같은 이름을 가진 아이템이 둘 이상 있을 수 없으며, 이름 충돌을 해결하는 도구를 사용할 수 있습니다.

러스트에는 코드 조직화에 필요한 기능이 여럿 있습니다. 어떤 세부 정보를 외부에 노출할지, 비공개로 둘지, 프로그램의 스코프 내 어떤 이름이 있는지 등 다양합니다. 이를 통틀어 모듈 시스템이라 하며, 다음 기능들이 포함됩니다:

  • 패키지: 크레이트를 빌드하고, 테스트하고, 공유하는 데 사용하는 카고 기능입니다.
  • 크레이트: 라이브러리나 실행 가능한 모듈로 구성된 트리 구조입니다.
  • 모듈use: 구조, 스코프를 제어하고, 조직 세부 경로를 감추는 데 사용합니다.
  • 경로: 구조체, 함수, 모듈 등의 이름을 지정합니다.

이번 장에서는 이 기능들을 모두 다뤄보면서 이 기능들이 상호작용하는 방식을 논의하고 이를 사용하여 스코프를 관리하는 방법을 설명하겠습니다. 이번 장을 마치고 나면, 모듈 시스템을 확실히 이해하고 프로처럼 스코프를 다룰 수 있을 거랍니다!