K8S, DDD, CQRS, ES, gRPC를 활용한 Go 서버/API 보일러플레이트

Go API 시작 키트

이 프로젝트는 K8S, DDD, CQRS, ES, gRPC와 같은 최신 기술 스택을 기반으로 한 Go 서버 및 API 개발을 위한 보일러플레이트를 제공합니다. 개발 및 프로덕션 환경을 위한 Kubernetes 구성을 포함하여, 프로덕션 환경과 유사한 환경에서 작업함으로써 구성 오류를 최소화합니다.

여러 서비스(예: 인증 또는 사용자 도메인)를 위한 단일 저장소(mono-repository) 구조를 채택했습니다. 공유 패키지 외에 각 서비스는 자체 코드베이스를 가지며, 이를 통해 보일러플레이트를 단순화합니다. 서비스 간 통신은 gRPC를 통해 이루어집니다. 각 서비스는 외부 통신을 위한 HTTP API 또는 gRPC 엔드포인트를 노출할 수 있습니다.

이 프로젝트 설정은 전체 Kubernetes 클러스터 및/또는 각 마이크로서비스의 환경 구성 시간을 단축하는 데 도움이 됩니다. 각 서비스를 개별 저장소로 분리하거나 단일 저장소로 유지하는 것은 선호도에 따라 선택할 수 있습니다.

웹 UI 예제 (React)

이 보일러플레이트에는 API와의 상호작용을 보여주는 간단한 웹 UI가 포함되어 있습니다. 배포 및 호스트 설정이 완료되면 https://api.go-api-template.local에서 UI에 접근할 수 있습니다.

핵심 개념

  1. REST API
  2. Docker
  3. Kubernetes
  4. Helm 차트
  5. Terraform
  6. gRPC
  7. 도메인 주도 설계 (DDD)
  8. CQRS
  9. 이벤트 소싱 (Event Sourcing)
  10. 육각형, 양파, 클린 아키텍처
  11. OAuth2

보일러플레이트에서 사용되는 주요 패키지

  1. gorouter
  2. message-bus
  3. gollback
  4. shutdown
  5. pubsub
  6. pushpull
  7. gocontainer

문서

  • 위키
  • 패키지 수준 문서
  • 시작 가이드
  • 설치 및 설정
  • 구성
  • 가이드

빠른 시작

로컬호스트 별칭

/etc/hosts 파일을 편집하여 localhost 별칭을 추가합니다.

go-api-template git:(main) cat /etc/hosts
##
# Host Database
#
# localhost is used to configure the loopback interface
# when the system is booting. Do not change this entry.
##
127.0.0.1 go-api-template.local api.go-api-template.local maildev.go-api-template.local mysql.go-api-template.local

릴리스 빌드

로컬 이미지

make docker-build BIN=auth-service
make docker-build BIN=migrate
make docker-build BIN=user-service
make docker-build BIN=web

GitHub Package Registry

메타데이터를 사용하여 태그를 생성하면 GitHub 워크플로우가 트리거되어 Docker 이미지가 GitHub Package Registry에 게시됩니다. 태그 v1.0.0-authauth 서비스의 빌드를 트리거하여 1.0.0 Docker 이미지 태그를 게시합니다. cmd 디렉터리에서 모든 서비스에 대한 릴리스를 생성할 수 있습니다.

v1.0.0-auth
v1.0.0-user
v1.0.0-web
v1.0.0-migrate

main.yaml 파일에서 이미지 세부 정보를 다음과 같이 교체합니다.

  image:
-    repository: go-api-template-user
+    repository: docker.pkg.github.com/template/go-api-template/go-api-template-user
-    tag: latest
+    tag: 1.0.0
    pullPolicy: IfNotPresent

모든 서비스와 migrate init 컨테이너에 대해 이 작업을 반복합니다.

개인 레지스트리

Docker에 로그인합니다.

docker login

Docker 설정 파일을 복사합니다.

cp ~/.docker/config.json ./k8s/.docker/config.json

config.json을 확인합니다.

배포

make terraform-install

제거

make terraform-destroy

영구 볼륨(Persistent Volume)이 종료 시 스택(stack)되는 경우가 있습니다. 이는 영구 볼륨이 보호되고 있을 때 발생할 수 있습니다. 다음 명령으로 확인할 수 있습니다.

kubectl describe pvc data-pvc --namespace=go-api-template | grep Finalizers

Output:
Finalizers:    [kubernetes.io/pvc-protection]

kubectl patch를 사용하여 finalizersnull로 설정하여 이 문제를 해결할 수 있습니다.

kubectl patch pvc data-pvc --namespace=go-api-template -p '{"metadata":{"finalizers": []}}' --type=merge

빌드 태그

Build flags는 다른 영속성 계층(persistence layers)을 위해 사용됩니다. 자세한 내용은 services.go 파일을 참조하세요. 제공되는 계층은 mysql, mongo, memory입니다. 필요한 경우 주어진 패턴을 따라 쉽게 새 계층을 추가할 수 있습니다.

go build -tags=mysql_persistence

사용 가능한 빌드 태그

  • persistence_mysql (mysql 서비스 컨테이너)
  • persistence_mongodb (mongodb 서비스 컨테이너)

중요 플래그가 제공되지 않으면, 영속성 계층은 기본적으로 memory로 설정됩니다(Docker 이미지는 persistence_mysql 플래그가 설정됨). 각 서비스의 Dockerfile을 참조하세요.

도메인 로직

명령 분배(Dispatching command)

다음은 POST 요청을 사용하여 샘플 JSON을 전송하는 예제입니다.

curl -d '{"username":"testuser"}' -H "Content-Type: application/json" -X POST https://api.go-api-template.local/users/v1/dispatch/user/create-user --insecure

API 뷰

공개 라우트(Public routes)

사용자 프로필 정보 조회: https://api.go-api-template.local/users/v1/profile/34e7ed39-aa94-4ef2-9422-401bba9fc812

{"id":"34e7ed39-aa94-4ef2-9422-401bba9fc812","username":"testuser"}

사용자 목록 조회: https://api.go-api-template.local/users/v1/all?page=1&limit=10

{"page":1,"limit":20,"total":1,"users":[{"id":"34e7ed39-aa94-4ef2-9422-401bba9fc812","username":"testuser"}]}

보호된 라우트(Protected routes)

보호된 라우트에 접근하려면 인증 토큰을 사용하세요: https://api.go-api-template.local/users/v1/profile/me.

{"code": "401","message": "Unauthorized"}

사용자에게 액세스 토큰을 요청합니다.

curl -d '{"username":"testuser"}' -H "Content-Type: application/json" -X POST https://api.go-api-template.local/users/v1/auth/request-token --insecure

메일 캐atcher에서 액세스 토큰을 가져옵니다: https://maildev.go-api-template.local.

인증 토큰을 사용하여 보호된 라우트에 접근합니다: https://api.go-api-template.local/users/v1/profile/me?authToken=eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJyXHUwMDE277-977-977-977-9IiwiZXhwIjoxNTU5NjEwOTc2LCJzdWIiOiIzNGU3ZWQzOS1hYTk0LTRlZjItOTQyMi00MDFiYmE5ZmM4MTIifQ.pEkgtDAvNh2D3Dtgfpu4tt-Atn1h6QwMkDhz4KpgFxNX8jE7fQH00J6K5V7CV063pigxWhOMMTRLmQdhzhajzQ

{"id":"34e7ed39-aa94-4ef2-9422-401bba9fc812","username":"testuser"}

태그: go kubernetes DDD CQRS gRPC

6월 18일 23:50에 게시됨