Kim Seogyu
Backend

Enterprise Go 시리즈 #1: 프로젝트 설계와 구조화

Go 서비스에서 유지보수 가능한 프로젝트 구조를 잡는 실전 기준을 정리합니다.

Published 2026년 1월 1일2 min read215 words

Enterprise Go 시리즈 #1: 프로젝트 설계와 구조화

핵심 원칙

  • main은 최대한 얇게 유지
  • 조립(composition)은 internal/app로 집중
  • 공개 API가 아니면 기본값은 internal

권장 구조

project/
├── cmd/
│   └── api/
│       └── main.go
├── internal/
│   ├── app/
│   ├── api/
│   ├── service/
│   └── data/
├── pkg/            # 외부 공개가 필요할 때만
└── Makefile

Hollow Main 패턴

package main

func main() {
	if err := app.Run(); err != nil {
		os.Exit(1)
	}
}

main에서 의존성 조립까지 다 하면 테스트 가능한 진입점이 사라집니다.

internal/app의 책임

  • 설정 로딩
  • 의존성 조립
  • 프로세스 라이프사이클(시작/종료)
func Run() error {
	cfg := LoadConfig()
	db := data.NewDB(cfg)
	svc := service.New(db)
	server := api.NewHTTPServer(svc)
	return server.Run()
}

진화 전략

  • 초기 PoC: 단일 main.go
  • 코드가 커지면: cmd + internal 분리
  • 바이너리가 늘면: cmd/{api,worker,admin} 확장

처음부터 과도하게 계층을 만들기보다, 경계가 생길 때 분리하는 방식이 유지보수에 유리합니다.

자주 하는 실수

  • pkg를 너무 일찍 열어 API 호환성 부담 생성
  • 도메인/인프라 경계를 파일 경로만으로 구분하고 책임은 섞어둠
  • main에서 설정, DI, 서버 실행, 시그널 처리까지 모두 처리

요약

좋은 Go 구조의 핵심은 화려한 폴더 트리가 아니라 책임 분리입니다. main을 얇게 유지하고 internal/app를 조립 루트로 고정하면 규모가 커져도 구조가 무너지지 않습니다.

Share

Related Articles

Comments

이 블로그는 제가 알고 있는 것들을 잊지 않기 위해 기록하는 공간입니다.
직접 작성한 글도 있고, AI의 도움을 받아 정리한 글도 있습니다.
정확하지 않은 내용이 있을 수 있으니 참고용으로 봐주세요.

© 2026 Seogyu Kim