-
Notifications
You must be signed in to change notification settings - Fork 0
SCRUM-117 식당 주인은 사용자가 예약을 하면 해당 알림을 받을 수 있다 #4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
e5dadde
c9e5ccd
59fd16e
16612bf
6844014
686a9a0
0d3eb61
ba9b9c3
18b83b3
f033261
6c0b07c
4d271b4
ddbcc1b
e162c4e
743dc12
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,79 @@ | ||||||||||||||||||||||||||
| name: dev-cd | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| on: | ||||||||||||||||||||||||||
| push: | ||||||||||||||||||||||||||
| branches: | ||||||||||||||||||||||||||
| - "develop" | ||||||||||||||||||||||||||
| - "SCRUM-117" | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| permissions: | ||||||||||||||||||||||||||
| contents: read | ||||||||||||||||||||||||||
| checks: write | ||||||||||||||||||||||||||
| actions: read | ||||||||||||||||||||||||||
| pull-requests: write | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| jobs: | ||||||||||||||||||||||||||
| test: | ||||||||||||||||||||||||||
| uses: ./.github/workflows/Dev_CI.yml | ||||||||||||||||||||||||||
| secrets: inherit | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| build: | ||||||||||||||||||||||||||
| needs: test | ||||||||||||||||||||||||||
| runs-on: ubuntu-latest | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| steps: | ||||||||||||||||||||||||||
| - name: Checkout Code | ||||||||||||||||||||||||||
| uses: actions/checkout@v4 | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| - name: Setting dev-secret.yml | ||||||||||||||||||||||||||
| run: | | ||||||||||||||||||||||||||
| echo "${{ secrets.DEV_SECRET_YML }}" > ./src/main/resources/dev-secret.yml | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| - name: Set up JDK 21 | ||||||||||||||||||||||||||
| uses: actions/setup-java@v4 | ||||||||||||||||||||||||||
| with: | ||||||||||||||||||||||||||
| distribution: 'temurin' | ||||||||||||||||||||||||||
| java-version: '21' | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| - name: Make gradlew executable | ||||||||||||||||||||||||||
| run: chmod +x gradlew | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| - name: bootJar with Gradle | ||||||||||||||||||||||||||
| run: ./gradlew bootJar --info | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| - name: Change artifact file name | ||||||||||||||||||||||||||
| run: mv build/libs/*.jar build/libs/app.jar | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| - name: Upload artifact file | ||||||||||||||||||||||||||
| uses: actions/upload-artifact@v4 | ||||||||||||||||||||||||||
| with: | ||||||||||||||||||||||||||
| name: app-artifact | ||||||||||||||||||||||||||
| path: ./build/libs/app.jar | ||||||||||||||||||||||||||
| if-no-files-found: error | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
|
Comment on lines
+47
to
+53
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion 업로드 경로도 서브모듈 경로로 정합성 유지 아티팩트 업로드 경로를 실제 위치로 수정해야 합니다. - - name: Upload artifact file
+ - name: Upload artifact file
uses: actions/upload-artifact@v4
with:
name: app-artifact
- path: ./build/libs/app.jar
+ path: ./api-owner/build/libs/app.jar
if-no-files-found: error📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||
| - name: Upload deploy scripts | ||||||||||||||||||||||||||
| uses: actions/upload-artifact@v4 | ||||||||||||||||||||||||||
| with: | ||||||||||||||||||||||||||
| name: deploy-scripts | ||||||||||||||||||||||||||
| path: ./scripts/dev/ | ||||||||||||||||||||||||||
| if-no-files-found: error | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| deploy: | ||||||||||||||||||||||||||
| needs: build | ||||||||||||||||||||||||||
| runs-on: dev | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| steps: | ||||||||||||||||||||||||||
| - name: Download artifact file | ||||||||||||||||||||||||||
| uses: actions/download-artifact@v4 | ||||||||||||||||||||||||||
| with: | ||||||||||||||||||||||||||
| name: app-artifact | ||||||||||||||||||||||||||
| path: ~/app | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| - name: Download deploy scripts | ||||||||||||||||||||||||||
| uses: actions/download-artifact@v4 | ||||||||||||||||||||||||||
| with: | ||||||||||||||||||||||||||
| name: deploy-scripts | ||||||||||||||||||||||||||
| path: ~/app/scripts | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| - name: Replace application to latest | ||||||||||||||||||||||||||
| run: sudo sh ~/app/scripts/replace-new-version.sh | ||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,91 @@ | ||||||||||||||||||||||||||||||||||
| name: dev-ci | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| on: | ||||||||||||||||||||||||||||||||||
| pull_request: | ||||||||||||||||||||||||||||||||||
| branches: | ||||||||||||||||||||||||||||||||||
| - develop | ||||||||||||||||||||||||||||||||||
| workflow_call: | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| permissions: | ||||||||||||||||||||||||||||||||||
| contents: read | ||||||||||||||||||||||||||||||||||
| checks: write | ||||||||||||||||||||||||||||||||||
| pull-requests: write | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| jobs: | ||||||||||||||||||||||||||||||||||
| build-and-push: | ||||||||||||||||||||||||||||||||||
| runs-on: ubuntu-latest | ||||||||||||||||||||||||||||||||||
| timeout-minutes: 10 | ||||||||||||||||||||||||||||||||||
| env: | ||||||||||||||||||||||||||||||||||
| TEST_REPORT: true | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| services: | ||||||||||||||||||||||||||||||||||
| mysql: | ||||||||||||||||||||||||||||||||||
| image: mysql:8.0 | ||||||||||||||||||||||||||||||||||
| env: | ||||||||||||||||||||||||||||||||||
| MYSQL_ROOT_PASSWORD: "" | ||||||||||||||||||||||||||||||||||
| MYSQL_ALLOW_EMPTY_PASSWORD: "yes" | ||||||||||||||||||||||||||||||||||
| MYSQL_DATABASE: wellmeet_noti_test | ||||||||||||||||||||||||||||||||||
| ports: | ||||||||||||||||||||||||||||||||||
| - 3306:3306 | ||||||||||||||||||||||||||||||||||
|
Comment on lines
+25
to
+29
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💡 Verification agent 🧩 Analysis chainMySQL DB 이름 불일치 가능성(wellmeet_noti_test vs wellmeet_noti)
테스트 프로파일 유무와 사용 DB를 확인해 주세요:
🏁 Script executed: #!/bin/bash
# 테스트 프로파일 및 DB URL 탐색
fd -HI "application-test.yml" || echo "⚠️ application-test.yml 없음"
rg -n "spring\.datasource\.url" -C2 src/main/resources || trueLength of output: 133 테스트·로컬 프로파일에서 실제로 사용 중인 DB 이름과 URL을 명확히 파악하기 위해 아래 스크립트를 실행해 주세요: 이 결과로 🏁 Script executed: #!/bin/bash
echo "===== application-local.yml datasource 설정 ====="
rg -n "datasource" -C3 src/main/resources/application-local.yml || true
echo "===== application-test.yml datasource 설정 ====="
rg -n "datasource" -C3 src/main/resources/application-test.yml || trueLength of output: 793 Run Tests 단계에서 🏁 Script executed: #!/bin/bash
echo "===== Run Tests 섹션 ====="
rg -n "Run Tests" -C5 .github/workflows/Dev_CI.yml || true
echo "===== SPRING_PROFILES_ACTIVE 설정 ====="
rg -n "SPRING_PROFILES_ACTIVE" -C3 .github/workflows/Dev_CI.yml || echo "⚠️ SPRING_PROFILES_ACTIVE 설정 없음"Length of output: 527 default 프로파일로 실행될 때 로드되는 🏁 Script executed: #!/bin/bash
echo "===== application.yml 파일 위치 확인 ====="
fd -HI src/main/resources/application.yml || echo "⚠️ application.yml 없음"
echo "===== application.yml datasource 설정 ====="
rg -n "datasource" -C3 src/main/resources/application.yml || trueLength of output: 359 Run Tests 단계에 SPRING_PROFILES_ACTIVE=test 설정 - name: Run Tests With Gradle
run: ./gradlew test
+ env:
+ SPRING_PROFILES_ACTIVE: test📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||
| options: >- | ||||||||||||||||||||||||||||||||||
| --health-cmd="mysqladmin ping" | ||||||||||||||||||||||||||||||||||
| --health-interval=10s | ||||||||||||||||||||||||||||||||||
| --health-timeout=5s | ||||||||||||||||||||||||||||||||||
| --health-retries=3 | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| zookeeper: | ||||||||||||||||||||||||||||||||||
| image: confluentinc/cp-zookeeper:7.0.1 | ||||||||||||||||||||||||||||||||||
| env: | ||||||||||||||||||||||||||||||||||
| ZOOKEEPER_CLIENT_PORT: 2181 | ||||||||||||||||||||||||||||||||||
| ZOOKEEPER_TICK_TIME: 2000 | ||||||||||||||||||||||||||||||||||
| ports: | ||||||||||||||||||||||||||||||||||
| - 2181:2181 | ||||||||||||||||||||||||||||||||||
| options: >- | ||||||||||||||||||||||||||||||||||
| --health-cmd="curl -f http://localhost:8080/commands/stat || exit 1" | ||||||||||||||||||||||||||||||||||
| --health-interval=10s | ||||||||||||||||||||||||||||||||||
| --health-timeout=10s | ||||||||||||||||||||||||||||||||||
| --health-retries=5 | ||||||||||||||||||||||||||||||||||
|
Comment on lines
+44
to
+47
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Zookeeper 헬스체크 커맨드가 잘못되었습니다.
- --health-cmd="curl -f http://localhost:8080/commands/stat || exit 1"
+ --health-cmd="bash -c 'echo ruok | nc -w 2 localhost 2181 | grep imok'"
--health-interval=10s
--health-timeout=10s
--health-retries=5📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| kafka: | ||||||||||||||||||||||||||||||||||
| image: confluentinc/cp-kafka:7.0.1 | ||||||||||||||||||||||||||||||||||
| env: | ||||||||||||||||||||||||||||||||||
| KAFKA_BROKER_ID: 1 | ||||||||||||||||||||||||||||||||||
| KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181 | ||||||||||||||||||||||||||||||||||
| KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT | ||||||||||||||||||||||||||||||||||
| KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://localhost:9092 | ||||||||||||||||||||||||||||||||||
| KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1 | ||||||||||||||||||||||||||||||||||
|
Comment on lines
+50
to
+56
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Kafka 리스너 바인딩 명시(KAFKA_LISTENERS) 추가 권장
kafka:
image: confluentinc/cp-kafka:7.0.1
env:
KAFKA_BROKER_ID: 1
KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT
+ KAFKA_LISTENERS: PLAINTEXT://0.0.0.0:9092
KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://localhost:9092📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||
| KAFKA_TRANSACTION_STATE_LOG_MIN_ISR: 1 | ||||||||||||||||||||||||||||||||||
| KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: 1 | ||||||||||||||||||||||||||||||||||
| KAFKA_AUTO_CREATE_TOPICS_ENABLE: true | ||||||||||||||||||||||||||||||||||
| ports: | ||||||||||||||||||||||||||||||||||
| - 9092:9092 | ||||||||||||||||||||||||||||||||||
| options: >- | ||||||||||||||||||||||||||||||||||
| --health-cmd="timeout 10s bash -c 'until printf \"\" 2>>/dev/null >>/dev/tcp/localhost/9092; do sleep 1; done'" | ||||||||||||||||||||||||||||||||||
| --health-interval=10s | ||||||||||||||||||||||||||||||||||
| --health-timeout=10s | ||||||||||||||||||||||||||||||||||
| --health-retries=10 | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| steps: | ||||||||||||||||||||||||||||||||||
| - uses: actions/checkout@v4 | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| - name: Setting local-secret.yml | ||||||||||||||||||||||||||||||||||
| run: | | ||||||||||||||||||||||||||||||||||
| echo "${{ secrets.LOCAL_SECRET_YML }}" > ./src/main/resources/local-secret.yml | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| - name: Set up JDK 21 | ||||||||||||||||||||||||||||||||||
| uses: actions/setup-java@v4 | ||||||||||||||||||||||||||||||||||
| with: | ||||||||||||||||||||||||||||||||||
| java-version: '21' | ||||||||||||||||||||||||||||||||||
| distribution: 'temurin' | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| - name: Setup Gradle | ||||||||||||||||||||||||||||||||||
| uses: gradle/actions/setup-gradle@v4 | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| - name: Grant Permission | ||||||||||||||||||||||||||||||||||
| run: chmod +x ./gradlew | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| - name: Build With Gradle | ||||||||||||||||||||||||||||||||||
| run: ./gradlew clean build -x test | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| - name: Run Tests With Gradle | ||||||||||||||||||||||||||||||||||
| run: ./gradlew test | ||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -36,3 +36,4 @@ out/ | |
| ### VS Code ### | ||
| .vscode/ | ||
| /src/main/resources/local-secret.yml | ||
| .serena/ | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,40 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #!/bin/bash | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| PID=$(lsof -t -i:8080) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # 프로세스 종료 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if [ -z "$PID" ]; then | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| echo "No process is using port 8080." | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| else | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| echo "Killing process with PID: $PID" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| kill -15 "$PID" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # 직전 명령(프로세스 종료 명령)이 정상 동작했는지 확인 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if [ $? -eq 0 ]; then | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| echo "Process $PID terminated successfully." | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| else | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| echo "Failed to terminate process $PID." | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+3
to
+18
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion 종료 대기/강제 종료 루프 추가 필요
-if [ -z "$PID" ]; then
+if [ -z "$PID" ]; then
echo "No process is using port 8080."
else
echo "Killing process with PID: $PID"
kill -15 "$PID"
# 직전 명령(프로세스 종료 명령)이 정상 동작했는지 확인
if [ $? -eq 0 ]; then
echo "Process $PID terminated successfully."
else
echo "Failed to terminate process $PID."
fi
+ # 포트 해제 대기(최대 30초), 미해제 시 SIGKILL
+ for i in {1..30}; do
+ if ! lsof -t -i:8080 >/dev/null; then
+ break
+ fi
+ sleep 1
+ done
+ if lsof -t -i:8080 >/dev/null; then
+ echo "Force killing process $PID"
+ kill -9 "$PID" || true
+ fi
fi📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| JAR_FILE=$(ls /home/ubuntu/app/*.jar | head -n 1) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| echo "JAR 파일 실행: $JAR_FILE" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+20
to
+23
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 하드코딩된 경로 제거 및 아티팩트 명 일치 워크플로는 -JAR_FILE=$(ls /home/ubuntu/app/*.jar | head -n 1)
+APP_DIR="${APP_DIR:-$HOME/app}"
+JAR_FILE="$APP_DIR/app.jar"
+if [ ! -f "$JAR_FILE" ]; then
+ echo "JAR not found: $JAR_FILE"
+ exit 1
+fi
-
-echo "JAR 파일 실행: $JAR_FILE"
+echo "JAR 파일 실행: $JAR_FILE"📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # 애플리케이션 로그 파일 설정 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| APP_LOG_DIR="/home/ubuntu/app/logs" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| APP_LOG_FILE="$APP_LOG_DIR/application-$(date +%Y%m%d-%H%M%S).log" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| echo "애플리케이션 로그 파일: $APP_LOG_FILE" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+25
to
+29
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion 로그 디렉터리 생성 누락 로그 디렉터리가 없으면 리다이렉션이 실패합니다. APP_LOG_DIR="/home/ubuntu/app/logs"
APP_LOG_FILE="$APP_LOG_DIR/application-$(date +%Y%m%d-%H%M%S).log"
echo "애플리케이션 로그 파일: $APP_LOG_FILE"
+mkdir -p "$APP_LOG_DIR"📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| sudo nohup java \ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| -Dspring.profiles.active=dev \ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| -Duser.timezone=Asia/Seoul \ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| -Dserver.port=8080 \ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| -Ddd.service=wellmeet-notification \ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| -Ddd.env=dev \ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| -jar "$JAR_FILE" > "$APP_LOG_FILE" 2>&1 & | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+30
to
+36
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. SC2024: sudo가 리다이렉션에 영향 없음 — root 권한으로 파일 쓰기 보장 필요 현재 리다이렉션은 호출 쉘 권한으로 수행되어 권한 오류가 날 수 있습니다. -sudo nohup java \
- -Dspring.profiles.active=dev \
- -Duser.timezone=Asia/Seoul \
- -Dserver.port=8080 \
- -Ddd.service=wellmeet-notification \
- -Ddd.env=dev \
- -jar "$JAR_FILE" > "$APP_LOG_FILE" 2>&1 &
+sudo sh -c "nohup java \
+ -Dspring.profiles.active=dev \
+ -Duser.timezone=Asia/Seoul \
+ -Dserver.port=8080 \
+ -Ddd.service=wellmeet-notification \
+ -Ddd.env=dev \
+ -jar \"$JAR_FILE\" >> \"$APP_LOG_FILE\" 2>&1 &"📝 Committable suggestion
Suggested change
🧰 Tools🪛 Shellcheck (0.10.0)[warning] 36-36: sudo doesn't affect redirects. Use ..| sudo tee file (SC2024) 🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| echo "애플리케이션이 백그라운드에서 실행되었습니다." | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| echo "로그 확인: tail -f $APP_LOG_FILE" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| echo "=== 배포 완료 ===" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,49 @@ | ||||||||||||||||||
| package com.wellmeet.config; | ||||||||||||||||||
|
|
||||||||||||||||||
| import com.wellmeet.notification.consumer.dto.NotificationMessage; | ||||||||||||||||||
| import java.util.HashMap; | ||||||||||||||||||
| import java.util.Map; | ||||||||||||||||||
| import org.apache.kafka.clients.consumer.ConsumerConfig; | ||||||||||||||||||
| import org.apache.kafka.common.serialization.StringDeserializer; | ||||||||||||||||||
| import org.springframework.beans.factory.annotation.Value; | ||||||||||||||||||
| import org.springframework.context.annotation.Bean; | ||||||||||||||||||
| import org.springframework.context.annotation.Configuration; | ||||||||||||||||||
| import org.springframework.kafka.annotation.EnableKafka; | ||||||||||||||||||
| import org.springframework.kafka.config.ConcurrentKafkaListenerContainerFactory; | ||||||||||||||||||
| import org.springframework.kafka.core.ConsumerFactory; | ||||||||||||||||||
| import org.springframework.kafka.core.DefaultKafkaConsumerFactory; | ||||||||||||||||||
| import org.springframework.kafka.support.serializer.JsonDeserializer; | ||||||||||||||||||
|
|
||||||||||||||||||
| @EnableKafka | ||||||||||||||||||
| @Configuration | ||||||||||||||||||
| public class KafkaConfig { | ||||||||||||||||||
|
|
||||||||||||||||||
| @Value("${spring.kafka.bootstrap-servers}") | ||||||||||||||||||
| private String bootstrapServers; | ||||||||||||||||||
|
|
||||||||||||||||||
| @Value("${spring.kafka.consumer.group-id}") | ||||||||||||||||||
| private String groupId; | ||||||||||||||||||
|
|
||||||||||||||||||
| @Bean | ||||||||||||||||||
| public ConsumerFactory<String, NotificationMessage> consumerFactory() { | ||||||||||||||||||
| Map<String, Object> props = new HashMap<>(); | ||||||||||||||||||
| props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapServers); | ||||||||||||||||||
| props.put(ConsumerConfig.GROUP_ID_CONFIG, groupId); | ||||||||||||||||||
| props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class); | ||||||||||||||||||
| props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, JsonDeserializer.class); | ||||||||||||||||||
| props.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest"); | ||||||||||||||||||
|
|
||||||||||||||||||
| props.put(JsonDeserializer.USE_TYPE_INFO_HEADERS, false); | ||||||||||||||||||
| props.put(JsonDeserializer.TRUSTED_PACKAGES, "com.wellmeet.consumer.dto"); | ||||||||||||||||||
| props.put(JsonDeserializer.VALUE_DEFAULT_TYPE, NotificationMessage.class); | ||||||||||||||||||
| return new DefaultKafkaConsumerFactory<>(props); | ||||||||||||||||||
|
Comment on lines
+36
to
+39
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. JsonDeserializer TRUSTED_PACKAGES 경로 오타로 역직렬화 실패 가능성 DTO 패키지명이 다음 최소 패치 권장: - props.put(JsonDeserializer.TRUSTED_PACKAGES, "com.wellmeet.consumer.dto");
- props.put(JsonDeserializer.VALUE_DEFAULT_TYPE, NotificationMessage.class);
+ props.put(JsonDeserializer.TRUSTED_PACKAGES, "com.wellmeet.notification.consumer.dto");
+ props.put(JsonDeserializer.VALUE_DEFAULT_TYPE, "com.wellmeet.notification.consumer.dto.NotificationMessage");📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| @Bean | ||||||||||||||||||
| public ConcurrentKafkaListenerContainerFactory<String, NotificationMessage> kafkaListenerContainerFactory() { | ||||||||||||||||||
| ConcurrentKafkaListenerContainerFactory<String, NotificationMessage> factory = | ||||||||||||||||||
| new ConcurrentKafkaListenerContainerFactory<>(); | ||||||||||||||||||
| factory.setConsumerFactory(consumerFactory()); | ||||||||||||||||||
| return factory; | ||||||||||||||||||
| } | ||||||||||||||||||
| } | ||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| package com.wellmeet.notification.consumer; | ||
|
|
||
| import com.wellmeet.notification.repository.OwnerNotificationEnabledRepository; | ||
| import com.wellmeet.notification.repository.UserNotificationEnabledRepository; | ||
| import java.util.List; | ||
| import lombok.RequiredArgsConstructor; | ||
| import org.springframework.stereotype.Component; | ||
|
|
||
| @Component | ||
| @RequiredArgsConstructor | ||
| public class NotificationChecker { | ||
|
|
||
| private final OwnerNotificationEnabledRepository ownerNotificationEnabledRepository; | ||
| private final UserNotificationEnabledRepository userNotificationEnabledRepository; | ||
|
|
||
| public List<String> check(String recipient, String recipientType) { | ||
| return null; | ||
| } | ||
|
Comment on lines
+16
to
+18
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. null 반환으로 인한 NPE 및 채널 확인 실패 🤖 Prompt for AI Agents |
||
| } | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,24 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| package com.wellmeet.notification.consumer; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import com.wellmeet.notification.consumer.dto.NotificationMessage; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import java.util.List; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import lombok.RequiredArgsConstructor; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import lombok.extern.slf4j.Slf4j; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import org.springframework.kafka.annotation.KafkaListener; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import org.springframework.stereotype.Service; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @Slf4j | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @Service | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @RequiredArgsConstructor | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public class NotificationConsumer { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private final NotificationChecker notificationChecker; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private final NotificationSender notificationSender; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @KafkaListener(topics = "notification", groupId = "notification-group") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public void consume(NotificationMessage message) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| List<String> enabled = notificationChecker.check(message.getNotification().getRecipient(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| message.getNotification().getRecipientType()); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| notificationSender.send(message, enabled); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
18
to
23
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion 토픽/그룹 하드코딩 제거 + 메타데이터 포함 로깅으로 운용성 개선
-import org.springframework.kafka.annotation.KafkaListener;
+import org.springframework.kafka.annotation.KafkaListener;
+import org.apache.kafka.clients.consumer.ConsumerRecord;
@@
- @KafkaListener(topics = "notification", groupId = "notification-group")
- public void consume(String message) {
- log.info("Received message from notification topic: {}", message);
+ @KafkaListener(
+ topics = "${notification.topic:notification}",
+ groupId = "${spring.kafka.consumer.group-id}"
+ )
+ public void consume(ConsumerRecord<String, String> record) {
+ log.info("Consumed reservation event: topic={}, partition={}, offset={}, key={}, value={}",
+ record.topic(), record.partition(), record.offset(), record.key(), record.value());
}메일/SMS/웹푸시 전달 로직을 붙이는 구현이 필요하면, 인터페이스와 간단한 어댑터(이벤트→도메인 DTO 변환) 초안을 제공하겠습니다. 📝 Committable suggestion
Suggested change
Comment on lines
+19
to
+23
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 에러 처리 로직 누락으로 메시지 처리 안정성 저하
다음 diff를 적용하여 에러 처리 및 로깅을 추가하세요: @KafkaListener(topics = "notification", groupId = "notification-group")
public void consume(NotificationMessage message) {
+ try {
+ log.info("Processing notification message: recipient={}, type={}",
+ message.getNotification().getRecipient(),
+ message.getNotification().getRecipientType());
+
List<String> enabled = notificationChecker.check(message.getNotification().getRecipient(),
message.getNotification().getRecipientType());
notificationSender.send(message, enabled);
+
+ log.info("Successfully processed notification message for recipient={}",
+ message.getNotification().getRecipient());
+ } catch (Exception e) {
+ log.error("Failed to process notification message: recipient={}, error={}",
+ message.getNotification().getRecipient(), e.getMessage(), e);
+ throw e; // Re-throw to trigger Kafka retry/DLQ logic
+ }
}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| package com.wellmeet.notification.consumer; | ||
|
|
||
| import com.wellmeet.notification.consumer.dto.NotificationMessage; | ||
| import com.wellmeet.notification.repository.NotificationHistoryRepository; | ||
| import com.wellmeet.notification.webpush.WebPushService; | ||
| import java.util.List; | ||
| import lombok.RequiredArgsConstructor; | ||
| import org.springframework.stereotype.Component; | ||
|
|
||
| @Component | ||
| @RequiredArgsConstructor | ||
| public class NotificationSender { | ||
|
|
||
| private final WebPushService webPushService; | ||
| private final NotificationHistoryRepository notificationHistoryRepository; | ||
|
|
||
| public void send(NotificationMessage payload, List<String> enabled) { | ||
|
|
||
| } | ||
|
Comment on lines
+17
to
+19
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 비어 있는 send 구현으로 기능이 수행되지 않습니다 🤖 Prompt for AI Agents |
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| package com.wellmeet.notification.consumer.dto; | ||
|
|
||
| import java.time.LocalDateTime; | ||
| import lombok.Getter; | ||
| import lombok.NoArgsConstructor; | ||
|
|
||
| @Getter | ||
| @NoArgsConstructor | ||
| public class MessageHeader { | ||
|
|
||
| private String messageId; | ||
| private LocalDateTime timestamp; | ||
| private String source; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| package com.wellmeet.notification.consumer.dto; | ||
|
|
||
| import lombok.Getter; | ||
| import lombok.NoArgsConstructor; | ||
|
|
||
| @Getter | ||
| @NoArgsConstructor | ||
| public class NotificationInfo { | ||
|
|
||
| private String type; | ||
| private String category; | ||
| private String recipient; | ||
|
Comment on lines
+6
to
+12
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chainJackson 역직렬화 호환성 점검 + 타입 안전성 개선 제안
적용 예시(필드 접근 허용 및 unknown 필드 무시): package com.wellmeet.notification.consumer.dto;
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Getter;
import lombok.NoArgsConstructor;
@Getter
@NoArgsConstructor
+@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY)
+@JsonIgnoreProperties(ignoreUnknown = true)
public class NotificationInfo {
private String type;
private String category;
private String recipient;
}다음 스크립트로 역직렬화 설정(필드 가시성/JsonDeserializer/신뢰 패키지) 존재 여부를 확인해 주세요: 🏁 Script executed: #!/bin/bash
# Jackson 필드 가시성/AutoDetect/Deserializer 설정 탐색
rg -n -C2 -e '@JsonAutoDetect' -e 'setVisibility' -e 'JsonAutoDetect.Visibility' -e 'fieldVisibility' --type=java --type=yml --type=properties
# Spring Kafka JsonDeserializer 및 trusted.packages 설정 탐색
rg -n -C2 -e 'JsonDeserializer' -e 'spring.kafka.consumer' -e 'trusted.packages' --type=java --type=yml --type=properties
# 커스텀 ObjectMapper Bean 정의 탐색
rg -n -C2 -P 'ObjectMapper\s+\w+\s*\(' --type=javaLength of output: 55 🏁 Script executed: #!/bin/bash
set -euo pipefail
echo "=== File: NotificationInfo.java (first 200 lines) ==="
sed -n '1,200p' src/main/java/com/wellmeet/notification/consumer/dto/NotificationInfo.java || true
echo
echo "=== Search: Jackson annotations / ObjectMapper config / module registration ==="
rg -n -C2 --hidden -S '@JsonAutoDetect|@JsonIgnoreProperties|JsonAutoDetect.Visibility|setVisibility|fieldVisibility|Jackson2ObjectMapperBuilder|new ObjectMapper|@Bean\s+ObjectMapper|registerModule|SimpleModule|addDeserializer|@JsonComponent' || true
echo
echo "=== Search: Kafka JsonDeserializer / trusted.packages / spring.kafka.consumer ==="
rg -n -C2 --hidden -S 'JsonDeserializer|trusted.packages|spring.kafka.consumer|value-deserializer|key-deserializer|spring.kafka.properties' || true
echo
echo "=== Search: application.yml / application.yaml / application.properties for trusted.packages or spring.kafka.consumer ==="
rg -n -C2 --hidden -S 'trusted.packages|spring.kafka.consumer' -g 'application.*' -g '**/application.*' || true
echo
echo "=== Search: any mention of NotificationInfo usage (deserialization targets) ==="
rg -n -C2 --hidden -S 'NotificationInfo' || trueLength of output: 5962 조치 필요 — NotificationInfo 역직렬화 접근성 설정 및 Kafka JsonDeserializer trusted.packages 수정(치명적)
🤖 Prompt for AI Agents |
||
| private String recipientType; | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| package com.wellmeet.notification.consumer.dto; | ||
|
|
||
| import lombok.Getter; | ||
| import lombok.NoArgsConstructor; | ||
|
|
||
| @Getter | ||
| @NoArgsConstructor | ||
| public class NotificationMessage { | ||
|
|
||
| private MessageHeader header; | ||
| private NotificationInfo notification; | ||
| private NotificationPayload payload; | ||
| } | ||
|
Comment on lines
+6
to
+13
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Kafka/Jackson 역직렬화 실패 가능성: setter 부재 + 다형성 payload 문제
다음 패치를 권장합니다(Setter + unknown 필드 허용): package com.wellmeet.notification.consumer.dto;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Getter;
+import lombok.Setter;
import lombok.NoArgsConstructor;
@Getter
+@Setter
@NoArgsConstructor
+@JsonIgnoreProperties(ignoreUnknown = true)
public class NotificationMessage {
private MessageHeader header;
private NotificationInfo notification;
private NotificationPayload payload;
}또한, 다형성 역직렬화를 위해 NotificationPayload에 타입 정보를 선언하세요(다른 파일 변경): // src/main/java/com/wellmeet/notification/consumer/dto/NotificationPayload.java
package com.wellmeet.notification.consumer.dto;
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "payloadType")
@JsonSubTypes({
@JsonSubTypes.Type(value = ReservationCreatedPayload.class, name = "RESERVATION_CREATED")
})
public abstract class NotificationPayload {}생성 측에서 JSON에 "payloadType": "RESERVATION_CREATED"를 포함시키세요. 🤖 Prompt for AI Agents |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| package com.wellmeet.notification.consumer.dto; | ||
|
|
||
| public abstract class NotificationPayload { | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
빌드 산출물에 dev-secret.yml 포함 위험
빌드 단계에서 dev-secret.yml을 리소스에 기록하면 업로드되는 JAR 내부에 비밀이 포함됩니다. 이는 아티팩트 유출 리스크입니다. 배포 단계에서만 파일을 생성·주입하도록 이동하세요.
다음처럼 빌드 단계에서 제거하고, 배포 단계에서 생성하도록 변경:
배포 단계에 추가:
애플리케이션이 외부 파일을 읽도록(코드/스크립트 측) JVM 옵션 예:
-Dspring.config.import=optional:file:~/app/config/dev-secret.yml
📝 Committable suggestion
🤖 Prompt for AI Agents