콘텐츠로 이동

ADR-0001: Language: Go

Umbra 의 백엔드 언어로 Go 1.23 을 채택한다.

Status

Accepted

  • Decided at — 2026-04-13
  • Decided by — Pablo

Context

Umbra 는 luxtra-bot 의 후속작이다. luxtra-bot 은 Rust + Twilight 로 구현되었지만 진욱의 Rust 학습 곡선이 가팔라 페어 개발 속도가 현저히 떨어졌고, 결국 프로젝트가 정체되어 폐기되었다. Umbra 는 같은 비즈니스 가치를 "페어 개발이 가능한 스택" 으로 재구현하는 프로젝트이다.

새 언어 선택의 제약 조건:

  • Pablo 와 진욱이 함께 구현 가능해야 함
  • 결제 SaaS 수준의 프로덕션 안정성
  • Discord 봇 생태계에 성숙한 라이브러리 존재
  • Fly.io 같은 일반적 플랫폼에서 배포 가능
  • 학습 곡선이 Rust 보다 현저히 낮아야 함

후보 언어: Go, TypeScript (Node/Bun), Python, Kotlin.

Decision

Go 1.23 을 백엔드 언어로 채택한다.

선택 근거:

  • 낮은 학습 곡선 — Go 는 문법이 단순하고 개념 수가 적다. 진욱이 수 주 내 실무 생산성에 도달 가능하다.
  • Discord 봇 생태계 — disgo 가 Components V2 를 정식 지원하며 활발히 유지보수된다.
  • concurrency 모델 — goroutine 과 channel 은 Discord Gateway + HTTP API + 백그라운드 작업의 동시성을 자연스럽게 처리한다.
  • 표준 라이브러리net/http, context, slog 등이 프로덕션 품질로 제공된다.
  • 빠른 컴파일과 배포 — 정적 바이너리로 distroless Docker 이미지에 가볍게 배포된다.
  • Pablo 경험 — 이미 Go 숙련도가 있다. 리드 역할에 공백이 없다.

Consequences

Positive

  • 페어 개발 속도 향상, 진욱의 기여도 증가
  • Discord 봇 생태계 활용으로 차별화 영역(Recovery)에 집중 가능
  • 바이너리 배포 단순성으로 Fly.io 운영 부담 ↓
  • 표준 라이브러리 완성도로 외부 의존성 최소화

Negative

  • Rust 대비 제로 코스트 추상화 포기 (예: no enum ADT, no generics on methods)
  • 에러 처리 verbosity (if err != nil 반복)
  • Generics 가 상대적으로 제한적 (1.18+ 지원하나 실사용 사례 누적 중)

Neutral

  • Nabi 런타임 위 Rust 재작성 계획이 존재하므로 Go 는 중간 단계 (ADR-0031 참조)
  • 도메인 모델은 언어 무관하게 설계 (Hexagonal) 하여 재작성 비용 완화

Alternatives considered

Alternative 1: TypeScript (Node/Bun)

Pros

  • 프론트엔드와 언어 통일, 풀스택 TypeScript
  • Node 생태계 최대 규모
  • Bun 런타임으로 빠른 시작

Cons

  • long-running Discord Gateway 프로세스에 덜 적합
  • Discord 라이브러리 중 Components V2 지원이 검증되지 않음
  • 결제 도메인의 타입 안전성은 런타임 검증에 의존 (Go 의 컴파일 타입 안전성 대비 약함)

Why rejected — 백엔드-프론트엔드 언어 통일 이점보다 Go 의 concurrency 모델과 Discord 생태계 성숙도가 더 큰 가치. 풀스택 통일은 Phase 2 검토 가능.

Alternative 2: Python (FastAPI)

Pros

  • 학습 곡선 가장 낮음
  • 결제 도메인 레퍼런스 풍부

Cons

  • Discord 봇 라이브러리(discord.py)의 Components V2 지원 미흡
  • long-running 프로세스의 GIL 제약
  • 타입 시스템이 런타임 의존

Why rejected — Discord 라이브러리 생태계와 GIL 제약이 Umbra 의 요구에 맞지 않음.

Alternative 3: Kotlin (Spring)

Pros

  • JVM 생태계 성숙도
  • JDA (Discord 라이브러리) 존재

Cons

  • JVM 메모리 풋프린트와 시작 시간이 Fly.io machine 에 부담
  • 진욱과 Pablo 모두 Spring 경험 낮음
  • Gradle/Maven 빌드 부담

Why rejected — 경험 공백과 배포 풋프린트가 문제. Luxtra 팀 어느 곳에서도 Kotlin/Spring 을 메인으로 쓰지 않는다.

Alternative 4: Rust (luxtra-bot 방식 유지)

Pros

  • 가장 강력한 타입 시스템
  • zero-cost abstraction
  • Pablo 의 선호 언어

Cons

  • 진욱의 학습 곡선이 페어 개발 속도를 막음 (이미 luxtra-bot 에서 검증된 문제)
  • 변경 빈도가 높은 비즈니스 도메인에서 borrow checker 마찰

Why rejected — luxtra-bot 에서 입증된 문제. Rust 재채택은 진욱의 숙련도가 충분히 쌓인 후 Nabi 런타임 위 재작성으로 진행 (ADR-0031).

Compliance

  • go.mod 에 Go 1.23 명시
  • .tool-versions 또는 mise.toml 에 Go 1.23 고정
  • CI 는 Go 1.23 으로 테스트 (golangci-lint, go test)

Revisit triggers

  • Nabi 런타임 완성 + 진욱의 Rust 숙련도 도달 → Rust 재작성 (ADR-0031 발동)
  • Go 버전 업그레이드 (1.24+) — 주요 기능 도입 시 별도 ADR
  • 팀 규모 확장으로 언어 분산이 필요해지면 재검토

References

  • ADR-0002 — Discord 라이브러리 선택
  • ADR-0003 — HTTP 프레임워크 선택
  • ADR-0031 — 미래 Rust 재작성 계획