Go에서의 종속성 관리
Go는 종속성 관리를 위해 일반적인 접근 방식을 취하고 있습니다.
즉, 아티팩트 기반이 아닌 소스 기반입니다.
아티팩트 기반 종속성 관리 시스템에서는 패키지가 소스 코드에서 생성된 아티팩트로 구성되어 있으며,
소스 코드와는 별도의 저장소 시스템에 저장됩니다.
예를 들어, 많은 NodeJS 패키지가 npmjs.org
를 패키지 저장소로 사용하고 github.com
을
소스 저장소로 사용합니다. 반면, Go의 패키지는 소스 코드이며, 패키지를 배포하는 것은 아티팩트 생성이나
별도의 저장소와 관련이 없습니다. Go 패키지는 VCS 서버의 버전 관리 저장소에 저장되어야 합니다.
종속성은 직접 해당 VCS 서버에서 가져오거나, 해당 VCS 서버에서 가져오는 중개 프록시를 통해 가져옵니다.
버전 관리
Go 1.11은 Go 생태계에 모듈과 일급 패키지 버전 관리를 도입했습니다. 이전에는 Go에서 버전 관리에 대한 잘 정의된 메커니즘이 없었습니다. 3자 버전 관리 도구가 존재했지만, 기본 Go 경험에는 버전 관리에 대한 지원이 없었습니다.
Go 모듈은 시맨틱 버전 관리를 사용합니다.
모듈의 버전은 유효한 시맨틱 버전으로 v
로 접두사 붙은 VCS(버전 관리 시스템) 태그로 정의됩니다.
예를 들어, gitlab.com/my/project
의 버전 1.0.0
을 배포하려면 개발자가 Git 태그 v1.0.0
을 생성해야 합니다.
0과 1 이외의 주요 버전의 경우, 모듈 이름은 /vX
로 접미사가 붙어야 하며, 여기서 X는 주요 버전입니다.
예를 들어, gitlab.com/my/project
의 버전 v2.0.0
은
gitlab.com/my/project/v2
로 이름이 지정되고 가져와야 합니다.
Go는 특정 VCS 커밋을 참조하는 특별한 시맨틱 버전인 ‘의사 버전(pseudo-versions)’을 사용합니다. 시맨틱 버전의 프리릴리스 구성 요소는 타임스탬프와 커밋 식별자의 처음 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 웹사이트의 이 블로그 게시물 시리즈를 참조하세요.
‘모듈’과 ‘패키지’
- 패키지는
*.go
파일이 포함된 폴더입니다. - 모듈은
go.mod
파일이 포함된 폴더입니다. - 모듈은 대개 패키지입니다. 즉,
go.mod
파일과*.go
파일이 포함된 폴더입니다. - 모듈은 서브디렉터리를 가질 수 있으며, 서브디렉터리는 패키지가 될 수 있습니다.
- 모듈은 일반적으로 VCS 저장소(예: Git, SVN, Hg 등)의 형태로 제공됩니다.
- 모듈의 서브디렉터리가 모듈인 경우, 이는 서로 다른 별개의 모듈이며
포함된 모듈에서 제외됩니다.
- 모듈
repo
가 주어지면,repo/sub
에go.mod
파일이 포함된 경우,repo/sub
와 그 안에 포함된 모든 파일은 별도의 모듈이며repo
의 일부가 아닙니다.
- 모듈
이름 지정
모듈 또는 패키지의 이름은 표준 라이브러리를 제외하고는 다음 형식이어야 합니다: (sub.)*domain.tld(/path)*
. 이는 URL과 유사하지만 URL은 아닙니다. 패키지 이름에는 스킴(예: https://
)이 포함될 수 없으며, 포트 번호를 가질 수 없습니다. example.com:8443/my/package
는 유효한 이름이 아닙니다.
패키지 가져오기
Go 1.12 이전에 패키지를 가져오는 프로세스는 다음과 같았습니다:
-
https://{패키지 이름}?go-get=1
을 조회합니다. - 응답에서
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
로 시작하는 패키지가 https://gitlab.com/my/project.git
에서 Git을 사용하여 가져와야 함을 나타냅니다.
모듈 가져오기
Go 1.12는 체크섬 데이터베이스와 모듈 프록시를 도입했습니다.
체크섬
go.mod
외에, 모듈에는 go.sum
파일이 있습니다. 이 파일은 모듈 또는 모듈의 종속성 중 하나가 참조하는 모든 버전의 코드 및 go.mod
파일의 SHA-256 체크섬을 기록합니다. Go는 새로운 종속성을 참조할 때마다 go.sum
을 지속적으로 업데이트합니다.
Go가 모듈의 종속성을 가져올 때, 해당 종속성이 이미 go.sum
에 항목이 있다면, Go는 이러한 종속성의 체크섬을 검증합니다. 만약 체크섬이 go.sum
에 있는 내용과 일치하지 않으면, 빌드는 실패합니다. 이는 특정 버전의 모듈이 개발자나 악의적인 당사자에 의해 변경되지 않도록 보장합니다.
Go 1.12+는 체크섬 데이터베이스를 사용하도록 구성할 수 있습니다. 그렇게 구성된 경우, Go가 종속성을 가져올 때 해당 종속성이 go.sum
에서 일치하는 항목이 없으면, Go는 다운로드한 종속성에서 계산하는 대신 구성된 체크섬 데이터베이스에 대해 체크섬을 조회합니다. 체크섬 데이터베이스에서 종속성을 찾을 수 없으면, 빌드는 실패합니다. 다운로드된 종속성의 체크섬이 체크섬 데이터베이스의 결과와 일치하지 않으면, 빌드는 실패합니다. 다음 환경 변수로 제어됩니다:
-
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://{모듈 또는 패키지 이름}?go-get=1
에 쿼리합니다. - 응답에서
go-import
메타 태그를 확인합니다. - 메타 태그에 의해 표시된 VCS를 사용하여 레포지토리를 가져옵니다.
-
{vcs}
필드가mod
인 경우, URL은 VCS 대신 모듈 프록시로 간주해야 합니다.
-
-
모듈이 직접 가져오고 있고 종속성으로 가져오지 않는 경우, 멈춥니다.
-
go.sum
에 모듈에 해당하는 항목이 포함되어 있다면, 체크섬을 검증하고 멈춥니다. -
GOSUMDB
가 체크섬 데이터베이스를 식별하고 모듈이GONOSUMDB
또는GOPRIVATE
에 의해 제외되지 않았다면, 모듈의 체크섬을 가져와서go.sum
에 추가하고 다운로드한 소스와 이를 검증합니다. -
GOSUMDB
가off
이거나 모듈이 제외된 경우, 다운로드한 소스에서 체크섬을 계산하고 이를go.sum
에 추가합니다.
다운로드된 소스는 go.mod
파일을 포함해야 합니다. go.mod
파일에는 모듈의 이름을 지정하는 module
지시문이 포함되어야 합니다. If go.mod
가 지정한 모듈 이름이 모듈을 가져오는 데 사용된 이름과 일치하지 않으면 모듈이 컴파일되지 않습니다.
모듈이 직접 가져오고 있고 버전이 지정되지 않았거나 모듈이 종속성으로 추가되고 있고 버전이 지정되지 않았다면, Go는 모듈의 최신 버전을 사용합니다. 모듈이 프록시에서 가져오면 Go는 버전 목록을 위해 프록시를 요청하고 최신 버전을 선택합니다. 모듈이 직접 가져오면 Go는 태그 목록을 위해 레포지토리를 쿼리하고 유효한 의미론적 버전 중에서 최신 버전을 선택합니다.
인증
Go 1.13 이전 버전에서는 Go가 수행하는 요청에 대한 인증 지원이 다소 일관성이 없었습니다. Go 1.13은 .netrc
인증 지원을 개선했습니다. 요청이 HTTPS를 통해 이루어지고 일치하는 .netrc
항목을 찾을 수 있다면, Go는 요청에 HTTP Basic 인증 자격 증명을 추가합니다. Go는 HTTP를 통해 이루어진 요청을 인증하지 않습니다. Go는 자격 증명이 포함된 GOPROXY
의 HTTP 전용 항목을 거부합니다.
향후 버전에서 Go는 임의의 인증 헤더에 대한 지원을 추가할 수 있습니다. 자세한 내용은 golang/go#26232
를 참조하십시오.