Go 의존성 관리
Go는 의존성 관리에 대해 이례적인 방식을 취하는데, 이는 패키지와 관련된 아티팩트가 아닌 소스 기반으로 이루어진다는 점이다. 아티팩트 기반 의존성 관리 시스템에서는 패키지가 소스 코드에서 생성된 아티팩트로 구성되며 소스 코드와는 별도의 리포지터리 시스템에 저장된다. 예를 들어, 많은 NodeJS 패키지는 패키지 리포지터리로 npmjs.org
을 사용하고 소스 리포지터리로 github.com
을 사용한다. 반면, Go의 패키지는 소스 코드이며, 패키지 릴리스는 아티팩트 생성이나 별도의 리포지터리가 관여하지 않는다. Go 패키지는 반드시 VCS 서버에 있는 버전 관리 리포지터리에 저장되어야 한다. 의존성은 VCS 서버에서 직접 가져오거나 중간 프록시를 통해 가져온다.
버전 관리
Go 1.11에서 모듈과 Go 생태계에 대한 첫 번째 클래스 패키지 버전 관리가 도입되었다. 이전에는 Go에는 버전 관리에 대한 명확한 메커니즘이 없었다. 3rd party 버전 관리 도구가 존재했지만, 기본 Go 경험에는 버전 관리를 위한 지원이 없었다.
Go 모듈은 의미 있는 버전를 사용한다. 모듈의 버전은 VCS(버전 관리 시스템) 태그로 정의되며 v
로 시작하는 유효한 의미 있는 버전으로 구성된다. 예를 들어, gitlab.com/my/project
의 버전 1.0.0
을 릴리스하기 위해서는 개발자가 v1.0.0
태그를 생성해야 한다.
0과 1 이외의 주 버전에 대해, 모듈 이름은 반드시 /vX
로 끝나야 한다. 예를 들어, gitlab.com/my/project
의 버전 v2.0.0
은 gitlab.com/my/project/v2
로 명명되고 가져와야 한다.
Go는 특정 VCS 커밋을 참조하는 특별한 의미 있는 버전인 ‘의사 버전’을 사용한다. 의미 있는 버전의 프리 릴리스 컴포넌트는 타임스탬프로 시작하거나 끝나야 하며, 커밋 식별자의 처음 12자를 포함해야 한다.
-
vX.0.0-yyyymmddhhmmss-abcdefabcdef
: X에 대한 이전 태그 커밋이 없을 때 -
vX.Y.Z-pre.0.yyyymmddhhmmss-abcdefabcdef
: 가장 최근의 이전 태그가 vX.Y.Z-pre인 경우 -
vX.Y.(Z+1)-0.yyyymmddhhmmss-abcdefabcdef
: 가장 최근의 이전 태그가 vX.Y.Z인 경우
VCS 태그가 이러한 패턴 중 하나와 일치하는 경우, 무시된다.
Go 모듈 및 버전 관리에 대한 완전한 이해를 위해서는 공식 Go 웹사이트의 이 블로그 시리즈를 참조하십시오.
‘모듈’ vs ‘패키지’
- 패키지는
*.go
파일을 포함하는 폴더이다. - 모듈은
go.mod
파일을 포함하는 폴더이다. - 모듈은 보통
go.mod
파일과*.go
파일을 포함하는 패키지이다. - 모듈은 서브디렉터리를 가질 수 있으며, 해당 서브디렉터리는 패키지일 수 있다.
- 모듈은 대개 VCS 리포지터리(Git, SVN, Hg 등) 형태로 제공된다.
- 모듈의 서브디렉터리 중 모듈인 경우, 해당 모듈은 별도의 모듈로 취급되어 모듈에 포함되지 않는다.
- 모듈
repo
가 주어지면,repo/sub
가go.mod
파일을 포함하는 경우repo/sub
및 해당 파일은 별도의 모듈로 취급되어repo
의 일부가 아니다.
- 모듈
명명
표준 라이브러리를 제외한 모듈 또는 패키지의 이름은 일련의 규칙을 따라야 한다. 이는 URL과 유사하지만 URL은 아니다. 패키지 이름에는 https://
와 같은 스킴이 없어야 하며 포트 번호가 있어서는 안 된다. example.com:8443/my/package
는 유효한 이름이 아니다.
패키지 가져오기
Go 1.12 이전에 패키지를 가져오는 과정은 다음과 같다:
-
https://{package name}?go-get=1
을 쿼리한다. -
go-import
메타 태그를 위한 응답을 스캔한다. -
go-import
메타 태그에 표시된 VCS를 사용하여 메타 태그가 가리키는 리포지터리를 가져온다.
메타 태그는 <meta name="go-import" content="{prefix} {vcs} {url}">
형식을 가져야 한다. 예를 들어, gitlab.com/my/project git https://gitlab.com/my/project.git
은 gitlab.com/my/project
로 시작하는 패키지는 gitlab.com/my/project.git
에서 Git을 사용하여 가져와야 한다는 것을 나타낸다.
모듈 가져오기
Go 1.12에서는 체크섬 데이터베이스와 모듈 프록시가 도입되었다.
체크섬
go.mod
외에도 모듈은 go.sum
파일을 가진다. 이 파일은 모듈이나 모듈의 의존성 중 하나가 참조하는 모든 버전의 코드와 go.mod
파일의 SHA-256 체크섬을 기록한다. Go는 새로운 의존성이 참조됨에 따라 지속적으로 go.sum
을 업데이트한다.
Go는 모듈의 의존성을 가져올 때, 만약 이러한 의존성에 대한 go.sum
항목이 이미 존재한다면 해당 체크섬을 확인한다. 체크섬이 go.sum
에 있는 것과 일치하지 않으면 빌드가 실패한다. 이를 통해 모듈의 특정 버전이 개발자에 의해 또는 악의적인 당사자에 의해 변경될 수 없도록 보장한다.
Go 1.12+는 체크섬 데이터베이스를 사용하도록 구성할 수 있다. 이렇게 구성된 경우 모듈의 의존성을 가져올 때 go.sum
에 해당 항목이 없으면 다운로드된 의존성에서 체크섬을 계산하는 대신 구성된 체크섬 데이터베이스에 대한 쿼리를 수행한다. 의존성이 체크섬 데이터베이스에서 찾을 수 없는 경우 빌드가 실패한다. 다운로드된 의존성의 체크섬이 체크섬 데이터베이스의 결과와 일치하지 않으면 빌드가 실패한다. 다음 환경 변수가 이를 제어한다:
-
GOSUMDB
는 쿼리할 체크섬 데이터베이스의 이름 및 필요에 따라 공개 키와 서버 URL을 식별한다.- 값이
off
이면 체크섬 데이터베이스 쿼리를 완전히 비활성화한다. - Go 1.13+에서는
GOSUMDB
가 정의되지 않은 경우sum.golang.org
를 사용한다.
- 값이
-
GONOSUMDB
는 체크섬 데이터베이스 쿼리가 비활성화되어야 하는 모듈 접미사의 쉼표로 구분된 디렉터리이다. 와일드카드를 지원한다. -
GOPRIVATE
는 다른 기능들 뿐만 아니라GONOSUMDB
와 유사한 기능을 하는 모듈 이름의 쉼표로 구분된 디렉터리이다.
프록시
Go 1.12+는 모듈을 모듈의 VCS에서 직접 가져오는 대신 모듈을 Go 프록시에서 가져오도록 구성할 수 있다. 이렇게 구성된 경우 모듈을 가져올 때, Go는 구성된 프록시를 순서대로 시도한다. 다음 환경 변수가 이를 제어한다:
-
GOPROXY
는 쿼리할 모듈 프록시의 쉼표로 구분된 디렉터리이다.- 값이
direct
인 경우 모듈 프록시 쿼리를 완전히 비활성화한다. - 디렉터리의 마지막 항목이
direct
인 경우에는, 프록시가 해당 의존성을 제공하지 않으면 Go는 위에서 설명된 프로세스로 되돌아간다. - Go 1.13+에서는
GOPROXY
가 정의되지 않은 경우proxy.golang.org,direct
를 사용한다.
- 값이
-
GONOPROXY
는 직접 가져와야 하는 모듈 접미사의 쉼표로 구분된 디렉터리이다. 와일드카드를 지원한다. -
GOPRIVATE
는 다른 기능들 뿐만 아니라GONOPROXY
와 유사한 기능을 하는 모듈 이름의 쉼표로 구분된 디렉터리이다.
가져오기
Go 1.12부터 모듈 또는 패키지를 가져오는 과정은 다음과 같다:
-
GOPROXY
가 프록시 디렉터리이고 모듈이GONOPROXY
나GOPRIVATE
에 의해 제외되지 않은 경우, 순서대로 요청하고 첫 번째 유효한 응답에서 중단한다. -
GOPROXY
가direct
인 경우 또는 모듈이 제외될 경우 또는GOPROXY
가,direct
로 끝나고 어떤 프록시도 해당 의존성을 제공하지 않은 경우, 돌아간다.-
https://{module or package name}?go-get=1
을 쿼리한다. -
go-import
메타 태그를 위한 응답을 스캔한다. -
go-import
메타 태그에 표시된 VCS를 사용하여 메타 태그가 가리키는 리포지터리를 가져온다. -
{vcs}
필드가mod
인 경우, URL은 VCS 대신 모듈 프록시로 취급해야 한다.
-
- 모듈이 직접 가져오는 경우이고 버전이 지정되지 않았거나, 의존성으로 추가되는 모듈인 경우이고 버전이 지정되지 않았을 때, Go는 모듈의 가장 최근 버전을 사용한다. 모듈이 프록시에서 가져오는 경우, Go는 프록시에 버전 디렉터리을 쿼리하고 가장 최신 버전을 선택한다. 모듈이 직접 가져오는 경우, Go는 리포지터리에서 태그 디렉터리을 쿼리하고 가장 최신의 유효한 의미 있는 버전을 선택한다.
인증
Go 1.13 이전 버전에서는 Go에 의해 수행된 요청의 인증 지원이 다소 일관성이 없었습니다.
Go 1.13에서는 .netrc
인증의 지원이 향상되었습니다. HTTPS를 통해 요청이 이루어지고 .netrc
항목이 일치하는 경우, Go는 HTTP 기본 인증 자격 증명을 요청에 추가합니다. Go는 HTTP를 통해 이루어지는 요청에 대해 인증을 수행하지 않습니다. 또한 GOPROXY
에서 임베디드 자격 증명을 가진 HTTP 전용 항목은 Go에서 거부합니다.
향후 버전에서, Go는 임의의 인증 헤더를 지원할 수 있습니다.
자세한 내용은 golang/go#26232
을 참조하세요.