Go Build Toolchain

Go 프로젝트에서 자주 쓰는 빌드/검증 커맨드를 정리한다.


1. go mod tidy

tidy = "깔끔하게 정리하다". go.mod/go.sum을 깔끔하게 정리하는 명령어. 코드에서 실제로 import하는 패키지만 go.mod/go.sum에 남기고 나머지는 제거한다.

go mod tidy

하는 일:

  • 코드에서 import하지만 go.mod에 없는 패키지 → 추가
  • go.mod에 있지만 코드에서 import하지 않는 패키지 → 제거
  • go.sum에서 불필요한 체크섬 엔트리 → 제거
# 흐름
소스코드 스캔 → import 목록 수집 → go.mod 비교 → 추가/제거 → go.sum 갱신

CI에서 go mod tidy를 실행한 뒤 diff가 있으면 실패시키는 패턴이 일반적이다. 개발자가 의존성 정리를 빠뜨린 걸 잡아낸다.

go mod tidy
git diff --exit-code go.mod go.sum

관련 명령어

go mod download   # go.mod 기준으로 의존성 다운로드 (정리는 안 함)
go mod verify     # go.sum 체크섬 검증
go mod vendor     # vendor/ 디렉토리에 의존성 복사
go mod graph      # 의존성 그래프 출력

2. go vet

Go 소스코드의 정적 분석 도구. 컴파일은 되지만 버그일 가능성이 높은 코드를 잡아낸다.

go vet ./...

잡아내는 것들:

  • fmt.Printf 포맷과 인자 타입 불일치
  • 도달 불가능한 코드
  • 구조체 태그 오류
  • 잘못된 sync 사용 (mutex 복사 등)
  • 잘못된 context 사용
// go vet이 잡아내는 예시

// Printf 포맷 불일치
fmt.Printf("%d", "hello")  // vet: wrong type for %d

// mutex 값 복사
var mu sync.Mutex
mu2 := mu  // vet: assignment copies lock value

// 사용하지 않는 결과
fmt.Sprintf("hello")  // vet: result not used

go vet은 컴파일러가 잡지 못하는 논리적 실수를 잡아주므로, CI에서 반드시 돌려야 한다.

go vet vs linter

go vet golangci-lint
범위 Go 공식 도구, 보수적 여러 linter 통합 (vet 포함)
오탐 거의 없음 설정에 따라 다름
용도 확실한 버그 감지 코드 스타일 + 버그 감지

3. go build

소스코드를 컴파일하여 바이너리를 생성한다.

go build ./...              # 전체 패키지 빌드 (바이너리 생성 없이 컴파일 확인)
go build -o bin/myapp ./cmd/myapp   # 바이너리 출력 경로 지정

빌드 과정

소스코드 파싱
    → import 의존성 해석
    → 패키지별 컴파일 (병렬)
    → 링킹
    → 바이너리 출력

Go는 패키지 단위로 컴파일하고, 변경되지 않은 패키지는 캐시를 재사용한다.

자주 쓰는 옵션

# 빌드 캐시 무시하고 전체 재빌드
go build -a ./...

# 빌드 시 ldflags로 변수 주입 (버전 정보 등)
go build -ldflags "-X main.version=1.0.0 -X main.commit=$(git rev-parse HEAD)" -o bin/myapp ./cmd/myapp

# CGO 비활성화 (순수 Go 바이너리, static linking)
CGO_ENABLED=0 go build -o bin/myapp ./cmd/myapp

# 크로스 컴파일
GOOS=linux GOARCH=amd64 go build -o bin/myapp ./cmd/myapp

ldflags 활용

빌드 시점에 변수 값을 주입할 수 있다. 버전, 커밋 해시, 빌드 시간 등을 바이너리에 심는 패턴.

package main

var (
	version = "dev"
	commit  = "none"
)

func main() {
	fmt.Printf("version: %s, commit: %s\n", version, commit)
}
go build -ldflags "-X main.version=1.2.3 -X main.commit=abc1234" -o bin/myapp

4. 일반적인 빌드 순서

go mod tidy      # 1. 의존성 정리
go vet ./...     # 2. 정적 분석
go test ./...    # 3. 테스트
go build ./...   # 4. 빌드

CI에서도 이 순서를 따르는 것이 일반적이다.