From 1a3571d66c91ba7b01696418e9626385775a413a Mon Sep 17 00:00:00 2001 From: Jinseong Date: Mon, 24 Nov 2025 00:03:32 +0900 Subject: [PATCH 1/3] =?UTF-8?q?docs:=20README=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 514 +++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 492 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index 3727f8a..efa43b0 100644 --- a/README.md +++ b/README.md @@ -1,38 +1,508 @@ -# Base Project -Spring Boot 기반 프로젝트 템플릿 +
+ +# 🚀 Docker Compose 기반 CI/CD 파이프라인 + +### Spring Boot 애플리케이션을 위한 AWS 인프라 구성 및 자동화 배포 시스템 + +[![Docker](https://img.shields.io/badge/Docker-2496ED?style=flat&logo=docker&logoColor=white)](https://www.docker.com/) +[![AWS](https://img.shields.io/badge/AWS-FF9900?style=flat&logo=amazonaws&logoColor=white)](https://aws.amazon.com/) +[![GitHub Actions](https://img.shields.io/badge/GitHub_Actions-2088FF?style=flat&logo=githubactions&logoColor=white)](https://github.com/features/actions) + +
+ +--- + +## 📋 목차 + +- [프로젝트 개요](#-프로젝트-개요) +- [기술 스택](#-기술-스택) +- [아키텍처](#-아키텍처) +- [주요 기능](#-주요-기능) +- [사전 준비](#-사전-준비) +- [시작하기](#-시작하기) +- [CI/CD 파이프라인](#-cicd-파이프라인) + +--- + +## 🎯 프로젝트 개요 + +> 본 프로젝트는 Docker Compose와 GitHub Actions 기반의 CI/CD 구성 예제를 정리한 Repository입니다. + +### 📌 주요 목표 + +``` +✅ 자동화된 배포 코드 푸시부터 서버 배포까지 자동화 +✅ 환경 분리 Local / Dev / Prod 환경의 명확한 분리 +✅ 무중단 배포 Nginx 기반 Blue-Green 배포로 서비스 중단 최소화 +✅ 보안 관리 Private 서브모듈과 환경변수를 통한 민감 정보 관리 +✅ 배포 알림 Discord 웹훅을 통한 개발 현황 및 배포 상태 알림 +``` + +--- + +## 🛠 기술 스택 + +### Backend +![Java](https://img.shields.io/badge/Java-007396?style=flat&logo=openjdk&logoColor=white) +![Spring Boot](https://img.shields.io/badge/Spring%20Boot-6DB33F?style=flat&logo=springboot&logoColor=white) +![Spring Data JPA](https://img.shields.io/badge/Spring%20Data%20JPA-6DB33F?style=flat&logo=spring&logoColor=white) +![MySQL](https://img.shields.io/badge/MySQL-4479A1?style=flat&logo=mysql&logoColor=white) +![Redis](https://img.shields.io/badge/Redis-DC382D?style=flat&logo=redis&logoColor=white) + +### Infrastructure +![Docker](https://img.shields.io/badge/Docker-2496ED?style=flat&logo=docker&logoColor=white) +![Docker Compose](https://img.shields.io/badge/Docker%20Compose-2496ED?style=flat&logo=docker&logoColor=white) +![Nginx](https://img.shields.io/badge/Nginx-009639?style=flat&logo=nginx&logoColor=white) + +![AWS](https://img.shields.io/badge/AWS-FF9900?style=flat&logo=amazonaws&logoColor=white) +![EC2](https://img.shields.io/badge/EC2-FF9900?style=flat&logo=amazonec2&logoColor=white) +![RDS](https://img.shields.io/badge/RDS-527FFF?style=flat&logo=amazonrds&logoColor=white) +![ALB](https://img.shields.io/badge/ALB-8C4FFF?style=flat&logo=amazonaws&logoColor=white) +![NAT Gateway](https://img.shields.io/badge/NAT%20Gateway-FF9900?style=flat&logo=amazonaws&logoColor=white) + +### CI/CD +![GitHub Actions](https://img.shields.io/badge/GitHub%20Actions-2088FF?style=flat&logo=githubactions&logoColor=white) +![Bash Script](https://img.shields.io/badge/Bash_Script-4EAA25?style=flat&logo=gnubash&logoColor=white) + +--- + +## 🏗 아키텍처 + +### AWS 인프라 구조 + +![AWS Architecture](https://github.com/user-attachments/assets/76584cc0-9955-46d3-b518-911eda8744ba) + +### 애플리케이션 구조 (Blue-Green 배포) + +![Application Architecture](https://github.com/user-attachments/assets/bed0b70f-6c9b-4f6e-aa1e-62da96213bc5) + +--- + +## ✨ 주요 기능 + +### 🔄 1. 자동화된 CI/CD 파이프라인 + + + + + + +
+ +#### 🧪 TEST.yml + +**트리거** +- 커밋 푸시 (main, develop 제외) +- PR 생성 (main, develop 대상) + +**프로세스** +``` +1️⃣ 코드 체크아웃 및 의존성 캐싱 +2️⃣ H2 + Redis 기반 테스트 실행 +3️⃣ 테스트 결과 리포트 생성 +4️⃣ PR에 테스트 결과 자동 코멘트 +``` + + + +#### 🚀 CICD.yml + +**트리거** +- develop/main 브랜치 머지 +

+ +**프로세스** +``` +1️⃣ Gradle 빌드 및 Docker 이미지 생성 +2️⃣ DockerHub에 이미지 푸시 +3️⃣ Self-hosted Runner에서 배포 실행 +4️⃣ Blue-Green 무중단 배포 +``` + +
+ +### 🔵🟢 2. Blue-Green 무중단 배포 + +```mermaid +graph LR + A[새 버전 컨테이너 시작] --> B{헬스체크
최대 45초} + B -->|성공| C[Nginx upstream 변경] + C --> D[기존 컨테이너 중지] + B -->|실패| E[새 컨테이너 중지] + E --> F[기존 컨테이너 유지] +``` + +### 📦 3. 환경별 설정 관리 + +| 환경 | 용도 | Spring Boot | MySQL | Redis | +|:---:|:---:|:---:|:------:|:---:| +| **Test** | CI 테스트 | GitHub Actions | H2* | Embedded | +| **Local** | 개발자 로컬 | IDE | Docker | Docker | +| **Dev** | 개발 서버 | Docker | RDS | Docker | +| **Prod** | 운영 서버 | Docker | RDS | Docker | + +### 🔒 4. 보안 강화 + +- **Private 서브모듈**: 민감한 설정 파일 분리 관리 +- **환경변수**: DB 연결 정보 등 런타임 주입 +- **Self-hosted Runner**: GitHub-hosted Runner 대신 자체 Runner 사용으로 개발/운영 서버 보안그룹을 Runner IP로만 제한 + +### 🔔 5. 실시간 알림 (Discord 웹훅) + +``` +📝 커밋 푸시 +📋 PR 생성 +✅ TEST.yml 테스트 결과 +🚀 CICD.yml 배포 결과 (성공/실패) +``` --- -## 1️⃣ 새로운 레포지토리 생성 시 초기 작업 +## 📌 사전 준비 + +### 1. DockerHub 설정 + +- 저장소 생성 및 Access Token 발급 필요 + +### 2. Discord 웹훅 설정 + +- 알림을 받을 서버의 특정 채널 웹훅 URL 필요 + +### 3. Self-hosted Runner 설정 + +- GitHub Actions Runner를 Bastion Host EC2에 설치 및 등록 필요 + +### 4. Private 서브모듈 생성 + +```bash +# 1. GitHub에서 Private Repository 생성 + +# 2. 메인 프로젝트에 서브모듈 추가 +git submodule add <서브모듈 Repository URL> config + +# 3. config 디렉토리에 properties 파일 생성 +cd config +touch application-test.properties +touch application-local.properties +touch application-dev.properties +touch application-prod.properties + +# 4. properties 파일 작성 후 커밋 +git add . +git commit -m "Initial properties files" +git push origin main -1. 템플릿 레포지토리를 기반으로 새 레포 생성 -2. 라벨 설정: base 레포를 참고하여 동일하게 생성 -3. 브랜치 규칙 설정 : base 레포를 참고하여 동일하게 생성 +# 5. 메인 프로젝트로 돌아와서 서브모듈 변경사항 커밋 +cd .. +git add .gitmodules config +git commit -m "Add config submodule" +git push +``` + +### 5. build.gradle 설정 + +```gradle +// Private 서브모듈의 properties 파일을 resources로 복사 +tasks.register("copyPrivateProperties", Copy) { + from './config' + include "*.properties" + into 'src/main/resources' +} + +// 빌드 시 자동으로 properties 복사 +processResources.dependsOn('copyPrivateProperties') +``` + +### 6. .gitignore 설정 + +```gitignore +# 복사된 properties 파일은 추적하지 않음 +src/main/resources/application-*.properties +``` + +## 🚀 시작하기 + +> 💡 **AWS 인프라 구성은 다루지 않습니다.** +> VPC, EC2, RDS, ALB 등의 설정이 완료된 상태를 전제로 합니다. + +### 1️⃣ 저장소 클론 + +```bash +# Private 서브모듈 포함하여 클론 +git clone --recurse-submodules <메인 프로젝트 Repository URL> + +# 이미 클론한 경우 서브모듈 초기화 +git submodule update --init --recursive +``` + +### 2️⃣ GitHub Secrets 설정 + +> Repository → Settings → Secrets and variables → Actions + +
+🔐 Private 서브모듈 + +``` +PERSONAL_ACCESS_TOKEN: GitHub PAT +``` + +
+ +
+🐳 Docker Hub + +``` +DOCKER_ID: DockerHub 사용자명 +DOCKER_PASSWORD: DockerHub 액세스 토큰 +DOCKER_REPOSITORY: DockerHub 저장소명 +``` + +
+ +
+💬 Discord 웹훅 + +``` +DISCORD_DEV_WEBHOOK: 개발 채널 웹훅 URL +DISCORD_PROD_WEBHOOK: 운영 채널 웹훅 URL +``` + +
+ +
+🔧 개발 서버 (Dev) + +``` +EC2_DEV_HOST: 개발 서버 EC2 Private IP +EC2_DEV_PEM_KEY: 개발 서버 SSH Private Key (전체 내용) +DB_DEV_URL: jdbc:mysql://dev-rds-endpoint:3306/database?useSSL=true&serverTimezone=Asia/Seoul +DB_DEV_USERNAME: RDS 사용자명 +DB_DEV_PASSWORD: RDS 비밀번호 +REDIS_DEV_PASSWORD: Redis 비밀번호 +``` + +
+ +
+🚀 운영 서버 (Prod) + +``` +EC2_PROD_HOST: 운영 서버 EC2 Private IP +EC2_PROD_PEM_KEY: 운영 서버 SSH Private Key (전체 내용) +DB_PROD_URL: jdbc:mysql://prod-rds-endpoint:3306/database?useSSL=true&serverTimezone=Asia/Seoul +DB_PROD_USERNAME: RDS 사용자명 +DB_PROD_PASSWORD: RDS 비밀번호 +REDIS_PROD_PASSWORD: Redis 비밀번호 +``` + +
+ +### 3️⃣ Application Properties 작성 + +#### 📝 각 환경별 작성 예시 + +```properties +# MySQL +spring.datasource.url=jdbc:mysql://localhost:3306/database?characterEncoding=UTF-8&serverTimezone=Asia/Seoul&useSSL=false +spring.datasource.username=사용자명 +spring.datasource.password=비밀번호 +spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver + +# JPA +spring.jpa.hibernate.ddl-auto=update +spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect +spring.jpa.properties.hibernate.format_sql=true +spring.jpa.properties.hibernate.default_batch_fetch_size=100 +spring.jpa.show-sql=true + +# Redis +spring.data.redis.host=localhost +spring.data.redis.port=6379 +spring.data.redis.password=비밀번호 + +# Logging +logging.level.root=INFO +logging.level.your.package.name=DEBUG +logging.level.org.hibernate.SQL=DEBUG +logging.level.org.hibernate.type.descriptor.sql=TRACE + +# Actuator +management.endpoints.web.exposure.include=health,info +management.endpoint.health.show-details=always +``` + +#### ⚠️ Dev/Prod 환경은 환경변수 사용 필수 + +```properties +# ❌ 하드코딩 금지 +spring.datasource.url=jdbc:mysql://prod-rds:3306/database +spring.datasource.password=actual_password +spring.data.redis.password=actual_redis_password + +# ✅ 플레이스홀더 사용 +spring.datasource.url=${DB_URL} +spring.datasource.username=${DB_USERNAME} +spring.datasource.password=${DB_PASSWORD} +spring.data.redis.password=${REDIS_PASSWORD} +``` + +### 4️⃣ 로컬 개발 환경 설정 + +```bash +# 1. Docker Compose로 MySQL + Redis 실행 +docker-compose up -d + +# 2. 컨테이너 상태 확인 +docker-compose ps +``` + +#### 애플리케이션 실행 + +**방법 1: IDE (ex.IntelliJ IDEA)** +``` +1. Run/Debug Configurations 열기 +2. Edit Configurations... 선택 +3. Active profiles: local 입력 +4. Run 버튼 클릭 +``` + +**방법 2: Gradle 명령어** +```bash +./gradlew bootRun --args='--spring.profiles.active=local' +``` + +### 5️⃣ Nginx 설정 (개발/운영 서버) + +```bash +# 각 서버에 Nginx 설정 디렉토리 생성 & 파일 생성 +mkdir -p /home/ubuntu/nginx +vi /home/ubuntu/nginx/nginx.conf +``` + +> ⚠️ **수동 배치 이유** +> - `docker-compose.infra.yml`에서 nginx.conf를 볼륨으로 마운트: `/home/ubuntu/nginx/nginx.conf:/etc/nginx/nginx.conf` +> - CICD.yml에서 매번 덮어쓰면 현재 활성화된 컨테이너(Blue/Green) 정보가 초기화되어 배포가 실패합니다 +> - 따라서 nginx.conf는 최초 1회 수동으로 서버에 생성합니다 --- -## 2️⃣ 브랜치명 규칙 +## 🔄 CI/CD 파이프라인 + +### 📊 브랜치 전략 (Git Flow) + +``` +┌─────────────┐ +│ main │ ← 운영 배포 +└──────▲──────┘ + │ +┌──────┴──────┐ +│ develop │ ← 개발 배포 +└──────▲──────┘ + │ + ┌───┴────┐ + │feature/│ 기능 개발 + │ ... │ + └────────┘ +``` + +### 🔀 워크플로우 + +#### 1️⃣ 기능 개발 + +```bash +# feature 브랜치 생성 +git checkout -b feature/14-new-feature + +# 개발 및 커밋 +git add . +git commit -m "feat: 새로운 기능 추가" + +# 푸시 → TEST.yml 자동 실행 ✅ +git push origin feature/14-new-feature +``` -- 형식: `타입/ISSUE번호-설명` -- 타입: feature, bugfix, refactor, chore, test, hotfix, docs -- ex) - - feature/114-auth-login - - release/v1.2.0 (예외) +#### 2️⃣ Pull Request + +```mermaid +graph LR + A[PR 생성] --> B[TEST.yml 자동 실행] + B --> C[테스트 결과 코멘트] + C --> D[코드 리뷰] + D --> E[Merge] +``` + +#### 3️⃣ 개발 서버 배포 + +```mermaid +graph LR + A[develop merge] --> B[CICD.yml 자동 실행] + B --> C[Docker 이미지 빌드] + C --> D[DockerHub 푸시] + D --> E[Dev EC2 배포] + E --> F[Blue-Green 전환] + F --> G[Discord 알림] +``` + +#### 4️⃣ 운영 서버 배포 + +```mermaid +graph LR + A[main merge] --> B[CICD.yml 자동 실행] + B --> C[Docker 이미지 빌드] + C --> D[DockerHub 푸시] + D --> E[Prod EC2 배포] + E --> F[Blue-Green 전환] + F --> G[Discord 알림] +``` --- -## 3️⃣ 커밋 메시지 규칙 +## 📁 프로젝트 구조 -- 형식: `타입: 내용` -
(필요 시 작업 상세 설명을 본문에 작성) -- 타입: feat, fix, refactor, chore, test, docs, release -- ex) - - feat: 로그인 기능 추가 - - fix: 회원가입 오류 수정 +``` +docker-compose-deploy/ +├── .github/ +│ └── workflows/ +│ ├── TEST.yml # 테스트 파이프라인 +│ └── CICD.yml # 빌드 & 배포 파이프라인 +├── deploy/ +│ ├── docker-compose.infra.yml # Nginx + Redis +│ ├── docker-compose.server.yml # Spring Boot (Blue/Green) +│ └── server-deploy.sh # 배포 스크립트 +├── nginx/ +│ └── nginx.conf # Nginx 설정 파일 +├── config/ # Private 서브모듈 +│ ├── application-test.properties +│ ├── application-local.properties +│ ├── application-dev.properties +│ └── application-prod.properties +├── src/ +│ ├── main/ +│ │ ├── java/ +│ │ └── resources/ +│ └── test/ +├── docker-compose.yml # 로컬 개발용 (MySQL + Redis) +├── Dockerfile +├── build.gradle +├── .gitignore +├── .gitmodules +└── README.md +``` --- -## 4️⃣ PR 제목 규칙 +## 🌐 서버 접근 방법 + +### 개발 서버 (Dev) +```bash +# Public IP로 직접 접근 +http://[DEV_EC2_PUBLIC_IP]:80 +``` + +### 운영 서버 (Prod) +```bash +# ALB DNS로 접근 (Private Subnet 내 EC2) +http://[ALB_DNS_NAME] +``` -- 이슈 제목과 동일한 형식으로 작성 -- 형식: `[타입] 내용` \ No newline at end of file +> 💡 운영 서버는 Private Subnet에 위치하여 ALB를 통해서만 접근 가능합니다. \ No newline at end of file From c8a29daa671562e80c7b7643f0026b86231e43b4 Mon Sep 17 00:00:00 2001 From: Jinseong Date: Mon, 24 Nov 2025 00:16:43 +0900 Subject: [PATCH 2/3] =?UTF-8?q?docs:=20README=202=EC=B0=A8=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 59 ++++++++++++++++++++++--------------------------------- 1 file changed, 24 insertions(+), 35 deletions(-) diff --git a/README.md b/README.md index efa43b0..092aea9 100644 --- a/README.md +++ b/README.md @@ -70,11 +70,11 @@ ### AWS 인프라 구조 -![AWS Architecture](https://github.com/user-attachments/assets/76584cc0-9955-46d3-b518-911eda8744ba) + ### 애플리케이션 구조 (Blue-Green 배포) -![Application Architecture](https://github.com/user-attachments/assets/bed0b70f-6c9b-4f6e-aa1e-62da96213bc5) + --- @@ -125,11 +125,11 @@ ```mermaid graph LR - A[새 버전 컨테이너 시작] --> B{헬스체크
최대 45초} - B -->|성공| C[Nginx upstream 변경] - C --> D[기존 컨테이너 중지] - B -->|실패| E[새 컨테이너 중지] - E --> F[기존 컨테이너 유지] + New_Container["새 버전 컨테이너 시작"] --> HealthCheck{"헬스체크
최대 45초"} + HealthCheck -->|성공| Upstream["Nginx upstream 변경"] + Upstream --> Stop_Old["기존 컨테이너 중지"] + HealthCheck -->|실패| Stop_New["새 컨테이너 중지"] + Stop_New --> Keep_Old["기존 컨테이너 유지"] ``` ### 📦 3. 환경별 설정 관리 @@ -350,10 +350,10 @@ spring.data.redis.password=${REDIS_PASSWORD} ```bash # 1. Docker Compose로 MySQL + Redis 실행 -docker-compose up -d +docker compose up -d # 2. 컨테이너 상태 확인 -docker-compose ps +docker compose ps ``` #### 애플리케이션 실행 @@ -361,7 +361,6 @@ docker-compose ps **방법 1: IDE (ex.IntelliJ IDEA)** ``` 1. Run/Debug Configurations 열기 -2. Edit Configurations... 선택 3. Active profiles: local 입력 4. Run 버튼 클릭 ``` @@ -374,7 +373,7 @@ docker-compose ps ### 5️⃣ Nginx 설정 (개발/운영 서버) ```bash -# 각 서버에 Nginx 설정 디렉토리 생성 & 파일 생성 +# 각 서버에 Nginx 디렉토리 생성 & 파일 생성 mkdir -p /home/ubuntu/nginx vi /home/ubuntu/nginx/nginx.conf ``` @@ -425,34 +424,24 @@ git push origin feature/14-new-feature ```mermaid graph LR - A[PR 생성] --> B[TEST.yml 자동 실행] - B --> C[테스트 결과 코멘트] - C --> D[코드 리뷰] - D --> E[Merge] + PR["PR 생성"] --> TEST["TEST.yml 자동 실행"] + TEST --> Comment["테스트 결과 코멘트"] + Comment --> Review["코드 리뷰"] + Review --> Merge["Merge"] ``` -#### 3️⃣ 개발 서버 배포 +#### 3️⃣ 개발/운영 서버 배포 -```mermaid -graph LR - A[develop merge] --> B[CICD.yml 자동 실행] - B --> C[Docker 이미지 빌드] - C --> D[DockerHub 푸시] - D --> E[Dev EC2 배포] - E --> F[Blue-Green 전환] - F --> G[Discord 알림] -``` - -#### 4️⃣ 운영 서버 배포 - -```mermaid +```mermaid graph LR - A[main merge] --> B[CICD.yml 자동 실행] - B --> C[Docker 이미지 빌드] - C --> D[DockerHub 푸시] - D --> E[Prod EC2 배포] - E --> F[Blue-Green 전환] - F --> G[Discord 알림] + Dev[develop merge] --> CICD[CICD.yml 자동 실행] + Prod[main merge] --> CICD + + CICD --> Build[Docker 이미지 빌드] + Build --> Push[DockerHub 푸시] + Push --> Deploy[EC2 배포] + Deploy --> BG[Blue-Green 전환] + BG --> Notify[Discord 알림] ``` --- From 857870438bb7fd6b8a40bdc35f1000293200b4dc Mon Sep 17 00:00:00 2001 From: Jinseong Date: Mon, 24 Nov 2025 00:39:39 +0900 Subject: [PATCH 3/3] =?UTF-8?q?docs:=20README=203=EC=B0=A8=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 223 ++++++++++++++++++++++++++++-------------------------- 1 file changed, 115 insertions(+), 108 deletions(-) diff --git a/README.md b/README.md index 092aea9..7590218 100644 --- a/README.md +++ b/README.md @@ -18,8 +18,8 @@ - [기술 스택](#-기술-스택) - [아키텍처](#-아키텍처) - [주요 기능](#-주요-기능) -- [사전 준비](#-사전-준비) -- [시작하기](#-시작하기) +- [로컬 개발 준비](#-로컬-개발-준비) +- [배포 준비](#-배포-준비) - [CI/CD 파이프라인](#-cicd-파이프라인) --- @@ -158,48 +158,76 @@ graph LR --- -## 📌 사전 준비 +## 📌 로컬 개발 준비 -### 1. DockerHub 설정 +### 1️⃣ Private 서브모듈 설정 -- 저장소 생성 및 Access Token 발급 필요 - -### 2. Discord 웹훅 설정 - -- 알림을 받을 서버의 특정 채널 웹훅 URL 필요 - -### 3. Self-hosted Runner 설정 - -- GitHub Actions Runner를 Bastion Host EC2에 설치 및 등록 필요 - -### 4. Private 서브모듈 생성 +#### 1) 서브모듈 추가 ```bash # 1. GitHub에서 Private Repository 생성 # 2. 메인 프로젝트에 서브모듈 추가 git submodule add <서브모듈 Repository URL> config +``` -# 3. config 디렉토리에 properties 파일 생성 +#### 2) 각 환경별 Properties 작성 + +```bash +# config 디렉토리에 properties 파일 생성 cd config touch application-test.properties touch application-local.properties touch application-dev.properties touch application-prod.properties +``` -# 4. properties 파일 작성 후 커밋 -git add . -git commit -m "Initial properties files" -git push origin main +```properties +# MySQL +spring.datasource.url=jdbc:mysql://localhost:3306/database?characterEncoding=UTF-8&serverTimezone=Asia/Seoul&useSSL=false +spring.datasource.username=사용자명 +spring.datasource.password=비밀번호 +spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver -# 5. 메인 프로젝트로 돌아와서 서브모듈 변경사항 커밋 -cd .. -git add .gitmodules config -git commit -m "Add config submodule" -git push +# JPA +spring.jpa.hibernate.ddl-auto=update +spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect +spring.jpa.properties.hibernate.format_sql=true +spring.jpa.properties.hibernate.default_batch_fetch_size=100 +spring.jpa.show-sql=true + +# Redis +spring.data.redis.host=localhost +spring.data.redis.port=6379 +spring.data.redis.password=비밀번호 + +# Logging +logging.level.root=INFO +logging.level.your.package.name=DEBUG +logging.level.org.hibernate.SQL=DEBUG +logging.level.org.hibernate.type.descriptor.sql=TRACE + +# Actuator +management.endpoints.web.exposure.include=health,info +management.endpoint.health.show-details=always +``` + +#### ⚠️ Dev/Prod 환경은 환경변수 사용 필수 + +```properties +# ❌ 하드코딩 금지 +spring.datasource.url=jdbc:mysql://prod-rds:3306/database +spring.datasource.password=actual_password +spring.data.redis.password=actual_redis_password + +# ✅ 플레이스홀더 사용 +spring.datasource.url=${DB_URL} +spring.datasource.username=${DB_USERNAME} +spring.datasource.password=${DB_PASSWORD} +spring.data.redis.password=${REDIS_PASSWORD} ``` -### 5. build.gradle 설정 +#### 3) build.gradle 설정 ```gradle // Private 서브모듈의 properties 파일을 resources로 복사 @@ -213,19 +241,29 @@ tasks.register("copyPrivateProperties", Copy) { processResources.dependsOn('copyPrivateProperties') ``` -### 6. .gitignore 설정 +#### 4) .gitignore 설정 ```gitignore # 복사된 properties 파일은 추적하지 않음 src/main/resources/application-*.properties ``` -## 🚀 시작하기 +#### 5) 커밋 및 푸시 -> 💡 **AWS 인프라 구성은 다루지 않습니다.** -> VPC, EC2, RDS, ALB 등의 설정이 완료된 상태를 전제로 합니다. +```bash +# 1. 커밋 +git add . +git commit -m "Initial properties files" +git push origin main -### 1️⃣ 저장소 클론 +# 2. 메인 프로젝트로 돌아와서 서브모듈 변경사항 커밋 +cd .. +git add .gitmodules config +git commit -m "Add config submodule" +git push +``` + +### 2️⃣ 저장소 클론 ```bash # Private 서브모듈 포함하여 클론 @@ -235,7 +273,49 @@ git clone --recurse-submodules <메인 프로젝트 Repository URL> git submodule update --init --recursive ``` -### 2️⃣ GitHub Secrets 설정 +### 3️⃣ 로컬 개발 환경 설정 + +```bash +# 1. Docker Compose로 MySQL + Redis 실행 +docker compose up -d + +# 2. 컨테이너 상태 확인 +docker compose ps +``` + +#### 애플리케이션 실행 + +**방법 1: IDE (ex.IntelliJ IDEA)** +``` +1. Run/Debug Configurations 열기 +2. Active profiles: local 입력 +3. Run 버튼 클릭 +``` + +**방법 2: Gradle 명령어** +```bash +./gradlew bootRun --args='--spring.profiles.active=local' +``` + +--- + +## 🚀 배포 준비 + +> 💡 VPC, EC2, RDS, ALB 등 주요 AWS 리소스는 아키텍처 설계대로 이미 구성되어 있다고 가정합니다. + +### 1️⃣ DockerHub 설정 + +- 저장소 생성 및 Access Token 발급 필요 + +### 2️⃣ Discord 웹훅 설정 + +- 알림을 받을 서버의 특정 채널 웹훅 URL 필요 + +### 3️⃣ Self-hosted Runner 설정 + +- GitHub Actions Runner를 Bastion Host EC2에 설치 및 등록 필요 + +### 4️⃣ GitHub Secrets 설정 > Repository → Settings → Secrets and variables → Actions @@ -297,83 +377,10 @@ REDIS_PROD_PASSWORD: Redis 비밀번호 -### 3️⃣ Application Properties 작성 - -#### 📝 각 환경별 작성 예시 - -```properties -# MySQL -spring.datasource.url=jdbc:mysql://localhost:3306/database?characterEncoding=UTF-8&serverTimezone=Asia/Seoul&useSSL=false -spring.datasource.username=사용자명 -spring.datasource.password=비밀번호 -spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver - -# JPA -spring.jpa.hibernate.ddl-auto=update -spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect -spring.jpa.properties.hibernate.format_sql=true -spring.jpa.properties.hibernate.default_batch_fetch_size=100 -spring.jpa.show-sql=true - -# Redis -spring.data.redis.host=localhost -spring.data.redis.port=6379 -spring.data.redis.password=비밀번호 - -# Logging -logging.level.root=INFO -logging.level.your.package.name=DEBUG -logging.level.org.hibernate.SQL=DEBUG -logging.level.org.hibernate.type.descriptor.sql=TRACE - -# Actuator -management.endpoints.web.exposure.include=health,info -management.endpoint.health.show-details=always -``` - -#### ⚠️ Dev/Prod 환경은 환경변수 사용 필수 - -```properties -# ❌ 하드코딩 금지 -spring.datasource.url=jdbc:mysql://prod-rds:3306/database -spring.datasource.password=actual_password -spring.data.redis.password=actual_redis_password - -# ✅ 플레이스홀더 사용 -spring.datasource.url=${DB_URL} -spring.datasource.username=${DB_USERNAME} -spring.datasource.password=${DB_PASSWORD} -spring.data.redis.password=${REDIS_PASSWORD} -``` - -### 4️⃣ 로컬 개발 환경 설정 - -```bash -# 1. Docker Compose로 MySQL + Redis 실행 -docker compose up -d - -# 2. 컨테이너 상태 확인 -docker compose ps -``` - -#### 애플리케이션 실행 - -**방법 1: IDE (ex.IntelliJ IDEA)** -``` -1. Run/Debug Configurations 열기 -3. Active profiles: local 입력 -4. Run 버튼 클릭 -``` - -**방법 2: Gradle 명령어** -```bash -./gradlew bootRun --args='--spring.profiles.active=local' -``` - ### 5️⃣ Nginx 설정 (개발/운영 서버) ```bash -# 각 서버에 Nginx 디렉토리 생성 & 파일 생성 +# 각 서버에 Nginx 디렉토리 생성 & 설정 파일 생성 mkdir -p /home/ubuntu/nginx vi /home/ubuntu/nginx/nginx.conf ``` @@ -381,7 +388,7 @@ vi /home/ubuntu/nginx/nginx.conf > ⚠️ **수동 배치 이유** > - `docker-compose.infra.yml`에서 nginx.conf를 볼륨으로 마운트: `/home/ubuntu/nginx/nginx.conf:/etc/nginx/nginx.conf` > - CICD.yml에서 매번 덮어쓰면 현재 활성화된 컨테이너(Blue/Green) 정보가 초기화되어 배포가 실패합니다 -> - 따라서 nginx.conf는 최초 1회 수동으로 서버에 생성합니다 +> - 따라서 nginx.conf는 수동으로 서버에 생성합니다 --- @@ -439,7 +446,7 @@ graph LR CICD --> Build[Docker 이미지 빌드] Build --> Push[DockerHub 푸시] - Push --> Deploy[EC2 배포] + Push --> Deploy[해당 EC2 배포] Deploy --> BG[Blue-Green 전환] BG --> Notify[Discord 알림] ```