Go의 의존성 관리

이영민·2021년 12월 8일
0

History

~ v1.10

GOPATH 내에서만 관리.
$GOPATH/src 하위 디렉토리에서만 프로젝트를 생성할 수 있었음.

의존성 해결 방법

  1. 외부 패키지들을 vendor 디렉토리에 저장시킨 뒤 빌드에 참여시킴.
  2. 도커 이미지 상에서 GOPATH에 패키지들을 저장하여 도커 이미지로 관리.

v1.11 ~ v1.12

Go Module이 옵션 기능으로 등장.
디렉토리가 $GOPATH에 설정한 경로 상에 위치할 경우 go.mod 파일이 있더라도 모듈 모드로 동작하지 않음.
모듈 모드를 사용하기 위해서는 GO111MODULE이라는 환경변수를 on으로 설정.

v1.13 ~

디렉토리에 go.mod 파일이 있으면 기본적으로 모듈 모드로 동작.
v1.17부터 GOPATH를 통한 의존성 관리 기능이 없어질 거라는 얘기가 있었는데, 아직 있긴 한 듯.
다만 deprecated인 건 확실한 것 같음.

GOPATH vs Go Module

여러 프로젝트를 $GOPATH 단일 경로로 관리할 경우 각 프로젝트 의존성 패키지가 섞여 관리가 힘들어짐.
Go Module을 사용할 경우 프로젝트 별로 의존성 관리를 할 수 있음.

Go Module

A module is a collection of Go packages stored in a file tree with a go.mod file at its root.

최상위 디렉토리에 go.mod 파일을 만들면 해당 파일과 하위 패키지들을 포함한 모듈이 됨.

  • go.mod가 있는 곳이 module root.
  • Go Module은 프로젝트 디렉토리가 $GOPATH/src 외부에 있고, go.mod을 포함하거나 go.mod가 있는 디렉토리의 하위 경로일 때 사용 가능.

외부 모듈 버전 관리

외부 모듈 경로와 버전이 go.mod 파일에 기록됨. 외부 모듈을 다시 구성해야 할 경우 해당 버전으로 모듈 다운로드.

  • go 지시자가 생략되어 있고 go 명령어로 go.mod를 업데이트할 수 없을 경우 v1.11로 간주.
    • go 지시자는 v1.12부터 자동으로 추가되기 시작
  • go.mod가 없거나 go.mod에 go 지시자가 생략되어 있을 경우 v1.16으로 간주.
    • GOPATH 모드로 개발되었을 경우 go.mod가 없을 수 있음.
    • vendor/modules.txt는 v1.17까지도 go.mod의 go 버전을 기록하지 않음.
module sample
go 1.13
require (
	github.com/aliyun/aliyun-oss-go-sdk v2.0.5+incompatible
	github.com/artdarek/go-unzip v0.0.0-20180315101617-33dc05190e4b
	github.com/asaskevich/govalidator v0.0.0-20200108200545-475eaeb16496
	github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f // indirect
	github.com/extrame/ole2 v0.0.0-20160812065207-d69429661ad7 // indirect
	github.com/go-sql-driver/mysql v1.5.0
	github.com/go-xorm/xorm v0.7.9
	github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0
	github.com/labstack/echo v3.3.10+incompatible
	github.com/pangpanglabs/echoswagger v1.1.0
	github.com/pangpanglabs/goutils v0.0.0-20200116103626-3f9fcfaa29b0
	github.com/sergeilem/xls v0.0.1
	github.com/tealeg/xlsx v1.0.5
	github.com/urfave/cli v1.22.2
	golang.org/x/image v0.0.0-20200119044424-58c23975cae1
)

명령어

go mod init [path]

go.mod를 생성. path에는 해당 프로젝트의 패키지 명 입력.
path는 github에 업로드 후 모듈로 사용하게 되면 github.com/계정명/프로젝트명 의 형태로 사용하기 때문에 처음부터 이 형태로 작성하는 것을 권장.

go get [path]

path에 패키지 주소를 입력하여 외부 패키지를 다운 받음. 이 때 go.mod에도 함께 기록함.

go mod vendor

$GOPATH의 경로에서 해당 프로젝트 경로로 의존성 패키지 복사.

go run -mod vendor main.go

복사한 패키지를 통해 로컬 vendor 경로의 패키지를 사용할 수 있음.(Python의 venv처럼)

go get 동작 방식

Go Module을 사용하지 않을 경우

  1. import path를 보고 어떤 vcs를 사용하는지 판단.
  2. 해당 vcs에 맞는 스키마를 통해 패키지를 다운로드.
  • github.com으로 시작할 경우 github.com 호스팅과 git vcs를 사용한다고 판단하여 https:// 와 git+ssh:// 스키마 순서로 다운로드 시도.

Go Module을 사용할 경우

  1. https://proxy.golang.org (공식 프록시 서버, 설정에 따라 바뀔 수 있음.)에서 미러링된 모듈 검색.
  • 없으면 direct에서 검색.(저장소에 직접 접근.)
  1. 모듈을 발견하면 다운로드 받고 go.sum에서 체크섬 수행.
  • 체크섬이 없으면 https://sum.golang.org (공식 체크섬 DB 서버, 설정에 따라 바뀔 수 있음.)에서 체크섬 값 가져옴.
  1. go.sum 업데이트.
  • go.sum은 디펜던시별 체크섬을 기록해 두고, 변조 여부를 검사하는 데에 사용.
    • 처음 다운로드 받은 모듈과 나중에 다운로드 받는 모듈이 같은 비트를 갖는지 검사하여, 여러 이유로 프로젝트가 의존하는 모듈이 예상치 못하게 변형되는 일을 방지.

버전 관리 할 때는 go.mod와 go.sum 둘 다 올리자.

환경 변수

  • GO111MODULE=[on | off | auto]
    • Go Module을 사용할지 지정.
  • GOPROXY=[proxy server url]
    • Module 모드에서 외부 모듈 다운로드할 때 참조.
  • GOSUMDB=[sum db server url]
    • Module 모드에서 체크섬 수행할 때 참조.
  • GONOPROXY=[directory]
    • 프록시 사용에서 제외할 경로 목록.
  • GONOSUMDB=[directory]
    • 체크섬에서 제외할 경로 목록.
  • GOPRIVATE=[directory]
    • 프록시와 체크섬에서 제외할 경로 목록.

참고자료

profile
중니어 개발자

0개의 댓글