학습 결과: 잠근 두 모듈 패키지를 구성하고 선택한 테스트와 패키지 진입점을 실행한 뒤, .tpz 프로젝트와 토파즈 컴파일러 없이 Python 제품을 실행합니다.
선행 학습: 실패와 리소스를 마치고 topaz와 Python 3.11 이상을 설치해야 합니다.
기본 스캐폴드로 시작하기
프로젝트를 둘 디렉터리에서 다음을 실행합니다.
topaz init --root study-plan
cd study-plan
init은 기존 프로젝트를 덮어쓰지 않습니다. topaz.toml과 src/main.tpz를 만들지만, 잠금 파일과 테스트는 만들지 않습니다. 진입점 소스를 바꾸고 모듈과 선택 테스트를 추가해 다음 구조를 만드세요.
study-plan/
├── topaz.toml
├── src/
│ ├── main.tpz
│ └── plan.tpz
└── tests/
└── plan.tpz스캐폴드가 만든 매니페스트는 다음과 같습니다.
[package]
name = "study-plan"
version = "0.1.0"
language = "5.10"
entry = "src/main.tpz"
[build]
target = "native"
deterministic = true
[dependencies]
std = "5.10"
모듈 두 개 만들기
src/plan.tpz에는 도메인과 재사용할 연산을 둡니다.
export record StudyTask {
title: string,
minutes: int,
done: bool = false,
}
function parseMinutes(text: string) -> Result<int, string> {
match toInt(text) {
case Some(value) if value > 0 => Ok(value)
case _ => Err("minutes must be a positive integer")
}
}
export function makeTask(
title: string,
minuteText: string,
done: bool = false,
) -> Result<StudyTask, string> {
let minutes = parseMinutes(minuteText)?
Ok(StudyTask { title: title, minutes: minutes, done: done })
}
export function summarize(tasks: Array<StudyTask>) -> string {
let mut remaining = 0
for task in tasks {
if !task.done {
remaining = remaining + task.minutes
}
}
"tasks={tasks.length}, remaining={remaining} minutes"
}export를 붙인 이름만 다른 모듈에서 볼 수 있습니다. parseMinutes는 모듈 내부 구현으로 남습니다.
src/main.tpz는 공개된 이름을 가져오고 패키지 진입점을 제공합니다.
import src.plan { StudyTask, makeTask, summarize }
export function main(args: Array<string>, stdin: string) -> Result<int, string> {
let tasks: Array<StudyTask> = [
makeTask("Run first program", "10", true)?,
makeTask("Build application", "25", false)?,
]
print(summarize(tasks))
Ok(0)
}명시적인 main은 명령줄 인수와 표준 입력을 받고 종료 코드 또는 오류 문자열을 반환합니다. 이 애플리케이션은 둘 다 사용하지 않지만, 시그니처를 통해 제품 경계가 드러납니다.
tests/plan.tpz를 추가하세요.
import src.plan { StudyTask, makeTask, summarize }
match makeTask("Read syntax map", "15") {
case Ok(task) => assert(task.minutes == 15, "valid minutes")
case Err(message) => assert(false, message)
}
match makeTask("Read syntax map", "later") {
case Ok(_) => assert(false, "invalid minutes were accepted")
case Err(message) => assert(
message == "minutes must be a positive integer",
"invalid minutes",
)
}
let tasks: Array<StudyTask> = [
StudyTask { title: "Run first program", minutes: 10, done: true },
StudyTask { title: "Build application", minutes: 25 },
]
assert(
summarize(tasks) == "tasks=2, remaining=25 minutes",
"summary",
)격리된 TestHost는 테스트에서 쓰는 정본 assert(...) 함수를 제공합니다. 이 파일은 제품 코드를 바꾸지 않고 올바른 입력, 잘못된 입력, 최종 요약을 검사합니다.
잠그고, 포맷하고, 검사하고, 테스트하고, 실행하기
의존성 잠금을 만들고 내용을 확인합니다.
topaz lock --root .
생성된 topaz.lock은 다음과 같습니다.
[[package]]
name = "study-plan"
version = "0.1.0"
source = "root"
manifest_hash = "sha256:780ff549a9fb9b09d27c62df8ce48e70c1fc7b33d6d429e6bb826685f42e7615"
이제 로컬 품질 확인을 순서대로 실행합니다.
topaz fmt --check --root .
topaz check --root . --locked
topaz test tests/plan.tpz --root . --locked
fmt --check는 파일을 고치지 않고 포맷 차이를 알리고, check는 해석된 유닛 전체를 검사하며, 명시한 경로는 테스트 진입점 하나를 선택합니다. 테스트 결과는 다음과 같습니다.
tests/plan.tpz: test-ok패키지 진입점을 실행합니다.
topaz run --root . --locked
다음 한 줄이 출력됩니다.
tasks=2, remaining=25 minutes토파즈 프로젝트 없이 빌드하고 실행하기
스캐폴드의 기본 대상은 native이지만, 명령에서 다른 대상을 명시할 수 있습니다. 이 과정에서 사용할 Python 제품을 빌드하세요.
topaz build --target python --root . --locked --out-dir ../study-plan-product
Python을 고른 데에는 이유가 있습니다. 실행할 때 Python 3.11 이상은 필요하지만, 입문 경로에 Rust 설치까지 추가하지 않아도 됩니다. 관리되는 제품 디렉터리에는 정확히 다음 파일이 들어 있습니다.
study-plan-product/
├── GENERATED-OUTPUT-NOTICE.txt
├── LICENSE
├── NOTICE
├── program.py
├── topaz-artifact.json
└── topaz_py_rt.py토파즈 프로젝트 전체를 다른 곳으로 옮긴 뒤 제품 디렉터리에서 실행합니다.
cd ..
mv study-plan source-unavailable
cd study-plan-product
python3 program.py
PowerShell에서는 이동 명령을 Rename-Item study-plan source-unavailable로 바꾸고, 실행할 때 python program.py를 사용하세요. 패키지 실행과 바이트 단위로 같은 결과가 나옵니다.
tasks=2, remaining=25 minutes제품 안에는 생성된 Python과 런타임 지원 파일이 남아 있습니다. 여기서 “원본 없이”란 .tpz 파일이 없고 토파즈 프로젝트, 컴파일러, 레지스트리, 빌드 작업 공간이 필요하지 않다는 뜻입니다.
경계 여섯 개 구분하기
- 파일은
.tpz소스 파일 하나입니다. - 모듈은 파일이
export로 드러내는 이름 공간입니다. - 유닛은 진입점과 가져오기에서 함께 해석되는 토파즈 파일 집합입니다.
- 패키지는
topaz.toml과topaz.lock에 제품 식별 정보와 잠근 의존성을 기록합니다. - 대상은 Python처럼 어떤 형태의 제품을 만들지 고릅니다.
- 산출물은 전달하고 실행할 수 있도록 빌드가 만든 관리 결과입니다.
선택: 소스 작업 흐름인가, 제품 경계인가?
토파즈 프로젝트를 고치는 동안에는 check, test, run으로 빠르게 소스 수준 피드백을 받으세요. 실제 전달물을 확인할 때는 build를 실행하고 프로젝트 밖에서 그 산출물을 테스트하세요. 소스 트리 안에서만 실행하면 프로그램은 증명하지만 전달 경계까지 증명하지는 못합니다.
직접 해보기
src/main.tpz의 두 번째 작업 시간 문자열을 "25"에서 "30"으로 바꾸세요. 전체 흐름을 통과하려면 어떤 예상 결과를 바꿔야 할까요?
정답 보기
패키지와 Python 제품은 tasks=2, remaining=30 minutes를 출력해야 합니다. 선택 테스트는 자체적으로 25분 작업을 만들기 때문에 기존 요약이 그대로 옳고 계속 통과합니다. 이는 테스트가 main의 데이터에 몰래 의존하지 않고 자체 픽스처를 소유한다는 뜻입니다.
다음 단계로 넘어갈 준비
위 여섯 경계를 설명하고, 잠금 파일을 다시 만들어 강제하며, fmt --check, check, 선택한 test, run을 실행하고, .tpz 프로젝트를 치운 뒤 Python 제품까지 실행할 수 있다면 입문 경로를 완주했습니다.
문법 한눈에 보기를 지도로 삼고, 필요한 부분은 모듈과 가시성, 애플리케이션 루프, 산출물과 배포에서 더 깊이 살펴보세요.