Skip to content

ADR-10: 표준 Go 프로젝트 레이아웃

🇺🇸 English Version

날짜작성자영향 리포지토리
2025-12-23@KubrickCodecore

Context

문제 정의

독립 Go 라이브러리로서(ADR-01: 코어 라이브러리 분리 참조), 코어는 외부 프로젝트에서 go get으로 사용 가능해야 함. 비표준 디렉토리 구조는 소비자와 생태계 도구에 마찰을 일으킴.

기술적 문제

go.mod가 하위 디렉토리에 중첩되어 있으면(예: src/pkg/go.mod), 외부 소비자가 모듈을 직접 import할 수 없음. replace directive를 사용해야 하며, 이는:

  • 표준 go get 워크플로우를 깨뜨림
  • 의존성 업데이트에 수동 조율 필요
  • Go 모듈 프록시 및 체크섬 데이터베이스와 호환 불가
  • 생태계 도구(goimports, gopls 등) 혼란

Decision

루트 레벨 go.mod와 공개 패키지용 pkg/ 디렉토리로 표준 Go 프로젝트 레이아웃을 채택함.

specvital/core/
├── go.mod              # 루트에 모듈 정의
├── go.sum
├── pkg/                # 공개 패키지
│   ├── domain/         # 도메인 모델
│   ├── parser/         # 파서 엔진
│   ├── source/         # Source 추상화
│   └── crypto/         # 암호화 유틸리티
└── ...

소비자는 패키지를 직접 import:

go
import "github.com/specvital/core/pkg/parser"

Options Considered

Option A: 루트 go.mod + pkg/ 디렉토리 (선택됨)

공개 패키지를 pkg/ 하위에 두는 표준 Go 프로젝트 레이아웃.

장점:

  • replace directive 없이 직접 import
  • Go 모듈 프록시 및 체크섬 데이터베이스 호환
  • 생태계 도구와 원활하게 동작
  • Go 개발자에게 익숙한 구조
  • 공개(pkg/)와 내부(internal/) 패키지 명확한 분리

단점:

  • pkg/ 내 모든 패키지가 공개 API
  • API 안정성 유지에 규율 필요
  • internal/ 사용하지 않으면 내부 패키지 컴파일 타임 강제 없음

Option B: 중첩된 go.mod (예: src/pkg/go.mod)

하위 디렉토리에 모듈 정의.

장점:

  • 다른 디렉토리 구성 선호도 허용
  • 모노레포에서 다른 언어와 공존 가능

단점:

  • 외부 소비자에게 replace directive 필요
  • 표준 Go 도구 워크플로우 깨짐
  • 모듈 프록시 캐싱과 호환 불가
  • 비표준으로 기여자에게 혼란

Option C: internal/ 전용

모든 패키지를 internal/ 디렉토리 하위에 배치.

장점:

  • 컴파일 타임 강제: 외부 패키지가 import 불가
  • 소비자 영향 없이 자유로운 리팩토링

단점:

  • 라이브러리 목적과 모순: 외부 사용을 위해 설계됨
  • 공개 API 노출 없음
  • 재사용 가능한 라이브러리에 부적합

Consequences

Positive

  1. 마찰 없는 소비

    • 외부 프로젝트에서 표준 go get github.com/specvital/core 사용
    • 수동 replace directive 불필요
    • 표준 도구로 의존성 업데이트 작동 (Dependabot, Renovate)
  2. 생태계 호환성

    • Go 모듈 프록시가 모듈 캐시
    • 체크섬 데이터베이스가 무결성 검증 제공
    • goimports, gopls 정상 동작
  3. 개발자 경험

    • Go 개발자에게 익숙한 표준 레이아웃
    • 기여자 온보딩 시간 단축
    • pkg/에 명확한 공개 API 표면

Negative

  1. API 안정성 책임

    • pkg/ 하위 모든 패키지가 공개 API임
    • 호환성 깨는 변경에 메이저 버전 범프 필요
    • 완화: 노출하지 않을 구현 세부사항은 internal/ 사용
  2. 리팩토링 제약

    • pkg/ 내 패키지를 자유롭게 이름 변경/이동 불가
    • 완화: 보수적인 API 설계, 수정보다 확장 포인트 활용

패키지 가시성

디렉토리가시성용도
pkg/공개외부 프로젝트용 내보낸 API
internal/비공개구현 세부사항 (필요시 사용)

References

Open-source test coverage insights