diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index ba722fe..14a8948 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -9,12 +9,13 @@ on: env: # Backend paths BACKEND_JAR_PATH: build/libs/ - REMOTE_BACKEND_PATH: "~/mywiki" - + JAR_FILENAME: mywiki.jar + REMOTE_BACKEND_PATH: "~/mywiki/backend" + # Frontend paths FRONTEND_SRC_PATH: ./frontend FRONTEND_BUILD_PATH: frontend/build - REMOTE_FRONTEND_PATH: "/var/www/nginx" + REMOTE_FRONTEND_PATH: "~/mywiki/frontend" jobs: deploy-backend: @@ -39,12 +40,6 @@ jobs: - name: Build Backend JAR run: ./gradlew bootJar - - name: Find JAR file name - id: find_jar - run: | - JAR_FILE=$(find ${{ env.BACKEND_JAR_PATH }} -name "*.jar" | head -n 1) - echo "jar_file=$JAR_FILE" >> $GITHUB_OUTPUT - - name: Create backend .env file run: | echo "DB_HOST=${{ secrets.DB_HOST }}" > .env @@ -52,36 +47,32 @@ jobs: echo "DB_PASSWORD=${{ secrets.DB_PASSWORD }}" >> .env echo "GOOGLE_CLIENT_ID=${{ secrets.GOOGLE_CLIENT_ID }}" >> .env echo "GOOGLE_CLIENT_SECRET=${{ secrets.GOOGLE_CLIENT_SECRET }}" >> .env - echo "OAUTH2_REDIRECT_URI=http://${{ secrets.SERVER_HOST }}" >> .env - - - name: Create remote directory - uses: appleboy/ssh-action@master - with: - host: ${{ secrets.SERVER_HOST }} - username: ${{ secrets.SERVER_USERNAME }} - key: ${{ secrets.SSH_SECRET }} - script: mkdir -p ${{ env.REMOTE_BACKEND_PATH }} + echo "OAUTH2_REDIRECT_URI=${{ vars.OAUTH2_REDIRECT_URI }}" >> .env + echo "CORS_ALLOWED_ORIGINS=${{ vars.CORS_ALLOWED_ORIGINS }}" >> .env - name: SCP JAR file - uses: appleboy/scp-action@master + uses: appleboy/scp-action@v1 with: host: ${{ secrets.SERVER_HOST }} username: ${{ secrets.SERVER_USERNAME }} key: ${{ secrets.SSH_SECRET }} - source: "${{ steps.find_jar.outputs.jar_file }}" - target: "${{ env.REMOTE_BACKEND_PATH }}/app.jar" + source: "${{ env.BACKEND_JAR_PATH }}${{ env.JAR_FILENAME }}" + target: "${{ env.REMOTE_BACKEND_PATH }}" + strip_components: 2 + overwrite: true - name: SCP .env file - uses: appleboy/scp-action@master + uses: appleboy/scp-action@v1 with: host: ${{ secrets.SERVER_HOST }} username: ${{ secrets.SERVER_USERNAME }} key: ${{ secrets.SSH_SECRET }} source: ".env" target: "${{ env.REMOTE_BACKEND_PATH }}" + overwrite: true - name: Execute remote deploy script - uses: appleboy/ssh-action@master + uses: appleboy/ssh-action@v1 with: host: ${{ secrets.SERVER_HOST }} username: ${{ secrets.SERVER_USERNAME }} @@ -89,11 +80,17 @@ jobs: script: | cd ${{ env.REMOTE_BACKEND_PATH }} echo "Stopping existing application..." - pgrep -f app.jar | xargs -r kill -15 || true - sleep 5 + # PID 파일이 있으면, 해당 파일의 PID를 읽어 프로세스를 종료합니다. + if [ -f ./mywiki.pid ]; then + kill -15 $(cat ./mywiki.pid) || true + rm ./mywiki.pid + sleep 5 + fi + echo "Starting new application..." set -o allexport; source .env; set +o allexport - nohup java -jar app.jar > app.log 2>&1 & + # 새 애플리케이션을 백그라운드로 실행하고, 프로세스 ID를 app.pid 파일에 저장합니다. + nohup java -jar ${{ env.JAR_FILENAME }} > app.log 2>&1 & echo $! > ./mywiki.pid deploy-frontend: name: Deploy Frontend @@ -119,7 +116,7 @@ jobs: npm run build - name: Prepare remote directory - uses: appleboy/ssh-action@master + uses: appleboy/ssh-action@v1 with: host: ${{ secrets.SERVER_HOST }} username: ${{ secrets.SERVER_USERNAME }} @@ -130,7 +127,7 @@ jobs: rm -rf ${{ env.REMOTE_FRONTEND_PATH }}/* - name: SCP Frontend files - uses: appleboy/scp-action@master + uses: appleboy/scp-action@v1 with: host: ${{ secrets.SERVER_HOST }} username: ${{ secrets.SERVER_USERNAME }} diff --git a/build.gradle.kts b/build.gradle.kts index f51c604..3665ae3 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -64,3 +64,7 @@ kotlin { tasks.withType { useJUnitPlatform() } + +tasks.withType { + archiveFileName.set("mywiki.jar") +} diff --git a/frontend/public/index.html b/frontend/public/index.html index aa069f2..032e634 100644 --- a/frontend/public/index.html +++ b/frontend/public/index.html @@ -24,7 +24,7 @@ work correctly both with client-side routing and a non-root public URL. Learn how to configure a non-root public URL by running `npm run build`. --> - React App + My Wiki diff --git a/frontend/public/manifest.json b/frontend/public/manifest.json index 080d6c7..ab24385 100644 --- a/frontend/public/manifest.json +++ b/frontend/public/manifest.json @@ -1,6 +1,6 @@ { - "short_name": "React App", - "name": "Create React App Sample", + "short_name": "My Wiki", + "name": "집단지성을 이용한 거대하고 효율적인 지식 저장소 구축 프로젝트", "icons": [ { "src": "favicon.ico", diff --git a/frontend/src/api/apiClient.ts b/frontend/src/api/apiClient.ts index db84b7b..ea3ec67 100644 --- a/frontend/src/api/apiClient.ts +++ b/frontend/src/api/apiClient.ts @@ -1,7 +1,7 @@ import axios from 'axios'; const apiClient = axios.create({ - baseURL: process.env.REACT_APP_API_BASE_URL || 'http://localhost:8080', + baseURL: process.env.REACT_APP_API_BASE_URL || '', withCredentials: true, // 세션 쿠키 사용을 위해 필수 }); diff --git a/frontend/src/pages/LoginPage.tsx b/frontend/src/pages/LoginPage.tsx index 78d4cb6..0d1bbab 100644 --- a/frontend/src/pages/LoginPage.tsx +++ b/frontend/src/pages/LoginPage.tsx @@ -7,9 +7,8 @@ import './LoginPage.css'; const LoginPage: React.FC = () => { const handleLogin = () => { - if (process.env.REACT_APP_API_BASE_URL) { - window.location.href = `${process.env.REACT_APP_API_BASE_URL}/oauth2/authorization/google`; - } + const baseUrl = process.env.REACT_APP_API_BASE_URL || ''; + window.location.href = `${baseUrl}/oauth2/authorization/google`; }; return ( diff --git a/nginx-prod.conf b/nginx-prod.conf index cefcdb2..f8fb4ad 100644 --- a/nginx-prod.conf +++ b/nginx-prod.conf @@ -26,8 +26,8 @@ server { try_files $uri $uri/ /index.html; } - # API 요청을 백엔드 서버(localhost:8080)로 전달 - location /api/ { + # API, 인증 요청을 백엔드 서버(localhost:8080)로 전달 + location ~ ^/(api|oauth2|login/oauth2) { proxy_pass http://localhost:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; diff --git a/src/main/kotlin/com/yhproject/mywiki/config/SecurityConfig.kt b/src/main/kotlin/com/yhproject/mywiki/config/SecurityConfig.kt index 7c1bf19..e43dac9 100644 --- a/src/main/kotlin/com/yhproject/mywiki/config/SecurityConfig.kt +++ b/src/main/kotlin/com/yhproject/mywiki/config/SecurityConfig.kt @@ -17,7 +17,8 @@ import org.springframework.web.cors.UrlBasedCorsConfigurationSource @EnableWebSecurity class SecurityConfig( private val customOAuth2UserService: CustomOAuth2UserService, - @Value("\${app.oauth2.redirect-uri}") private val redirectUri: String + @Value("\${app.oauth2.redirect-uri}") private val redirectUri: String, + @Value("\${app.cors.allowed-origins}") private val allowedOrigins: String ) { @Bean @@ -56,7 +57,7 @@ class SecurityConfig( @Bean fun corsConfigurationSource(): CorsConfigurationSource { val configuration = CorsConfiguration() - configuration.allowedOrigins = listOf("http://localhost:3000") + configuration.allowedOrigins = allowedOrigins.split(",") configuration.allowedMethods = listOf("GET", "POST", "PUT", "DELETE", "OPTIONS") configuration.allowedHeaders = listOf("*") configuration.allowCredentials = true diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 9c43757..42ec3b4 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -1,9 +1,12 @@ +server: + forward-headers-strategy: framework + spring: application: name: mywiki datasource: - url: jdbc:mysql://localhost:3306/mywiki + url: jdbc:mysql://${DB_HOST:localhost}:3306/mywiki username: ${DB_USERNAME:mywiki} password: ${DB_PASSWORD:1234} driver-class-name: com.mysql.cj.jdbc.Driver @@ -30,3 +33,5 @@ spring: app: oauth2: redirect-uri: ${OAUTH2_REDIRECT_URI:http://localhost:3000} + cors: + allowed-origins: ${CORS_ALLOWED_ORIGINS:http://localhost:3000} diff --git a/src/test/resources/application.yml b/src/test/resources/application.yml index b35908a..785b267 100644 --- a/src/test/resources/application.yml +++ b/src/test/resources/application.yml @@ -25,3 +25,5 @@ spring: app: oauth2: redirect-uri: http://localhost:3000 + cors: + allowed-origins: http://localhost:3000