패키지
고친 사람 github-actions[bot]
패키지는 흩어진 코드를 이름 하나로 묶어 한 덩어리로 다루게 해 줍니다. 그런데 무엇을 위해 묶느냐에 따라 가리키는 물건이 갈립니다. 코드 안에서는 이름이 서로 부딪히지 않게 나누는 묶음을 말합니다. 배포할 때는 내려받아 설치하는 소프트웨어 한 벌을 말합니다.
쉽고 빠른 이해
무슨 일을 하는 물건인가 — 코드 여러 개에 이름 하나를 붙여 묶습니다. 자바 소스 파일 맨 위에 적어 두는 묶음 이름이 그 하나입니다. pip install 로 내려받는 라이브러리도 패키지입니다. 두 물건은 서로 다르지만 따로 놀지는 않습니다. 배포 패키지를 설치하면 그 안에 든 코드 패키지를 바로 쓸 수 있습니다. 코드 이야기에 나오면 앞의 뜻, 설치 이야기에 나오면 뒤의 뜻입니다.
왜 이렇게 하나 — 코드 쪽은 두 팀이 같은 클래스 이름을 써도 부딪히지 않게 하려고 묶습니다. 배포 쪽은 남이 만든 소프트웨어를 이름과 버전으로 받아 오게 하려고 묶습니다. 필요한 다른 패키지까지 함께 챙기게 합니다.
어떻게 도나
- 코드 패키지는 묶음마다 이름 집합을 따로 가져 서로 부딪히지 않게 합니다
- 배포 패키지는 결과물에 이름과 버전과 필요한 패키지 목록을 붙입니다
- 설치 도구가 그 목록을 읽고 빠진 것이 있으면 알려 줍니다
대가 — 설치할 때 쓰는 이름과 코드에서 부르는 이름이 다를 수 있습니다. 코드에 적힌 이름만 보고 같은 이름을 설치하면 엉뚱한 패키지가 깔릴 수 있습니다.
상세
이 절은 「패키지」가 가리키는 두 물건을 차례로 봅니다. 하나는 코드 안에서 이름을 나누는 코드 패키지입니다. 다른 하나는 내려받아 설치하는 배포 패키지입니다. 끝에서는 두 물건이 한 라이브러리 안에서 만나는 대목을 봅니다.
두 뜻은 서로 다른 물건을 가리키지만 따로 노는 것은 아닙니다. 배포 패키지를 설치하면 그 안에 든 코드 패키지를 바로 쓸 수 있습니다. 그래서 한 라이브러리를 두고 두 뜻이 함께 나옵니다.
코드를 나누는 패키지
자바 프로그램은 패키지들의 모음으로 짜입니다. 패키지마다 클래스와 인터페이스 이름의 집합을 따로 갖습니다. 그래서 이름 충돌을 막는 데 도움이 됩니다. 이렇게 이름이 겹치지 않게 나눈 구역을 네임스페이스라고 부릅니다.
자바에서는 소스 파일 맨 위에 그 파일이 속할 패키지를 적습니다.
package jag.scrabble.board; // 이 파일의 클래스는 jag.scrabble.board 패키지에 속한다
패키지 이름은 점으로 이은 계층입니다. 작은 프로그램이나 가볍게 짜는 코드는 패키지에 이름을 안 붙여도 되고 짧은 이름으로도 됩니다. 널리 배포할 코드라면 점으로 이은 긴 이름으로 겹치지 않는 이름을 골라야 합니다. 두 개발 그룹이 우연히 같은 패키지 이름을 골랐다가 나중에 한 프로그램에서 만나면 충돌이 납니다. 긴 이름을 고르면 그 충돌을 막는 데 도움이 됩니다.
간단한 구성에서는 패키지 이름을 디렉터리 경로로 바꿔 저장할 수 있습니다. 점을 디렉터리 구분자로 바꿔 jag.scrabble.board 를 jag/scrabble/board 로 두는 식입니다. 이것은 방법의 하나일 뿐입니다. 패키지를 어떻게 만들고 저장할지는 자바를 돌리는 쪽 시스템이 정합니다.
패키지 이름은 소스 코드 안의 이름입니다. 실행할 때 자바가 읽는 것은 컴파일한 클래스 파일입니다. 클래스 파일 여럿을 한 파일로 묶은 것이 JAR(Java ARchive, 자바 아카이브) 파일입니다.
그 클래스 파일을 어디서 찾을지는 클래스패스가 정합니다. 클래스패스는 클래스 파일을 찾아볼 디렉터리와 JAR 파일 같은 것의 목록입니다. 패키지 이름을 적어 두는 일과 그 코드를 찾아 싣는 일은 이렇게 따로 놓여 있습니다.
파이썬은 패키지를 모듈의 한 종류로 둡니다. 모듈은 파이썬 코드를 불러오는 단위입니다. 패키지는 그 모듈 가운데 다른 모듈을 안에 담을 수 있는 종류입니다. 예를 들어 email 패키지 안에 email.mime 하위 패키지가 있습니다. 그 안에 email.mime.text 모듈이 있습니다.
파이썬 패키지는 흔히 디렉터리에, 모듈은 그 안의 파일에 빗대어 설명합니다. 패키지와 모듈이 꼭 파일 시스템에서 오는 것은 아니라서 이 대응은 빗댄 것입니다.
코드 패키지가 하는 일이 하나 더 있습니다. 패키지 밖에서 무엇이 보일지를 정합니다. 언어마다 감추는 방법이 다릅니다.
| 언어 | 무엇이 한 패키지가 되나 | 패키지 밖에 감추는 법 |
|---|---|---|
| 자바 | 맨 위에 같은 package 선언을 단 소스 파일들 |
public 같은 접근 제어자를 안 붙인 최상위 클래스와 인터페이스는 그 패키지 안에서만 쓸 수 있다 |
| 파이썬 | 하위 모듈을 담을 수 있는 모듈. 대개 디렉터리 하나 | 밑줄 하나로 시작하는 이름은 내부용이라는 약한 표시다. from M import * 에 딸려 오지 않는다 |
| Go | 같은 디렉터리에서 함께 컴파일되는 소스 파일들. 파일마다 맨 위에 package 절을 단다 |
첫 글자가 대문자이고, 패키지 블록에서 선언한 이름이거나 필드 이름 · 메서드 이름인 것만 밖으로 내보낸다. 나머지는 내보내지 않는다 |
배포하는 패키지
남이 만든 라이브러리를 쓰려면 코드 파일만으로는 모자랍니다. 그 라이브러리의 이름과 버전을 알아야 합니다. 그 라이브러리가 기대는 다른 패키지도 함께 있어야 합니다. 이렇게 먼저 깔려 있어야 하는 다른 패키지를 의존성이라고 부릅니다.
배포 패키지는 내려받아 설치할 수 있는 소프트웨어 한 벌입니다. 버전이 붙은 압축 파일입니다. 그 안에 코드와 함께 쓰는 자원 파일이 들어 있습니다. 사용자가 인터넷에서 내려받아 설치하는 것이 이 파일입니다.
결과물에 붙는 이름 · 버전 · 의존성 같은 정보를 메타데이터라고 부릅니다. 메타데이터를 어디에 적는지는 생태계마다 다릅니다.
| 생태계 | 패키지의 모양 | 이름 · 버전 · 의존성이 적히는 곳 |
|---|---|---|
| npm | package.json 이 기술하는 폴더, 또는 그 폴더를 압축한 파일 |
package.json |
| 파이썬 | 버전이 붙은 압축 파일 | 의존성은 pyproject.toml 의 dependencies 에 이름으로 적는다. 이름과 버전이 적히는 곳은 자료에 없다(미확인) |
| 자바(Maven) | 대개 JAR 파일과 POM(Project Object Model, 프로젝트 객체 모델) 파일 | POM. 프로젝트 정보와 버전 · 의존성을 담는 XML(Extensible Markup Language) 파일이다 |
| 데비안 계열 리눅스 | .deb 파일 |
패키지 안에 든 control 파일의 Package · Version · Depends 필드 |
이 정보를 읽고 패키지를 설치하는 도구를 패키지 관리자라고 부릅니다. 파이썬의 pip, 자바스크립트의 npm, 데비안의 dpkg 가 그런 도구입니다. dpkg 는 apt 같은 앞단 도구를 거쳐 쓰기도 합니다.
의존성이 어떻게 쓰이는지는 데비안의 예가 잘 보여 줍니다. C 컴파일러 gcc 를 담은 패키지는 링커와 어셈블러를 담은 binutils 패키지에 기댑니다. binutils 없이 gcc 를 설치하려 하면 dpkg 가 binutils 도 필요하다는 오류를 내고 설치를 멈춥니다.
패키지를 모아 두고 내려받게 해 주는 곳도 생태계마다 있습니다. 이런 곳을 패키지 색인이라고 부릅니다. 파이썬에서 가장 널리 알려진 색인이 PyPI(Python Package Index, 파이썬 패키지 색인)입니다. npm 에서는 npm 레지스트리, 데비안에서는 데비안 아카이브가 그 곳입니다.
PyPI 같은 색인 안에서도, 데비안 아카이브 안에서도 배포 패키지 이름은 하나뿐이어야 합니다.
두 뜻이 한 라이브러리에서 만나는 대목
두 뜻은 따로 노는 것 같습니다. 하지만 한 라이브러리 안에서 동시에 나옵니다. 배포 패키지 하나가 코드 패키지를 담아 오기 때문입니다.
파이썬에서 pip install pkg 의 pkg 는 배포 패키지 이름입니다. import pkg 의 pkg 는 코드 패키지 이름입니다. 배포 패키지를 설치하고 나면 그 안에 든 코드 패키지를 import 할 수 있습니다.
대개는 배포 패키지 하나가 이름이 같은 코드 패키지 하나를 줍니다. 코드 패키지가 아닌 모듈 하나를 줄 때도 있습니다. pip install numpy 로 설치하면 import numpy 로 부릅니다. 그런데 이름이 같은 것은 관례일 뿐입니다. PyPI 를 비롯한 패키지 색인은 두 이름 사이의 관계를 강제하지 않습니다.
그래서 두 이름이 갈리는 라이브러리가 있습니다. 이미지 처리 라이브러리 Pillow 는 설치할 때는 Pillow 라는 배포 이름을 씁니다. 코드에서는 PIL 로 부릅니다. 까닭은 포크에 있습니다. 포크는 기존 라이브러리의 코드를 복제해 따로 이어 가는 것입니다.
Pillow 는 PIL 라이브러리의 포크로 시작했습니다. 기존 PIL 사용자가 적은 수고로 옮겨 오게 하려고 코드 이름을 PIL 로 남겼습니다. 더 넓게 보면 포크가 배포 이름과 코드 이름이 갈리는 흔한 원인입니다.
배포 패키지 하나가 코드 패키지 여럿을 주기도 합니다. 덜 흔한 경우입니다. attrs 배포 패키지는 새 API(Application Programming Interface, 애플리케이션 프로그래밍 인터페이스)를 담은 attrs 코드 패키지를 줍니다. 예전 API 를 담은 attr 코드 패키지도 함께 줍니다. attr 쪽도 계속 지원합니다.
flowchart TD
I1["pip install Pillow"] --> D1
subgraph D1["배포 패키지 · Pillow"]
C1["코드 패키지 · PIL"]
end
C1 --> U1["import PIL"]
I2["pip install attrs"] --> D2
subgraph D2["배포 패키지 · attrs"]
C2["코드 패키지 · attrs"]
C3["코드 패키지 · attr"]
end
C2 --> U2["import attrs"]
C3 --> U3["import attr"]
그림에서 바깥 상자를 다루는 쪽은 패키지 관리자입니다. 안쪽 상자를 다루는 쪽은 개발자가 쓴 코드입니다.
배포 이름은 색인 안에서 하나뿐이어야 합니다. 코드 패키지 이름에는 그런 제약이 없습니다. 같은 이름의 코드 패키지를 여러 배포 패키지가 줄 수 있습니다. 이때도 포크가 흔한 원인입니다.
두 뜻을 섞으면 대가가 따릅니다. 코드에서 import foo 를 봤다고 PyPI 의 foo 를 덮어놓고 설치하면 안 됩니다. 의도하지 않은 패키지가 깔릴 수 있습니다. 경우에 따라 그것이 악성 패키지일 수도 있습니다.
맥락별 뜻
이 절은 「패키지」를 쓰는 세 맥락을 갈라 봅니다. 맥락마다 그 뜻을 정의한 문서를 따로 댑니다. 재는 것은 세 뜻이 같은 물건을 가리키느냐입니다.
| 맥락 | 이 맥락에서의 뜻 | 출처 |
|---|---|---|
| 프로그래밍 언어의 코드 구성 | 클래스 · 함수 같은 이름을 나눠 담는 묶음. 패키지마다 이름 집합을 따로 갖는다 | 자바 언어 명세 7장 · 파이썬 언어 레퍼런스 「Packages」 · Go 언어 명세 「Packages」 |
| 언어 생태계의 배포 | 내려받아 설치할 수 있는 소프트웨어 한 벌. 프로젝트를 가리키기도 하고, 그 프로젝트의 특정 버전을 담은 파일을 가리키기도 한다 | 파이썬 패키징 안내서 「Distribution package vs. import package」 · 같은 안내서의 용어집 · npm 문서 「About packages and modules」 |
| 리눅스 배포판 | 배포판의 패키지 관리 시스템이 시스템에 설치하는 묶음. 실행 파일 · 설정 파일 · 매뉴얼 페이지 · 문서를 담는다 | 데비안 FAQ(Frequently Asked Questions, 자주 묻는 질문) 7장 · 데비안 정책 3장 |
첫째 줄과 나머지 두 줄은 가리키는 물건의 종류가 다릅니다. 첫째 줄은 코드 안의 이름 구역입니다. 둘째와 셋째 줄은 설치하는 파일 묶음입니다.
flowchart TD
P["「패키지」"]
P --> K1["코드 안의 이름 구역"]
P --> K2["설치하는 파일 묶음"]
K1 --> C1["코드 구성 맥락 · 파이썬 용어로 import package"]
K2 --> C2["언어 생태계의 배포 맥락 · 파이썬 용어로 distribution package"]
K2 --> C3["리눅스 배포판 맥락"]
코드 구성 맥락
이 맥락에서 패키지는 프로그램을 짜는 동안 쓰는 이름 구역입니다. 패키지에는 클래스와 인터페이스가 들어 있습니다. 하위 패키지도 들 수 있습니다.
파이썬 쪽 용어로는 이것을 import package 라고 부릅니다. import 문으로 불러오는 이름이기 때문입니다.
언어 생태계의 배포 맥락
이 맥락에서 패키지는 내려받아 설치하는 단위입니다. 앞에서 배포 패키지라고 부른 것이 이것입니다. pip install pkg 를 칠 때나 pyproject.toml 에 dependencies = ["pkg"] 를 적을 때 pkg 가 이 뜻입니다. PyPI 를 검색해서 나오는 목록도 이 뜻의 패키지들입니다.
파이썬 쪽 용어로는 이것을 distribution package 라고 부릅니다. 이 말은 대개 「프로젝트」와 같은 뜻입니다. 한편 한 프로젝트의 특정 버전을 담은 파일 하나를 가리킬 때도 씁니다.
파이썬 쪽은 두 뜻을 헷갈리지 않게 하려고 필요할 때마다 import package 와 distribution package 를 풀어 씁니다. 평소에는 둘 다 그냥 「package」라고 부르기 때문입니다.
npm 에서도 패키지는 이 뜻입니다. package.json 이 기술하는 파일이나 디렉터리가 패키지입니다. npm 레지스트리에 올리려면 package.json 이 반드시 있어야 합니다.
리눅스 배포판 맥락
이 맥락에서 패키지는 운영체제에 소프트웨어를 까는 단위입니다. 데비안 패키지는 두 종류입니다. 원래 소스와 데비안용 변경을 담는 소스 패키지가 하나입니다. 실행 파일 · 설정 파일 · 매뉴얼 페이지 · 저작권 정보 · 문서를 담는 바이너리 패키지가 다른 하나입니다. 바이너리 패키지는 대개 확장자가 .deb 입니다.
.deb 패키지 하나에는 파일이 두 벌 들어 있습니다. 한 벌은 설치할 때 시스템에 놓을 파일입니다. 다른 한 벌은 패키지 메타데이터 파일입니다. 설치나 제거 때 도는 스크립트와 control 파일이 여기 듭니다.
언어 생태계의 배포 맥락과 이 맥락은 둘 다 설치하는 묶음을 말합니다. 갈리는 것은 설치를 맡는 주체입니다. 언어 쪽은 pip 과 npm 이 설치합니다. 리눅스 배포판 쪽은 배포판의 패키지 관리 시스템인 dpkg 와 그 앞단 apt 가 설치합니다. 파이썬 쪽 용어에서도 리눅스 배포판의 패키지는 다른 뜻으로 셉니다.
어느 뜻인지 가르는 단서
글이나 대화에서 「패키지」가 나오면 함께 붙은 낱말을 봅니다. 대개 그것만으로 어느 맥락인지 갈립니다.
| 함께 나오는 말 | 맥락 |
|---|---|
import 한다 · package 선언 · 하위 패키지 · 패키지 안에서만 보인다 |
코드 구성 |
pip install · npm install · 의존성에 적는다 · PyPI · 레지스트리에 올린다 |
언어 생태계의 배포 |
.deb · apt · dpkg · 데비안 아카이브 |
리눅스 배포판 |
경계
「패키지」와 가장 자주 섞이는 이웃 말이 「모듈」입니다. 다만 그 둘의 관계는 생태계마다 다릅니다. 파이썬에서는 패키지가 모듈의 한 종류입니다. Go 에서는 모듈이 패키지 여럿을 묶는 단위입니다. npm 에서는 두 말이 일부만 겹칩니다. 이 절은 그중 npm 의 정의를 가지고 한 경우를 판정합니다.
node_modules 안에 있는 자바스크립트 파일 하나는 require() 로 불러올 수 있습니다. 이 파일은 패키지인가. 아닙니다. 모듈입니다.
npm 에서 모듈은 node_modules 디렉터리 안에서 Node.js 의 require() 나 import 로 불러올 수 있는 파일이나 디렉터리입니다. require() 로 불러오려면 둘 중 하나여야 합니다. package.json 에 main 항목을 적어 둔 폴더이거나, 자바스크립트 파일 하나입니다. main 항목이 무엇을 가리키는지는 자료에 없습니다(미확인).
패키지는 package.json 이 기술하는 파일이나 디렉터리입니다. 모듈은 package.json 이 없어도 됩니다. 그래서 모든 모듈이 패키지인 것은 아닙니다. package.json 을 가진 모듈만 패키지이기도 합니다.
flowchart TD
subgraph M["모듈 · require 로 불러올 수 있는 파일이나 디렉터리"]
F["자바스크립트 파일 하나 · package.json 없음"]
subgraph P["패키지이기도 한 모듈"]
D["main 항목을 적어 둔 package.json 을 가진 폴더"]
end
end
판정의 근거는 package.json 의 유무입니다. 자바스크립트 파일 하나에는 package.json 이 없습니다. 그러니 불러올 수는 있어도 패키지는 아닙니다.
이견
맥락별 뜻은 낱말 하나가 여러 물건을 가리키는 갈림이었습니다. 이 절은 방향이 반대인 갈림을 봅니다. 여러 프로젝트가 가져다 쓰는 단위 하나를 생태계마다 다른 이름으로 부르는 갈림입니다. 그 단위는 앞에서 「배포 패키지」라고 부른 것과 같습니다.
| 생태계 | 가져다 쓰는 단위를 부르는 이름 | 그 생태계에서 「package」가 가리키는 것 | 누가 그렇게 부르나 |
|---|---|---|---|
| Go | module. 함께 릴리스되고 버전이 붙고 배포된다 | 같은 디렉터리에서 함께 컴파일되는 소스 파일 묶음. 코드 단위다 | Go 모듈 레퍼런스 · How to Write Go Code |
| Rust | crate. 라이브러리와 바꿔 쓰는 말이다 | Cargo.toml 을 갖고 crate 를 하나 이상 묶는 단위 |
The Rust Programming Language 7.1 |
| Maven | artifact. Maven 이 내려받고 설치하고 배포하는 파일이다 | packaging 설정값의 이름에 낱말이 들어 있다. 그 값의 기본은 jar 다 |
Maven 문서 「Introduction to the POM」 · 「Artifacts」 |
| npm · PyPI · 데비안 | package | 가져다 쓰는 단위와 같다 | npm 문서 · 파이썬 패키징 안내서 · 데비안 FAQ |
Go — module 과 package
Go 문서는 함께 릴리스되고 버전이 붙고 배포되는 패키지들의 묶음을 module 이라고 부릅니다. 모듈은 go.mod 파일에 선언한 모듈 경로로 가리킵니다. go.mod 에는 그 모듈의 의존성 정보도 함께 적힙니다.
Go 에서 package 는 코드 단위로 남습니다. 모듈 안의 패키지 경로는 모듈 경로에 하위 디렉터리를 이은 것입니다. 예를 들어 golang.org/x/net 모듈의 html 디렉터리에 든 패키지는 경로가 golang.org/x/net/html 입니다.
Rust — crate 와 package
The Rust Programming Language 는 crate 를 Rust 컴파일러가 한 번에 다루는 가장 작은 코드 단위라고 정의합니다. 라이브러리 crate 는 여러 프로젝트가 나눠 쓸 기능을 정의합니다. 같은 책에 따르면 Rust 개발자들이 「crate」라고 하면 대개 라이브러리 crate 를 뜻합니다. 이 말을 「라이브러리」와 바꿔 쓰기도 합니다.
같은 책에서 package 는 crate 를 하나 이상 묶어 기능 한 벌을 내는 단위입니다. 패키지에는 그 crate 들을 어떻게 빌드할지 적은 Cargo.toml 파일이 있습니다. 패키지 하나에 라이브러리 crate 는 많아야 하나입니다. 바이너리 crate 는 여럿 둘 수 있습니다.
flowchart TD
subgraph GO["Go — package 가 안쪽에 선다"]
M["module · go.mod 에 경로를 선언한다"]
M --> GP["package · golang.org/x/net/html"]
end
subgraph RS["Rust — package 가 바깥쪽에 선다"]
PK["package · Cargo.toml 을 갖는다"]
PK --> CR1["라이브러리 crate · 많아야 하나"]
PK --> CR2["바이너리 crate · 여럿 둘 수 있다"]
end
같은 낱말이 Go 에서는 안쪽 층에 붙고 Rust 에서는 바깥쪽 층에 붙습니다.
Maven — artifact 와 packaging
Maven 문서는 Maven 이 내려받고 설치하고 배포하는 파일을 artifact 라고 부릅니다. artifact 는 대개 POM 과 JAR 입니다. groupId:artifactId:version 꼴의 좌표로 가리킵니다. 셋을 이어 붙인 것이 그 프로젝트의 완전한 artifact 이름입니다.
Maven 에서 「package」 낱말은 packaging 이라는 설정값의 이름으로 나옵니다. 모든 Maven 프로젝트가 이 값을 하나씩 갖습니다. POM 에 따로 적지 않으면 기본값은 jar 입니다. 이 값이 무엇을 정하는지는 자료에 없습니다(미확인).
npm · PyPI · 데비안 문서는 이 단위를 그냥 package 라고 부릅니다.
관련 항목
코드 패키지와 함께 이름을 나누는 언어 요소
네임스페이스 · 모듈 · 하위 패키지 · 클래스 · 인터페이스 · 접근 제어자 · import · 식별자
자바가 코드 패키지를 찾아 싣는 데 쓰는 요소
클래스패스 · 클래스 파일 · JAR · 자바 언어 명세 · 자바 모듈 시스템
배포 패키지를 받아서 설치하는 도구
패키지 관리자 · npm · pip · Maven · Gradle · Cargo
배포 패키지를 담는 파일 형식
WAR · wheel · tarball · 컨테이너 이미지
배포 패키지에 붙는 이름 · 버전 · 의존성 정보
메타데이터 · 버전 번호 · 시맨틱 버저닝 · 의존성 · package.json · pom.xml · pyproject.toml · go.mod · Cargo.toml · 락 파일
배포 패키지가 올라가는 저장소
PyPI · npm 레지스트리 · Maven 중앙 저장소 · 아티팩트 저장소 · 패키지 저장소
리눅스 배포판에서 시스템 패키지를 다루는 도구와 형식
리눅스 배포판 · 데비안 · dpkg · apt · deb · 데비안 아카이브
배포 단위를 패키지 대신 가리키는 다른 이름
Go 모듈 · crate · 아티팩트 · 라이브러리
배포 패키지가 거치는 릴리스 단계
빌드 · 빌드 아티팩트 · 릴리스 엔지니어링 · 배포 · 패키지 서명
배포 패키지에서 자주 나는 장애
의존성 지옥 · 버전 충돌 · 타이포스쿼팅 · 소프트웨어 공급망 보안
다른 이름: package