Skip to content
Closed

Main #202

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
64 changes: 64 additions & 0 deletions .github/workflows/deploy-dev.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
name: Java CI/CD with Gradle (Dev Server)

on:
push:
branches: [ "dev" ]
workflow_dispatch:

jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Set up JDK 21
uses: actions/setup-java@v4
with:
java-version: '21'
distribution: 'temurin'
cache: 'gradle'

- name: Build with Gradle
run: |
chmod +x ./gradlew
./gradlew build -x test

# // 1. JAR 파일만 전송 준비 (환경변수는 서버에서 직접 생성하는게 더 깔끔해)
- name: Prepare deployment files
run: |
mkdir -p deploy
cp build/libs/*-SNAPSHOT.jar deploy/

# // 2. JAR 파일 EC2로 전송
- name: Copy files to EC2
uses: appleboy/scp-action@v0.1.7
with:
host: ${{ secrets.EC2_HOST }}
username: ${{ secrets.EC2_USERNAME }}
key: ${{ secrets.EC2_SSH_KEY }}
source: "deploy/*"
target: "~/dev-server"
strip_components: 1

# // 3. EC2 서버에서 실행 스크립트
- name: Deploy to EC2
uses: appleboy/ssh-action@v1.0.3
with:
host: ${{ secrets.EC2_HOST }}
username: ${{ secrets.EC2_USERNAME }}
key: ${{ secrets.EC2_SSH_KEY }}
script: |
# 1. 기존 8081 프로세스 종료
fuser -k 8081/tcp || true

cd ~/dev-server

# 2. .env 파일 생성
cat <<'EOF' > .env
${{ secrets.ENV_VARIABLES }}
EOF

# 3. 환경 변수 로드 및 메모리 제한 걸어서 실행
# // 1. set -a로 .env 로드, -Xmx256m으로 메모리 방어
set -a; source .env; set +a
nohup java -Xmx256m -Dserver.port=8081 -jar *-SNAPSHOT.jar > dev-app.log 2>&1 &
66 changes: 66 additions & 0 deletions .github/workflows/deploy-main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
name: Java CI/CD with Gradle (Main Server)

on:
push:
branches: [ "main" ]
workflow_dispatch:

jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Set up JDK 21
uses: actions/setup-java@v4
with:
java-version: '21'
distribution: 'temurin'
cache: 'gradle'

- name: Build with Gradle
run: |
chmod +x ./gradlew
./gradlew build -x test

# // 1. 전송용 폴더에 JAR 파일만 준비 (환경변수는 보안상 서버에서 직접 생성)
- name: Prepare deployment files
run: |
mkdir -p deploy
cp build/libs/*-SNAPSHOT.jar deploy/

# // 2. 메인 서버 폴더로 JAR 전송
- name: Copy files to EC2
uses: appleboy/scp-action@v0.1.7
with:
host: ${{ secrets.EC2_HOST }}
username: ${{ secrets.EC2_USERNAME }}
key: ${{ secrets.EC2_SSH_KEY }}
source: "deploy/*"
target: "~/main-server"
strip_components: 1

# // 3. 운영 서버 실행 스크립트
- name: Deploy to EC2
uses: appleboy/ssh-action@v1.0.3
with:
host: ${{ secrets.EC2_HOST }}
username: ${{ secrets.EC2_USERNAME }}
key: ${{ secrets.EC2_SSH_KEY }}
script: |
# 1. 기존 8080 프로세스 종료
fuser -k 8080/tcp || true

# 2. 운영 서버 폴더 이동
cd ~/main-server

# 3. .env 파일 생성 (운영 전용 Secrets 사용)
# // 1. EOF를 써서 특수문자 깨짐 없이 안전하게 저장
cat <<'EOF' > .env
${{ secrets.ENV_VARIABLES }}
EOF

# 4. 환경 변수 로드 및 운영 서버 실행
# // 2. 운영은 400MB 제한으로 안정성 확보
set -a; source .env; set +a
nohup java -Xmx400m -Dserver.port=8080 -jar *-SNAPSHOT.jar > server.log 2>&1 &
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,7 @@ out/
.vscode/

### Setting ###
.env
.env
postgres_data/
src/main/resources/application-local.yml
.claude
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ git push origin {생성한-브랜치-명}
## 📂 Project Structure

```
com.swyp.app
com.swyp.picke
├── AppApplication.java
├── domain
Expand Down
83 changes: 57 additions & 26 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,52 +1,83 @@
plugins {
id 'java'
id 'org.springframework.boot' version '4.0.3'
id 'io.spring.dependency-management' version '1.1.7'
id 'java'
id 'org.springframework.boot' version '3.5.11'
id 'io.spring.dependency-management' version '1.1.7'
}

group = 'com.swyp'
group = 'com.swyp.picke'
version = '0.0.1-SNAPSHOT'
description = 'SWYP APP 4th'
description = 'PICKE - SWYP APP 4th'

java {
toolchain {
languageVersion = JavaLanguageVersion.of(21)
}
toolchain {
languageVersion = JavaLanguageVersion.of(21)
}
}

configurations {
compileOnly {
extendsFrom annotationProcessor
}
compileOnly {
extendsFrom annotationProcessor
}
}

repositories {
mavenCentral()
mavenCentral()
google()
}

dependencies {
// Web
implementation 'org.springframework.boot:spring-boot-starter-webmvc'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-validation'

// JPA
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'

// Security
implementation 'org.springframework.boot:spring-boot-starter-security'
// Swagger
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:3.0.1'
// Lombok

// JWT
implementation 'io.jsonwebtoken:jjwt-api:0.12.6'
runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.12.6'
runtimeOnly 'io.jsonwebtoken:jjwt-jackson:0.12.6'

// HTTP Client (소셜 API 호출용)
implementation 'org.springframework.boot:spring-boot-starter-webflux'

// AdMob SSV 검증을 위한 Tink 라이브러리
implementation 'com.google.crypto.tink:apps-rewardedads:1.9.1'
testImplementation 'com.google.crypto.tink:apps-rewardedads:1.9.1'

// Swagger
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.8.16'

// Google Cloud TTS
implementation 'com.google.cloud:google-cloud-texttospeech:2.58.0'

// AWS S3
implementation 'io.awspring.cloud:spring-cloud-aws-starter-s3:3.3.0'

// Lombok
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'

// devTools
developmentOnly 'org.springframework.boot:spring-boot-devtools'
// PostgreSQL
developmentOnly 'org.springframework.boot:spring-boot-devtools'

// DB
runtimeOnly 'org.postgresql:postgresql'
// Test
testImplementation 'org.springframework.boot:spring-boot-starter-data-jpa-test'
testImplementation 'org.springframework.boot:spring-boot-starter-security-test'
testImplementation 'org.springframework.boot:spring-boot-starter-webmvc-test'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
runtimeOnly 'com.h2database:h2'

// Thymeleaf
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'

// Test
testRuntimeOnly 'com.h2database:h2'
testImplementation 'org.springframework.boot:spring-boot-starter-test' // JPA, Web 테스트 기능 모두 포함
testImplementation 'org.springframework.security:spring-security-test' // 시큐리티 전용 테스트
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
}

tasks.named('test') {
useJUnitPlatform()
}
useJUnitPlatform()
}
21 changes: 21 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
version: '3.8'

services:
db:
image: postgres:15
container_name: pique-postgres-db
restart: always
environment:
POSTGRES_DB: ${DB_NAME}
POSTGRES_USER: ${DB_USER}
POSTGRES_PASSWORD: ${DB_PASSWORD}
ports:
- "${DB_PORT}:5432"
volumes:
- ./postgres_data:/var/lib/postgresql/data
networks:
- pique-network

networks:
pique-network:
driver: bridge
52 changes: 52 additions & 0 deletions docs/api-specs/api-path-changes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# API 경로 변경/추가 요약 (프론트 전달용)

아래는 **사용자용 API 기준**으로, 기존 대비 바뀐 경로와 새로 분리/추가된 경로를 정리한 문서입니다.
관리자(`admin`) 경로는 제외했습니다.

## 1. 변경된 경로 (기존 → 현재)

### 1.1 콘텐츠 조회

| 기존(통합 Battle 타입 분기) | 현재(도메인 분리) |
|---|---|
| `GET /api/v1/battles?type=QUIZ` | `GET /api/v1/quizzes` |
| `GET /api/v1/battles/{battleId}` (QUIZ 상세) | `GET /api/v1/quizzes/{quizId}` |
| `GET /api/v1/battles?type=POLL` | `GET /api/v1/polls` |
| `GET /api/v1/battles/{battleId}` (POLL 상세) | `GET /api/v1/polls/{pollId}` |

### 1.2 투표 제출/조회

| 기존(통합 투표 처리) | 현재(도메인별 투표) |
|---|---|
| `POST /api/v1/battles/{battleId}/votes/...` (퀴즈 선택 제출에 재사용) | `POST /api/v1/battles/{battleId}/quiz-vote` |
| `GET /api/v1/battles/{battleId}/votes/me` (퀴즈 결과 확인에 재사용) | `GET /api/v1/battles/{battleId}/quiz-vote/me` |
| `POST /api/v1/battles/{battleId}/votes/...` (Poll 선택 제출에 재사용) | `POST /api/v1/battles/{battleId}/poll-vote` |
| `GET /api/v1/battles/{battleId}/votes/me` (Poll 결과 확인에 재사용) | `GET /api/v1/battles/{battleId}/poll-vote/me` |

## 2. 추가된 경로 (프론트에서 새로 호출 필요)

- `GET /api/v1/quizzes`
- `GET /api/v1/quizzes/{quizId}`
- `GET /api/v1/polls`
- `GET /api/v1/polls/{pollId}`
- `POST /api/v1/battles/{battleId}/quiz-vote`
- `GET /api/v1/battles/{battleId}/quiz-vote/me`
- `POST /api/v1/battles/{battleId}/poll-vote`
- `GET /api/v1/battles/{battleId}/poll-vote/me`

## 3. 유지되는 경로 (변경 없음)

- 배틀 전용 투표:
- `POST /api/v1/battles/{battleId}/votes/pre`
- `POST /api/v1/battles/{battleId}/votes/post`
- `GET /api/v1/battles/{battleId}/vote-stats`
- `GET /api/v1/battles/{battleId}/votes/me`

- 배틀 조회:
- `GET /api/v1/battles`
- `GET /api/v1/battles/{battleId}`
- `GET /api/v1/battles/today`

## 4. 참고

- `quiz-vote`, `poll-vote` 경로의 Path Variable 이름은 코드상 `battleId`로 되어 있지만, 내부적으로는 각각 `quizId`, `pollId`로 처리됩니다.
Loading
Loading