Go 모듈은 Go 1.11+에서 도입된 표준 의존성 관리 메커니즘입니다. 주요 파일은 go.mod(최소 의존성 및 버전을 정의)와 go.sum(해시를 통해 무결성을 보장)입니다.
의존성을 추가하려면 다음을 사용합니다:
go get github.com/pkg/errors@v0.9.1
의존성을 업데이트하려면 아래와 같이 입력합니다:
go get -u ./... go mod tidy # 사용하지 않는 것 삭제
Go는 의미론적 버전 관리(semver)를 지원하며, 의존성은 엄격하게 고정됩니다: 프로젝트는 반복 가능하고 빌드는 결정론적입니다. 하지만 다음 사항을 고려해야 합니다:
go.sum 파일을 삭제하고 go build 명령을 실행하면 어떻게 되며, 이것이 위험한 이유는 무엇인가요?
많은 사람들은 Go가 단순히 의존성을 처음부터 다시 빌드할 것이라고 생각합니다. 그러나 go.sum 파일은 사용되는 모든 모듈의 해시를 포함하고 있으며, 공급망 공격으로부터 보호합니다. 이를 삭제하면,
다음 빌드 시 Go가 의존성을 다시 다운로드하고 파일을 재생성하지만, 만약 의존성 리포지토리가 악의적으로 변경되었다면 보호가 무너집니다! 프로덕션에서 코드가 대체되는 위험이 발생합니다.
이야기
대규모 프로젝트에서 리포지토리가 vendoring에서 go 모듈로 전환되었고, 버전을 고정하는 것을 잊었습니다. 한 달 후 서드파티 패키지 업데이트로 인해 호환성이 깨져 구 버전 브랜치를 빌드할 수 없게 되어 코드의 재현성이 사라졌습니다.
이야기
다른 프로젝트에서 개발자가 실수로 go.sum을 삭제했습니다. 재실행 후 팀은 일부 의존성이 변경되었고, 마이너 버전 호환성 문제로 인해 버그가 발생했으며, 이로 인해 여러 일전으로 되돌아가야 했습니다.
이야기
로컬 디렉토리에 대한 replace 경로(replace ... = ../some/library)가 배포 전에 삭제되지 않아 CI/CD 파이프라인에서 빌드가 실패했습니다. 외부 시스템이 로컬 파일에 접근할 수 없었고, 프로덕션이 잘못된 버전에 "고정"되었습니다.