diff --git "a/.github/ISSUE_TEMPLATE/\354\235\264\352\270\270\354\226\264\353\225\214-\353\262\204\352\267\270-\353\246\254\355\217\254\355\212\270\360\237\220\236.md" "b/.github/ISSUE_TEMPLATE/\354\235\264\352\270\270\354\226\264\353\225\214-\353\262\204\352\267\270-\353\246\254\355\217\254\355\212\270\360\237\220\236.md"
new file mode 100644
index 000000000..97e4c6778
--- /dev/null
+++ "b/.github/ISSUE_TEMPLATE/\354\235\264\352\270\270\354\226\264\353\225\214-\353\262\204\352\267\270-\353\246\254\355\217\254\355\212\270\360\237\220\236.md"
@@ -0,0 +1,33 @@
+---
+name: "이길어때 버그 리포트\U0001F41E"
+about: 버그 제보를 통해 서비스를 개선해주세요.
+title: "[BUG]"
+labels: "\U0001F41EBUG"
+assignees: minson96
+
+---
+
+📜 버그 제보
+버그에 대한 간단한 설명을 제공해주세요.
+
+👟 발생 경위
+1. 버그가 발생하게 된 경위를 설명해주세요
+2. 스크린샷 등 추가적인 정보가 있으면 더 빠르게 대응할 수 있어요
+
+👍 예상 동작
+해당 경위를 통해 기대했던 예상 동작에 대해서 설명해주세요
+
+👎 실제 동작
+버그와 함께 동작한 실제 화면을 설명해주세요. (스크린샷이 첨부되면 더 좋아요)
+
+🖥️ 사용 기기
+버그가 발생된 환경의 기기를 간단히 설명해주세요. (예: 아이폰 14, 맥북 m1에어, 갤럭시북...)
+
+🛜 브라우저 환경
+서비스에 접속한 브라우저 환경에 대해 설명해주세요. (예: 크롬, 사파리, 파이어폭스...)
+
+📋 추가정보
+서비스 개선을 위해 전달해주실 추가적인 정보가 있다면 제공해주세요!
+
+👀 비슷한 버그가 이미 발견되어 이슈화되었는지 확인하셨나요?
+- [ ] 네 비슷한 버그가 아직 보고되지 않은 것을 확인했습니다.
diff --git "a/.github/ISSUE_TEMPLATE/\354\235\264\352\270\270\354\226\264\353\225\214-\354\235\264\354\212\210-\355\205\234\355\224\214\353\246\277\342\255\220\357\270\217.md" "b/.github/ISSUE_TEMPLATE/\354\235\264\352\270\270\354\226\264\353\225\214-\354\235\264\354\212\210-\355\205\234\355\224\214\353\246\277\342\255\220\357\270\217.md"
index 7f1f78cfe..147ef7219 100644
--- "a/.github/ISSUE_TEMPLATE/\354\235\264\352\270\270\354\226\264\353\225\214-\354\235\264\354\212\210-\355\205\234\355\224\214\353\246\277\342\255\220\357\270\217.md"
+++ "b/.github/ISSUE_TEMPLATE/\354\235\264\352\270\270\354\226\264\353\225\214-\354\235\264\354\212\210-\355\205\234\355\224\214\353\246\277\342\255\220\357\270\217.md"
@@ -3,7 +3,7 @@ name: 이길어때 이슈 템플릿⭐️
about: 이길어때 개발 시 진행사항 공유를 위한 이슈 템플릿
title: ''
labels: ''
-assignees: ''
+assignees: stoneHee99, minson96
---
diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md
index 6708e865b..b3dd80309 100644
--- a/.github/pull_request_template.md
+++ b/.github/pull_request_template.md
@@ -1,7 +1,5 @@
## Motivation 🧐
--
-
## Key Changes 🔑
diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml
deleted file mode 100644
index f7dc17d44..000000000
--- a/.github/workflows/cd.yml
+++ /dev/null
@@ -1,78 +0,0 @@
-# This workflow uses actions that are not certified by GitHub.
-# They are provided by a third-party and are governed by
-# separate terms of service, privacy policy, and support
-# documentation.
-# This workflow will build a Java project with Gradle and cache/restore any dependencies to improve the workflow execution time
-# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-gradle
-name: Java CD with Gradle
-on:
- push:
- branches: [ "main" ]
-permissions:
- contents: read
-defaults:
- run:
- working-directory: ./backend
-jobs:
- build:
- runs-on: ubuntu-latest
- steps:
-
- ## jdk setting
- - uses: actions/checkout@v3
- - name: Set up JDK 21
- uses: actions/setup-java@v3
- with:
- java-version: '21'
- distribution: 'temurin'
- ## docker-compose.yml 생성 후 secret 값 복붙
- - uses: actions/checkout@v3
- - run: touch docker-compose.yml
- - run: echo "${{ secrets.DOCKER_COMPOSE }}" > docker-compose.yml
- ## application secrets 값 주입
- - name: Set application.yml
- run: |
- sed -i "s|@MASTER_DB_URL@|${{ secrets.MASTER_DB_URL }}|g" ./yigil-api/src/main/resources/application.yml
- sed -i "s|@MASTER_DB_USERNAME@|${{ secrets.MASTER_DB_USERNAME }}|g" ./yigil-api/src/main/resources/application.yml
- sed -i "s|@MASTER_DB_PASSWORD@|${{ secrets.MASTER_DB_PASSWORD }}|g" ./yigil-api/src/main/resources/application.yml
- sed -i "s|@SLAVE_DB_URL@|${{ secrets.SLAVE_DB_URL }}|g" ./yigil-api/src/main/resources/application.yml
- sed -i "s|@SLAVE_DB_USERNAME@|${{ secrets.SLAVE_DB_USERNAME }}|g" ./yigil-api/src/main/resources/application.yml
- sed -i "s|@SLAVE_DB_PASSWORD@|${{ secrets.SLAVE_DB_PASSWORD }}|g" ./yigil-api/src/main/resources/application.yml
- sed -i "s|@REDIS_HOST@|${{ secrets.REDIS_HOST }}|g" ./yigil-api/src/main/resources/application.yml
- sed -i "s|@REDIS_PORT@|${{ secrets.REDIS_PORT }}|g" ./yigil-api/src/main/resources/application.yml
- sed -i "s|@S3_BUCKET@|${{ secrets.S3_BUCKET }}|g" ./yigil-api/src/main/resources/application.yml
- sed -i "s|@AWS_ACCESS_KEY@|${{ secrets.AWS_ACCESS_KEY }}|g" ./yigil-api/src/main/resources/application.yml
- sed -i "s|@AWS_SECRET_KEY@|${{ secrets.AWS_SECRET_KEY }}|g" ./yigil-api/src/main/resources/application.yml
- sed -i "s|@SLACK_WEBHOOK_URI@|${{ secrets.SLACK_WEBHOOK_URI }}|g" ./yigil-api/src/main/resources/application.yml
- cat ./yigil-api/src/main/resources/*
- # Gradle Build를 위한 권한 부여
- - name: Grant execute permission for gradlew
- run: chmod +x gradlew
- # Gradle Build (test 제외)
- - name: Build with Gradle
- run: ./gradlew clean build -x test
- # DockerHub 로그인
- - name: DockerHub Login
- uses: docker/login-action@v2
- with:
- username: ${{ secrets.DOCKERHUB_USERNAME }}
- password: ${{ secrets.DOCKERHUB_PASSWORD }}
- # Docker 이미지 빌드
- - name: Docker Image Build
- run: docker build -t ${{ secrets.DOCKERHUB_USERNAME }}/${{ secrets.PROJECT_NAME }} . --platform=linux/amd64
- # DockerHub Push
- - name: DockerHub Push
- run: docker push ${{ secrets.DOCKERHUB_USERNAME }}/${{ secrets.PROJECT_NAME }}
-
- # EC2 인스턴스 접속 및 애플리케이션 실행
- - name: Application Run
- uses: appleboy/ssh-action@v0.1.6
- with:
- host: ${{ secrets.EC2_HOST }}
- username: ${{ secrets.EC2_USERNAME }}
- key: ${{ secrets.EC2_KEY }}
-
- script: |
- sudo docker-compose pull
- sudo docker-compose down
- sudo docker-compose up -d
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
deleted file mode 100644
index 1a8248980..000000000
--- a/.github/workflows/ci.yml
+++ /dev/null
@@ -1,68 +0,0 @@
-# This workflow uses actions that are not certified by GitHub.
-# They are provided by a third-party and are governed by
-# separate terms of service, privacy policy, and support
-# documentation.
-# This workflow will build a Java project with Gradle and cache/restore any dependencies to improve the workflow execution time
-# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-gradle
-
-name: Java CI with Gradle
-
-on:
- pull_request:
- branches: [ "develop" ]
-
-permissions:
- contents: read
-
-defaults:
- run:
- working-directory: ./backend
-
-jobs:
- build:
- runs-on: ubuntu-latest
-
- steps:
- ## jdk setting
- - uses: actions/checkout@v3
- - name: Set up JDK 21
- uses: actions/setup-java@v3
- with:
- java-version: '21'
- distribution: 'temurin'
- ## application.yml 생성 후 secret 값 복붙
-
- - name: make properties files
- shell: bash
- env:
- JASYPT_SECRET_KEY: ${{ secrets.JASYPT_SECRET_KEY }}
- KAKAO_TOKEN_INFO_URL: ${{ secrets.KAKAO_TOKEN_INFO_URL }}
- run: |
- echo "Jasypt-Secret-Key=$JASYPT_SECRET_KEY" > ./yigil-api/src/main/resources/config.properties
- echo "kakao.token.info.url=$KAKAO_TOKEN_INFO_URL" > ./yigil-api/src/main/resources/url.properties
-
- - name: Set application.yml
- run: |
- sed -i "s|@MASTER_DB_URL@|${{ secrets.MASTER_DB_URL }}|g" ./yigil-api/src/main/resources/application.yml
- sed -i "s|@MASTER_DB_USERNAME@|${{ secrets.MASTER_DB_USERNAME }}|g" ./yigil-api/src/main/resources/application.yml
- sed -i "s|@MASTER_DB_PASSWORD@|${{ secrets.MASTER_DB_PASSWORD }}|g" ./yigil-api/src/main/resources/application.yml
- sed -i "s|@SLAVE_DB_URL@|${{ secrets.SLAVE_DB_URL }}|g" ./yigil-api/src/main/resources/application.yml
- sed -i "s|@SLAVE_DB_USERNAME@|${{ secrets.SLAVE_DB_USERNAME }}|g" ./yigil-api/src/main/resources/application.yml
- sed -i "s|@SLAVE_DB_PASSWORD@|${{ secrets.SLAVE_DB_PASSWORD }}|g" ./yigil-api/src/main/resources/application.yml
- sed -i "s|@REDIS_HOST@|${{ secrets.REDIS_HOST }}|g" ./yigil-api/src/main/resources/application.yml
- sed -i "s|@REDIS_PORT@|${{ secrets.REDIS_PORT }}|g" ./yigil-api/src/main/resources/application.yml
- sed -i "s|@S3_BUCKET@|${{ secrets.S3_BUCKET }}|g" ./yigil-api/src/main/resources/application.yml
- sed -i "s|@AWS_ACCESS_KEY@|${{ secrets.AWS_ACCESS_KEY }}|g" ./yigil-api/src/main/resources/application.yml
- sed -i "s|@AWS_SECRET_KEY@|${{ secrets.AWS_SECRET_KEY }}|g" ./yigil-api/src/main/resources/application.yml
- sed -i "s|@SLACK_WEBHOOK_URI@|${{ secrets.SLACK_WEBHOOK_URI }}|g" ./yigil-api/src/main/resources/application.yml
- cat ./yigil-api/src/main/resources/*
-
-
- # Gradle Build를 위한 권한 부여
- - name: Grant execute permission for gradlew
- run: chmod +x gradlew
-
- # Gradle Build (test 제외)
- - name: Build with Gradle
- run: ./gradlew clean build
-
diff --git a/.github/workflows/cr.yml b/.github/workflows/cr.yml
deleted file mode 100644
index 2141793b5..000000000
--- a/.github/workflows/cr.yml
+++ /dev/null
@@ -1,21 +0,0 @@
-name: Code Review
-
-permissions:
- contents: read
- pull-requests: write
-
-on:
- pull_request:
-
- types: [opened, reopened, synchronize]
-
-jobs:
- test:
- runs-on: ubuntu-latest
- steps:
- - uses: anc95/ChatGPT-CodeReview@main
- env:
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
- LANGUAGE: Korean
- PROMPT: 당신은 10년차 시니어 개발자입니다. 우리가 작성한 코드에 문제가 없는지 리뷰해주세요. 대답은 한국어로 작성해주시고 보안 이슈, 버그, 변수명 체크는 꼭 해주세요. 단순한 부분이나 큰 이슈가 없는 부분은 리뷰해주지 않아도 되요. 대답 잘하면 200$ tip 줄게요.
diff --git a/.github/workflows/dev-backend-cd.yml b/.github/workflows/dev-backend-cd.yml
new file mode 100644
index 000000000..19b91caac
--- /dev/null
+++ b/.github/workflows/dev-backend-cd.yml
@@ -0,0 +1,140 @@
+# This workflow uses actions that are not certified by GitHub.
+# They are provided by a third-party and are governed by
+# separate terms of service, privacy policy, and support
+# documentation.
+# This workflow will build a Java project with Gradle and cache/restore any dependencies to improve the workflow execution time
+# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-gradle
+name: Java CD with Gradle
+on:
+ pull_request:
+ types: ["closed"]
+ branches: [ "develop" ]
+permissions:
+ contents: read
+ id-token: write
+defaults:
+ run:
+ working-directory: ./backend
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ if: >
+ github.event.pull_request.merged == true &&
+ contains(join(github.event.pull_request.labels.*.name, ','), '🛜Backend')
+ steps:
+
+ # jdk setting
+ - uses: actions/checkout@v3
+ - name: Set up JDK 21
+ uses: actions/setup-java@v3
+ with:
+ java-version: '21'
+ distribution: 'temurin'
+ # application secrets 값 주입
+ - name: Set application.yml
+ run: |
+ sed -i "s|@MASTER_DB_URL@|${{ secrets.MASTER_DB_URL }}|g" ./yigil-api/src/main/resources/application.yml
+ sed -i "s|@MASTER_DB_USERNAME@|${{ secrets.MASTER_DB_USERNAME }}|g" ./yigil-api/src/main/resources/application.yml
+ sed -i "s|@MASTER_DB_PASSWORD@|${{ secrets.MASTER_DB_PASSWORD }}|g" ./yigil-api/src/main/resources/application.yml
+ sed -i "s|@SLAVE_DB_URL@|${{ secrets.SLAVE_DB_URL }}|g" ./yigil-api/src/main/resources/application.yml
+ sed -i "s|@SLAVE_DB_USERNAME@|${{ secrets.SLAVE_DB_USERNAME }}|g" ./yigil-api/src/main/resources/application.yml
+ sed -i "s|@SLAVE_DB_PASSWORD@|${{ secrets.SLAVE_DB_PASSWORD }}|g" ./yigil-api/src/main/resources/application.yml
+ sed -i "s|@REDIS_HOST@|${{ secrets.REDIS_HOST }}|g" ./yigil-api/src/main/resources/application.yml
+ sed -i "s|@REDIS_PORT@|${{ secrets.REDIS_PORT }}|g" ./yigil-api/src/main/resources/application.yml
+ sed -i "s|@S3_BUCKET@|${{ secrets.S3_BUCKET }}|g" ./yigil-api/src/main/resources/application.yml
+ sed -i "s|@AWS_ACCESS_KEY@|${{ secrets.AWS_ACCESS_KEY }}|g" ./yigil-api/src/main/resources/application.yml
+ sed -i "s|@AWS_SECRET_KEY@|${{ secrets.AWS_SECRET_KEY }}|g" ./yigil-api/src/main/resources/application.yml
+ sed -i "s|@SLACK_WEBHOOK_URI@|${{ secrets.SLACK_WEBHOOK_URI }}|g" ./yigil-api/src/main/resources/application.yml
+ sed -i "s|@YIGIL_API_PORT@|${{ secrets.YIGIL_API_PORT }}|g" ./yigil-api/src/main/resources/application.yml
+ - name: Set admin application.yml
+ run: |
+ sed -i "s|@MASTER_DB_URL@|${{ secrets.MASTER_DB_URL }}|g" ./yigil-admin/src/main/resources/application.yml
+ sed -i "s|@MASTER_DB_USERNAME@|${{ secrets.MASTER_DB_USERNAME }}|g" ./yigil-admin/src/main/resources/application.yml
+ sed -i "s|@MASTER_DB_PASSWORD@|${{ secrets.MASTER_DB_PASSWORD }}|g" ./yigil-admin/src/main/resources/application.yml
+ sed -i "s|@SLAVE_DB_URL@|${{ secrets.SLAVE_DB_URL }}|g" ./yigil-admin/src/main/resources/application.yml
+ sed -i "s|@SLAVE_DB_USERNAME@|${{ secrets.SLAVE_DB_USERNAME }}|g" ./yigil-admin/src/main/resources/application.yml
+ sed -i "s|@SLAVE_DB_PASSWORD@|${{ secrets.SLAVE_DB_PASSWORD }}|g" ./yigil-admin/src/main/resources/application.yml
+ sed -i "s|@REDIS_HOST@|${{ secrets.REDIS_HOST }}|g" ./yigil-admin/src/main/resources/application.yml
+ sed -i "s|@REDIS_PORT@|${{ secrets.REDIS_PORT }}|g" ./yigil-admin/src/main/resources/application.yml
+ sed -i "s|@S3_BUCKET@|${{ secrets.S3_BUCKET }}|g" ./yigil-admin/src/main/resources/application.yml
+ sed -i "s|@AWS_ACCESS_KEY@|${{ secrets.AWS_ACCESS_KEY }}|g" ./yigil-admin/src/main/resources/application.yml
+ sed -i "s|@AWS_SECRET_KEY@|${{ secrets.AWS_SECRET_KEY }}|g" ./yigil-admin/src/main/resources/application.yml
+ sed -i "s|@SLACK_WEBHOOK_URI@|${{ secrets.SLACK_WEBHOOK_URI }}|g" ./yigil-admin/src/main/resources/application.yml
+ sed -i "s|@YIGIL_ADMIN_PORT@|${{ secrets.YIGIL_ADMIN_PORT }}|g" ./yigil-admin/src/main/resources/application.yml
+ sed -i "s|@JWT_SECRET@|${{ secrets.JWT_SECRET }}|g" ./yigil-admin/src/main/resources/application.yml
+ sed -i "s|@MAIL_HOST@|${{ secrets.MAIL_HOST }}|g" ./yigil-admin/src/main/resources/application.yml
+ sed -i "s|@MAIL_PORT@|${{ secrets.MAIL_PORT }}|g" ./yigil-admin/src/main/resources/application.yml
+ sed -i "s|@MAIL_USERNAME@|${{ secrets.MAIL_USERNAME }}|g" ./yigil-admin/src/main/resources/application.yml
+ sed -i "s|@MAIL_PASSWORD@|${{ secrets.MAIL_PASSWORD }}|g" ./yigil-admin/src/main/resources/application.yml
+ - name: Set admin application.yml
+ run: |
+ sed -i "s|@MASTER_DB_URL@|${{ secrets.MASTER_DB_URL }}|g" ./place-region-batch/src/main/resources/application.yml
+ sed -i "s|@MASTER_DB_USERNAME@|${{ secrets.MASTER_DB_USERNAME }}|g" ./place-region-batch/src/main/resources/application.yml
+ sed -i "s|@MASTER_DB_PASSWORD@|${{ secrets.MASTER_DB_PASSWORD }}|g" ./place-region-batch/src/main/resources/application.yml
+ sed -i "s|@SLACK_WEBHOOK_URI@|${{ secrets.SLACK_WEBHOOK_URI }}|g" ./place-region-batch/src/main/resources/application.yml
+ sed -i "s|@PLACE_REGION_BATCH_PORT@|${{ secrets.PLACE_REGION_BATCH_PORT }}|g" ./place-region-batch/src/main/resources/application.yml
+ # Dockerfile secrets 값 주입
+ - name: Set Dockerfile
+ run: |
+ sed -i "s|@YIGIL_API_PORT@|${{ secrets.YIGIL_API_PORT }}|g" ./yigil-api/Dockerfile
+ sed -i "s|@YIGIL_ADMIN_PORT@|${{ secrets.YIGIL_ADMIN_PORT }}|g" ./yigil-admin/Dockerfile
+ # Gradle Build를 위한 권한 부여
+ - name: Grant execute permission for gradlew
+ run: chmod +x gradlew
+ # Gradle Build (test 제외)
+ - name: Build with Gradle
+ run: ./gradlew clean build
+ # AWS 로그인
+ - name: Configure AWS credentials
+ uses: aws-actions/configure-aws-credentials@v3
+ with:
+ aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY }}
+ aws-secret-access-key: ${{ secrets.AWS_SECRET_KEY }}
+ aws-region: ap-northeast-2
+
+ - name: Login to Amazon ECR
+ id: login-ecr
+ uses: aws-actions/amazon-ecr-login@v2
+ # Docker 이미지 빌드
+ - name: Docker image build
+ run : |
+ cd yigil-api
+ docker build -t ${{ secrets.AWS_ECR }}/${{ secrets.YIGIL_API_BACK }} . --platform=linux/amd64
+ - name: Docker image build
+ run : |
+ cd yigil-admin
+ docker build -t ${{ secrets.AWS_ECR }}/${{ secrets.YIGIL_ADMIN_BACK }} . --platform=linux/amd64
+ - name: Docker image build
+ run : |
+ cd support
+ docker build -t ${{ secrets.AWS_ECR }}/${{ secrets.YIGIL_SUPPORT }} . --platform=linux/amd64
+ - name: Docker image build
+ run : |
+ cd place-region-batch
+ docker build -t ${{ secrets.AWS_ECR }}/${{ secrets.PLACE_REGION_BATCH }} . --platform=linux/amd64
+ - name: Docker image push
+ run : |
+ cd yigil-api
+ docker push ${{ secrets.AWS_ECR }}/${{ secrets.YIGIL_API_BACK }}
+ - name: Docker image push
+ run : |
+ cd yigil-admin
+ docker push ${{ secrets.AWS_ECR }}/${{ secrets.YIGIL_ADMIN_BACK }}
+ - name: Docker image push
+ run : |
+ cd support
+ docker push ${{ secrets.AWS_ECR }}/${{ secrets.YIGIL_SUPPORT }}
+ - name: Docker image push
+ run : |
+ cd place-region-batch
+ docker push ${{ secrets.AWS_ECR }}/${{ secrets.PLACE_REGION_BATCH }}
+ # EC2 인스턴스 접속 및 애플리케이션 실행
+ - name: Application Run
+ uses: appleboy/ssh-action@v0.1.6
+ with:
+ host: ${{ secrets.EC2_HOST_DEV }}
+ username: ${{ secrets.EC2_USERNAME }}
+ key: ${{ secrets.EC2_KEY }}
+
+ script: |
+ sh ./gitaction.sh
diff --git a/.github/workflows/dev-backend-ci.yml b/.github/workflows/dev-backend-ci.yml
new file mode 100644
index 000000000..8964360d3
--- /dev/null
+++ b/.github/workflows/dev-backend-ci.yml
@@ -0,0 +1,99 @@
+# This workflow uses actions that are not certified by GitHub.
+# They are provided by a third-party and are governed by
+# separate terms of service, privacy policy, and support
+# documentation.
+# This workflow will build a Java project with Gradle and cache/restore any dependencies to improve the workflow execution time
+# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-gradle
+
+name: Java CI with Gradle
+
+on:
+ pull_request:
+ types: [opened]
+ branches: [ "develop" ]
+
+permissions:
+ contents: read
+
+defaults:
+ run:
+ working-directory: ./backend
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ if: contains(join(github.event.pull_request.labels.*.name, ','), '🛜Backend')
+ steps:
+ ## jdk setting
+ - uses: actions/checkout@v3
+ - name: Set up JDK 21
+ uses: actions/setup-java@v3
+ with:
+ java-version: '21'
+ distribution: 'temurin'
+ ## application.yml 생성 후 secret 값 복붙
+
+ - name: make properties files
+ shell: bash
+ env:
+ JASYPT_SECRET_KEY: ${{ secrets.JASYPT_SECRET_KEY }}
+ KAKAO_TOKEN_INFO_URL: ${{ secrets.KAKAO_TOKEN_INFO_URL }}
+ run: |
+ echo "Jasypt-Secret-Key=$JASYPT_SECRET_KEY" > ./yigil-api/src/main/resources/config.properties
+ echo "kakao.token.info.url=$KAKAO_TOKEN_INFO_URL" > ./yigil-api/src/main/resources/url.properties
+
+ - name: Set api application.yml
+ run: |
+ sed -i "s|@MASTER_DB_URL@|${{ secrets.MASTER_DB_URL }}|g" ./yigil-api/src/main/resources/application.yml
+ sed -i "s|@MASTER_DB_USERNAME@|${{ secrets.MASTER_DB_USERNAME }}|g" ./yigil-api/src/main/resources/application.yml
+ sed -i "s|@MASTER_DB_PASSWORD@|${{ secrets.MASTER_DB_PASSWORD }}|g" ./yigil-api/src/main/resources/application.yml
+ sed -i "s|@SLAVE_DB_URL@|${{ secrets.SLAVE_DB_URL }}|g" ./yigil-api/src/main/resources/application.yml
+ sed -i "s|@SLAVE_DB_USERNAME@|${{ secrets.SLAVE_DB_USERNAME }}|g" ./yigil-api/src/main/resources/application.yml
+ sed -i "s|@SLAVE_DB_PASSWORD@|${{ secrets.SLAVE_DB_PASSWORD }}|g" ./yigil-api/src/main/resources/application.yml
+ sed -i "s|@REDIS_HOST@|${{ secrets.REDIS_HOST }}|g" ./yigil-api/src/main/resources/application.yml
+ sed -i "s|@REDIS_PORT@|${{ secrets.REDIS_PORT }}|g" ./yigil-api/src/main/resources/application.yml
+ sed -i "s|@S3_BUCKET@|${{ secrets.S3_BUCKET }}|g" ./yigil-api/src/main/resources/application.yml
+ sed -i "s|@AWS_ACCESS_KEY@|${{ secrets.AWS_ACCESS_KEY }}|g" ./yigil-api/src/main/resources/application.yml
+ sed -i "s|@AWS_SECRET_KEY@|${{ secrets.AWS_SECRET_KEY }}|g" ./yigil-api/src/main/resources/application.yml
+ sed -i "s|@SLACK_WEBHOOK_URI@|${{ secrets.SLACK_WEBHOOK_URI }}|g" ./yigil-api/src/main/resources/application.yml
+ sed -i "s|@YIGIL_API_PORT@|${{ secrets.YIGIL_API_PORT }}|g" ./yigil-api/src/main/resources/application.yml
+ # cat ./yigil-api/src/main/resources/*
+
+ - name: Set admin application.yml
+ run: |
+ sed -i "s|@MASTER_DB_URL@|${{ secrets.MASTER_DB_URL }}|g" ./yigil-admin/src/main/resources/application.yml
+ sed -i "s|@MASTER_DB_USERNAME@|${{ secrets.MASTER_DB_USERNAME }}|g" ./yigil-admin/src/main/resources/application.yml
+ sed -i "s|@MASTER_DB_PASSWORD@|${{ secrets.MASTER_DB_PASSWORD }}|g" ./yigil-admin/src/main/resources/application.yml
+ sed -i "s|@SLAVE_DB_URL@|${{ secrets.SLAVE_DB_URL }}|g" ./yigil-admin/src/main/resources/application.yml
+ sed -i "s|@SLAVE_DB_USERNAME@|${{ secrets.SLAVE_DB_USERNAME }}|g" ./yigil-admin/src/main/resources/application.yml
+ sed -i "s|@SLAVE_DB_PASSWORD@|${{ secrets.SLAVE_DB_PASSWORD }}|g" ./yigil-admin/src/main/resources/application.yml
+ sed -i "s|@REDIS_HOST@|${{ secrets.REDIS_HOST }}|g" ./yigil-admin/src/main/resources/application.yml
+ sed -i "s|@REDIS_PORT@|${{ secrets.REDIS_PORT }}|g" ./yigil-admin/src/main/resources/application.yml
+ sed -i "s|@S3_BUCKET@|${{ secrets.S3_BUCKET }}|g" ./yigil-admin/src/main/resources/application.yml
+ sed -i "s|@AWS_ACCESS_KEY@|${{ secrets.AWS_ACCESS_KEY }}|g" ./yigil-admin/src/main/resources/application.yml
+ sed -i "s|@AWS_SECRET_KEY@|${{ secrets.AWS_SECRET_KEY }}|g" ./yigil-admin/src/main/resources/application.yml
+ sed -i "s|@SLACK_WEBHOOK_URI@|${{ secrets.SLACK_WEBHOOK_URI }}|g" ./yigil-admin/src/main/resources/application.yml
+ sed -i "s|@YIGIL_ADMIN_PORT@|${{ secrets.YIGIL_ADMIN_PORT }}|g" ./yigil-admin/src/main/resources/application.yml
+ sed -i "s|@JWT_SECRET@|${{ secrets.JWT_SECRET }}|g" ./yigil-admin/src/main/resources/application.yml
+ sed -i "s|@MAIL_HOST@|${{ secrets.MAIL_HOST }}|g" ./yigil-admin/src/main/resources/application.yml
+ sed -i "s|@MAIL_PORT@|${{ secrets.MAIL_PORT }}|g" ./yigil-admin/src/main/resources/application.yml
+ sed -i "s|@MAIL_USERNAME@|${{ secrets.MAIL_USERNAME }}|g" ./yigil-admin/src/main/resources/application.yml
+ sed -i "s|@MAIL_PASSWORD@|${{ secrets.MAIL_PASSWORD }}|g" ./yigil-admin/src/main/resources/application.yml
+ - name: Set admin application.yml
+ run: |
+ sed -i "s|@MASTER_DB_URL@|${{ secrets.MASTER_DB_URL }}|g" ./place-region-batch/src/main/resources/application.yml
+ sed -i "s|@MASTER_DB_USERNAME@|${{ secrets.MASTER_DB_USERNAME }}|g" ./place-region-batch/src/main/resources/application.yml
+ sed -i "s|@MASTER_DB_PASSWORD@|${{ secrets.MASTER_DB_PASSWORD }}|g" ./place-region-batch/src/main/resources/application.yml
+ sed -i "s|@SLACK_WEBHOOK_URI@|${{ secrets.SLACK_WEBHOOK_URI }}|g" ./place-region-batch/src/main/resources/application.yml
+ sed -i "s|@PLACE_REGION_BATCH_PORT@|${{ secrets.PLACE_REGION_BATCH_PORT }}|g" ./place-region-batch/src/main/resources/application.yml
+ # cat ./yigil-admin/src/main/resources/*
+
+
+ # Gradle Build를 위한 권한 부여
+ - name: Grant execute permission for gradlew
+ run: chmod +x gradlew
+
+ # Gradle Build (test 제외)
+ - name: Build with Gradle
+ run: ./gradlew clean build test
+
diff --git a/.github/workflows/dev-frontend-cd.yml b/.github/workflows/dev-frontend-cd.yml
new file mode 100644
index 000000000..afa5fabb0
--- /dev/null
+++ b/.github/workflows/dev-frontend-cd.yml
@@ -0,0 +1,63 @@
+name: Frontend CD
+
+on:
+ pull_request:
+ types: ["closed"]
+ branches: ["develop"]
+permissions:
+ contents: read
+ id-token: write
+defaults:
+ run:
+ working-directory: ./frontend
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ if: >
+ github.event.pull_request.merged == true &&
+ contains(join(github.event.pull_request.labels.*.name, ','), '💻Frontend')
+ timeout-minutes: 15
+ steps:
+ - uses: actions/checkout@v4
+ with:
+ sparse-checkout: frontend
+
+ - uses: actions/setup-node@v4
+ with:
+ node-version: 20
+ cache: "npm"
+ cache-dependency-path: "**/package-lock.json"
+ - name: npm install library
+ run: npm ci
+ # npm 테스트 진행
+ - name: Run test
+ run: npm run test
+ # AWS 로그인
+ - name: Configure AWS credentials
+ uses: aws-actions/configure-aws-credentials@v3
+ with:
+ aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY }}
+ aws-secret-access-key: ${{ secrets.AWS_SECRET_KEY }}
+ aws-region: ap-northeast-2
+
+ - name: Login to Amazon ECR
+ id: login-ecr
+ uses: aws-actions/amazon-ecr-login@v2
+ # Docker 이미지 빌드
+ - name: Docker image build
+ run : |
+ docker build -t ${{ secrets.AWS_ECR }}/${{ secrets.YIGIL_API_FRONT }} . --platform=linux/amd64
+ - name: Docker image push
+ run : |
+ docker push ${{ secrets.AWS_ECR }}/${{ secrets.YIGIL_API_FRONT }}
+ # EC2 인스턴스 접속 및 애플리케이션 실행
+ - name: Application Run
+ uses: appleboy/ssh-action@v0.1.6
+ with:
+ host: ${{ secrets.EC2_HOST_DEV }}
+ username: ${{ secrets.EC2_USERNAME }}
+ key: ${{ secrets.EC2_KEY }}
+
+ script: |
+ sh ./gitaction.sh
diff --git a/.github/workflows/frontend-ci.yml b/.github/workflows/dev-frontend-ci.yml
similarity index 61%
rename from .github/workflows/frontend-ci.yml
rename to .github/workflows/dev-frontend-ci.yml
index c40731482..d7a2d06d7 100644
--- a/.github/workflows/frontend-ci.yml
+++ b/.github/workflows/dev-frontend-ci.yml
@@ -1,9 +1,8 @@
name: Frontend CI
on:
- push:
pull_request:
- branches: [ "develop" ]
+ branches: ["develop"]
defaults:
run:
@@ -12,20 +11,19 @@ defaults:
jobs:
test:
runs-on: ubuntu-latest
+ if: contains(join(github.event.pull_request.labels.*.name, ','), '💻Frontend')
timeout-minutes: 15
steps:
- uses: actions/checkout@v4
with:
- sparse-checkout:
- frontend
+ sparse-checkout: frontend
- uses: actions/setup-node@v4
with:
node-version: 20
- cache: 'npm'
- cache-dependency-path: '**/package-lock.json'
+ cache: "npm"
+ cache-dependency-path: "**/package-lock.json"
- run: npm ci
- name: Run test
run: npm run test
-
diff --git a/.github/workflows/prod-backend-cd.yml b/.github/workflows/prod-backend-cd.yml
new file mode 100644
index 000000000..4ad1195ca
--- /dev/null
+++ b/.github/workflows/prod-backend-cd.yml
@@ -0,0 +1,143 @@
+# This workflow uses actions that are not certified by GitHub.
+# They are provided by a third-party and are governed by
+# separate terms of service, privacy policy, and support
+# documentation.
+# This workflow will build a Java project with Gradle and cache/restore any dependencies to improve the workflow execution time
+# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-gradle
+name: Java CD with Gradle
+on:
+ pull_request:
+ types: [ "closed" ]
+ branches: [ "main" ]
+permissions:
+ contents: read
+ id-token: write
+defaults:
+ run:
+ working-directory: ./backend
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ if: >
+ github.event.pull_request.merged == true &&
+ contains(join(github.event.pull_request.labels.*.name, ','), '🛜Backend')
+ steps:
+ ## jdk setting
+ - uses: actions/checkout@v3
+ - name: Set up JDK 21
+ uses: actions/setup-java@v3
+ with:
+ java-version: '21'
+ distribution: 'temurin'
+ ## application secrets 값 주입
+ - name: Set api application.yml
+ run: |
+ sed -i "s|@MASTER_DB_URL@|${{ secrets.MASTER_DB_URL_PROD }}|g" ./yigil-api/src/main/resources/application.yml
+ sed -i "s|@MASTER_DB_USERNAME@|${{ secrets.MASTER_DB_USERNAME }}|g" ./yigil-api/src/main/resources/application.yml
+ sed -i "s|@MASTER_DB_PASSWORD@|${{ secrets.MASTER_DB_PASSWORD }}|g" ./yigil-api/src/main/resources/application.yml
+ sed -i "s|@SLAVE_DB_URL@|${{ secrets.SLAVE_DB_URL_PROD }}|g" ./yigil-api/src/main/resources/application.yml
+ sed -i "s|@SLAVE_DB_USERNAME@|${{ secrets.SLAVE_DB_USERNAME }}|g" ./yigil-api/src/main/resources/application.yml
+ sed -i "s|@SLAVE_DB_PASSWORD@|${{ secrets.SLAVE_DB_PASSWORD }}|g" ./yigil-api/src/main/resources/application.yml
+ sed -i "s|@REDIS_HOST@|${{ secrets.REDIS_HOST }}|g" ./yigil-api/src/main/resources/application.yml
+ sed -i "s|@REDIS_PORT@|${{ secrets.REDIS_PORT }}|g" ./yigil-api/src/main/resources/application.yml
+ sed -i "s|@S3_BUCKET@|${{ secrets.S3_BUCKET }}|g" ./yigil-api/src/main/resources/application.yml
+ sed -i "s|@AWS_ACCESS_KEY@|${{ secrets.AWS_ACCESS_KEY }}|g" ./yigil-api/src/main/resources/application.yml
+ sed -i "s|@AWS_SECRET_KEY@|${{ secrets.AWS_SECRET_KEY }}|g" ./yigil-api/src/main/resources/application.yml
+ sed -i "s|@SLACK_WEBHOOK_URI@|${{ secrets.SLACK_WEBHOOK_URI }}|g" ./yigil-api/src/main/resources/application.yml
+ sed -i "s|@YIGIL_API_PORT@|${{ secrets.YIGIL_API_PORT }}|g" ./yigil-api/src/main/resources/application.yml
+ # cat ./yigil-api/src/main/resources/*
+ - name: Set admin application.yml
+ run: |
+ sed -i "s|@MASTER_DB_URL@|${{ secrets.MASTER_DB_URL_PROD }}|g" ./yigil-admin/src/main/resources/application.yml
+ sed -i "s|@MASTER_DB_USERNAME@|${{ secrets.MASTER_DB_USERNAME }}|g" ./yigil-admin/src/main/resources/application.yml
+ sed -i "s|@MASTER_DB_PASSWORD@|${{ secrets.MASTER_DB_PASSWORD }}|g" ./yigil-admin/src/main/resources/application.yml
+ sed -i "s|@SLAVE_DB_URL@|${{ secrets.SLAVE_DB_URL_PROD }}|g" ./yigil-admin/src/main/resources/application.yml
+ sed -i "s|@SLAVE_DB_USERNAME@|${{ secrets.SLAVE_DB_USERNAME }}|g" ./yigil-admin/src/main/resources/application.yml
+ sed -i "s|@SLAVE_DB_PASSWORD@|${{ secrets.SLAVE_DB_PASSWORD }}|g" ./yigil-admin/src/main/resources/application.yml
+ sed -i "s|@REDIS_HOST@|${{ secrets.REDIS_HOST }}|g" ./yigil-admin/src/main/resources/application.yml
+ sed -i "s|@REDIS_PORT@|${{ secrets.REDIS_PORT }}|g" ./yigil-admin/src/main/resources/application.yml
+ sed -i "s|@S3_BUCKET@|${{ secrets.S3_BUCKET }}|g" ./yigil-admin/src/main/resources/application.yml
+ sed -i "s|@AWS_ACCESS_KEY@|${{ secrets.AWS_ACCESS_KEY }}|g" ./yigil-admin/src/main/resources/application.yml
+ sed -i "s|@AWS_SECRET_KEY@|${{ secrets.AWS_SECRET_KEY }}|g" ./yigil-admin/src/main/resources/application.yml
+ sed -i "s|@SLACK_WEBHOOK_URI@|${{ secrets.SLACK_WEBHOOK_URI }}|g" ./yigil-admin/src/main/resources/application.yml
+ sed -i "s|@YIGIL_ADMIN_PORT@|${{ secrets.YIGIL_ADMIN_PORT }}|g" ./yigil-admin/src/main/resources/application.yml
+ sed -i "s|@JWT_SECRET@|${{ secrets.JWT_SECRET }}|g" ./yigil-admin/src/main/resources/application.yml
+ sed -i "s|@MAIL_HOST@|${{ secrets.MAIL_HOST }}|g" ./yigil-admin/src/main/resources/application.yml
+ sed -i "s|@MAIL_PORT@|${{ secrets.MAIL_PORT }}|g" ./yigil-admin/src/main/resources/application.yml
+ sed -i "s|@MAIL_USERNAME@|${{ secrets.MAIL_USERNAME }}|g" ./yigil-admin/src/main/resources/application.yml
+ sed -i "s|@MAIL_PASSWORD@|${{ secrets.MAIL_PASSWORD }}|g" ./yigil-admin/src/main/resources/application.yml
+ # cat ./yigil-admin/src/main/resources/*
+ - name: Set admin application.yml
+ run: |
+ sed -i "s|@MASTER_DB_URL@|${{ secrets.MASTER_DB_URL_PROD }}|g" ./place-region-batch/src/main/resources/application.yml
+ sed -i "s|@MASTER_DB_USERNAME@|${{ secrets.MASTER_DB_USERNAME }}|g" ./place-region-batch/src/main/resources/application.yml
+ sed -i "s|@MASTER_DB_PASSWORD@|${{ secrets.MASTER_DB_PASSWORD }}|g" ./place-region-batch/src/main/resources/application.yml
+ sed -i "s|@SLACK_WEBHOOK_URI@|${{ secrets.SLACK_WEBHOOK_URI }}|g" ./place-region-batch/src/main/resources/application.yml
+ sed -i "s|@PLACE_REGION_BATCH_PORT@|${{ secrets.PLACE_REGION_BATCH_PORT }}|g" ./place-region-batch/src/main/resources/application.yml
+ ## Dockerfile secrets 값 주입
+ - name: Set Dockerfile
+ run: |
+ sed -i "s|@YIGIL_API_PORT@|${{ secrets.YIGIL_API_PORT }}|g" ./yigil-api/Dockerfile
+ sed -i "s|@YIGIL_ADMIN_PORT@|${{ secrets.YIGIL_ADMIN_PORT }}|g" ./yigil-admin/Dockerfile
+ sed -i "s|@PLACE_REGION_BATCH_PORT@|${{ secrets.PLACE_REGION_BATCH_PORT }}|g" ./yigil-admin/Dockerfile
+ # Gradle Build를 위한 권한 부여
+ - name: Grant execute permission for gradlew
+ run: chmod +x gradlew
+ # Gradle Build (test 제외)
+ - name: Build with Gradle
+ run: ./gradlew clean build
+ ## AWS에 로그인합니다. aws-region은 서울로 설정(ap-northeast-2)했습니다
+ - name: Configure AWS credentials
+ uses: aws-actions/configure-aws-credentials@v3
+ with:
+ aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY }}
+ aws-secret-access-key: ${{ secrets.AWS_SECRET_KEY }}
+ aws-region: ap-northeast-2
+ ## ECR에 로그인합니다
+ - name: Login to Amazon ECR
+ id: login-ecr
+ uses: aws-actions/amazon-ecr-login@v2
+ # Docker 이미지 빌드
+ - name: Docker image build
+ run : |
+ cd yigil-api
+ docker build -t ${{ secrets.AWS_ECR }}/${{ secrets.YIGIL_API_BACK_PROD }} . --platform=linux/amd64
+ - name: Docker image build
+ run : |
+ cd yigil-admin
+ docker build -t ${{ secrets.AWS_ECR }}/${{ secrets.YIGIL_ADMIN_BACK_PROD }} . --platform=linux/amd64
+ - name: Docker image build
+ run : |
+ cd support
+ docker build -t ${{ secrets.AWS_ECR }}/${{ secrets.YIGIL_SUPPORT_PROD }} . --platform=linux/amd64
+ - name: Docker image build
+ run : |
+ cd place-region-batch
+ docker build -t ${{ secrets.AWS_ECR }}/${{ secrets.PLACE_REGION_BATCH_PROD }} . --platform=linux/amd64
+ - name: Docker image push
+ run : |
+ cd yigil-api
+ docker push ${{ secrets.AWS_ECR }}/${{ secrets.YIGIL_API_BACK_PROD }}
+ - name: Docker image push
+ run : |
+ cd yigil-admin
+ docker push ${{ secrets.AWS_ECR }}/${{ secrets.YIGIL_ADMIN_BACK_PROD }}
+ - name: Docker image push
+ run : |
+ cd support
+ docker push ${{ secrets.AWS_ECR }}/${{ secrets.YIGIL_SUPPORT_PROD }}
+ - name: Docker image push
+ run : |
+ cd place-region-batch
+ docker push ${{ secrets.AWS_ECR }}/${{ secrets.PLACE_REGION_BATCH_PROD }}
+
+ # EC2 인스턴스 접속 및 애플리케이션 실행
+ - name: Application Run
+ uses: appleboy/ssh-action@v0.1.6
+ with:
+ host: ${{ secrets.EC2_HOST_PROD }}
+ username: ${{ secrets.EC2_USERNAME }}
+ key: ${{ secrets.EC2_KEY }}
+
+ script: |
+ sh ./gitaction.sh
diff --git a/.github/workflows/prod-frontend-cd.yml b/.github/workflows/prod-frontend-cd.yml
new file mode 100644
index 000000000..d00771c5c
--- /dev/null
+++ b/.github/workflows/prod-frontend-cd.yml
@@ -0,0 +1,62 @@
+name: Frontend CD
+
+on:
+ push:
+ branches: ["main"]
+permissions:
+ contents: read
+ id-token: write
+defaults:
+ run:
+ working-directory: ./frontend
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ if: >
+ github.event.pull_request.merged == true &&
+ contains(join(github.event.pull_request.labels.*.name, ','), '💻Frontend')
+ timeout-minutes: 15
+ steps:
+ - uses: actions/checkout@v4
+ with:
+ sparse-checkout: frontend
+
+ - uses: actions/setup-node@v4
+ with:
+ node-version: 20
+ cache: "npm"
+ cache-dependency-path: "**/package-lock.json"
+ - name: npm install library
+ run: npm ci
+ # npm 테스트 진행
+ - name: Run test
+ run: npm run test
+ # AWS 로그인
+ - name: Configure AWS credentials
+ uses: aws-actions/configure-aws-credentials@v3
+ with:
+ aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY }}
+ aws-secret-access-key: ${{ secrets.AWS_SECRET_KEY }}
+ aws-region: ap-northeast-2
+
+ - name: Login to Amazon ECR
+ id: login-ecr
+ uses: aws-actions/amazon-ecr-login@v2
+ # Docker 이미지 빌드
+ - name: Docker image build
+ run : |
+ docker build -t ${{ secrets.AWS_ECR }}/${{ secrets.YIGIL_API_FRONT }} . --platform=linux/amd64
+ - name: Docker image push
+ run : |
+ docker push ${{ secrets.AWS_ECR }}/${{ secrets.YIGIL_API_FRONT }}
+ # EC2 인스턴스 접속 및 애플리케이션 실행
+ - name: Application Run
+ uses: appleboy/ssh-action@v0.1.6
+ with:
+ host: ${{ secrets.EC2_HOST_PROD }}
+ username: ${{ secrets.EC2_USERNAME }}
+ key: ${{ secrets.EC2_KEY }}
+
+ script: |
+ sh ./gitaction.sh
diff --git a/.gitignore b/.gitignore
index ddb919823..458993db7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,48 +1,362 @@
-HELP.md
-.gradle
-build/
-!gradle/wrapper/gradle-wrapper.jar
-!**/src/main/**/build/
-!**/src/test/**/build/
-
-### STS ###
-.apt_generated
-.classpath
-.factorypath
-.project
-.settings
-.springBeans
-.sts4-cache
-bin/
-!**/src/main/**/bin/
-!**/src/test/**/bin/
-
-### IntelliJ IDEA ###
-.idea
+ll# Created by https://www.toptal.com/developers/gitignore/api/intellij,java,macos,windows
+# Edit at https://www.toptal.com/developers/gitignore?templates=intellij,java,macos,windows
+
+### Intellij ###
+# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
+# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
+
+# User-specific stuff
+.idea/**/workspace.xml
+.idea/**/tasks.xml
+.idea/**/usage.statistics.xml
+.idea/**/dictionaries
+.idea/**/shelf
+
+# AWS User-specific
+.idea/**/aws.xml
+
+# Generated files
+.idea/**/contentModel.xml
+
+# Sensitive or high-churn files
+.idea/**/dataSources/
+.idea/**/dataSources.ids
+.idea/**/dataSources.local.xml
+.idea/**/sqlDataSources.xml
+.idea/**/dynamic.xml
+.idea/**/uiDesigner.xml
+.idea/**/dbnavigator.xml
+
+# Gradle
+.idea/**/gradle.xml
+.idea/**/libraries
+
+# Gradle and Maven with auto-import
+# When using Gradle or Maven with auto-import, you should exclude module files,
+# since they will be recreated, and may cause churn. Uncomment if using
+# auto-import.
+# .idea/artifacts
+# .idea/compiler.xml
+# .idea/jarRepositories.xml
+# .idea/modules.xml
+# .idea/*.iml
+# .idea/modules
+# *.iml
+# *.ipr
+
+# CMake
+cmake-build-*/
+
+# Mongo Explorer plugin
+.idea/**/mongoSettings.xml
+
+# File-based project format
*.iws
-*.iml
-*.ipr
+
+# IntelliJ
out/
-!**/src/main/**/out/
-!**/src/test/**/out/
-
-### NetBeans ###
-/nbproject/private/
-/nbbuild/
-/dist/
-/nbdist/
-/.nb-gradle/
-
-### VS Code ###
-.vscode/
-`
-### application*.yml ###
-src/main/resources/*.yml
-application.yml
+# mpeltonen/sbt-idea plugin
+.idea
+.idea_modules/
+
+# JIRA plugin
+atlassian-ide-plugin.xml
+
+# Cursive Clojure plugin
+.idea/replstate.xml
+
+# SonarLint plugin
+.idea/sonarlint/
+
+# Crashlytics plugin (for Android Studio and IntelliJ)
+com_crashlytics_export_strings.xml
+crashlytics.properties
+crashlytics-build.properties
+fabric.properties
+
+# Editor-based Rest Client
+.idea/httpRequests
+
+# Android studio 3.1+ serialized cache file
+.idea/caches/build_file_checksums.ser
+
+### Intellij Patch ###
+# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721
+
+# *.iml
+# modules.xml
+# .idea/misc.xml
+# *.ipr
+
+# Sonarlint plugin
+# https://plugins.jetbrains.com/plugin/7973-sonarlint
+.idea/**/sonarlint/
+
+# SonarQube Plugin
+# https://plugins.jetbrains.com/plugin/7238-sonarqube-community-plugin
+.idea/**/sonarIssues.xml
+
+# Markdown Navigator plugin
+# https://plugins.jetbrains.com/plugin/7896-markdown-navigator-enhanced
+.idea/**/markdown-navigator.xml
+.idea/**/markdown-navigator-enh.xml
+.idea/**/markdown-navigator/
+
+# Cache file creation bug
+# See https://youtrack.jetbrains.com/issue/JBR-2257
+.idea/$CACHE_FILE$
+
+# CodeStream plugin
+# https://plugins.jetbrains.com/plugin/12206-codestream
+.idea/codestream.xml
+
+# Azure Toolkit for IntelliJ plugin
+# https://plugins.jetbrains.com/plugin/8053-azure-toolkit-for-intellij
+.idea/**/azureSettings.xml
+
+### Java ###
+# Compiled class file
+*.class
+
+# Log file
+*.log
+
+# BlueJ files
+*.ctxt
+
+# Mobile Tools for Java (J2ME)
+.mtj.tmp/
+
+# Package Files #
+*.jar
+*.war
+*.nar
+*.ear
+*.zip
+*.tar.gz
+*.rar
+
+# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
+hs_err_pid*
+replay_pid*
+
+### macOS ###
+# General
.DS_Store
+.AppleDouble
+.LSOverride
+
+# Icon must end with two \r
+Icon
+
+
+# Thumbnails
+._*
+
+# Files that might appear in the root of a volume
+.DocumentRevisions-V100
+.fseventsd
+.Spotlight-V100
+.TemporaryItems
+.Trashes
+.VolumeIcon.icns
+.com.apple.timemachine.donotpresent
+
+# Directories potentially created on remote AFP share
+.AppleDB
+.AppleDesktop
+Network Trash Folder
+Temporary Items
+.apdisk
+
+### macOS Patch ###
+# iCloud generated files
+*.icloud
+
+### Windows ###
+# Windows thumbnail cache files
+Thumbs.db
+Thumbs.db:encryptable
+ehthumbs.db
+ehthumbs_vista.db
+
+# Dump file
+*.stackdump
+
+# Folder config file
+[Dd]esktop.ini
+
+# Recycle Bin used on file shares
+$RECYCLE.BIN/
+
+# Windows Installer files
+*.cab
+*.msi
+*.msix
+*.msm
+*.msp
+
+# Windows shortcuts
+*.lnk
+
+# End of https://www.toptal.com/developers/gitignore/api/intellij,java,macos,windows
+
+### Node ###
+# Logs
+logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+lerna-debug.log*
+.pnpm-debug.log*
+
+# Diagnostic reports (https://nodejs.org/api/report.html)
+report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
+
+# Runtime data
+pids
+*.pid
+*.seed
+*.pid.lock
+
+# Directory for instrumented libs generated by jscoverage/JSCover
+lib-cov
+
+# Coverage directory used by tools like istanbul
+coverage
+*.lcov
+
+# nyc test coverage
+.nyc_output
+
+# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
+.grunt
+
+# Bower dependency directory (https://bower.io/)
+bower_components
+
+# node-waf configuration
+.lock-wscript
+
+# Compiled binary addons (https://nodejs.org/api/addons.html)
+build/Release
+
+# Dependency directories
+node_modules/
+jspm_packages/
+
+# Snowpack dependency directory (https://snowpack.dev/)
+web_modules/
+
+# TypeScript cache
+*.tsbuildinfo
+
+# Optional npm cache directory
+.npm
+
+# Optional eslint cache
+.eslintcache
+
+# Optional stylelint cache
+.stylelintcache
+
+# Microbundle cache
+.rpt2_cache/
+.rts2_cache_cjs/
+.rts2_cache_es/
+.rts2_cache_umd/
+
+# Optional REPL history
+.node_repl_history
+
+# Output of 'npm pack'
+*.tgz
+
+# Yarn Integrity file
+.yarn-integrity
+
+# dotenv environment variable files
+.env
+.env.development.local
+.env.test.local
+.env.production.local
+.env.local
+
+# parcel-bundler cache (https://parceljs.org/)
+.cache
+.parcel-cache
+
+# Next.js build output
+.next
+out
+
+# Nuxt.js build / generate output
+.nuxt
+dist
+
+# Gatsby files
+.cache/
+# Comment in the public line in if your project uses Gatsby and not Next.js
+# https://nextjs.org/blog/next-9-1#public-directory-support
+# public
+
+# vuepress build output
+.vuepress/dist
+
+# vuepress v2.x temp and cache directory
+.temp
+
+# Docusaurus cache and generated files
+.docusaurus
+
+# Serverless directories
+.serverless/
+
+# FuseBox cache
+.fusebox/
+
+# DynamoDB Local files
+.dynamodb/
+
+# TernJS port file
+.tern-port
+
+# Stores VSCode versions used for testing VSCode extensions
+.vscode-test
+
+# yarn v2
+.yarn/cache
+.yarn/unplugged
+.yarn/build-state.yml
+.yarn/install-state.gz
+.pnp.*
+
+### Node Patch ###
+# Serverless Webpack directories
+.webpack/
+
+# Optional stylelint cache
+
+# SvelteKit build / generate output
+.svelte-kit
+
+### react ###
+.DS_*
+**/*.backup.*
+**/*.back.*
+
+node_modules
+
+*.sublime*
+
+psd
+thumb
+sketch
+
+# End of https://www.toptal.com/developers/gitignore/api/node,react
-.github/
-.gradle/
-.idea/
+backend/support/domain/src/main/generated/*
+*.yml
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 000000000..b33bc7b39
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "admin-frontend"]
+ path = admin-frontend
+ url = https://github.com/Kernel360/f1-yigil-admin-frontend.git
diff --git a/README.md b/README.md
index e13ded0cc..a308cff63 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,62 @@
# f1-Yigil
+
+## 이길 로그
-## 이길
+## 프로젝트 기획 및 목적
+
+"이길 로그" 서비스는 지도 기반의 일정 및 장소 공유 플랫폼으로, 사용자들은 여행이나 다양한 활동
+중에 방문한 장소들을 지도 상에 마킹하고 그에 대한 일정을 작성할 수 있습니다. 각 일정에는 사용자가
+촬영한 사진과 함께 제목, 평점, 그리고 간단한 내용을 추가하여 기록할 수 있습니다. 이를 통해
+사용자들은 자신의 경험을 다양한 면에서 기록하고 공유할 수 있습니다.
+
+## 배포 주소
+[이길 로그](https://yigil.co.kr)
+
+## 주요 기능
+
+### 별점 기능
+redis 캐싱을 활용하여 사용자들이 빠르게 볼 수 있도록 구현되어있다. 추후에 batch를 통해 실시간이 아닌
+주기적인 갱신을 진행하려고 합니다. 혹시 여기서 비효율적이거나 더 나은 방법이 있는지 궁금합니다.
+추가적으로 초기 batch 기간을 어느정도로 정해야 하는지 궁금합니다.
+
+### 팔로잉 팔로워 기능
+followerCount와 followingCount를 redis를 활용하여 접근할 수 있도록 캐싱이 적용됩니다.
+
+### 어드민 페이지 기능
+어드민 페이지는 OAuth + 세션방식이 아니라 jwt 토큰 인증방식을 사용합니다.
+
+### 알림 기능
+webflux를 활용하여 SSE 알림을 구현하였습니다.
+
+### 소셜 로그인 기능
+로그인은 카카오 소셜로그인만 있습니다.
+OAuth를 통해 카카오나 구글에서 토큰을 받아서 인증을 하고 추가정보를 받아서 회원가입을 진행하고
+연결 유지는 세션을 통해서 진행합니다.
+
+## 집중적으로 코드리뷰 필요한 부분
+
+### 이벤트 기반 파일 업로드 과정
+파일을 비동기식으로 업로드를 진행하는데 이 부분을 용도에 맞게 적용이 되었는지 궁금합니다.
+고쳐야 하거나 개선을 할 부분이 있는지 궁금합니다.
+
+event -> yigil-api/src/main/java/kr/co/yigil에 file 도메인에 있습니다.
+attachFile -> support안에 있다.
+파일 업로드가 필요하면 파일 업로드 이벤트를 만들고 그 안에 파일 콜백함수를 만듭니다.
+그러면 이벤트가 publisher를 통해 이벤트를 발행하면 event listener에서 s3에 파일
+을 업로드 한 후 파일의 주소를 담은 attachfile을 만들어 callback 함수를 실행해줍니다.
+그 이후에 attachfile을 받아 파일에 저장하거나 spot을 save하거나 update를 수행합니다.
+
+### 게시글 관련 기능
+구조를 먼저 설명 드리면 travel을 상속받는 spot과 course가 있고 travel에는 공통적으로
+게시글의 타이틀이나 내용, 고유 ID, 멤버 정보 등이 있습니다. 그리고 course는 spot들이 모여서 구성되어 있습니다.
+
+Spot에는 좌표값을 Point 객체로 얻고 좌표값에 위치한 장소에 대한 각종 정보를 place 객체로 포함하고 있습니다.
+file의 주소나 정보를 담은 attachfile도 포함하고 있습니다.
+
+나중에는 거리 순으로 근처 spot들을 조회할 예정인데 거리를 구하는 것이 너무 비효율적인 것 같아
+어떻게 처리하면 효율적일지 고민입니다.
+
+### 좋아요 기능
+Redis에 캐싱을 하는 과정에 있어서 동시에 캐싱 요청을 처리했을 때 데이터 정합성이 보장되지 않은 채로
+캐싱될 수 있지 않을까 하는 걱정이 들었습니다.
+ㅇ
diff --git a/admin-frontend/yigil-admin/src/components/snippet/UserInfo.tsx b/admin-frontend/yigil-admin/src/components/snippet/UserInfo.tsx
new file mode 100644
index 000000000..9a74277d4
--- /dev/null
+++ b/admin-frontend/yigil-admin/src/components/snippet/UserInfo.tsx
@@ -0,0 +1,90 @@
+import React, { useState, useEffect } from "react";
+import { useNavigate } from "react-router-dom";
+
+import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
+import { Button } from "@/components/ui/button";
+import { EnvelopeOpenIcon } from "@radix-ui/react-icons";
+import { Link } from "react-router-dom";
+import {
+ Popover,
+ PopoverContent,
+ PopoverTrigger,
+} from "@/components/ui/popover";
+
+interface UserInfoProps {
+ username: string;
+ profile_url: string;
+}
+
+const UserInfo: React.FC = () => {
+ const [user, setUser] = useState(null);
+ const navigate = useNavigate();
+
+ useEffect(() => {
+ const accessToken = getCookie("accessToken");
+
+ if (accessToken) {
+ fetch("https://yigil.co.kr/admin/api/v1/admins/info", {
+ headers: {
+ Authorization: `${accessToken}`,
+ },
+ })
+ .then((response) => response.json())
+ .then((data) => setUser(data))
+ .catch((error) => console.error("Error:", error));
+ }
+ }, []);
+
+ const deleteCookie = (name: string) => {
+ document.cookie = `${name}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;`;
+ };
+
+ const handleLogout = () => {
+ deleteCookie("accessToken");
+ deleteCookie("refreshToken");
+
+ navigate("/admin/login");
+ };
+
+ return (
+
+ {user ? (
+
+
+
+
+ {user.username[0]}
+
+
+
+
+
+
{user.username}
+
+ 관리자님, 환영합니다!
+
+
+
+
+
+
+
+
+ ) : (
+
+
+
+ )}
+
+ );
+};
+
+export default UserInfo;
+
+function getCookie(name: string): string | undefined {
+ const value = `; ${document.cookie}`;
+ const parts = value.split(`; ${name}=`);
+ if (parts.length === 2) return parts.pop()?.split(";").shift();
+}
diff --git a/admin-frontend/yigil-admin/src/components/snippet/withAuthProtection.tsx b/admin-frontend/yigil-admin/src/components/snippet/withAuthProtection.tsx
new file mode 100644
index 000000000..6af7872a6
--- /dev/null
+++ b/admin-frontend/yigil-admin/src/components/snippet/withAuthProtection.tsx
@@ -0,0 +1,28 @@
+import React, { useEffect } from "react";
+import { useNavigate } from "react-router-dom";
+
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
+function withAuthProtection>(
+ WrappedComponent: React.ComponentType
+) {
+ return function ProtectedComponent(props: T) {
+ const navigate = useNavigate();
+
+ useEffect(() => {
+ const accessToken = getCookie("accessToken");
+ if (!accessToken) {
+ navigate("/admin/login");
+ }
+ }, [navigate]);
+
+ return ;
+ };
+}
+
+export default withAuthProtection;
+
+function getCookie(name: string): string | undefined {
+ const value = `; ${document.cookie}`;
+ const parts = value.split(`; ${name}=`);
+ if (parts.length === 2) return parts.pop()?.split(";").shift();
+}
diff --git a/admin-frontend/yigil-admin/vite.config.ts b/admin-frontend/yigil-admin/vite.config.ts
new file mode 100644
index 000000000..7bbdbbeed
--- /dev/null
+++ b/admin-frontend/yigil-admin/vite.config.ts
@@ -0,0 +1,18 @@
+import path from "path";
+import react from "@vitejs/plugin-react";
+import svgr from "vite-plugin-svgr";
+import { defineConfig } from "vite";
+
+// https://vitejs.dev/config/
+export default defineConfig({
+ // server: {
+ // port: 5173,
+ // host: "0.0.0.0",
+ // },
+ plugins: [react(), svgr()],
+ resolve: {
+ alias: {
+ "@": path.resolve(__dirname, "./src"),
+ },
+ },
+});
diff --git a/backend/.gitignore b/backend/.gitignore
index c0e2cb3df..f984fb72e 100644
--- a/backend/.gitignore
+++ b/backend/.gitignore
@@ -169,4 +169,11 @@ gradle-app.setting
# End of https://www.toptal.com/developers/gitignore/api/java,gradle,intellij
-src/test/java/kr/co/yigil/global/config/JasyptApplicationTest.java
\ No newline at end of file
+src/test/java/kr/co/yigil/global/config/JasyptApplicationTest.java
+
+# Q class
+support/src/main/generated/*
+
+place-region-batch/src/main/resources/application.yml
+yigil-api/src/main/resources/application.yml
+yigil-admin/src/main/resources/application.yml
\ No newline at end of file
diff --git a/backend/build.gradle b/backend/build.gradle
index 0710b22d3..8507ad611 100644
--- a/backend/build.gradle
+++ b/backend/build.gradle
@@ -1,10 +1,15 @@
+buildscript {
+ ext {
+ queryDslVersion = "5.1.0"
+ }
+}
+
plugins {
id 'java'
id 'org.springframework.boot' version '3.2.0'
id 'io.spring.dependency-management' version '1.1.4'
id 'org.jetbrains.kotlin.jvm'
id "org.asciidoctor.jvm.convert" version "3.3.2"
- id 'jacoco'
}
group = 'kr.co'
@@ -20,10 +25,6 @@ ext {
set('snippetsDir', file("build/generated-snippets"))
}
-jacoco {
- toolVersion = '0.8.5'
-}
-
allprojects {
repositories {
mavenCentral()
@@ -35,20 +36,16 @@ tasks.named('test') {
useJUnitPlatform()
}
-tasks.withType(Test) {
- jacoco.includeNoLocationClasses = true
-}
kotlin {
jvmToolchain(21)
}
bootJar {
- enabled = false
+ enabled = false
}
jar {
- enabled = true
+ enabled = true
}
-
diff --git a/backend/place-region-batch/Dockerfile b/backend/place-region-batch/Dockerfile
new file mode 100644
index 000000000..694fef1b5
--- /dev/null
+++ b/backend/place-region-batch/Dockerfile
@@ -0,0 +1,9 @@
+FROM openjdk:21-jdk
+
+WORKDIR /app
+
+COPY build/libs/place-region-batch-0.0.1-SNAPSHOT.jar app.jar
+
+EXPOSE 8001
+
+CMD ["java", "-jar", "app.jar"]
diff --git a/backend/place-region-batch/build.gradle b/backend/place-region-batch/build.gradle
new file mode 100644
index 000000000..547a9ad92
--- /dev/null
+++ b/backend/place-region-batch/build.gradle
@@ -0,0 +1,51 @@
+plugins {
+ id 'java'
+ id 'org.springframework.boot' version '3.2.0'
+ id 'io.spring.dependency-management' version '1.1.4'
+ id 'org.jetbrains.kotlin.jvm'
+}
+
+bootJar {
+ mainClass = 'kr.co.yigil.BatchApplication'
+}
+
+group = 'kr.co.yigil'
+version = '0.0.1-SNAPSHOT'
+
+repositories {
+ mavenCentral()
+}
+
+dependencies {
+ implementation project(':support:log')
+ implementation project(':support:domain')
+
+ implementation 'org.springframework.boot:spring-boot-starter-batch'
+
+ compileOnly 'org.projectlombok:lombok'
+ annotationProcessor 'org.projectlombok:lombok'
+
+ implementation 'org.springframework.boot:spring-boot-starter-data-jdbc'
+ implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
+ runtimeOnly 'org.postgresql:postgresql'
+ implementation 'org.postgresql:postgresql'
+ implementation 'org.hibernate:hibernate-core:6.4.0.Final'
+ implementation 'org.hibernate:hibernate-spatial:6.4.0.Final'
+
+ testImplementation 'org.springframework.boot:spring-boot-starter-test'
+
+ implementation 'com.github.gavlyukovskiy:p6spy-spring-boot-starter:1.9.0'
+ implementation 'com.github.maricn:logback-slack-appender:1.6.1'
+
+ implementation 'org.locationtech.jts:jts-core:1.19.0'
+ implementation 'org.locationtech.jts.io:jts-io-common:1.19.0'
+
+ implementation "com.querydsl:querydsl-jpa:${queryDslVersion}:jakarta"
+ annotationProcessor "com.querydsl:querydsl-apt:${queryDslVersion}:jakarta"
+ annotationProcessor "jakarta.annotation:jakarta.annotation-api"
+ annotationProcessor 'jakarta.persistence:jakarta.persistence-api'
+}
+
+test {
+ useJUnitPlatform()
+}
\ No newline at end of file
diff --git a/backend/place-region-batch/src/main/java/kr/co/yigil/BatchApplication.java b/backend/place-region-batch/src/main/java/kr/co/yigil/BatchApplication.java
new file mode 100644
index 000000000..45b23ad19
--- /dev/null
+++ b/backend/place-region-batch/src/main/java/kr/co/yigil/BatchApplication.java
@@ -0,0 +1,11 @@
+package kr.co.yigil;
+
+import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+@SpringBootApplication
+public class BatchApplication {
+ public static void main(String[] args) {
+ SpringApplication.run(BatchApplication.class, args);
+ }
+}
diff --git a/backend/place-region-batch/src/main/java/kr/co/yigil/batch/config/QueryDslConfig.java b/backend/place-region-batch/src/main/java/kr/co/yigil/batch/config/QueryDslConfig.java
new file mode 100644
index 000000000..04a420abd
--- /dev/null
+++ b/backend/place-region-batch/src/main/java/kr/co/yigil/batch/config/QueryDslConfig.java
@@ -0,0 +1,19 @@
+package kr.co.yigil.batch.config;
+
+import com.querydsl.jpa.impl.JPAQueryFactory;
+import jakarta.persistence.EntityManager;
+import lombok.RequiredArgsConstructor;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+@RequiredArgsConstructor
+public class QueryDslConfig {
+
+ private final EntityManager em;
+
+ @Bean
+ public JPAQueryFactory jpaQueryFactory(){
+ return new JPAQueryFactory(em);
+ }
+}
\ No newline at end of file
diff --git a/backend/place-region-batch/src/main/java/kr/co/yigil/batch/job/DemographicPlaceJobConfig.java b/backend/place-region-batch/src/main/java/kr/co/yigil/batch/job/DemographicPlaceJobConfig.java
new file mode 100644
index 000000000..8e0a1b668
--- /dev/null
+++ b/backend/place-region-batch/src/main/java/kr/co/yigil/batch/job/DemographicPlaceJobConfig.java
@@ -0,0 +1,111 @@
+package kr.co.yigil.batch.job;
+
+import java.time.LocalDateTime;
+import java.util.List;
+import java.util.Map;
+import kr.co.yigil.member.Ages;
+import kr.co.yigil.member.Gender;
+import kr.co.yigil.place.domain.DemographicPlace;
+import kr.co.yigil.place.domain.Place;
+import kr.co.yigil.place.infrastructure.DemographicPlaceRepository;
+import kr.co.yigil.travel.infrastructure.SpotRepository;
+import lombok.RequiredArgsConstructor;
+import org.springframework.batch.core.Job;
+import org.springframework.batch.core.Step;
+import org.springframework.batch.core.job.builder.JobBuilder;
+import org.springframework.batch.core.launch.support.RunIdIncrementer;
+import org.springframework.batch.core.repository.JobRepository;
+import org.springframework.batch.core.step.builder.StepBuilder;
+import org.springframework.batch.item.ItemProcessor;
+import org.springframework.batch.item.ItemReader;
+import org.springframework.batch.item.ItemWriter;
+import org.springframework.batch.item.data.RepositoryItemWriter;
+import org.springframework.batch.item.data.builder.RepositoryItemReaderBuilder;
+import org.springframework.batch.item.data.builder.RepositoryItemWriterBuilder;
+import org.springframework.batch.repeat.RepeatStatus;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.domain.Sort.Direction;
+import org.springframework.transaction.PlatformTransactionManager;
+
+@Configuration
+@RequiredArgsConstructor
+public class DemographicPlaceJobConfig {
+
+ private final SpotRepository spotRepository;
+ private final DemographicPlaceRepository demographicPlaceRepository;
+
+ @Bean
+ public Job demographicPlaceJob(
+ JobRepository jobRepository,
+ Step calculateDemographicPlacesStep,
+ Step clearDemographicPlacesStep
+ ) {
+ return new JobBuilder("demographicPlaceJob", jobRepository)
+ .start(clearDemographicPlacesStep)
+ .next(calculateDemographicPlacesStep)
+ .incrementer(new RunIdIncrementer())
+ .build();
+ }
+
+ @Bean
+ public Step clearDemographicPlacesStep(JobRepository jobRepository, PlatformTransactionManager platformTransactionManager) {
+ return new StepBuilder("clearDemographicPlacesStep", jobRepository)
+ .tasklet((contribution, chunkContext) -> {
+ demographicPlaceRepository.deleteAll();
+ return RepeatStatus.FINISHED;
+ }, platformTransactionManager)
+ .build();
+ }
+
+ @Bean
+ public Step calculateDemographicPlacesStep(
+ JobRepository jobRepository,
+ PlatformTransactionManager platformTransactionManager,
+ ItemReader