Post

Monorepo - Frontend + Backend - 02

Monorepo - Frontend + Backend - 02

Kustomize를 사용한 환경별 배포 (dev, staging, prod) 와 Helm Chart를 통한 패키징 기능을 추가

📁 최종 디렉토리 구조

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
my-org-monorepo/
├── apps/
│   ├── web-app/            # React + Tailwind (Vite + TypeScript)
│   └── spring-backend/    # Spring Boot (Java 17 + Gradle)
├── packages/
│   ├── shared-types/       # 공통 TypeScript 타입
│   └── shared-utils/      # 공통 유틸리티 함수
├── k8s/
│   └── spring-backend/
│       └── base/          # 공통 Kubernetes 매니페스트
│       └── overlays/
│           ├── dev/
│           ├── staging/
│           └── prod/
├── helm/
│   ├── web-app/
│   └── spring-backend/
├── argocd/
│   ├── web-app/
│   └── spring-backend/
├── turbo.json
├── package.json
├── tsconfig.json
├── .gitignore
└── README.md

1. Kustomize로 환경별 배포 설정 (spring-backend)

📁 기본 구조

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
k8s/spring-backend/
├── base/
│   ├── deployment.yaml
│   ├── service.yaml
│   └── kustomization.yaml
└── overlays/
    ├── dev/
    │   ├── kustomization.yaml
    │   └── configmap.yaml
    ├── staging/
    │   ├── kustomization.yaml
    │   └── configmap.yaml
    └── prod/
        ├── kustomization.yaml
        └── configmap.yaml

📄 base/deployment.yaml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
apiVersion: apps/v1
kind: Deployment
metadata:
  name: spring-backend
spec:
  replicas: 1
  selector:
    matchLabels:
      app: spring-backend
  template:
    metadata:
      labels:
        app: spring-backend
    spec:
      containers:
        - name: spring-backend
          image: my-org/spring-backend:latest
          ports:
            - containerPort: 8080

📄 base/service.yaml

1
2
3
4
5
6
7
8
9
10
apiVersion: v1
kind: Service
metadata:
  name: spring-backend
spec:
  selector:
    app: spring-backend
  ports:
    - port: 80
      targetPort: 8080

📄 base/kustomization.yaml

1
2
3
resources:
  - deployment.yaml
  - service.yaml

📄 overlays/dev/kustomization.yaml

1
2
3
4
5
6
7
8
9
10
11
12
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
metadata:
  name: dev

bases:
  - ../../base

configMapGenerator:
  - name: spring-config
    literals:
      - SPRING_PROFILES_ACTIVE=dev

2. Helm Chart로 패키징 (helm/spring-backend)

1
2
3
mkdir -p helm/spring-backend
cd helm/spring-backend
helm create .

기본 helm create로 생성된 구조를 수정해 배포 설정을 맞춤화한다

📄 values.yaml (간단 예시)

1
2
3
4
5
6
7
8
9
10
image:
  repository: my-org/spring-backend
  tag: latest
  pullPolicy: IfNotPresent

service:
  port: 80
  targetPort: 8080

replicaCount: 1

📄 templates/deployment.yaml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
apiVersion: apps/v1
kind: Deployment
metadata:
  name: 
spec:
  replicas: 
  selector:
    matchLabels:
      app: spring-backend
  template:
    metadata:
      labels:
        app: spring-backend
    spec:
      containers:
        - name: spring-backend
          image: ":"
          ports:
            - containerPort: 8080

3. ArgoCD Application 예시 (helm 기반)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# argocd/spring-backend/spring-backend-helm-application.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: spring-backend-dev
spec:
  project: default
  source:
    repoURL: https://github.com/your-org/your-monorepo.git
    targetRevision: HEAD
    path: helm/spring-backend
    helm:
      valueFiles:
        - values.yaml
        - values-dev.yaml
  destination:
    server: https://kubernetes.default.svc
    namespace: spring-dev
  syncPolicy:
    automated:
      selfHeal: true

4. Helm Chart: React 프론트엔드

1
2
3
mkdir -p helm/web-app
cd helm/web-app
helm create .

📄 values.yaml

1
2
3
4
5
6
7
image:
  repository: my-org/web-app
  tag: latest

service:
  port: 80
  targetPort: 3000

📄 templates/deployment.yaml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-app
spec:
  replicas: 1
  selector:
    matchLabels:
      app: web-app
  template:
    metadata:
      labels:
        app: web-app
    spec:
      containers:
        - name: web-app
          image: ":"
          ports:
            - containerPort: 3000

5. ArgoCD ApplicationSet (선택 사항)

ApplicationSet를 사용하면 여러 환경(dev, staging, prod)을 자동으로 생성 가능

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# argocd/spring-backend/applicationset.yaml
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: spring-backend-set
spec:
  generators:
    - list:
        elements:
          - cluster: https://kubernetes.default.svc
            namespace: spring-dev
            values: dev
          - cluster: https://kubernetes.default.svc
            namespace: spring-staging
            values: staging
          - cluster: https://kubernetes.default.svc
            namespace: spring-prod
            values: prod

  template:
    spec:
      application:
        metadata:
          name: spring-backend-
        spec:
          source:
            repoURL: https://github.com/your-org/your-monorepo.git
            path: helm/spring-backend
            targetRevision: HEAD
            helm:
              valueFiles:
                - values-.yaml
          destination:
            server: 
            namespace: 
          syncPolicy:
            automated:
              selfHeal: true

6. Turborepo를 통한 Helm & Kustomize 작업 실행

Turborepo로 Helm과 Kustomize 작업도 실행 가능

📄 turbo.json

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
{
  "pipeline": {
    "build": {
      "dependsOn": ["^build"],
      "outputs": ["dist/**", "build/libs/**"]
    },
    "lint": {
      "dependsOn": ["^lint"]
    },
    "test": {
      "dependsOn": ["^test"]
    },
    "k8s:apply": {
      "cache": false,
      "outputs": [],
      "dependsOn": ["build"],
      "inputs": ["k8s/**/*", "helm/**/*"],
      "executor": "local",
      "cli": {
        "command": "kubectl apply -k k8s/spring-backend/overlays/"
      }
    },
    "helm:install": {
      "cache": false,
      "outputs": [],
      "dependsOn": ["build"],
      "inputs": ["helm/web-app/**/*", "helm/spring-backend/**/*"],
      "executor": "local",
      "cli": {
        "command": "helm upgrade --install spring-backend helm/spring-backend -f helm/spring-backend/values-.yaml"
      }
    }
  }
}

7. CI/CD GitHub Actions 예시

.github/workflows/deploy.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
name: Deploy to Kubernetes with Helm and ArgoCD

on:
  push:
    branches:
      - main

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v3

      - name: Setup Helm
        uses: azure/setup-helm@v3

      - name: Build Spring Boot
        run: |
          cd apps/spring-backend
          ./gradlew build

      - name: Build React App
        run: |
          cd apps/web-app
          npm install
          npm run build

      - name: Build and Push Docker Image
        run: |
          docker build -t my-org/web-app:latest -f apps/web-app/Dockerfile .
          docker build -t my-org/spring-backend:latest -f apps/spring-backend/Dockerfile .
          docker push my-org/web-app:latest
          docker push my-org/spring-backend:latest

      - name: Helm Install
        run: |
          helm upgrade --install spring-backend helm/spring-backend -f helm/spring-backend/values-prod.yaml
          helm upgrade --install web-app helm/web-app -f helm/web-app/values-prod.yaml

      - name: ArgoCD Sync
        run: |
          argocd app sync spring-backend
          argocd app sync web-app

8. Dockerfile 추가

📄 apps/web-app/Dockerfile

1
2
3
4
5
6
7
8
FROM node:20 as build
WORKDIR /app
COPY . .
RUN npm install && npm run build
FROM nginx
COPY --from=build /app/dist /usr/share/nginx/html
EXPOSE 3000
CMD ["nginx", "-g", "daemon off;"]

📄 apps/spring-backend/Dockerfile

1
2
3
4
FROM eclipse-temurin:17-jdk-alpine
WORKDIR /app
COPY build/libs/demo-0.0.1-SNAPSHOT.jar app.jar
ENTRYPOINT ["java", "-jar", "app.jar"]

📌 요약

이 Monorepo는 다음과 같은 기능을 포함한다:

기능설명
Turborepo빌드, 테스트, 린트, 테스트 자동화
React + TailwindVite + TypeScript 기반 프론트엔드
Spring BootJava 17 + Gradle 기반 백엔드
Kustomize환경별 배포 설정 (dev, staging, prod)
Helm앱 단위 패키징 및 버전 관리
ArgoCDGitOps 기반 자동 배포
GitHub ActionsCI/CD 파이프라인 자동화
This post is licensed under CC BY 4.0 by the author.