패키지, 크레이트, 모듈로 프로젝트 키우기
패키지, 크레이트, 모듈로 프로젝트 키우기
큰 프로그램을 작성하다 보면 코드를 조직화하는 일이 점점 중요해져요. 관련된 기능끼리 묶고, 서로 구분되는 기능은 코드를 나눠서 만들면 특정 기능을 구현한 코드가 어디 있는지, 그 기능의 동작을 바꾸려면 어디를 건드려야 하는지가 훨씬 명확해져요. 아직까지 우리가 만든 프로그램은 한 파일에 한 모듈로만 있었는데, 프로젝트가 커지면 여러 모듈로, 또 여러 파일로 쪼개서 정리하게 돼요. 이번 장에서는 그 조직화의 토대가 되는 패키지와 크레이트, 모듈을 차례로 살펴볼게요.
왜 코드를 조직화해야 하나요
지금까지 작성한 프로그램은 모두 한 모듈에, 한 파일에 들어 있었어요. 프로젝트가 커지면 코드를 여러 모듈로 나누고, 다시 여러 파일로 쪼개서 정리해야 해요. 패키지(package)는 여러 바이너리 크레이트를 담을 수 있고, 선택적으로 하나의 라이브러리 크레이트를 담을 수 있어요. 패키지가 더 커지면 일부를 떼어내 별도의 크레이트로 만들고, 그걸 외부 의존성으로 사용할 수도 있어요. 이 장에서는 이 기법들을 전부 다룹니다. 함께 발전하는 서로 연관된 패키지 무리로 이루어진 아주 큰 프로젝트에는 Cargo가 제공하는 워크스페이스(workspaces)를 쓰는데, 그건 14장의 "Cargo Workspaces"에서 다룰게요.
또 한 가지 다룰 것은 구현 세부 사항을 캡슐화(encapsulation)하는 방법이에요. 이걸 알면 코드를 더 높은 수준에서 재사용할 수 있어요. 한 번 연산을 구현해 두면, 다른 코드는 그 구현이 어떻게 동작하는지 몰라도 공개 인터페이스(public interface)를 통해 여러분의 코드를 호출할 수 있으니까요. 어떤 부분을 다른 코드가 사용할 수 있게 공개할지, 어떤 부분을 바꿀 권리를 스스로 남겨 두는 비공개 구현 세부 사항으로 둘지는 코드를 어떻게 쓰느냐가 결정해요. 이것도 머릿속에 담아 둬야 할 세부 사항의 양을 줄이는 또 하나의 방법이에요.
여기에 이어지는 개념이 스코프(scope)예요. 코드가 쓰이는 중첩된 문맥에는 "스코프 안에 있다"고 정의되는 이름들의 집합이 있어요. 코드를 읽고, 쓰고, 컴파일할 때 프로그래머와 컴파일러 모두 특정 위치의 특정 이름이 변수, 함수, struct, enum, 모듈, 상수, 아니면 다른 항목을 가리키는지, 그리고 그 항목이 무엇을 의미하는지를 알아야 해요. 스코프를 만들 수 있고, 어떤 이름이 스코프 안에 들어오고 나가는지도 바꿀 수 있어요. 같은 스코프 안에는 같은 이름을 가진 항목 두 개를 둘 수 없고, 이름 충돌을 해결하기 위한 도구들이 제공돼요.
러스트에는 코드의 조직, 어떤 세부 사항이 노출되고 어떤 것이 비공개인지, 그리고 프로그램의 각 스코프에 어떤 이름이 있는지를 관리하게 해 주는 기능이 많이 있어요. 이 기능들을 통틀어 모듈 시스템(module system) 이라고 부르기도 하는데, 여기에는 다음이 포함돼요.
- 패키지(Packages): 크레이트를 만들고, 테스트하고, 공유하게 해 주는 Cargo 기능
- 크레이트(Crates): 라이브러리나 실행 파일을 만들어내는 모듈의 트리
- 모듈과 use(Modules and use): 경로의 조직, 스코프, 비공개 여부를 제어하게 해 줌
- 경로(Paths): struct, 함수, 모듈 같은 항목에 이름을 붙이는 방법
이번 장에서 이 기능들을 모두 다루면서, 이들이 어떻게 상호작용하는지, 그리고 스코프를 관리하는 데 어떻게 쓰는지 설명할게요. 장이 끝나면 모듈 시스템을 확실히 이해하고 스코프를 프로답게 다룰 수 있게 될 거예요.