토파즈는 애플리케이션의 의도를 간결하게 표현하는 프로그래밍 언어입니다. Python이나 TypeScript처럼 읽기 쉽지만, 같은 뜻을 여러 방식으로 쓰기보다 일관된 문법을 택합니다. 사람이 직접 작성한 코드와 도구가 생성한 코드에 같은 규칙을 적용합니다.
기계를 세밀하게 제어해야 한다면 Rust가 더 알맞습니다. 토파즈는 그보다 한 층 위에서 명령줄 도구, 데이터 변환, 서비스 로직, 설정 처리, SQL·셸·경로를 다루는 프로그램에 집중합니다. 같은 소스를 바로 실행하거나 네이티브 프로그램, Python 제품, 웹 산출물로 만들 수 있습니다.
이 페이지는 토파즈가 어떤 작업에 알맞고 코드가 어떤 모습인지 소개합니다. 첫 수업은 아닙니다. 토파즈가 처음이라면 학습 경로를 따라가거나 Playground에서 첫 프로그램을 실행해 보세요. 언어 전체를 빠르게 훑을 때는 문법 한눈에 보기를, 설계 이유가 궁금할 때는 언어 철학을 읽으면 됩니다.
아래 예제는 실제 토파즈 도구로 검사하고 실행합니다.
토파즈 코드의 모습
유니코드를 기본으로
식별자는 렉서부터 Unicode입니다. 도메인 단어를 로마자로 흉내 내지 않고 그대로 코드에 둡니다.
function greet(name: string, language: string) -> string {
return match language {
case "한국어" => "안녕하세요, {name}님!"
case "Русский" => "Привет, {name}!"
case _ => "Hello, {name}!"
}
}
let 사용자 = "김토파즈"
print(greet(사용자, "한국어"))
print(greet("Topaz", "Русский"))안녕하세요, 김토파즈님!
Привет, Topaz!사용자는 평범한 변수입니다. 유니코드 식별자는 예외 기능이 아니라 언어의 기본입니다. 토파즈는 작성한 이름을 몰래 다른 형태로 바꾸지 않으며, 서로 헷갈릴 수 있는 모듈 이름은 오류로 처리합니다.
작고 닫힌 표면
자주 마주치는 선택에는 권장 형식이 있습니다. 복구 가능한 실패는 Result, 예상 가능한 부재는 Option, 정리는 defer로 나타내며, match는 모든 경우를 다뤘는지 검사합니다. 언어가 이런 선택을 정해 두므로 파일마다 새 방언을 만들 필요가 없습니다.
function parsePort(raw: string) -> Result<int, string> {
let n = toInt(raw) ?? -1
if n < 1 {
return Err("not a port: {raw}")
}
return Ok(n)
}
function startup(raw: string) -> Result<string, string> {
defer print("config closed")
let port = parsePort(raw)?
return Ok("listening on {port}")
}
print("{startup("8080")}")
print("{startup("http")}")config closed
Ok(listening on 8080)
config closed
Err(not a port: http)? 연산자는 Err를 호출한 쪽에 돌려주고, defer는 어떤 종료 경로에서도 실행됩니다. 그래서 두 결과 앞에 모두 config closed가 출력됩니다.
의도를 구조로 보존하는 템플릿
현재 등록된 템플릿 태그는 p, r, sh, sql입니다. 예를 들어 p"..."는 경로 템플릿이고, sql"..."은 SQL 원문과 보간된 매개변수를 문자열 하나로 합치지 않고 따로 보존합니다.
let table = "users"
let q = sql"select * from {table} where active = {true}"
print("{q}")<sql template, 3 part(s), 2 interpolation(s)>출력은 그 구조를 요약한 것입니다. 어떤 부분이 원문이고 어떤 부분이 보간된 값인지 템플릿 안에 그대로 남아 있습니다.
한 번 검사하고, 필요한 출력 선택하기
토파즈는 정적 타입 언어입니다. 프로그램을 실행하기 전에 파일 전체의 타입을 검사합니다.
type TrafficLight = "red" | "yellow" | "green"
function next(light: TrafficLight) -> TrafficLight {
return match light {
case "red" => "green"
case "green" => "yellow"
case _ => "red"
}
}topaz run은 코드를 읽고 이름과 타입을 검사한 뒤 곧바로 실행합니다. 같은 소스에서 topaz emit과 topaz build를 사용하면 다른 형태의 결과물을 만들 수 있습니다. Rust 대상은 독립 실행형 네이티브 바이너리를 만들고, Python 대상은 program.py와 실행에 필요한 topaz_py_rt.py를 만듭니다.
Rust와 Python 출력은 같은 언어 규칙을 따르도록 함께 시험합니다. 현재 지원 범위와 제한 사항은 도구 모음 상태에서 확인할 수 있습니다.
topaz build app.tpz --target python --out-dir py-out
토파즈가 맞지 않는 경우
소유권과 수명을 직접 제어해야 하거나, 안전하지 않은 메모리 경계와 임베디드 환경을 다루거나, 성능 병목을 세밀하게 최적화해야 한다면 Rust, C, Zig가 더 알맞습니다. 토파즈는 그런 저수준 제어를 목표로 하지 않습니다.
토파즈는 그 반대편 작업을 위한 언어입니다. 시스템 수준의 소스를 직접 다루지 않고 애플리케이션 로직을 배포하고 싶을 때, 도메인의 말을 코드에 그대로 남기고 싶을 때, 사람과 에이전트가 일관되게 만들 수 있는 작은 문법이 필요할 때 알맞습니다. 이런 작업을 시작하려면 학습 경로로 이어가세요.
말하는 방법은 하나.