패키지 쓰기와 만들기
hana add로 다른 사람이 만든 패키지를 가져다 쓰고, 내 패키지를 만들어 나누는 방법을 알아봐요.
패키지는 다른 사람이 (또는 내가) 만들어 둔 함수와 클래스 묶음이에요. Hana 런타임에는 패키지를 내려받고 관리하는 명령이 들어 있어요. 패키지는 git 저장소이고, 이름이 곧 저장소 주소예요. 중앙 서버는 없어요. 브라우저의 실행 버튼은 패키지를 쓸 수 없고, Hana 런타임으로 실행할 때만 써요.
패키지 쓰기
프로젝트 폴더에서 패키지를 추가해요. git이 설치되어 있어야 해요.
hana add github.com/주인/저장소
이 한 줄이 하는 일은 이래요.
- 저장소의
v1.2.0이나1.2.0같은 버전 태그 중 가장 높은 것을 골라요. - 그 버전을 내 컴퓨터의 캐시 폴더(
~/.hana/pkg)에 내려받아요. 폴더는 환경 변수HANA_HOME으로 바꿀 수 있어요. - 그 패키지가 필요로 하는 다른 패키지도 함께 내려받아요.
- 프로젝트 폴더에
hana.json과hana-lock.json을 써요.
버전을 직접 정하려면 @를 붙여요: hana add github.com/주인/저장소@1.2.0.
이제 저장소 경로를 그대로 대괄호 안에 써서 가져와요. 다른 표준 모듈과 똑같이 생겼어요.
[github.com/주인/저장소]에서 <인사하기>를 가져오자
<인사하기>("하나")를 출력하자
패키지는 하자용과 카나데용 진입점을 따로 가질 수 있어요. 내 스크립트의 언어에 맞는 진입점이 없으면 “이 언어의 진입점이 없어요”라는 오류가 나요.
hana.json과 hana-lock.json
{
"dependencies": {
"github.com/주인/저장소": "1.2.0"
}
}
hana.json은 내가 원하는 것이에요. 적힌 버전은 “이 버전 이상”이라는 뜻의 최소 버전이에요. ^나 ~ 같은 범위 표기는 없어요.
{
"github.com/주인/저장소": {
"version": "1.3.4",
"commit": "a1b2c3d4e5f6..."
}
}
hana-lock.json은 실제로 고른 것이에요. 정확한 버전과, 그때 그 버전의 태그가 가리키던 커밋이 적혀요. 내가 추가한 패키지뿐 아니라 그 패키지가 필요로 하는 패키지까지 모두 들어 있어요. 두 파일 모두 git에 함께 올려 두면, 다른 컴퓨터에서 hana install 한 번으로 똑같은 버전을 받아요.
같은 패키지를 여러 곳에서 서로 다른 최소 버전으로 요구하면, 요구된 것 중 가장 높은 버전을 하나만 골라요. 최소 버전만 적으니 “조건이 서로 안 맞아서 설치가 실패하는” 일이 없어요.
다른 컴퓨터에서, 그리고 다른 명령들
| 명령 | 하는 일 |
|---|---|
hana install |
hana-lock.json에 적힌 패키지를 모두 내려받아요. lock이 hana.json보다 모자라면 버전을 다시 골라요 |
hana remove github.com/주인/저장소 |
패키지를 빼요. 그 패키지 때문에만 필요했던 것도 lock에서 빠져요 |
hana list |
쓰고 있는 패키지와 버전을 보여줘요. *는 내가 직접 추가한 것이에요 |
hana why github.com/주인/저장소 |
그 패키지가 왜 들어와 있는지 보여줘요. 내가 직접 추가했는지, 어떤 패키지를 거쳐 들어왔는지(가 -> 나 -> 저장소)를 알려 줘요 |
hana outdated |
더 높은 버전이 나온 패키지를 보여줘요. 올리려면 hana add 경로@버전을 다시 실행해요 |
hana run은 아무것도 내려받지 않아요. 패키지가 설치되어 있지 않으면 “설치되어 있지 않아요”라는 오류로 hana install을 알려 줘요. lock에 적힌 커밋과 실제로 내려받은 커밋이 다르면(누군가 태그를 옮겼다면) 설치를 거부해요.
내 컴퓨터에 있는 패키지를 고치면서 쓰기
패키지를 만들면서 그 패키지를 쓰는 프로젝트도 함께 고칠 때는, hana.json에 replace를 적어 내려받기 대신 내 폴더를 가리키게 해요.
{
"dependencies": { "github.com/주인/저장소": "1.2.0" },
"replace": { "github.com/주인/저장소": "../저장소" }
}
replace는 이 프로젝트에서만 통하고, lock에는 적히지 않아요.
패키지 만들기
패키지는 git 저장소 하나예요. 폴더 구성은 이래요.
저장소/
├── hana.pkg.json
├── hari/
│ └── index.hr ← 하자 진입점
└── kanade/
└── index.knd ← 카나데 진입점
진입점은 둘 중 하나만 있어도 돼요. 진입점 안의 함수와 클래스를 다른 사람이 [github.com/주인/저장소]에서 …를 가져오자로 가져가요. hana.pkg.json은 패키지 자신의 정보예요.
{
"name": "github.com/주인/저장소",
"version": "1.2.0",
"dependencies": {
"github.com/주인/다른패키지": "2.0.0"
}
}
name은 저장소 경로와 같아야 해요(다르면 설치가 거부돼요).dependencies는 이 패키지가 필요로 하는 패키지와 최소 버전이에요. 패키지끼리 서로를 돌고 돌아 필요로 하면 설치가 거부돼요.- 진입점 경로를 바꾸려면
"entry": {"hari": "src/main.hr"}처럼 적어요. - 버전은 git 태그로 정해요. 새 버전을 낼 때
git tag v1.3.0을 만들고 푸시하면 돼요.
네이티브 라이브러리를 넣기
하자나 카나데로 하기 어려운 일은 Go나 C 같은 언어로 만든 라이브러리(.dll, .so, .dylib)에 맡길 수 있어요. 운영체제마다 미리 만들어 둔 파일을 hana.pkg.json에 적어요.
{
"native": {
"windows-amd64": {
"file": "native/저장소.dll",
"url": "https://주소/저장소-windows-amd64.dll",
"sha256": "…64자리…"
},
"linux-amd64": {
"file": "native/libjeojangso.so",
"url": "https://주소/libjeojangso-linux-amd64.so",
"sha256": "…64자리…"
}
}
}
hana add는 지금 컴퓨터의 플랫폼 것만 내려받고, sha256이 맞는지 확인해요. 다르면 파일을 버리고 설치를 멈춰요. 저장소 안에 파일이 이미 들어 있으면(file이 있으면) 내려받지 않아요. 라이브러리가 지켜야 하는 규칙은 hana 저장소의 native/native.go에 적혀 있어요.
설치 스크립트
미리 만든 파일을 못 주고 설치할 때 직접 빌드해야 한다면 설치 스크립트를 쓸 수 있어요. 셸을 거치지 않는 명령 배열로 적어요.
{
"scripts": {
"install": ["go", "build", "-buildmode=c-shared", "-o", "native/저장소.dll", "./native"]
}
}
스크립트는 컴퓨터에서 마음대로 돌아가는 프로그램이라, 그냥은 실행하지 않아요.
- 사용자가
hana add github.com/주인/저장소 --allow-scripts로 승인해야 해요. 승인하면hana.json의trustedScripts에 적혀요. - 승인한 스크립트의 해시가
hana-lock.json에 적혀요. 스크립트가 바뀌면 다시 승인하기 전까지 거부돼요. - 다른 패키지가 필요로 해서 딸려 온 패키지의 스크립트는 자동으로 허용되지 않아요. 패키지마다 따로 승인해요.
- 스크립트는
hana add와hana install안에서만 돌아요.hana run은 절대 실행하지 않아요. - 스크립트를 실행하기 전에 무슨 명령인지 화면에 보여 줘요.
승인하지 않은 스크립트는 건너뛰고 안내만 해요. 스크립트에는 샌드박스가 없으니, 믿을 수 있는 패키지에만 승인하세요.
알아 둘 것
- 패키지 안의 함수는 같은 패키지의 다른 함수와 그 패키지가 가져온 다른 패키지를 마음대로 불러요. 가져가는 사람이 그것들을 따로 가져올 필요가 없고, 내 스크립트에 같은 이름의 함수가 있어도 서로 가리지 않아요.
- 패키지 맨 위에 만든 변수와 문장은 그 패키지의 것이에요. 패키지는 처음 가져올 때 딱 한 번 준비되고(맨 위 문장이 한 번 실행돼요), 그 패키지의 함수는 그 변수를 읽고 바꿀 수 있어요. 여러 곳에서 가져와도 같은 변수를 함께 써요. 반대로 내 스크립트의 변수는 패키지의 함수에서 보이지 않아요.
- 클래스 이름은 프로그램 하나에 하나예요. 서로 다른 두 패키지(또는 내 스크립트)가 같은 이름의 클래스를 가지고 있으면 가져올 때 오류가 나서 알려 줘요. 하나를
<이름>을 <별칭>으로 가져오자로 가져와 다른 이름을 붙이면 돼요. 패키지를 만들 때는 클래스 이름이 다른 곳과 겹치지 않게 지어 주세요. - 패키지 경로는
github.com/주인/저장소처럼 호스트 이름(점이 있는)과 주인, 저장소 이름으로 이루어져야 해요. 저장소 안의 하위 폴더를 패키지로 쓸 수는 없어요. - 비공개 저장소도 받을 수 있어요. 내려받기는 컴퓨터의
git이 하니까,git에 로그인해 두거나(자격 증명 관리자) ssh 키를 등록해 두면 돼요. 터미널에서 실행하면git이 로그인을 물어볼 수도 있어요. ssh 주소로 받고 싶다면 환경 변수HANA_GIT_PROTOCOL=ssh를 설정하세요(git@github.com:주인/저장소로 받아요). 로그인이 안 되면 “로그인이 필요한 비공개 저장소이거나 저장소가 없어요”라고 알려 줘요. - Hana 런타임이 함께 주는
timezone같은 패키지는hana add없이 이름만으로 가져와요. - 패키지를 쓰는 프로그램을 실행 파일로 묶으면 패키지의 하리 코드는 프로그램 안에 들어가고, 네이티브 라이브러리는 실행 파일 옆에 함께 나와요.