diff --git a/deployment/uiux/Dockerfile b/deployment/uiux/Dockerfile new file mode 100644 index 0000000..52f3607 --- /dev/null +++ b/deployment/uiux/Dockerfile @@ -0,0 +1,25 @@ +# HGZero UI/UX Prototype Deployment +# Nginx 기반 정적 파일 서빙 + +FROM nginx:1.25-alpine + +# 메타데이터 +LABEL maintainer="HGZero Team" +LABEL description="HGZero UI/UX Prototype" +LABEL version="1.0.0" + +# 프로토타입 HTML 파일 복사 +COPY design/uiux/prototype/* /usr/share/nginx/html/ + +# nginx 설정 파일 복사 (커스텀 설정이 필요한 경우) +COPY deployment/uiux/nginx.conf /etc/nginx/conf.d/default.conf + +# 포트 노출 +EXPOSE 80 + +# Health check +HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ + CMD wget --quiet --tries=1 --spider http://localhost/ || exit 1 + +# nginx 실행 +CMD ["nginx", "-g", "daemon off;"] diff --git a/deployment/uiux/README.md b/deployment/uiux/README.md new file mode 100644 index 0000000..53ea7a1 --- /dev/null +++ b/deployment/uiux/README.md @@ -0,0 +1,276 @@ +# HGZero UI/UX Prototype Deployment + +회의록 작성 및 공유 개선 서비스의 UI/UX 프로토타입을 Kubernetes Pod로 배포하기 위한 가이드입니다. + +## 📁 디렉토리 구조 + +``` +deployment/uiux/ +├── Dockerfile # nginx 기반 Docker 이미지 빌드 파일 +├── nginx.conf # nginx 웹서버 설정 +├── build.sh # Linux/Mac용 이미지 빌드 스크립트 +├── build.bat # Windows용 이미지 빌드 스크립트 +├── k8s/ +│ ├── deployment.yaml # Kubernetes Deployment 매니페스트 +│ ├── service.yaml # Kubernetes Service 매니페스트 +│ └── ingress.yaml # Kubernetes Ingress 매니페스트 +└── README.md # 이 파일 +``` + +## 🎯 프로토타입 파일 + +배포 대상 프로토타입 HTML 파일 위치: +``` +design/uiux/prototype/ +├── 01-로그인.html +├── 02-대시보드.html +├── 03-회의예약.html +├── 04-템플릿선택.html +├── 05-회의진행.html +├── 07-회의종료.html +├── 10-회의록상세조회.html +├── 11-회의록수정.html +└── 12-회의록목록조회.html +``` + +## 🚀 Quick Start + +### 1. Docker 이미지 빌드 + +#### Linux/Mac +```bash +# 프로젝트 루트 디렉토리에서 실행 +cd /path/to/HGZero +chmod +x deployment/uiux/build.sh +./deployment/uiux/build.sh +``` + +#### Windows +```cmd +REM 프로젝트 루트 디렉토리에서 실행 +cd C:\path\to\HGZero +deployment\uiux\build.bat +``` + +### 2. Kubernetes 배포 + +```bash +# 모든 리소스 배포 +kubectl apply -f deployment/uiux/k8s/ + +# 또는 개별 배포 +kubectl apply -f deployment/uiux/k8s/deployment.yaml +kubectl apply -f deployment/uiux/k8s/service.yaml +kubectl apply -f deployment/uiux/k8s/ingress.yaml +``` + +### 3. 배포 확인 + +```bash +# Pod 상태 확인 +kubectl get pods -l app=hgzero-uiux-prototype + +# Service 확인 +kubectl get svc hgzero-uiux-prototype + +# Ingress 확인 (배포한 경우) +kubectl get ingress hgzero-uiux-prototype +``` + +### 4. 프로토타입 접근 + +#### 방법 1: Port Forward (개발 환경) +```bash +kubectl port-forward svc/hgzero-uiux-prototype 8080:80 +``` +브라우저에서 `http://localhost:8080` 접속 + +#### 방법 2: NodePort (테스트 환경) +```bash +# NodePort 확인 +kubectl get svc hgzero-uiux-prototype + +# 접속: http://:30080 +``` + +#### 방법 3: Ingress (운영 환경) +`/etc/hosts`에 다음 추가: +``` + prototype.hgzero.local +``` +브라우저에서 `http://prototype.hgzero.local` 접속 + +## 📝 상세 가이드 + +### Docker 이미지 빌드 + +#### 수동 빌드 +```bash +# 프로젝트 루트에서 실행 +docker build \ + -t hgzero-uiux-prototype:latest \ + -f deployment/uiux/Dockerfile \ + . +``` + +#### 태그 지정 빌드 +```bash +# 버전 태그 지정 +./deployment/uiux/build.sh v1.0.0 +``` + +#### 레지스트리 푸시 +```bash +# 환경 변수로 레지스트리 지정 +export DOCKER_REGISTRY=myregistry.example.com +./deployment/uiux/build.sh + +# 또는 수동 태그 및 푸시 +docker tag hgzero-uiux-prototype:latest myregistry.example.com/hgzero-uiux-prototype:latest +docker push myregistry.example.com/hgzero-uiux-prototype:latest +``` + +### Kubernetes 리소스 상세 + +#### Deployment 설정 +- **이미지**: `hgzero-uiux-prototype:latest` +- **레플리카**: 2개 +- **리소스 요청**: CPU 50m, Memory 64Mi +- **리소스 제한**: CPU 200m, Memory 128Mi +- **Health Check**: `/health` 엔드포인트 + +#### Service 설정 +- **타입**: NodePort +- **포트**: 80 (내부), 30080 (외부) +- **셀렉터**: `app=hgzero-uiux-prototype` + +#### Ingress 설정 +- **호스트**: `prototype.hgzero.local` +- **IngressClass**: nginx +- **경로**: `/` (모든 경로) + +### 커스터마이징 + +#### nginx 설정 수정 +`deployment/uiux/nginx.conf` 파일을 수정하여 웹서버 동작 변경 가능: +- 기본 인덱스 페이지 +- 캐시 정책 +- Gzip 압축 설정 +- 로깅 설정 + +#### Kubernetes 리소스 조정 +`deployment/uiux/k8s/*.yaml` 파일 수정: +- 레플리카 수 조정 +- 리소스 제한 변경 +- 서비스 타입 변경 (NodePort → LoadBalancer) +- Ingress 호스트명 변경 + +## 🔧 트러블슈팅 + +### 이미지 빌드 실패 +```bash +# Docker 데몬 확인 +docker ps + +# Dockerfile 경로 확인 +ls -la deployment/uiux/Dockerfile + +# 프로토타입 파일 확인 +ls -la design/uiux/prototype/*.html +``` + +### Pod 시작 실패 +```bash +# Pod 로그 확인 +kubectl logs -l app=hgzero-uiux-prototype + +# Pod 상세 정보 +kubectl describe pod + +# 이벤트 확인 +kubectl get events --sort-by='.lastTimestamp' +``` + +### 접근 불가 +```bash +# Service 엔드포인트 확인 +kubectl get endpoints hgzero-uiux-prototype + +# Pod 네트워크 테스트 +kubectl exec -it -- wget -O- http://localhost/health + +# Ingress 컨트롤러 확인 +kubectl get pods -n ingress-nginx +``` + +## 🔄 업데이트 및 재배포 + +### 이미지 업데이트 +```bash +# 1. 새 이미지 빌드 +./deployment/uiux/build.sh v1.0.1 + +# 2. Deployment 이미지 업데이트 +kubectl set image deployment/hgzero-uiux-prototype \ + nginx=hgzero-uiux-prototype:v1.0.1 + +# 3. 롤아웃 상태 확인 +kubectl rollout status deployment/hgzero-uiux-prototype +``` + +### 롤백 +```bash +# 이전 버전으로 롤백 +kubectl rollout undo deployment/hgzero-uiux-prototype + +# 특정 리비전으로 롤백 +kubectl rollout undo deployment/hgzero-uiux-prototype --to-revision=2 +``` + +## 🗑️ 리소스 삭제 + +```bash +# 모든 리소스 삭제 +kubectl delete -f deployment/uiux/k8s/ + +# 또는 개별 삭제 +kubectl delete deployment hgzero-uiux-prototype +kubectl delete service hgzero-uiux-prototype +kubectl delete ingress hgzero-uiux-prototype +``` + +## 📊 모니터링 + +### 리소스 사용량 확인 +```bash +# Pod 리소스 사용량 +kubectl top pods -l app=hgzero-uiux-prototype + +# 상세 메트릭 (Metrics Server 필요) +kubectl get --raw /apis/metrics.k8s.io/v1beta1/namespaces/default/pods +``` + +### 로그 확인 +```bash +# 실시간 로그 +kubectl logs -f -l app=hgzero-uiux-prototype + +# 최근 로그 (100줄) +kubectl logs --tail=100 -l app=hgzero-uiux-prototype + +# 이전 컨테이너 로그 +kubectl logs --previous +``` + +## 🔐 보안 고려사항 + +1. **프로덕션 환경**: Ingress에 TLS 설정 추가 +2. **네트워크 정책**: Pod 간 통신 제한 +3. **리소스 제한**: 명확한 리소스 쿼터 설정 +4. **이미지 보안**: 정기적인 베이스 이미지 업데이트 + +## 📚 참고 자료 + +- [Kubernetes Documentation](https://kubernetes.io/docs/) +- [Nginx Docker Official Image](https://hub.docker.com/_/nginx) +- [Kubernetes Best Practices](https://kubernetes.io/docs/concepts/configuration/overview/) diff --git a/deployment/uiux/build.sh b/deployment/uiux/build.sh new file mode 100644 index 0000000..8ac3841 --- /dev/null +++ b/deployment/uiux/build.sh @@ -0,0 +1,98 @@ +#!/bin/bash + +# HGZero UI/UX Prototype Docker Image Build Script + +set -e + +# 변수 설정 +IMAGE_NAME="hgzero-uiux-prototype" +IMAGE_TAG="${1:-latest}" +REGISTRY="${DOCKER_REGISTRY:-acrdigitalgarage02.azurecr.io}" +FULL_IMAGE_NAME="${REGISTRY}/${IMAGE_NAME}:${IMAGE_TAG}" + +# 색상 코드 +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' # No Color + +echo -e "${GREEN}======================================${NC}" +echo -e "${GREEN}HGZero UI/UX Prototype Image Build${NC}" +echo -e "${GREEN}======================================${NC}" +echo "" + +# 스크립트 디렉토리 경로 저장 +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +PROJECT_ROOT="$(cd "${SCRIPT_DIR}/../.." && pwd)" +DOCKERFILE_PATH="${SCRIPT_DIR}/Dockerfile" + +# Dockerfile 확인 +if [ ! -f "${DOCKERFILE_PATH}" ]; then + echo -e "${RED}Error: Dockerfile not found at ${DOCKERFILE_PATH}${NC}" + exit 1 +fi + +# 프로젝트 루트로 이동 +cd "${PROJECT_ROOT}" + +# 프로토타입 파일 확인 +if [ ! -d "design/uiux/prototype" ] || [ -z "$(ls -A design/uiux/prototype/*.html 2>/dev/null)" ]; then + echo -e "${RED}Error: Prototype HTML files not found in design/uiux/prototype/${NC}" + exit 1 +fi + +echo -e "${YELLOW}Building Docker image...${NC}" +echo "Image: ${FULL_IMAGE_NAME}" +echo "" + +# Docker 이미지 빌드 +docker build \ + -t ${IMAGE_NAME}:${IMAGE_TAG} \ + -t ${IMAGE_NAME}:latest \ + -t ${FULL_IMAGE_NAME} \ + -f ${DOCKERFILE_PATH} \ + . + +if [ $? -eq 0 ]; then + echo "" + echo -e "${GREEN}✓ Build successful!${NC}" + echo "" + echo "Created images:" + echo " - ${IMAGE_NAME}:${IMAGE_TAG}" + echo " - ${IMAGE_NAME}:latest" + echo " - ${FULL_IMAGE_NAME}" + echo "" + + # 이미지 정보 출력 + echo "Image details:" + docker images ${IMAGE_NAME}:${IMAGE_TAG} + echo "" + + # Push 옵션 + read -p "Push image to registry? (y/N): " -n 1 -r + echo + if [[ $REPLY =~ ^[Yy]$ ]]; then + echo -e "${YELLOW}Pushing image to registry...${NC}" + docker push ${FULL_IMAGE_NAME} + if [ $? -eq 0 ]; then + echo -e "${GREEN}✓ Push successful!${NC}" + else + echo -e "${RED}✗ Push failed${NC}" + exit 1 + fi + fi + + echo "" + echo -e "${GREEN}Next steps:${NC}" + echo "1. Deploy to Kubernetes:" + echo " kubectl apply -f k8s" + echo "" + echo "2. Check deployment status:" + echo " kubectl get pods -l app=hgzero-uiux-prototype" + + +else + echo "" + echo -e "${RED}✗ Build failed${NC}" + exit 1 +fi diff --git a/deployment/uiux/k8s/deployment.yaml b/deployment/uiux/k8s/deployment.yaml new file mode 100644 index 0000000..c28a0ea --- /dev/null +++ b/deployment/uiux/k8s/deployment.yaml @@ -0,0 +1,42 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: hgzero-uiux-prototype + namespace: hgzero + labels: + app: hgzero-uiux-prototype + tier: frontend + version: v1.0.0 +spec: + replicas: 1 + selector: + matchLabels: + app: hgzero-uiux-prototype + template: + metadata: + labels: + app: hgzero-uiux-prototype + tier: frontend + version: v1.0.0 + spec: + containers: + - name: nginx + image: acrdigitalgarage02.azurecr.io/hgzero-uiux-prototype:latest + imagePullPolicy: IfNotPresent + ports: + - containerPort: 80 + name: http + protocol: TCP + resources: + requests: + cpu: 50m + memory: 64Mi + limits: + cpu: 200m + memory: 128Mi + + env: + - name: TZ + value: "Asia/Seoul" + restartPolicy: Always + terminationGracePeriodSeconds: 5 diff --git a/deployment/uiux/k8s/ingress.yaml b/deployment/uiux/k8s/ingress.yaml new file mode 100644 index 0000000..747147e --- /dev/null +++ b/deployment/uiux/k8s/ingress.yaml @@ -0,0 +1,42 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: hgzero-uiux-prototype + namespace: hgzero + labels: + app: hgzero-uiux-prototype + tier: frontend + component: prototype + annotations: + # Nginx Ingress Controller 설정 + # rewrite-target 제거: Pod 내부 nginx가 직접 처리하도록 + nginx.ingress.kubernetes.io/ssl-redirect: "false" + + # CORS 설정 (필요시 활성화) + # nginx.ingress.kubernetes.io/enable-cors: "true" + # nginx.ingress.kubernetes.io/cors-allow-methods: "GET, OPTIONS" + # nginx.ingress.kubernetes.io/cors-allow-origin: "*" + + # 타임아웃 설정 + nginx.ingress.kubernetes.io/proxy-connect-timeout: "30" + nginx.ingress.kubernetes.io/proxy-send-timeout: "30" + nginx.ingress.kubernetes.io/proxy-read-timeout: "30" + + # 버퍼 크기 설정 + nginx.ingress.kubernetes.io/proxy-body-size: "10m" + + # Rate limiting (필요시 활성화) + # nginx.ingress.kubernetes.io/limit-rps: "10" +spec: + ingressClassName: nginx + rules: + - host: prototype.hgzero.kubepia.com + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: hgzero-uiux-prototype + port: + number: 80 diff --git a/deployment/uiux/k8s/service.yaml b/deployment/uiux/k8s/service.yaml new file mode 100644 index 0000000..eeb10ee --- /dev/null +++ b/deployment/uiux/k8s/service.yaml @@ -0,0 +1,19 @@ +apiVersion: v1 +kind: Service +metadata: + name: hgzero-uiux-prototype + namespace: hgzero + labels: + app: hgzero-uiux-prototype + tier: frontend +spec: + type: NodePort + selector: + app: hgzero-uiux-prototype + ports: + - name: http + protocol: TCP + port: 80 + targetPort: 80 + nodePort: 30080 + sessionAffinity: None diff --git a/deployment/uiux/nginx.conf b/deployment/uiux/nginx.conf new file mode 100644 index 0000000..8728426 --- /dev/null +++ b/deployment/uiux/nginx.conf @@ -0,0 +1,52 @@ +server { + listen 80; + server_name _; + + root /usr/share/nginx/html; + index 01-로그인.html; + + # 한글 파일명 지원 + charset utf-8; + + # 로그 설정 + access_log /var/log/nginx/access.log; + error_log /var/log/nginx/error.log; + + # 루트 경로를 명시적으로 로그인 페이지로 처리 + # 디렉토리처럼 처리하여 index 지시어가 작동하도록 함 + location = / { + try_files $uri/ /01-로그인.html; + } + + # 모든 다른 요청에 대해 기본 처리 + location / { + try_files $uri $uri/ /01-로그인.html; + } + + # index.html 요청도 로그인 페이지로 + location = /index.html { + return 301 /01-로그인.html; + } + + # 정적 파일 캐싱 + location ~* \.(html|css|js|png|jpg|jpeg|gif|ico|svg)$ { + expires 1d; + add_header Cache-Control "public, immutable"; + } + + # 헬스체크 엔드포인트 + location /health { + access_log off; + return 200 "OK\n"; + add_header Content-Type text/plain; + } + + # 404 처리 + error_page 404 /01-로그인.html; + + # gzip 압축 + gzip on; + gzip_vary on; + gzip_min_length 1024; + gzip_types text/plain text/css text/xml text/javascript application/x-javascript application/xml+rss; +}