sayu.day
Backend

Functional Options 패턴을 활용한 Go 설정 관리

Go에서 필수 인자와 선택 옵션을 분리해 생성자 API를 안정적으로 유지하는 방법을 정리합니다.

발행 2025년 12월 30일1196

같은 주제에서 이어 읽기

Append-Only 문서 버저닝 설계 및 구현

Backend 안에서 이어지는 글

왜 쓰는가

설정 필드가 늘어날수록 생성자 시그니처는 빠르게 깨집니다. Functional Options는 아래 두 가지를 분리해 문제를 줄입니다.

  • 필수값: 생성자 인자로 강제
  • 선택값: With... 옵션으로 오버라이드

기본 형태

type Config struct {
	batchSize int
	timeout   time.Duration
}

type Option func(*Config)

func WithBatchSize(v int) Option {
	return func(c *Config) {
		if v > 0 {
			c.batchSize = v
		}
	}
}

func WithTimeout(v time.Duration) Option {
	return func(c *Config) {
		if v > 0 {
			c.timeout = v
		}
	}
}

func NewWorker(client Client, handler Handler, opts ...Option) *Worker {
	cfg := Config{batchSize: 10, timeout: 5 * time.Second}
	for _, opt := range opts {
		opt(&cfg)
	}
	return &Worker{client: client, handler: handler, cfg: cfg}
}

실무 규칙

  • 필수 의존성(client, handler)은 절대 옵션으로 내리지 않기
  • 옵션 함수에서 유효성 검증 수행
  • 기본값은 생성자 내부에서 한 번만 정의

자주 하는 실수

  • 옵션끼리 충돌 규칙이 없음 (예: timeout 0 허용)
  • 생성자 외부에서 기본값을 중복 관리
  • 모든 값을 옵션으로 처리해 필수값 계약 붕괴

요약

Functional Options는 "유연한 설정" 패턴이 아니라 "생성자 안정성" 패턴입니다. 필수/선택 경계를 명확히 유지하면 API가 오래 버팁니다.

다음 읽기

이 생각이 이어지는 방향

Backend 더 보기
공유

읽은 뒤의 대화

읽은 뒤의 생각을 이어갑니다

질문, 반론, 조용한 후속 메모를 이 글 아래에 남길 수 있습니다.

sayu.day는 생각과 작업의 흔적을 천천히 정리하는 개인 출판물입니다.
직접 겪고 검토한 내용, 다시 읽을 만한 아이디어, 작업하며 남긴 메모를 모읍니다.
시간이 지난 글은 현재의 판단과 다를 수 있어 업데이트 맥락을 함께 남깁니다.

© 2026 sayu.day