winterjung blog


프로덕션 서버 개발을 위한 golang 패키지 추천

· last edited 2026-03-04

전 직장에서 go 언어를 처음 쓰기 시작해 현 직장에서도 계속 쓰며 약 5년간 활발히 사용하고 있다. 예전과 비교하면 go 생태계는 점점 풍부해지고, 고퍼콘 코리아를 비롯한 다양한 커뮤니티도 늘어나고, 레퍼런스도 많아지고 있다. 그럼에도 여전히 (비단 go 언어만 그런 건 아니지만) 잘 정리된 한국어 자료는 적고 시행착오를 겪어봐야 하는 부분이 많아 그동안 여러 동료와 함께 개발하며 겪었던 시행착오와 권장 사항을 프로덕션 환경에서 사용하는 golang과 gRPC, 뱅크샐러드 Go 코딩 컨벤션 두 편의 글로 정리하기도 했다. 그와 비슷한 결로 이번엔 주로 go 언어로 서버 개발을 하며 자주 사용하고 유용했던 패키지라이브러리를 정리해 봤다. go 언어에서 기본으로 제공하는 내장 패키지에도 net/http/httptest, crypto/rand 패키지처럼 믿고 쓸 수 있고 잘 만들어진 패키지는 많으나 이 글에선 서드 파티 패키지에 집중했다.

글을 쓸 때 마다 항상 드는 고민이 ‘이 정도면 “golang xxx package” 같은 키워드로 검색해도 금방 나올 텐데 괜히 적는 거 아닌가?‘라는 부분이다. 그럼에도 누군가의 의사결정 비용과 고민을 줄여주길 바라며, 또 이 글을 읽은 다양한 사람들이 얹어주는 한마디씩을 통해 이 글이 더 발전되길 바라며 소개해 본다.

업데이트: 2025 Go Developer Survey 설문에서 “Go 개발자들이 직면한 가장 큰 도전은 무엇인가요?” 질문에 응답자의 26%가 “신뢰할 수 있는 Go 모듈과 패키지 찾기”라고 답한만큼 그래도 이 글이 유용하길 바란다.

stretchr/testify#

func TestSomething(t *testing.T) {
  assert.Equal(t, expected, got, "they should be equal")
  assert.NoError(t, err)
  assert.Len(t, result, 1)
  assert.JSONEq(t, `{"name": "hello"}`, msg)
}

A toolkit with common assertions and mocks that plays nicely with the standard library

rs/zerolog & sirupsen/logrus#

import (
    "github.com/rs/zerolog"
    "github.com/rs/zerolog/log"
	"github.com/rs/zerolog/pkgerrors"
)

func main() {
	zerolog.ErrorStackMarshaler = pkgerrors.MarshalStack
	// ...
	log.Error().Stack().Err(err).Msg("failed to insert row to db")
}

rs/zerolog: Zero Allocation JSON Logger

import (
	log "github.com/sirupsen/logrus"
)

func main() {
	log.WithFields(log.Fields{
		"animal": "walrus",
	}).Info("A walrus appears")
}

sirupsen/logrus: Structured, pluggable logging for Go.

pkg/errors#

resp, err := userSvc.GetUser(ctx, &GetUserRequest{...})
if err != nil {
	return errors.Wrap(err, "user.GetUser")
}

Simple error handling primitives

hashicorp/go-multierror#

var errs *multierror.Error
if err := step1(); err != nil {
	errs = multierror.Append(errs, err)
}
if err := step2(); err != nil {
	errs = multierror.Append(errs, err)
}
return errs.ErrorOrNil()
// Output:
// 2 errors occurred:
//	* error 1
//	* error 2

A Go (golang) package for representing a list of errors as a single error.

samber/lo#

names := lo.Uniq([]string{"Samuel", "John", "Samuel"})
// []string{"Samuel", "John"}

A Lodash-style Go library based on Go 1.18+ Generics (map, filter, contains, find…)

shopspring/decimal#

func main() {
	price, err := decimal.NewFromString("136.02")
	quantity := decimal.NewFromInt(3)
	subtotal := price.Mul(quantity)

	fmt.Println("Subtotal:", subtotal) // Subtotal: 408.06
}

Arbitrary-precision fixed-point decimal numbers in Go

dgraph-io/ristretto#

func main() {
	cache, _ := ristretto.NewCache(&ristretto.Config[string,string]{
		NumCounters: 1e7,     // number of keys to track frequency of (10M).
		MaxCost:     1 << 30, // maximum cost of cache (1GB).
		BufferItems: 64,      // number of keys per Get buffer.
	})
	cache.Set("key", "value", 1)
	value, found := cache.Get("key")
	fmt.Println(value)
}

A high performance memory-bound Go cache

coocood/freecache#

cacheSize := 100 * 1024 * 1024 // 100MB
cache := freecache.NewCache(cacheSize)

cache.Set([]byte("key"), []byte("value"), 60) // 60 seconds TTL
value, err := cache.Get([]byte("key"))

A cache library for Go with zero GC overhead

volatiletech/sqlboiler#

import (
	"github.com/volatiletech/sqlboiler/v4"
)
func main() {
	users, err := model.Users().All(ctx, db)
	token, err := model.Tokens(model.TokenWhere.AccessToken.EQ(accessToken)).One(ctx, db)
}
	token.Update(ctx, db, boil.Whitelist(
        model.TokenColumns.AccessToken,
        model.TokenColumns.AccessTokenExpiredAt,
    ))

Generate a Go ORM tailored to your database schema.

DATA-DOG/go-sqlmock#

func TestShouldUpdateStats(t *testing.T) {
	db, mockDB, err := sqlmock.New()
	require.NoError(t, err)
	t.Cleanup(db.Close)

	mockDB.ExpectQuery(regexp.QuoteMeta(
		"SELECT * FROM `token` WHERE (`user_id` = ?);"
	)).WithArgs("some-valid-user-id").WillReturnRows(...)
}

Sql mock driver for golang to test database interactions

golangci/golangci-lint & mvdan/gofumpt#

# .golangci.yml
linters:
  enable:
    - govet
    - errcheck
    - staticcheck

formatters:
  enable:
    - gofumpt
  settings:
    gofumpt:
      extra-rules: true

golangci-lint: Fast linters runner for Go / gofumpt: A stricter gofmt

failsafe-go/failsafe-go#

retryPolicy := retrypolicy.NewBuilder[*http.Response]().
	HandleIf(func(r *http.Response, err error) bool {
		return r != nil && r.StatusCode == http.StatusTooManyRequests
	}).
	WithBackoff(time.Second, 30*time.Second).
	WithMaxRetries(3).
	Build()

resp, err := failsafe.With(retryPolicy).Get(func() (*http.Response, error) {
	return http.Get("https://example.com")
})

Fault tolerance and resilience patterns for Go

hashicorp/go-retryablehttp#

client := retryablehttp.NewClient()
client.RetryMax = 3

resp, err := client.Get("https://example.com/api")

Retryable HTTP client in Go

twmb/franz-go#

// producer
client, _ := kgo.NewClient(kgo.SeedBrokers("localhost:9092"))
defer client.Close()

ctx := context.Background()
client.Produce(ctx, &kgo.Record{Topic: "my-topic", Value: []byte("hello")}, nil)

// consumer
client, _ := kgo.NewClient(
	kgo.SeedBrokers("localhost:9092"),
	kgo.ConsumeTopics("my-topic"),
	kgo.ConsumerGroup("my-group"),
)
for {
	fetches := client.PollFetches(ctx)
	fetches.EachRecord(func(r *kgo.Record) {
		fmt.Println(string(r.Value))
	})
}

franz-go is a feature complete, pure Go library for Kafka from 0.8.0 through 4.1+. Producing, consuming, transacting, administrating, etc.

go-resty/resty & dghubble/sling#

// resty
client := resty.New()
resp, err := client.R().
	SetHeader("Accept", "application/json").
	SetResult(&ApiResponse{}).
	Get("https://api.example.com/users/1")

// sling
type Issue struct {
	Title string `json:"title"`
	Body  string `json:"body"`
}
issue := new(Issue)
resp, err := sling.New().Base("https://api.github.com/").
	Path("repos/user/repo/").
	Get("issues/1").
	ReceiveSuccess(issue)

go-resty: Simple HTTP, REST, and SSE client library for Go / dghubble/sling: A Go HTTP client library for creating and sending API requests

go-chi/chi#

r := chi.NewRouter()
r.Use(middleware.Logger)
r.Use(middleware.Recoverer)

r.Get("/", func(w http.ResponseWriter, r *http.Request) {
	w.Write([]byte("hello"))
})
r.Route("/users", func(r chi.Router) {
	r.Get("/", listUsers)
	r.Post("/", createUser)
	r.Get("/{userID}", getUser)
})

http.ListenAndServe(":3000", r)

lightweight, idiomatic and composable router for building Go HTTP services

그 외#


이렇게 그 동안 자주 사용하고 유용한 패키지를 정리해봤다. 위 내용은 서버 개발에 치중되어 있고, 너무 지엽적인 패키지(e.g. 레벤슈타인 거리 구하는 패키지)는 제외했는데 이 외에도 추천할만한 패키지가 있다면 계속 업데이트 할 예정이다.

참고할만한 다른 자료#