Go 언어로 애플리케이션을 만들기 위한 프로젝트 기본 레이아웃입니다. 디렉토리 구조를 통일된 패턴으로 정의하여 관리하여 각 디렉토리의 역할을 명확히 하고, 유지보수와 코드의 가독성을 높일 수 있습니다.
Architecture
다음과 같은 6가지 개념(Controller, Service, Repository, Storage, Domain, Pkg)을 기본 구조로 활용합니다. 각 개념에 대한 자세한 설명은 아래에 첨부하였습니다.
flowchart LR A0(user) --> B0 A0(user) --> B1 A0(user) --> B2 A1(event) --> B3 B0 --> C B1 --> C B2 --> C B3 --> C subgraph domain / pkg subgraph controller B0(controller/http) B1(controller/grpc) B2(controller/cmd) B3(controller/event) end C(service) --> |optionnal| D(repository) --> E(storage) end
Directories
├── cmd
│ ├── server
│ │ ├── internal
│ │ │ ├── env.go
│ │ │ └── server.go
│ │ └── server.go
│ ├── appname
│ │ ├── internal
│ │ │ ├── env.go
│ │ │ └── appname.go
│ │ └── appname.go
├── docs
├── internal
│ ├── controller
│ │ ├── cmd
│ │ ├── event
│ │ ├── grpc
│ │ └── http
│ ├── domain
│ ├── storage
│ │ ├── ...
│ │ └── ent
│ ├── repository
│ ├── service
│ └── pkg
├── mocks
├── testdata
│ .gitignore
│ .mockery.yaml
│ Dockerfile
│ Makefile
│ go.mod
│ go.sum
└── README.md
/cmd
프로젝트의 메인 애플리케이션(즉, main 패키지)이 위치하는 디렉토리입니다. cmd 디렉토리에는 최소한의 코드만 작성하고, 재사용성이 필요한 코드는 /internal
디렉토리에 작성합니다.
automaxprocs
automaxprocs 패키지는 CPU 코어 수를 자동으로 설정하도록 도와주는 도구입니다.(GOMAXPROCS 값을 자동으로 설정합니다.) container 환경에서 실행하려면 main 패키지에 go.uber.org/automaxprocs 패키지를 항상 import하여 사용합니다.
package main
import (
"fmt"
_ "go.uber.org/automaxprocs"
)
func main() {
fmt.Println("Hello")
}
/cmd/appname/appname.go
애플리케이션의 main 패키지로, 실행 가능한 애플리케이션의 진입점입니다. 디렉토리 이름과 파일 이름이 애플리케이션 이름과 동일하게 사용합니다..
package main
import (
"github.com/rs/zerolog/log"
_ "go.uber.org/automaxprocs"
"github.com/org/repository/cmd/appname/internal"
)
func main() {
// execute application
if err := internal.Run(); err != nil {
log.Fatal().Err(err)
}
}
/cmd/appname/internal
애플리케이션 실행에 필요한 환경 변수 설정 및 관련 코드를 작성하는 디렉토리입니다. 이 코드는 애플리케이션의 main 패키지에서 임포트하여 사용합니다.
/cmd/appname/internal/env.go
env 패키지를 사용하여 애플리케이션 실행에 필요한 환경 변수를 정의하는 파일입니다. 다른 패키지에서는 환경 변수를 직접 참조하지 않으며, 필요한 환경 변수 값을 주입받아 사용합니다.
package internal
import (
"github.com/caarlos0/env/v11"
)
// server environment
type environment struct {
AWSRegion string `env:"AWS_REGION"`
}
func parse() (*environment, error) {
var e environment
if err := env.Parse(&e); err != nil {
return nil, err
}
return &e, nil
}
/cmd/appname/internal/appname.go
메인 패키지 내에서 애플리케이션을 실행하는 데 필요한 핵심 코드를 작성합니다.
package internal
import (
"context"
"github.com/getsentry/sentry-go"
dd_tracer "gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer"
)
func Run() error {
// Initialize context
ctx := context.Background()
// Parse environment variables
env, err := parse()
if err != nil {
return err
}
// initialize sentry
if err := sentry.Init(sentry.ClientOptions{}); err != nil {
return err
}
defer sentry.Flush(2 * time.Second)
// initialize datadog tracer
dd_tracer.Start()
defer dd_tracer.Stop()
...
}
/docs
프로젝트와 관련된 문서 파일을 저장하는 디렉토리입니다. API 문서, 아키텍처 다이어그램, README 파일, Swagger 등 다양한 문서화를 포함할 수 있습니다.
/internal
프로젝트 내부에서 사용되는 다양한 공통 라이브러리 및 모듈을 포함하는 최상위 디렉토리입니다. 다음과 같은 하위 디렉토리를 포함합니다. Go 언어에서 internal 패키지는 Go 1.4 이후 도입된 기능으로, 특정 패키지를 외부에서 사용할 수 없도록 제한하는 역할을 합니다. 이를 통해 모듈화와 캡슐화를 강화하며, 패키지 설계 시 의도하지 않은 사용을 방지하는 데 유용합니다.
/internal/pkg
프로젝트 내부에서 재사용 가능한 공통 라이브러리를 작성하는 공간입니다.
/internal/controller/http
HTTP 서버 요청을 처리하는 레이어입니다. HTTP 서버는 Echo 프레임워크를 사용합니다.
/internal/controller/grpc
gRPC 서버 요청을 처리하는 레이어입니다. grpc-go / grpc-ecosystem 참고하여 구현합니다.
/internal/controller/cmd
CLI 명령어 구현을 레이어입니다. Cobra 라이브러리를 사용하여 CLI 명령어를 구현합니다.
/internal/controller/event
event 기반 서버 요청을 처리하는 레이어입니다.
/internal/domain
프로젝트 전반에 사용되는 데이터 구조체(Struct)를 관리하는 레이어입니다.
/internal/storage
데이터베이스, Redis, DynamoDB, ORM 등 인프라에 종속적인 코드를 작성하는 레이어입니다. ORM은 ent를 사용합니다.
/internal/repository
storage 패키지를 의존하여 데이터 핸들링을 수행하는 코드를 작성하는 레이어입니다.
/internal/service
비즈니스 로직을 처리하는 레이어입니다. 각종 비즈니스 규칙을 서비스로 구현합니다. 데이터 핸들링이 필요한 경우 repository패키지를 의존하여 작성합니다.
/mocks
테스트 코드에서 사용할 Mocking 관련 코드를 저장하는 디렉토리입니다. 실제 서비스나 데이터베이스 연결 없이도 테스트할 수 있도록 모의 객체(Mock Object)를 정의하여 독립적인 테스트 환경을 제공합니다. Mockery 라이브러리를 사용하여 인터페이스에 대한 Mock 객체를 자동 생성하고, 이를 통해 테스트의 신뢰성을 높입니다.
/testdata
테스트 코드에서 사용할 데이터를 저장하는 디렉토리입니다. 정적 파일, JSON 샘플 데이터, 이미지 파일 등이 포함될 수 있습니다.
Example
controller, service, repository 구조에 대한 예제입니다. interface를 사용하여 service에서 repository를 주입시키고, controller에서 service를 주입합니다.
package domain
import "time"
type User struct {
ID int64
Email string
CreatedAt time.Time
}
package repository
type UserRepository interface {
FindByID(ctx context.Context, id int64) (*domain.User, error)
}
package service
type UserService interface {
GetUserEmail(ctx context.Context, id int64) (string), error)
}
// interface를 사용하여 service, controol 사요
type userService struct {
repository repository.UserRepository
}
func New(repository repository.UserRepository) UserService {
return &userService{repository: repository}
}
package controller
type userController struct {
service service.UserService
}
func New(service service.UserService) *userController {
return &userController{service: service}
}
External Package
유용하게 사용하고 있는 외부 패키지를 정리해두었습니다.
env
환경 변수를 구조체(Struct) 형태로 쉽게 관리할 수 있도록 도와주는 패키지입니다. 설정 관리가 편리해지며, 코드 가독성을 높여줍니다.
zerolog
프로젝트 내부에서 구조화된 로그를 출력하기 위한 패키지입니다. 고성능, Zero Allocation의 효율적인 로깅을 지원하여 프로젝트의 성능을 높입니다.
go-json
Go의 표준 encoding/json 패키지를 대체하는 JSON 처리 라이브러리로, 성능이 뛰어나 JSON 처리 속도와 효율성을 높일 수 있습니다.
validator
유효성 검사를 위한 패키지로, 구조체와 필드에 다양한 검증 규칙을 적용하여 데이터의 무결성을 확보할 수 있습니다.
echo
HTTP 서버를 만들기 위한 웹 프레임워크입니다.
ent
RDBMS와의 상호작용을 위해 사용하는 ORM 라이브러리로, 타입 안전성을 보장하고 스키마 관리 및 데이터베이스 쿼리를 효율적으로 처리할 수 있습니다.
cobra
CLI(Command Line Interface) 도구를 개발할 때 사용하는 패키지로, 명령어 구조, 플래그 및 하위 명령어 등을 쉽게 구현할 수 있도록 지원합니다.
testify
Go 언어에서 테스트를 쉽게 작성할 수 있도록 도와주는 패키지입니다. 다양한 기능을 제공하며, 특히 Assertions 기능으로 코드가 예상대로 작동하는지 간단하게 검증할 수 있습니다. 또한, Mock 객체를 활용하여 테스트의 신뢰성을 높일 수 있습니다. testify는 단위 테스트의 품질을 높이고, 테스트 코드 작성을 간소화하는 데 유용합니다.
mockery
인터페이스에 대한 Mock 객체를 자동으로 생성해주는 패키지입니다. 이를 통해 테스트에서 실제 구현체 대신 Mock 객체를 사용함으로써 테스트의 독립성과 신뢰성을 높일 수 있습니다.
swag
Swagger 2.0 규격에 맞춰 RESTful API 문서를 자동으로 생성하는 패키지입니다. API의 엔드포인트, 요청, 응답 형식을 쉽게 시각화하여 개발자 간의 소통을 원활하게 하고 문서화를 간소화할 수 있습니다.
sentry-go
Sentry 연동을 위한 패키지입니다. 애플리케이션에서 발생하는 오류와 예외를 모니터링하고 추적할 수 있도록 지원하는 패키지입니다.
dd-trace-go
애플리케이션의 성능을 모니터링하고 추적할 수 있도록 해주는 DataDog APM 연동을 위한 패키지입니다
aws-sdk-go-v2
AWS 서비스를 쉽게 사용할 수 있도록 해주는 AWS SDK입니다. SDK를 통해 Amazon S3, DynamoDB, EC2, Lambda 등 다양한 AWS 서비스를 Go 애플리케이션에서 간편하게 호출하고 관리할 수 있습니다. aws-sdk-go-v2는 성능과 효율성을 고려하여 설계되었으며, 비동기 API 지원과 더불어 간결한 코드로 AWS 리소스와 상호작용할 수 있어 클라우드 기반 애플리케이션 개발에 유용합니다.