Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
e91460c
fix(room): ๋ช…์‹œ์  flush ์ œ๊ฑฐ ํ›„ ์ž๋™ flush๋กœ DB ๋ฐ˜์˜ ์ฒ˜๋ฆฌ
ydking0911 May 4, 2026
57c4702
feat: hard delete ๋กœ์ง์„ soft delete๋กœ ์ „ํ™˜
ydking0911 May 4, 2026
b3a03b8
test: ํ…Œ์ŠคํŠธ์ฝ”๋“œ ์ˆ˜์ •
ydking0911 May 4, 2026
cc5edc3
feat: ์ปจํ…Œ์ด๋„ˆ JFR/JMC ๊ธฐ๋ก ์„ค์ • ์ถ”๊ฐ€
KoungQ May 5, 2026
6cfefb1
chore: ์‹œํฌ๋ฆฟ ์„œ๋ธŒ๋ชจ๋“ˆ ๊ธฐ๋ฐ˜ ๋ฐฐํฌ ์„ค์ • ์ถ”๊ฐ€
KoungQ May 5, 2026
672b1bb
feat: ์ปจํ…Œ์ด๋„ˆ JFR/JMC ๊ธฐ๋ก ์„ค์ • ์ถ”๊ฐ€
KoungQ May 5, 2026
88d39d2
refactor: CD ํŒŒ์ดํ”„๋ผ์ธ ๋ณ€๊ฒฝ
KoungQ May 5, 2026
6203a3a
fix schema.sql and test code
ydking0911 May 5, 2026
b0f8694
fix: sql schema changed
ydking0911 May 5, 2026
e013bfb
fix: add sql DROP INDEX
ydking0911 May 5, 2026
2f9eb4e
Merge pull request #102 from DorumDorum/refactor/#101/db-flush-ํ˜ธ์ถœ-์ตœ์†Œํ™”โ€ฆ
ydking0911 May 6, 2026
58a3b96
refactor: ์„œ๋ฒ„ ๋ฆฌ์†Œ์Šค ์ŠคํŽ™ ์ตœ์ ํ™” ๋ฐ JVM/์ปค๋„ฅ์…˜ํ’€ ์„ค์ • ์ˆ˜์ •
ydking0911 May 6, 2026
76cbd5c
fix: github PR ๋ฆฌ๋ทฐ ๋ฐ˜์˜ - deploy ์ œํ•œ ์ˆ˜์ •, ์ด์Šค์ผ€์ดํ”„ ์ถ”๊ฐ€
ydking0911 May 8, 2026
9e0d81d
Merge pull request #106 from DorumDorum/refactor/#105/์„œ๋ฒ„-๋ฆฌ์†Œ์Šค-์ŠคํŽ™-์ตœ์ ํ™”
ydking0911 May 9, 2026
4ca6234
chore: JVM GC ํŠœ๋‹์šฉ k6 ๋ถ€ํ•˜ํ…Œ์ŠคํŠธ ํ™˜๊ฒฝ ์ถ”๊ฐ€
KoungQ May 10, 2026
bc6a753
fix: resolve conflict
KoungQ May 10, 2026
d6277f2
chore: secrets ๊ฒฝ๋กœ ๋ฐ˜์˜ ๋ฐ k6 ๋ถ€ํ•˜ํ…Œ์ŠคํŠธ ์„ค์ • ์ถ”๊ฐ€
KoungQ May 10, 2026
8aa4701
fix: Pinpoint Dockerfile ์—”ํŠธ๋ฆฌํฌ์ธํŠธ ์‹ ํ˜ธ ์ „๋‹ฌ ๊ฐœ์„ 
KoungQ May 10, 2026
78248f5
fix: JAVA_OPTS ์‚ฌ์šฉ ์‹œ JFR ์„ค์ • ์œ ์ง€
KoungQ May 11, 2026
5619d5c
fix: JFR ์‚ฐ์ถœ๋ฌผ์„ ํ˜ธ์ŠคํŠธ ๋กœ๊ทธ ๊ฒฝ๋กœ์— ์ €์žฅ
KoungQ May 12, 2026
58c41cb
fix: Prometheus ์›๊ฒฉ ์“ฐ๊ธฐ ์—”๋“œํฌ์ธํŠธ ๋กœ์ปฌ ๋ฐ”์ธ๋”ฉ
KoungQ May 12, 2026
3fe080e
chore: dockerignore ์ˆ˜์ •
KoungQ May 12, 2026
912c2d3
Merge pull request #104 from DorumDorum/feat/#103/gc-๋กœ๊ทธ-๋ฐ-jvm-ํ”„๋กœํŒŒ์ผ๋ง์„-โ€ฆ
KoungQ May 12, 2026
3e260eb
Merge branch 'production' into develop
KoungQ May 21, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
.git
.github
.gradle
.env
secrets
build
out
logs
load-testing/results/
*.jfr
*.hprof
gc.log*
*.iml
.idea
**/.DS_Store
Expand Down
120 changes: 43 additions & 77 deletions .github/workflows/cicd.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
# CI/CD์— ํ•„์š”ํ•œ GitHub Secrets (Repo Settings > Secrets and variables > Actions)
# - Docker Hub: DOCKERHUB_USERNAME, DOCKERHUB_TOKEN
# - Server: SERVER_HOST, SERVER_USER, SERVER_SSH_KEY, SERVER_SSH_PORT
# - GitHub repo/submodule access: GITHUB_TOKEN

name: cicd

Expand Down Expand Up @@ -40,8 +43,8 @@ jobs:

- name: Run tests
run: |
echo ">>> [CI] Running tests..."
./gradlew test --no-daemon
echo ">>> [CI] Running tests without integration tests..."
./gradlew test -PskipIntegrationTests --no-daemon
Comment thread
KoungQ marked this conversation as resolved.
echo ">>> [CI] Tests passed"

docker-build-and-push:
Expand Down Expand Up @@ -118,18 +121,6 @@ jobs:
IMAGE: ${{ secrets.DOCKERHUB_USERNAME }}/dorumdorum-be:pinpoint
DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }}
DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }}
FIREBASE_SERVICE_ACCOUNT_B64: ${{ secrets.FIREBASE_SERVICE_ACCOUNT_B64 }}
RDB_USERNAME: ${{ secrets.RDB_USERNAME }}
RDB_URL: ${{ secrets.RDB_URL }}
RDB_PASSWORD: ${{ secrets.RDB_PASSWORD }}
MYSQL_ROOT_PASSWORD: ${{ secrets.MYSQL_ROOT_PASSWORD }}
MYSQL_DATABASE: ${{ secrets.MYSQL_DATABASE }}
JWT_KEY: ${{ secrets.JWT_KEY }}
JWT_ACCESS_EXPIRATION: ${{ secrets.JWT_ACCESS_EXPIRATION }}
JWT_REFRESH_EXPIRATION: ${{ secrets.JWT_REFRESH_EXPIRATION }}
SMTP_USERNAME: ${{ secrets.SMTP_USERNAME }}
SMTP_PASSWORD: ${{ secrets.SMTP_PASSWORD }}
DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }}
CONTAINER_NAME: dorumdorum-be
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
REPO_FULL_NAME: ${{ github.repository }}
Expand All @@ -138,56 +129,11 @@ jobs:
username: ${{ secrets.SERVER_USER }}
key: ${{ secrets.SERVER_SSH_KEY }}
port: ${{ secrets.SERVER_SSH_PORT }}
envs: IMAGE,DOCKERHUB_USERNAME,DOCKERHUB_TOKEN,FIREBASE_SERVICE_ACCOUNT_B64,RDB_USERNAME,RDB_URL,RDB_PASSWORD,MYSQL_ROOT_PASSWORD,MYSQL_DATABASE,JWT_KEY,JWT_ACCESS_EXPIRATION,JWT_REFRESH_EXPIRATION,SMTP_USERNAME,SMTP_PASSWORD,CONTAINER_NAME,GITHUB_TOKEN,REPO_FULL_NAME,DISCORD_WEBHOOK
envs: IMAGE,DOCKERHUB_USERNAME,DOCKERHUB_TOKEN,CONTAINER_NAME,GITHUB_TOKEN,REPO_FULL_NAME
script_stop: true
script: |
set -e
echo ">>> [Deploy] SSH ์—ฐ๊ฒฐ๋จ, ํ™˜๊ฒฝ ๋ณ€์ˆ˜ ์ •๊ทœํ™” ์ค‘..."

RDB_USERNAME="$(printf '%s' "$RDB_USERNAME" | tr -d '\r\n')"
RDB_URL="$(printf '%s' "$RDB_URL" | tr -d '\r\n')"
RDB_PASSWORD="$(printf '%s' "$RDB_PASSWORD" | tr -d '\r\n')"
MYSQL_ROOT_PASSWORD="$(printf '%s' "$MYSQL_ROOT_PASSWORD" | tr -d '\r\n')"
MYSQL_DATABASE="$(printf '%s' "$MYSQL_DATABASE" | tr -d '\r\n')"
JWT_KEY="$(printf '%s' "$JWT_KEY" | tr -d '\r\n')"
JWT_ACCESS_EXPIRATION="$(printf '%s' "$JWT_ACCESS_EXPIRATION" | tr -d '\r\n')"
JWT_REFRESH_EXPIRATION="$(printf '%s' "$JWT_REFRESH_EXPIRATION" | tr -d '\r\n')"
SMTP_USERNAME="$(printf '%s' "$SMTP_USERNAME" | tr -d '\r\n')"
SMTP_PASSWORD="$(printf '%s' "$SMTP_PASSWORD" | tr -d '\r\n')"

DEPLOY_PATH="${HOME}/dorumdorum"
mkdir -p "$DEPLOY_PATH"
cd "$DEPLOY_PATH"
echo ">>> [Deploy] DEPLOY_PATH=$DEPLOY_PATH"

# 1) Firebase ์„œ๋น„์Šค ๊ณ„์ • ํŒŒ์ผ ์ƒ์„ฑ (VM์— ์ €์žฅ)
printf '%s' "$FIREBASE_SERVICE_ACCOUNT_B64" | base64 -d > firebase-service-account.json
chmod 600 firebase-service-account.json

# 2) ์ปจํ…Œ์ด๋„ˆ์—์„œ ์ฐธ์กฐํ•  ๊ฒฝ๋กœ๋ฅผ env๋กœ ๊ณ ์ •
FIREBASE_SERVICE_ACCOUNT_PATH="/app/firebase-service-account.json"

# 3) .env ์ƒ์„ฑ
# Pinpoint Web reads Spring datasource keys directly.
printf '%s\n' \
"SPRING_PROFILES_ACTIVE=prod" \
"RDB_USERNAME=$RDB_USERNAME" \
"RDB_URL=$RDB_URL" \
"RDB_PASSWORD=$RDB_PASSWORD" \
"MYSQL_ROOT_PASSWORD=$MYSQL_ROOT_PASSWORD" \
"MYSQL_DATABASE=$MYSQL_DATABASE" \
"SPRING_DATASOURCE_URL=$RDB_URL" \
"SPRING_DATASOURCE_USERNAME=$RDB_USERNAME" \
"SPRING_DATASOURCE_PASSWORD=$RDB_PASSWORD" \
"JWT_KEY=$JWT_KEY" \
"JWT_ACCESS_EXPIRATION=$JWT_ACCESS_EXPIRATION" \
"JWT_REFRESH_EXPIRATION=$JWT_REFRESH_EXPIRATION" \
"SMTP_USERNAME=$SMTP_USERNAME" \
"SMTP_PASSWORD=$SMTP_PASSWORD" \
"DISCORD_WEBHOOK=$DISCORD_WEBHOOK" \
"FIREBASE_SERVICE_ACCOUNT_PATH=$FIREBASE_SERVICE_ACCOUNT_PATH" > .env
chmod 600 .env
echo ">>> [Deploy] .env, firebase-service-account.json ์ƒ์„ฑ ์™„๋ฃŒ"
echo ">>> [Deploy] SSH ์—ฐ๊ฒฐ๋จ"

docker info >/dev/null 2>&1 || {
echo "Docker socket permission denied for current deploy user."
Expand All @@ -198,8 +144,8 @@ jobs:
echo "$DOCKERHUB_TOKEN" | docker login -u "$DOCKERHUB_USERNAME" --password-stdin
echo ">>> [Deploy] Docker Hub ๋กœ๊ทธ์ธ ์™„๋ฃŒ"

echo ">>> [Deploy] MySQL ์ด๋ฏธ์ง€ pull ์ค‘..."
docker pull mysql:8.0
echo ">>> [Deploy] PostgreSQL ์ด๋ฏธ์ง€ pull ์ค‘..."
docker pull postgres:16-alpine
echo ">>> [Deploy] Redis ์ด๋ฏธ์ง€ pull ์ค‘..."
docker pull redis:7-alpine
echo ">>> [Deploy] Backend ์ด๋ฏธ์ง€ pull ์ค‘..."
Expand All @@ -215,9 +161,14 @@ jobs:
echo ">>> [Deploy] COMPOSE_PATH=$COMPOSE_PATH, Git clone ์ค‘..."
rm -rf temp_repo

# Git์—์„œ production ๋ธŒ๋žœ์น˜๋กœ docker-compose.yml, monitoring ๊ฐ€์ ธ์˜ค๊ธฐ
# Git์—์„œ production ๋ธŒ๋žœ์น˜๋กœ docker-compose.yml, monitoring, secrets submodule ๊ฐ€์ ธ์˜ค๊ธฐ
git clone --depth 1 -b production "https://x-access-token:${GITHUB_TOKEN}@github.com/${REPO_FULL_NAME}.git" temp_repo
echo ">>> [Deploy] Clone ์™„๋ฃŒ, docker-compose.yml ยท monitoring ๋ณต์‚ฌ ์ค‘..."
(
cd temp_repo
git -c url."https://x-access-token:${GITHUB_TOKEN}@github.com/".insteadOf="https://github.com/" \
submodule update --init --recursive --depth 1
)
echo ">>> [Deploy] Clone ์™„๋ฃŒ, docker-compose.yml ยท monitoring ยท secrets ๋ณต์‚ฌ ์ค‘..."

if [ -f "temp_repo/BE/docker-compose.yml" ]; then
cp temp_repo/BE/docker-compose.yml .
Expand Down Expand Up @@ -248,6 +199,19 @@ jobs:
mkdir -p monitoring/prometheus monitoring/grafana/provisioning/dashboards/json monitoring/grafana/provisioning/datasources
fi

rm -rf secrets
if [ -d "temp_repo/BE/secrets" ]; then
cp -R temp_repo/BE/secrets .
echo ">>> [Deploy] BE/secrets ๋ณต์‚ฌ ์™„๋ฃŒ"
elif [ -d "temp_repo/secrets" ]; then
cp -R temp_repo/secrets .
echo ">>> [Deploy] secrets ๋ณต์‚ฌ ์™„๋ฃŒ"
else
echo "ERROR: secrets submodule directory not found in temp_repo/"
exit 1
fi
chmod 600 secrets/.env secrets/firebase-service-account.json

rm -rf temp_repo
echo ">>> [Deploy] temp_repo ์‚ญ์ œ, compose ํŒŒ์ผ ํ™•์ธ ์ค‘..."

Expand All @@ -257,21 +221,23 @@ jobs:
ls -la
exit 1
fi

# .env ํŒŒ์ผ๊ณผ firebase-service-account.json ๋ณต์‚ฌ
cp "$DEPLOY_PATH/.env" .
cp "$DEPLOY_PATH/firebase-service-account.json" .
echo ">>> [Deploy] .env, firebase-service-account.json ๋ณต์‚ฌ ์™„๋ฃŒ"

if [ ! -f "secrets/.env" ] || [ ! -f "secrets/firebase-service-account.json" ]; then
echo "ERROR: required secret files are missing"
ls -la secrets || true
exit 1
fi

# docker-compose๋กœ ๋ชจ๋“  ์„œ๋น„์Šค ์‹คํ–‰
export BACKEND_IMAGE="$IMAGE"
export CONTAINER_NAME="$CONTAINER_NAME"
COMPOSE="docker compose --env-file secrets/.env -f docker-compose.yml"
echo ">>> [Deploy] ๊ธฐ์กด ์ปจํ…Œ์ด๋„ˆ ์ •๋ฆฌ (down + ์ด๋ฆ„์œผ๋กœ ๊ฐ•์ œ ์ œ๊ฑฐ)..."
docker compose -f docker-compose.yml down --remove-orphans >/dev/null 2>&1 || true
$COMPOSE down --remove-orphans >/dev/null 2>&1 || true
docker rm -f dorumdorum-redis dorumdorum-be dorumdorum-prometheus dorumdorum-grafana zoo1 pinpoint-hbase pinpoint-collector pinpoint-web 2>/dev/null || true

echo ">>> [Deploy] [1/6] ZooKeeper ๊ธฐ๋™..."
docker compose -f docker-compose.yml up -d zoo1
$COMPOSE up -d zoo1
for i in $(seq 1 30); do
if docker ps --format '{{.Names}}' | grep -q '^zoo1$'; then
echo ">>> [Deploy] ZooKeeper up"
Expand All @@ -281,7 +247,7 @@ jobs:
done

echo ">>> [Deploy] [2/6] HBase ๊ธฐ๋™..."
docker compose -f docker-compose.yml up -d pinpoint-hbase
$COMPOSE up -d pinpoint-hbase
echo ">>> [Deploy] HBase ์ดˆ๊ธฐํ™” ๋Œ€๊ธฐ..."
HBASE_READY=0
for i in $(seq 1 300); do
Expand All @@ -305,7 +271,7 @@ jobs:
fi

echo ">>> [Deploy] [3/6] Pinpoint Collector ๊ธฐ๋™..."
docker compose -f docker-compose.yml up -d pinpoint-collector
$COMPOSE up -d pinpoint-collector
COLLECTOR_READY=0
for i in $(seq 1 60); do
if docker logs pinpoint-collector 2>&1 | grep -Eq "Started .*CollectorApp|Started CollectorApp"; then
Expand All @@ -322,7 +288,7 @@ jobs:
fi

echo ">>> [Deploy] [4/6] Pinpoint Web ๊ธฐ๋™..."
docker compose -f docker-compose.yml up -d pinpoint-web
$COMPOSE up -d pinpoint-web
WEB_READY=0
for i in $(seq 1 60); do
if docker logs pinpoint-web 2>&1 | grep -Eq "Started .*WebApp|Started WebApp|Started .*PinpointWebApplication"; then
Expand All @@ -339,10 +305,10 @@ jobs:
fi

echo ">>> [Deploy] [5/6] Backend ๊ธฐ๋™..."
docker compose -f docker-compose.yml up -d backend
$COMPOSE up -d backend

echo ">>> [Deploy] [6/6] Redis/Monitoring ๊ธฐ๋™..."
docker compose -f docker-compose.yml up -d redis prometheus grafana
$COMPOSE up -d redis prometheus grafana

echo ">>> [Deploy] ์˜ค๋ž˜๋œ ์ด๋ฏธ์ง€ ์ •๋ฆฌ ์ค‘..."
docker image prune -af --filter "until=168h"
Expand Down
11 changes: 10 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,16 @@ pinpoint-agent/tools/
.env
/analysis/

### JVM profiling artifacts ###
logs/
*.jfr
*.hprof
gc.log*

### k6 load test artifacts ###
load-testing/results/

# macOS artefacts
.DS_Store

docs/
docs/
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "secrets"]
path = secrets
url = https://github.com/DorumDorum/secrets
Comment thread
KoungQ marked this conversation as resolved.
4 changes: 3 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ WORKDIR /app

COPY --from=builder /app/build/libs/*.jar app.jar

RUN mkdir -p /app/logs/jfr

EXPOSE 8080

ENTRYPOINT ["sh", "-c", "exec java ${JAVA_OPTS} -Dspring.profiles.active=${SPRING_PROFILES_ACTIVE:-prod} -jar /app/app.jar"]
ENTRYPOINT ["sh", "-c", "DEFAULT_JAVA_OPTS=\"-XX:StartFlightRecording=name=dorumdorum,settings=${JFR_SETTINGS:-profile},disk=true,dumponexit=true,filename=/app/logs/jfr/dorumdorum-${JFR_RUN_ID:-cloud-load-test}.jfr,maxage=${JFR_MAX_AGE:-30m},maxsize=${JFR_MAX_SIZE:-512m}\"; EFFECTIVE_JAVA_OPTS=\"${DEFAULT_JAVA_OPTS} ${JAVA_OPTS:-}\"; exec java ${EFFECTIVE_JAVA_OPTS} -Dspring.profiles.active=${SPRING_PROFILES_ACTIVE:-prod} -jar /app/app.jar"]
Comment thread
KoungQ marked this conversation as resolved.
6 changes: 4 additions & 2 deletions Dockerfile.pinpoint
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ WORKDIR /app
COPY --from=builder /app/build/libs/*.jar app.jar
COPY --from=builder /app/pinpoint-agent /app/pinpoint-agent

RUN mkdir -p /app/logs/jfr

# Pinpoint Agent JVM ์˜ต์…˜ (ํ™˜๊ฒฝ๋ณ€์ˆ˜๋กœ Collector IP ๋“ฑ ์˜ค๋ฒ„๋ผ์ด๋“œ ๊ฐ€๋Šฅ)
ENV PINPOINT_VERSION=2.5.4
ENV PINPOINT_COLLECTOR_IP=pinpoint-collector
Expand All @@ -38,12 +40,12 @@ EXPOSE 8080

# pinpoint-root.config์—์„œ Collector IP ์˜ค๋ฒ„๋ผ์ด๋“œ (profiler.transport.grpc.collector.ip)
# -D ์˜ต์…˜์œผ๋กœ ์ „๋‹ฌ
ENTRYPOINT ["sh", "-c", "java \
ENTRYPOINT ["sh", "-c", "DEFAULT_JAVA_OPTS=\"-XX:StartFlightRecording=name=dorumdorum,settings=${JFR_SETTINGS:-profile},disk=true,dumponexit=true,filename=/app/logs/jfr/dorumdorum-${JFR_RUN_ID:-cloud-load-test}.jfr,maxage=${JFR_MAX_AGE:-30m},maxsize=${JFR_MAX_SIZE:-512m}\"; EFFECTIVE_JAVA_OPTS=\"${DEFAULT_JAVA_OPTS} ${JAVA_OPTS:-}\"; exec java \
-javaagent:/app/pinpoint-agent/pinpoint-bootstrap-${PINPOINT_VERSION}.jar \
-Dpinpoint.agentId=${PINPOINT_AGENT_ID} \
-Dpinpoint.applicationName=${PINPOINT_APPLICATION_NAME} \
-Dprofiler.transport.grpc.collector.ip=${PINPOINT_COLLECTOR_IP} \
-Dpinpoint.container=true \
${JAVA_OPTS} \
${EFFECTIVE_JAVA_OPTS} \
-Dspring.profiles.active=${SPRING_PROFILES_ACTIVE:-prod} \
-jar /app/app.jar"]
Comment thread
KoungQ marked this conversation as resolved.
4 changes: 4 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,10 @@ dependencies {

tasks.named('test') {
useJUnitPlatform()

if (project.hasProperty('skipIntegrationTests')) {
exclude '**/*IntegrationTest.class'
}
}

def generated = "$buildDir/generated/sources/annotationProcessor/java/main"
Expand Down
Loading
Loading