패키지가 왜 필요한가
언어를 학습하거나 간단한 스니펫을 시도하는 동안에는 단일 .0 파일이면 충분합니다. 프로젝트가 한 파일을 넘기는 순간부터는 패키지 — 매니페스트와 정해진 레이아웃을 가진 디렉터리 — 가 필요해집니다. 툴체인은 이 구조를 이해합니다.
낱개 파일에서 패키지로 넘어가면 좋은 점들:
- 프로젝트의 이름, 버전, 메타데이터를 둘 한 군데가 생깁니다.
- 진입점을 여러 개(실행 파일, 라이브러리, 테스트) 한 트리에 모을 수 있습니다.
- 예측 가능한 레이아웃 덕분에 도구가 설정 없이 소스를 찾을 수 있습니다.
- 파일 단위가 아니라 트리 전체에 대해
zero check/zero build를 돌릴 수 있습니다.
패키지 스캐폴딩하기
가장 빠른 시작 방법은 zero new입니다.
zero new cli hello
이 명령은 다음과 같은 레이아웃의 hello/ 디렉터리를 만듭니다.
hello/
├── zero.json
└── src/
└── main.0
cli는 템플릿 이름입니다. 실행 가능한 커맨드라인 프로그램을 만들죠. 다른 템플릿(라이브러리, 시스템 프로그램)도 같은 구조에 기본값만 다릅니다.
새 디렉터리로 cd한 뒤 실행해 보세요.
cd hello
zero run
패키지 디렉터리 안에서 파일을 지정하지 않고 zero run을 실행하면 zero.json의 기본 타겟을 가져와 실행합니다.
zero.json 매니페스트
스캐폴딩된 cli 패키지의 매니페스트는 다음과 같습니다.
{
"package": { "name": "hello", "version": "0.1.0" },
"targets": { "cli": { "kind": "exe", "main": "src/main.0" } }
}
최상위 키는 두 개: package와 targets. 앞쪽이 패키지를 식별하고, 뒤쪽이 컴파일러에게 무엇을 빌드할지 알려줍니다.
package
"package": {
"name": "hello",
"version": "0.1.0"
}
name— 패키지를 식별하는 슬러그. 소문자와 하이픈을 사용하세요.version— semver 문자열. 1.0 이전 패키지는0.x.y를 씁니다.
설명, 작성자, 라이선스, 저장소 등 다른 메타데이터 필드가 지원될 수 있습니다. 매니페스트가 아직 발전 중이라 권위 있는 스키마는 최신 Zero 문서를 확인하세요.
targets
"targets": {
"cli": { "kind": "exe", "main": "src/main.0" }
}
키(여기서는 cli)는 사용자가 정하는 _타겟 이름_입니다. 값은 각 타겟을 기술합니다.
kind— 이 타겟이 무엇인지. 실행 파일이라면exe. 다른 종류(라이브러리, 테스트)도 같은 구조를 따릅니다.main— 패키지 루트 기준 진입 소스 파일.
같은 패키지에 여러 타겟을 선언할 수도 있습니다.
{
"package": { "name": "image-tools", "version": "0.1.0" },
"targets": {
"convert": { "kind": "exe", "main": "src/convert.0" },
"resize": { "kind": "exe", "main": "src/resize.0" },
"lib": { "kind": "lib", "main": "src/lib.0" }
}
}
CLI에서 이름으로 특정 타겟을 빌드할 수 있어요.
zero build convert
zero run resize
src/ 디렉터리
모든 소스 파일은 src/ 아래에 둡니다. 컴파일러가 이 디렉터리를 자동으로 순회하므로, 매니페스트에 일일이 파일을 나열할 필요가 없습니다. 각 타겟의 main 필드가 진입 파일을 가리키고, 컴파일러는 그곳에서 시작해 import를 따라가며 필요한 나머지를 찾습니다.
도우미 모듈이 몇 개 있는 패키지는 이렇게 생길 수 있습니다.
image-tools/
├── zero.json
└── src/
├── convert.0
├── resize.0
├── lib.0
└── internal/
├── decoder.0
└── encoder.0
internal/ 하위 디렉터리는 단지 관례일 뿐이고, 매니페스트에 별도로 명시할 필요가 없습니다. convert.0 안의 import가 internal/decoder.0을 직접 가져옵니다.
빌드와 실행
패키지 안에서 자주 쓰게 되는 워크플로우:
zero check # 트리 전체를 타입 검사
zero run # 기본 타겟을 빌드하고 실행
zero run convert # 특정 이름의 타겟을 빌드하고 실행
zero build # 기본 타겟 빌드
zero build --all # 모든 타겟 빌드(지원되는 경우)
zero test # 모든 테스트 타겟 실행
CLI는 zero.json을 읽어 무엇을 할지 알아낸 뒤 진행합니다. 패키지 안에서 작업할 때는 경로를 일일이 지정할 일이 거의 없어요.
여러 소스 파일: 간단한 예시
src/main.0이 src/math.0의 도우미를 호출한다고 해봅시다. 도우미 파일:
pub fun double(value: i32) -> i32 {
return value * 2
}
진입 파일:
pub fun main(world: World) -> Void raises {
let result = double(21)
if result == 42 {
check world.out.write("forty two\n")
}
}
zero run으로 실행하세요. 이 단순한 경우에는 명시적인 import 선언 없이도 컴파일러가 소스 트리의 나머지에서 double 참조를 해결합니다. 패키지가 커지면 명시적인 import 시스템이 모듈 간 가시성을 다루게 됩니다. import 문법은 1.0 이전에 가장 변경 가능성이 큰 영역 중 하나이니, 최신 Zero 문서를 참고하세요.
Git에 커밋하면 안 되는 것
Zero 패키지의 .gitignore는 보통 다음을 포함합니다.
# 빌드 산출물과 캐시
/build/
/target/
# 에디터 부산물
.DS_Store
*.swp
빌드 출력 디렉터리 이름은 다를 수 있습니다 — 최신 툴체인 문서를 확인하세요. 규칙은 단순합니다. 소스는 들어가고, 빌드 산출물은 빠집니다.
패키지 공유
Zero는 1.0 이전이고 패키지 레지스트리는 아직 안정 표면에 포함되지 않았습니다. 지금 현실적인 공유 방법은:
- Git: 저장소를 클론한 뒤
zero check를 실행합니다. - 벤더링된 사본: 소스를 다른 프로젝트에 복사해 넣습니다.
레지스트리가 등장하면 패키지 참조는 zero.json의 의존성 필드로 들어갈 가능성이 높습니다. 지금 당장 스크립트로 자동화할 만한 기능이 아니라, 미래 기능 정도로 생각해 두세요.
다음 글: 언어 기초
이제 실제 Zero 프로젝트를 조직하는 데 필요한 모든 것을 갖췄습니다. 다음 챕터에서는 언어 자체로 줌인합니다. 시작은 let 바인딩 — Zero에서 값에 이름을 붙이는 방법입니다.
자주 묻는 질문
Zero 패키지가 뭔가요?
Zero 패키지는 zero.json 매니페스트와 .0 소스 파일을 담은 src/ 폴더로 이루어진 디렉터리입니다. 매니페스트는 패키지의 이름, 버전, 그리고 하나 이상의 '타겟'을 선언합니다. 각 타겟은 컴파일러에게 소스로부터 무엇(실행 파일, 라이브러리, 테스트 바이너리 등)을 빌드할지 알려줍니다.
새 Zero 패키지는 어떻게 만드나요?
zero new <템플릿> <이름>을 실행합니다. 예를 들어 zero new cli hello 같은 식이에요. CLI가 zero.json, src/main.0, 그리고 템플릿에 필요한 다른 파일들을 만들어 줍니다. 그다음에는 패키지 안에서 zero check, zero run, zero build를 사용하면 됩니다.
zero.json에는 무엇이 들어가나요?
zero.json에는 무엇이 들어가나요?최소한 name과 version을 가진 package 객체, 그리고 패키지가 빌드하는 각각의 항목을 기술하는 targets 객체가 들어갑니다. 타겟에는 kind(실행 파일이라면 exe 같은)와 진입 소스 파일을 가리키는 main이 있고요. 매니페스트 하나에 여러 타겟을 선언할 수 있습니다.
하나의 Zero 패키지에 여러 타겟을 둘 수 있나요?
네. 패키지에는 원하는 수만큼 타겟을 선언할 수 있어요. 예를 들어 CLI용 exe 타겟 하나, 재사용 가능한 라이브러리용 lib 타겟 하나, 그리고 테스트 타겟 한두 개를 둘 수 있죠. 각 타겟은 src/ 아래에 자기만의 진입점을 가지고, CLI에서 개별적으로 빌드하거나 실행할 수 있습니다.
컴파일러는 빌드 결과를 어디에 두나요?
빌드 산출물은 패키지 안의 빌드 디렉터리에 들어갑니다(정확한 경로는 구현에 따라 다르며, Zero가 1.0 이전이라 바뀔 수 있습니다). src/ 아래의 소스 트리는 절대 수정되지 않아요. 빌드 디렉터리는 언제든 버려도 되는 것으로 다루세요. git에 커밋하는 건 좋은 생각이 아닙니다.