Go Makefile Patterns

Go 프로젝트에서 Makefile을 구성하는 일반적인 패턴을 정리한다.


1. 기본 구조

APP_NAME := myapp
VERSION  := $(shell git describe --tags --always --dirty)
COMMIT   := $(shell git rev-parse --short HEAD)
LDFLAGS  := -X main.version=$(VERSION) -X main.commit=$(COMMIT)

.PHONY: all build test lint clean

all: lint test build

build:
	CGO_ENABLED=0 go build -ldflags "$(LDFLAGS)" -o bin/$(APP_NAME) ./cmd/$(APP_NAME)

test:
	go test -race -cover ./...

lint:
	go vet ./...
	golangci-lint run

clean:
	rm -rf bin/

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

.PHONY는 해당 target이 파일이 아니라 명령어라는 선언이다. 같은 이름의 파일이 있어도 항상 실행된다.


2. 자주 쓰는 Target

run — 로컬 실행

run:
	go run ./cmd/$(APP_NAME)

fmt — 코드 포맷팅

fmt:
	gofumpt -l -w .

gofmt보다 gofumpt가 더 엄격한 포맷팅을 적용한다.

generate — 코드 생성

generate:
	go generate ./...

protobuf, mock, sqlc 등 코드 생성 도구를 실행한다.

coverage — 커버리지 리포트

coverage:
	go test -coverprofile=coverage.out ./...
	go tool cover -html=coverage.out -o coverage.html

docker — 컨테이너 빌드

DOCKER_IMAGE := myapp
DOCKER_TAG   := $(VERSION)

docker:
	docker build -t $(DOCKER_IMAGE):$(DOCKER_TAG) .

3. Migration Target

DB migration 도구와 연동하는 패턴.

MIGRATE := migrate
DB_URL  := mysql://user:pass@tcp(localhost:3306)/mydb

migrate-up:
	$(MIGRATE) -path migrations -database "$(DB_URL)" up

migrate-down:
	$(MIGRATE) -path migrations -database "$(DB_URL)" down 1

migrate-create:
	$(MIGRATE) create -ext sql -dir migrations -seq $(name)
make migrate-create name=create_users_table
make migrate-up
make migrate-down

4. 환경별 변수

ENV ?= local

include config/$(ENV).env
export

run:
	go run ./cmd/$(APP_NAME)
make run              # config/local.env 사용
make run ENV=staging  # config/staging.env 사용

?=는 변수가 이미 설정되어 있지 않을 때만 기본값을 할당한다.


5. 실전 예시 (풀 Makefile)

APP_NAME := aap-coordinator
VERSION  := $(shell git describe --tags --always --dirty)
COMMIT   := $(shell git rev-parse --short HEAD)
LDFLAGS  := -X main.version=$(VERSION) -X main.commit=$(COMMIT)
ENV      ?= local

.PHONY: all build run test lint fmt tidy clean generate docker migrate-up migrate-down

all: tidy fmt lint test build

build:
	CGO_ENABLED=0 go build -ldflags "$(LDFLAGS)" -o bin/$(APP_NAME) ./cmd/$(APP_NAME)

run:
	go run ./cmd/$(APP_NAME)

test:
	go test -race -cover ./...

lint:
	go vet ./...
	golangci-lint run

fmt:
	gofumpt -l -w .

tidy:
	go mod tidy

clean:
	rm -rf bin/ coverage.out coverage.html

generate:
	go generate ./...

docker:
	docker build -t $(APP_NAME):$(VERSION) .

coverage:
	go test -coverprofile=coverage.out ./...
	go tool cover -html=coverage.out -o coverage.html

migrate-up:
	migrate -path migrations -database "$(DB_URL)" up

migrate-down:
	migrate -path migrations -database "$(DB_URL)" down 1

사용

make              # all (tidy → fmt → lint → test → build)
make build        # 빌드만
make test         # 테스트만
make lint         # 정적 분석
make run          # 로컬 실행
make docker       # Docker 이미지 빌드
make migrate-up   # DB migration 적용