From ea570b47b0ef46017d9a6ab1d28d18b2593add83 Mon Sep 17 00:00:00 2001 From: pilltong22 Date: Fri, 2 Jan 2026 17:06:56 +0900 Subject: [PATCH 01/56] =?UTF-8?q?build.gradle=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 4 ++-- .../sero/employee/command/domain/aggregate/Employee.java | 6 +++++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index 9688dd6b..4cc34a5d 100644 --- a/build.gradle +++ b/build.gradle @@ -39,8 +39,8 @@ dependencies { annotationProcessor 'org.projectlombok:lombok' /* Database */ - runtimeOnly 'com.mysql:mysql-connector-j' -// runtimeOnly 'org.mariadb.jdbc:mariadb-java-client' + // runtimeOnly 'com.mysql:mysql-connector-j' + runtimeOnly 'org.mariadb.jdbc:mariadb-java-client' /* Swagger OpenAPI */ implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.8.14' diff --git a/src/main/java/com/werp/sero/employee/command/domain/aggregate/Employee.java b/src/main/java/com/werp/sero/employee/command/domain/aggregate/Employee.java index 766b61c2..73d5ea62 100644 --- a/src/main/java/com/werp/sero/employee/command/domain/aggregate/Employee.java +++ b/src/main/java/com/werp/sero/employee/command/domain/aggregate/Employee.java @@ -1,5 +1,6 @@ package com.werp.sero.employee.command.domain.aggregate; +import com.fasterxml.jackson.annotation.JsonIgnore; // [추가] JSON 변환 시 순환참조 방지 import jakarta.persistence.*; import lombok.Getter; import lombok.NoArgsConstructor; @@ -9,6 +10,7 @@ @NoArgsConstructor @Entity public class Employee { + @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private int id; @@ -43,7 +45,9 @@ public class Employee { @Column(name = "created_at", nullable = false) private String createdAt; - @ManyToOne + // ▼▼▼ [핵심 수정 부분] ▼▼▼ + @ManyToOne(fetch = FetchType.LAZY) // 1. 지연 로딩: 필요할 때만 조회 (쿼리 폭탄 방지) @JoinColumn(name = "dept_id") + // @JsonIgnore // 2. JSON 무시: 직렬화 시 부서 정보를 쳐다보지 않음 (무한 루프 방지) private Department department; } \ No newline at end of file From 8bd8d377771f597da7086d9a76285123fecfaebe Mon Sep 17 00:00:00 2001 From: pilltong22 Date: Fri, 2 Jan 2026 17:14:05 +0900 Subject: [PATCH 02/56] =?UTF-8?q?@JsonIgnore=20=EC=A3=BC=EC=84=9D=20?= =?UTF-8?q?=ED=95=B4=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../werp/sero/employee/command/domain/aggregate/Employee.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/werp/sero/employee/command/domain/aggregate/Employee.java b/src/main/java/com/werp/sero/employee/command/domain/aggregate/Employee.java index 73d5ea62..b0ebb9dc 100644 --- a/src/main/java/com/werp/sero/employee/command/domain/aggregate/Employee.java +++ b/src/main/java/com/werp/sero/employee/command/domain/aggregate/Employee.java @@ -48,6 +48,6 @@ public class Employee { // ▼▼▼ [핵심 수정 부분] ▼▼▼ @ManyToOne(fetch = FetchType.LAZY) // 1. 지연 로딩: 필요할 때만 조회 (쿼리 폭탄 방지) @JoinColumn(name = "dept_id") - // @JsonIgnore // 2. JSON 무시: 직렬화 시 부서 정보를 쳐다보지 않음 (무한 루프 방지) + @JsonIgnore // 2. JSON 무시: 직렬화 시 부서 정보를 쳐다보지 않음 (무한 루프 방지) private Department department; } \ No newline at end of file From 54e92af8310e609a400a3228c020ac8f57d5613e Mon Sep 17 00:00:00 2001 From: pilltong22 Date: Fri, 2 Jan 2026 17:20:14 +0900 Subject: [PATCH 03/56] =?UTF-8?q?=EC=9E=AC=ED=8A=B8=EB=A6=AC=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .ebextensions/app.config | 12 +++ .github/workflows/deploy.yml | 157 +++++++++++++++++++++++++++++++++++ .platform/nginx.conf | 59 +++++++++++++ 3 files changed, 228 insertions(+) create mode 100644 .ebextensions/app.config create mode 100644 .github/workflows/deploy.yml create mode 100644 .platform/nginx.conf diff --git a/.ebextensions/app.config b/.ebextensions/app.config new file mode 100644 index 00000000..de8541c3 --- /dev/null +++ b/.ebextensions/app.config @@ -0,0 +1,12 @@ +files: + "/sbin/appstart" : + mode: "000755" + owner: webapp + group: webapp + content: | + #!/usr/bin/env bash + JAR_PATH=/var/app/current/application.jar + + # run app + killall java + java -Dfile.encoding=UTF-8 -jar $JAR_PATH diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml new file mode 100644 index 00000000..45df37a5 --- /dev/null +++ b/.github/workflows/deploy.yml @@ -0,0 +1,157 @@ +name: Deploy to Elastic Beanstalk + +# GitHub 저장소 읽기 권한 설정 +permissions: + contents: read + +# main 브랜치에 push 시 워크플로우 실행 +on: + push: + branches: + - main + +# 워크플로우 실행 작업 정의 +jobs: + deploy: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up JDK 17 + uses: actions/setup-java@v4 + with: + java-version: '17' + distribution: 'corretto' + + - name: Grant execute permission for gradlew + run: chmod +x ./gradlew + shell: bash + + # envsubst 설치 + - name: Install envsubst + run: sudo apt-get install -y gettext + + # 배포용 application.yml 파일을 환경 변수로 생성 + - name: Create application.yml.template + run: | + mkdir -p src/main/resources + cat > src/main/resources/application.yml.template <<'EOL' + server: + port: 5000 + + spring: + datasource: + driver-class-name: org.mariadb.jdbc.Driver + url: ${SPRING_DATASOURCE_URL} + username: ${SPRING_DATASOURCE_USERNAME} + password: ${SPRING_DATASOURCE_PASSWORD} + jpa: + hibernate: + ddl-auto: none + show-sql: true + database: mysql + properties: + hibernate: + format_sql: true + + # Redis 설정 (클러스터 + SSL) + data: + redis: + cluster: + max-redirects: 3 + nodes: ${REDIS_HOST}:${REDIS_PORT} + ssl: + enabled: true + + # AWS S3 설정 (spring 하위로 통합됨) + cloud: + aws: + s3: + bucket: ${AWS_S3_BUCKET} + region: + static: ${AWS_REGION} + credentials: + access-key: ${AWS_ACCESS_KEY} + secret-key: ${AWS_SECRET_KEY} + + jwt: + secret-key: ${JWT_SECRET} + access-token-expiration-time: ${JWT_EXPIRATION} + refresh-token-expiration-time: ${JWT_REFRESH_TOKEN_EXPIRATION_TIME} + + # MyBatis 설정 + mybatis: + mapper-locations: classpath:com/werp/sero/**/query/dao/*.xml + type-aliases-package: com.werp.sero.**.dto + configuration: + map-underscore-to-camel-case: true + EOL + + # envsubst는 환경 변수를 치환해주는 유틸리티로, 템플릿 파일의 ${VARIABLE} 형태의 변수를 실제 환경 변수 값으로 대체 + - name: Set Yaml + run: | + echo "DEBUG: Checking if RDS_PASSWORD is set..." + if [ -z "$SPRING_DATASOURCE_PASSWORD" ]; then + echo "ERROR: SPRING_DATASOURCE_PASSWORD is empty!" + else + echo "SUCCESS: SPRING_DATASOURCE_PASSWORD is set (length: ${#SPRING_DATASOURCE_PASSWORD})" + fi + envsubst < src/main/resources/application.yml.template > src/main/resources/application.yml + echo "Generated application.yml:" + cat src/main/resources/application.yml + env: + SPRING_DATASOURCE_URL: jdbc:mariadb://${{ secrets.RDS_HOSTNAME }}:${{ secrets.RDS_PORT }}/${{ secrets.RDS_DB_NAME }} + SPRING_DATASOURCE_USERNAME: ${{ secrets.RDS_USERNAME }} + SPRING_DATASOURCE_PASSWORD: ${{ secrets.RDS_PASSWORD }} + # REDIS_HOST는 포트 번호 없이 주소만 입력되어 있어야 합니다. + REDIS_HOST: ${{ secrets.REDIS_HOST }} + REDIS_PORT: ${{ secrets.REDIS_PORT }} + JWT_SECRET: ${{ secrets.JWT_SECRET }} + JWT_EXPIRATION: ${{ secrets.JWT_EXPIRATION }} + JWT_REFRESH_TOKEN_EXPIRATION_TIME: ${{ secrets.JWT_REFRESH_TOKEN_EXPIRATION_TIME }} + AWS_S3_BUCKET: ${{ secrets.AWS_S3_BUCKET }} + AWS_REGION: ${{ secrets.AWS_REGION }} + AWS_ACCESS_KEY: ${{ secrets.AWS_ACCESS_KEY }} + AWS_SECRET_KEY: ${{ secrets.AWS_SECRET_KEY }} + + ################################################# + + - name: Build with Gradle + run: ./gradlew clean build -x test + shell: bash + + - name: Get current time + uses: 1466587594/get-current-time@v2 + id: current-time + with: + format: YYYY-MM-DDTHH-mm-ss + utcOffset: "+09:00" + + - name: Show Current Time + run: echo "CurrentTime=${{steps.current-time.outputs.formattedTime}}" + shell: bash + + ############################################### + - name: Generate deployment package + run: | + mkdir -p deploy + cp build/libs/*.jar deploy/application.jar + cp Procfile deploy/Procfile + cp -r .ebextensions deploy/.ebextensions + cp -r .platform deploy/.platform + cd deploy && zip -r deploy.zip . + + - name: Deploy to Elastic Beanstalk + uses: einaregilsson/beanstalk-deploy@v22 + with: + aws_access_key: ${{ secrets.AWS_ACCESS_KEY_ID }} + aws_secret_key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + application_name: sero-b + environment_name: Sero-b-env + version_label: github-action-${{steps.current-time.outputs.formattedTime}} + region: ap-northeast-2 + deployment_package: deploy/deploy.zip + use_existing_version_if_available: false + wait_for_deployment: true + wait_for_environment_recovery: 300 \ No newline at end of file diff --git a/.platform/nginx.conf b/.platform/nginx.conf new file mode 100644 index 00000000..8dfebfae --- /dev/null +++ b/.platform/nginx.conf @@ -0,0 +1,59 @@ +user nginx; +error_log /var/log/nginx/error.log warn; +pid /var/run/nginx.pid; +worker_processes auto; +worker_rlimit_nofile 33282; + +events { + use epoll; + worker_connections 1024; + multi_accept on; +} + +http { + include /etc/nginx/mime.types; + default_type application/octet-stream; + + log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" "$http_x_forwarded_for"'; + + include conf.d/*.conf; + + map $http_upgrade $connection_upgrade { + default "upgrade"; + } + + upstream springboot { + server 127.0.0.1:5000; // 5000번으로 돌고 있는 백엔드 서버를 인지해라! + keepalive 1024; + } + + server { + listen 80 default_server; + listen [::]:80 default_server; + + location / { + proxy_pass http://springboot; + proxy_http_version 1.1; + proxy_set_header Connection $connection_upgrade; + proxy_set_header Upgrade $http_upgrade; + + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; // 로그분석 (어디서 유입, 차단하고 싶은 사람) + proxy_set_header X-Forwarded-Proto $scheme; + proxy_redirect off; + } + + access_log /var/log/nginx/access.log main; + + client_header_timeout 60; + client_body_timeout 60; + keepalive_timeout 60; + gzip off; + + # Include the Elastic Beanstalk generated locations + include conf.d/elasticbeanstalk/healthd.conf; + } +} \ No newline at end of file From 7684a03c62818883990e3ff702181b66b4743e95 Mon Sep 17 00:00:00 2001 From: pilltong22 Date: Fri, 2 Jan 2026 17:28:37 +0900 Subject: [PATCH 04/56] =?UTF-8?q?plain=20jar=20=EC=83=9D=EC=84=B1=20?= =?UTF-8?q?=EB=B9=84=ED=99=9C=EC=84=B1=ED=99=94=20(bootJar=EB=A7=8C=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/deploy.yml | 2 +- build.gradle | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 45df37a5..42e8a1ac 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -136,7 +136,7 @@ jobs: - name: Generate deployment package run: | mkdir -p deploy - cp build/libs/*.jar deploy/application.jar + cp build/libs/application.jar deploy/application.jar cp Procfile deploy/Procfile cp -r .ebextensions deploy/.ebextensions cp -r .platform deploy/.platform diff --git a/build.gradle b/build.gradle index 4cc34a5d..de3b6c8f 100644 --- a/build.gradle +++ b/build.gradle @@ -76,4 +76,14 @@ dependencies { tasks.named('test') { useJUnitPlatform() +} + +// plain jar 생성 비활성화 (bootJar만 생성) +jar { + enabled = false +} + +// bootJar 파일명을 application.jar로 설정 +bootJar { + archiveFileName = 'application.jar' } \ No newline at end of file From 3c1dc7c30ef109201ee331a57aebef2f31440a5b Mon Sep 17 00:00:00 2001 From: pilltong22 Date: Fri, 2 Jan 2026 17:32:14 +0900 Subject: [PATCH 05/56] =?UTF-8?q?Procfile=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Procfile | 1 + 1 file changed, 1 insertion(+) create mode 100644 Procfile diff --git a/Procfile b/Procfile new file mode 100644 index 00000000..ae5304ad --- /dev/null +++ b/Procfile @@ -0,0 +1 @@ +web: java -jar application.jar \ No newline at end of file From 018879ef2f6f31c15dba4021925b67523afc0ed9 Mon Sep 17 00:00:00 2001 From: pilltong22 Date: Fri, 2 Jan 2026 17:44:27 +0900 Subject: [PATCH 06/56] =?UTF-8?q?fix:=20=ED=94=84=EB=A1=A0=ED=8A=B8?= =?UTF-8?q?=EC=97=94=EB=93=9C=20ALB=20=EC=A3=BC=EC=86=8C=20CORS=20?= =?UTF-8?q?=ED=97=88=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/werp/sero/config/CorsConfig.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/werp/sero/config/CorsConfig.java b/src/main/java/com/werp/sero/config/CorsConfig.java index 88b026bf..cf22fd04 100644 --- a/src/main/java/com/werp/sero/config/CorsConfig.java +++ b/src/main/java/com/werp/sero/config/CorsConfig.java @@ -14,7 +14,10 @@ public class CorsConfig { public CorsConfigurationSource corsConfigurationSource() { CorsConfiguration configuration = new CorsConfiguration(); - configuration.setAllowedOrigins(List.of("http://localhost:5173")); + configuration.setAllowedOrigins(List.of( + "http://localhost:5173", + "http://sero-f-alb-2092902385.ap-northeast-2.elb.amazonaws.com" + )); configuration.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS")); configuration.setAllowedHeaders(List.of("*")); configuration.setAllowCredentials(true); From e74e7a1f9c77bf54d4fac450f689180eb99166ee Mon Sep 17 00:00:00 2001 From: pilltong22 Date: Sat, 3 Jan 2026 15:01:47 +0900 Subject: [PATCH 07/56] Update CorsConfig.java --- src/main/java/com/werp/sero/config/CorsConfig.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/com/werp/sero/config/CorsConfig.java b/src/main/java/com/werp/sero/config/CorsConfig.java index cf22fd04..f1d0a989 100644 --- a/src/main/java/com/werp/sero/config/CorsConfig.java +++ b/src/main/java/com/werp/sero/config/CorsConfig.java @@ -18,6 +18,7 @@ public CorsConfigurationSource corsConfigurationSource() { "http://localhost:5173", "http://sero-f-alb-2092902385.ap-northeast-2.elb.amazonaws.com" )); + configuration.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS")); configuration.setAllowedHeaders(List.of("*")); configuration.setAllowCredentials(true); From b43463ca9b0faa192c29a1389cbc91442cc1d01f Mon Sep 17 00:00:00 2001 From: pilltong22 <106594632+pilltong22@users.noreply.github.com> Date: Sun, 4 Jan 2026 23:40:02 +0900 Subject: [PATCH 08/56] =?UTF-8?q?develop=20=EB=A8=B8=EC=A7=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../werp/sero/production/command/infrastructure/service/.gitkeep | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 src/main/java/com/werp/sero/production/command/infrastructure/service/.gitkeep diff --git a/src/main/java/com/werp/sero/production/command/infrastructure/service/.gitkeep b/src/main/java/com/werp/sero/production/command/infrastructure/service/.gitkeep deleted file mode 100644 index e69de29b..00000000 From e20bf3a27db69c80e8d67e0d4c69eeba97685a6c Mon Sep 17 00:00:00 2001 From: pilltong22 Date: Mon, 5 Jan 2026 09:26:31 +0900 Subject: [PATCH 09/56] =?UTF-8?q?=EC=9E=AC=EB=B0=B0=ED=8F=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/deploy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 42e8a1ac..a92cc798 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -32,7 +32,7 @@ jobs: - name: Install envsubst run: sudo apt-get install -y gettext - # 배포용 application.yml 파일을 환경 변수로 생성 + # 배포용 application.yml 파일을 환경 변수로 생성! - name: Create application.yml.template run: | mkdir -p src/main/resources From 0d236a290aab2a25a6f5343f954ec5ed2d392e9b Mon Sep 17 00:00:00 2001 From: pilltong22 Date: Mon, 5 Jan 2026 09:55:09 +0900 Subject: [PATCH 10/56] =?UTF-8?q?codeDeploy=20=EC=84=A4=EC=A0=95,=20Agent?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/deploy.yml | 62 ++++++++++++++++++++++++------------ appspec.yml | 33 +++++++++++++++++++ scripts/health-check.sh | 38 ++++++++++++++++++++++ scripts/set-permissions.sh | 22 +++++++++++++ scripts/start.sh | 44 +++++++++++++++++++++++++ scripts/stop.sh | 38 ++++++++++++++++++++++ 6 files changed, 216 insertions(+), 21 deletions(-) create mode 100644 appspec.yml create mode 100644 scripts/health-check.sh create mode 100644 scripts/set-permissions.sh create mode 100644 scripts/start.sh create mode 100644 scripts/stop.sh diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index a92cc798..75c782f3 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -1,4 +1,4 @@ -name: Deploy to Elastic Beanstalk +name: Deploy to EC2 with CodeDeploy # GitHub 저장소 읽기 권한 설정 permissions: @@ -133,25 +133,45 @@ jobs: shell: bash ############################################### - - name: Generate deployment package + # CodeDeploy 배포 단계 + ############################################### + + # 1. 배포 패키지 생성 (appspec.yml 포함) + - name: Make deployment package run: | - mkdir -p deploy - cp build/libs/application.jar deploy/application.jar - cp Procfile deploy/Procfile - cp -r .ebextensions deploy/.ebextensions - cp -r .platform deploy/.platform - cd deploy && zip -r deploy.zip . - - - name: Deploy to Elastic Beanstalk - uses: einaregilsson/beanstalk-deploy@v22 + echo "> 배포 패키지 생성 중..." + zip -r sero-deploy-${{steps.current-time.outputs.formattedTime}}.zip \ + appspec.yml \ + scripts/ \ + build/libs/*.jar \ + -x "*.git*" "build/libs/*plain*" + + echo "> 생성된 파일 확인" + ls -lh sero-deploy-${{steps.current-time.outputs.formattedTime}}.zip + + # 2. AWS 자격 증명 설정 + - name: Configure AWS credentials + uses: aws-actions/configure-aws-credentials@v4 with: - aws_access_key: ${{ secrets.AWS_ACCESS_KEY_ID }} - aws_secret_key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - application_name: sero-b - environment_name: Sero-b-env - version_label: github-action-${{steps.current-time.outputs.formattedTime}} - region: ap-northeast-2 - deployment_package: deploy/deploy.zip - use_existing_version_if_available: false - wait_for_deployment: true - wait_for_environment_recovery: 300 \ No newline at end of file + aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} + aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + aws-region: ap-northeast-2 + + # 3. S3에 배포 패키지 업로드 + - name: Upload to S3 + run: | + echo "> S3에 배포 패키지 업로드 중..." + aws s3 cp \ + sero-deploy-${{steps.current-time.outputs.formattedTime}}.zip \ + s3://elasticbeanstalk-ap-northeast-2-257394460879/codedeploy/ + + # 4. CodeDeploy 배포 생성 + - name: Deploy with CodeDeploy + run: | + echo "> CodeDeploy 배포 시작..." + aws deploy create-deployment \ + --application-name sero-backend-app \ + --deployment-config-name CodeDeployDefault.AllAtOnce \ + --deployment-group-name sero-backend-dg \ + --s3-location bucket=elasticbeanstalk-ap-northeast-2-257394460879,key=codedeploy/sero-deploy-${{steps.current-time.outputs.formattedTime}}.zip,bundleType=zip \ + --description "GitHub Actions deployment at ${{steps.current-time.outputs.formattedTime}}" \ No newline at end of file diff --git a/appspec.yml b/appspec.yml new file mode 100644 index 00000000..ecd34f0f --- /dev/null +++ b/appspec.yml @@ -0,0 +1,33 @@ +version: 0.0 +os: linux +files: + - source: / + destination: /home/ec2-user/app/ + overwrite: yes + +permissions: + - object: / + pattern: "**" + owner: ec2-user + group: ec2-user + +hooks: + BeforeInstall: + - location: scripts/stop.sh + timeout: 60 + runas: ec2-user + + AfterInstall: + - location: scripts/set-permissions.sh + timeout: 60 + runas: ec2-user + + ApplicationStart: + - location: scripts/start.sh + timeout: 120 + runas: ec2-user + + ValidateService: + - location: scripts/health-check.sh + timeout: 60 + runas: ec2-user diff --git a/scripts/health-check.sh b/scripts/health-check.sh new file mode 100644 index 00000000..bd8ba949 --- /dev/null +++ b/scripts/health-check.sh @@ -0,0 +1,38 @@ +#!/bin/bash + +REPOSITORY=/home/ec2-user/app +PORT=5000 + +echo "> [$(date)] 애플리케이션 헬스체크 시작" >> $REPOSITORY/deploy.log + +# 최대 30초 동안 헬스체크 재시도 +for i in {1..30}; do + # 프로세스 실행 확인 + if ! pgrep -f 'java.*application.jar' > /dev/null; then + echo "> [$(date)] ERROR: 애플리케이션 프로세스가 실행 중이 아닙니다." >> $REPOSITORY/deploy.log + exit 1 + fi + + # HTTP 헬스체크 (Spring Boot Actuator가 있다면 /actuator/health, 없으면 루트 경로) + HTTP_STATUS=$(curl -s -o /dev/null -w "%{http_code}" http://localhost:$PORT/actuator/health 2>/dev/null) + + # Actuator가 없는 경우 루트 경로로 재시도 + if [ "$HTTP_STATUS" == "000" ] || [ "$HTTP_STATUS" == "404" ]; then + HTTP_STATUS=$(curl -s -o /dev/null -w "%{http_code}" http://localhost:$PORT/ 2>/dev/null) + fi + + # 200-299 또는 300-399 응답이면 성공 + if [ "$HTTP_STATUS" -ge 200 ] && [ "$HTTP_STATUS" -lt 400 ]; then + echo "> [$(date)] 헬스체크 성공 (HTTP $HTTP_STATUS)" >> $REPOSITORY/deploy.log + echo "> [$(date)] 배포 완료!" >> $REPOSITORY/deploy.log + exit 0 + fi + + echo "> [$(date)] 헬스체크 재시도 중... ($i/30) - HTTP $HTTP_STATUS" >> $REPOSITORY/deploy.log + sleep 1 +done + +# 30초 동안 성공하지 못하면 실패 +echo "> [$(date)] ERROR: 헬스체크 실패 - 애플리케이션이 정상적으로 시작되지 않았습니다." >> $REPOSITORY/deploy.log +echo "> [$(date)] 로그 확인: tail -n 100 $REPOSITORY/logs/application.log" >> $REPOSITORY/deploy.log +exit 1 diff --git a/scripts/set-permissions.sh b/scripts/set-permissions.sh new file mode 100644 index 00000000..fca5eedf --- /dev/null +++ b/scripts/set-permissions.sh @@ -0,0 +1,22 @@ +#!/bin/bash + +REPOSITORY=/home/ec2-user/app + +echo "> [$(date)] 파일 권한 설정 시작" >> $REPOSITORY/deploy.log + +# scripts 폴더의 모든 .sh 파일에 실행 권한 부여 +chmod +x $REPOSITORY/scripts/*.sh + +# jar 파일 찾기 +JAR_FILE=$(find $REPOSITORY/build/libs -name "*.jar" ! -name "*plain*" | head -n 1) + +if [ -n "$JAR_FILE" ]; then + chmod +x $JAR_FILE + echo "> [$(date)] JAR 파일 실행 권한 설정: $JAR_FILE" >> $REPOSITORY/deploy.log +else + echo "> [$(date)] WARNING: JAR 파일을 찾을 수 없습니다." >> $REPOSITORY/deploy.log +fi + +echo "> [$(date)] 파일 권한 설정 완료" >> $REPOSITORY/deploy.log + +exit 0 diff --git a/scripts/start.sh b/scripts/start.sh new file mode 100644 index 00000000..19ce4ad1 --- /dev/null +++ b/scripts/start.sh @@ -0,0 +1,44 @@ +#!/bin/bash + +REPOSITORY=/home/ec2-user/app + +echo "> [$(date)] 애플리케이션 시작 준비" >> $REPOSITORY/deploy.log + +# JAR 파일 찾기 (plain.jar 제외) +JAR_FILE=$(find $REPOSITORY/build/libs -name "*.jar" ! -name "*plain*" | head -n 1) + +if [ -z "$JAR_FILE" ]; then + echo "> [$(date)] ERROR: JAR 파일을 찾을 수 없습니다." >> $REPOSITORY/deploy.log + exit 1 +fi + +JAR_NAME=$(basename $JAR_FILE) +echo "> [$(date)] 실행할 JAR: $JAR_NAME" >> $REPOSITORY/deploy.log + +# 로그 디렉토리 생성 +mkdir -p $REPOSITORY/logs + +# 애플리케이션 시작 +echo "> [$(date)] 애플리케이션 시작..." >> $REPOSITORY/deploy.log + +nohup java -jar \ + -Dspring.profiles.active=prod \ + -Dserver.port=5000 \ + $JAR_FILE \ + > $REPOSITORY/logs/application.log 2>&1 & + +NEW_PID=$! +echo "> [$(date)] 애플리케이션 시작됨 (PID: $NEW_PID)" >> $REPOSITORY/deploy.log + +# 프로세스 시작 확인 (최대 10초 대기) +sleep 3 + +if ps -p $NEW_PID > /dev/null 2>&1; then + echo "> [$(date)] 애플리케이션이 정상적으로 시작되었습니다." >> $REPOSITORY/deploy.log + echo $NEW_PID > $REPOSITORY/app.pid + exit 0 +else + echo "> [$(date)] ERROR: 애플리케이션 시작 실패" >> $REPOSITORY/deploy.log + echo "> [$(date)] 로그 확인: tail -n 50 $REPOSITORY/logs/application.log" >> $REPOSITORY/deploy.log + exit 1 +fi diff --git a/scripts/stop.sh b/scripts/stop.sh new file mode 100644 index 00000000..99804832 --- /dev/null +++ b/scripts/stop.sh @@ -0,0 +1,38 @@ +#!/bin/bash + +REPOSITORY=/home/ec2-user/app + +echo "> [$(date)] 기존 애플리케이션 종료 시작" >> $REPOSITORY/deploy.log + +# 실행 중인 Spring Boot 애플리케이션 찾기 +CURRENT_PID=$(pgrep -f 'java.*application.jar') + +if [ -z "$CURRENT_PID" ]; then + echo "> [$(date)] 현재 실행 중인 애플리케이션이 없습니다." >> $REPOSITORY/deploy.log +else + echo "> [$(date)] 실행 중인 애플리케이션 PID: $CURRENT_PID" >> $REPOSITORY/deploy.log + echo "> [$(date)] 애플리케이션 종료 중..." >> $REPOSITORY/deploy.log + + # Graceful shutdown (SIGTERM) + kill -15 $CURRENT_PID + + # 프로세스가 종료될 때까지 최대 30초 대기 + for i in {1..30}; do + if ! ps -p $CURRENT_PID > /dev/null 2>&1; then + echo "> [$(date)] 애플리케이션이 정상적으로 종료되었습니다." >> $REPOSITORY/deploy.log + exit 0 + fi + sleep 1 + done + + # 30초 후에도 종료되지 않으면 강제 종료 + if ps -p $CURRENT_PID > /dev/null 2>&1; then + echo "> [$(date)] 강제 종료를 시도합니다." >> $REPOSITORY/deploy.log + kill -9 $CURRENT_PID + sleep 2 + fi + + echo "> [$(date)] 애플리케이션 종료 완료" >> $REPOSITORY/deploy.log +fi + +exit 0 From 3fd1e3ace5f18ae84ff6b50b2fea828bab1bf919 Mon Sep 17 00:00:00 2001 From: pilltong22 Date: Mon, 5 Jan 2026 15:55:00 +0900 Subject: [PATCH 11/56] =?UTF-8?q?test:=20CodeDeploy=20=EA=B6=8C=ED=95=9C?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80=20=ED=9B=84=20=EC=9E=AC=EB=B0=B0=ED=8F=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/werp/sero/config/CorsConfig.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/werp/sero/config/CorsConfig.java b/src/main/java/com/werp/sero/config/CorsConfig.java index f1d0a989..76cc9e87 100644 --- a/src/main/java/com/werp/sero/config/CorsConfig.java +++ b/src/main/java/com/werp/sero/config/CorsConfig.java @@ -16,7 +16,8 @@ public CorsConfigurationSource corsConfigurationSource() { configuration.setAllowedOrigins(List.of( "http://localhost:5173", - "http://sero-f-alb-2092902385.ap-northeast-2.elb.amazonaws.com" + "http://sero-f-alb-2092902385.ap-northeast-2.elb.amazonaws.com", + )); configuration.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS")); From ca017e658ff0d98642e9297f3d7b5b48f4c160fd Mon Sep 17 00:00:00 2001 From: pilltong22 Date: Mon, 5 Jan 2026 15:58:21 +0900 Subject: [PATCH 12/56] =?UTF-8?q?=EB=AC=B8=EB=B2=95=20=EC=98=A4=EB=A5=98?= =?UTF-8?q?=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/werp/sero/config/CorsConfig.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/com/werp/sero/config/CorsConfig.java b/src/main/java/com/werp/sero/config/CorsConfig.java index 76cc9e87..f1d0a989 100644 --- a/src/main/java/com/werp/sero/config/CorsConfig.java +++ b/src/main/java/com/werp/sero/config/CorsConfig.java @@ -16,8 +16,7 @@ public CorsConfigurationSource corsConfigurationSource() { configuration.setAllowedOrigins(List.of( "http://localhost:5173", - "http://sero-f-alb-2092902385.ap-northeast-2.elb.amazonaws.com", - + "http://sero-f-alb-2092902385.ap-northeast-2.elb.amazonaws.com" )); configuration.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS")); From 3fb5363441f106cda7e721cf9766a32c1d21f710 Mon Sep 17 00:00:00 2001 From: pilltong22 Date: Mon, 5 Jan 2026 16:10:46 +0900 Subject: [PATCH 13/56] =?UTF-8?q?=EC=9E=AC=EB=B0=B0=ED=8F=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/werp/sero/config/CorsConfig.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/werp/sero/config/CorsConfig.java b/src/main/java/com/werp/sero/config/CorsConfig.java index f1d0a989..e003b495 100644 --- a/src/main/java/com/werp/sero/config/CorsConfig.java +++ b/src/main/java/com/werp/sero/config/CorsConfig.java @@ -7,7 +7,7 @@ import org.springframework.web.cors.UrlBasedCorsConfigurationSource; import java.util.List; - +// @Configuration public class CorsConfig { @Bean From ec653dc5c354ee1f238026f36590f8bcf546fa49 Mon Sep 17 00:00:00 2001 From: pilltong22 Date: Mon, 5 Jan 2026 16:35:12 +0900 Subject: [PATCH 14/56] =?UTF-8?q?=ED=97=AC=EC=8A=A4=EC=B2=B4=ED=81=AC=20?= =?UTF-8?q?=EC=8B=9C=EA=B0=84=20=EC=A6=9D=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- appspec.yml | 2 +- scripts/health-check.sh | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/appspec.yml b/appspec.yml index ecd34f0f..f9966ffb 100644 --- a/appspec.yml +++ b/appspec.yml @@ -29,5 +29,5 @@ hooks: ValidateService: - location: scripts/health-check.sh - timeout: 60 + timeout: 180 runas: ec2-user diff --git a/scripts/health-check.sh b/scripts/health-check.sh index bd8ba949..d632ebdb 100644 --- a/scripts/health-check.sh +++ b/scripts/health-check.sh @@ -5,10 +5,10 @@ PORT=5000 echo "> [$(date)] 애플리케이션 헬스체크 시작" >> $REPOSITORY/deploy.log -# 최대 30초 동안 헬스체크 재시도 -for i in {1..30}; do - # 프로세스 실행 확인 - if ! pgrep -f 'java.*application.jar' > /dev/null; then +# 최대 60초 동안 헬스체크 재시도 (Spring Boot 시작 시간 고려) +for i in {1..60}; do + # 프로세스 실행 확인 (jar 파일 이름 무관하게 java 프로세스 확인) + if ! pgrep -f 'java.*\.jar' > /dev/null; then echo "> [$(date)] ERROR: 애플리케이션 프로세스가 실행 중이 아닙니다." >> $REPOSITORY/deploy.log exit 1 fi @@ -28,11 +28,11 @@ for i in {1..30}; do exit 0 fi - echo "> [$(date)] 헬스체크 재시도 중... ($i/30) - HTTP $HTTP_STATUS" >> $REPOSITORY/deploy.log - sleep 1 + echo "> [$(date)] 헬스체크 재시도 중... ($i/60) - HTTP $HTTP_STATUS" >> $REPOSITORY/deploy.log + sleep 2 done -# 30초 동안 성공하지 못하면 실패 +# 60초 동안 성공하지 못하면 실패 echo "> [$(date)] ERROR: 헬스체크 실패 - 애플리케이션이 정상적으로 시작되지 않았습니다." >> $REPOSITORY/deploy.log echo "> [$(date)] 로그 확인: tail -n 100 $REPOSITORY/logs/application.log" >> $REPOSITORY/deploy.log exit 1 From 95e3bd0d09b43ab9bc39f8d931e9f59ddb5d6cba Mon Sep 17 00:00:00 2001 From: pilltong22 Date: Mon, 5 Jan 2026 16:48:01 +0900 Subject: [PATCH 15/56] Update start.sh --- scripts/start.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/start.sh b/scripts/start.sh index 19ce4ad1..beff1f75 100644 --- a/scripts/start.sh +++ b/scripts/start.sh @@ -22,7 +22,6 @@ mkdir -p $REPOSITORY/logs echo "> [$(date)] 애플리케이션 시작..." >> $REPOSITORY/deploy.log nohup java -jar \ - -Dspring.profiles.active=prod \ -Dserver.port=5000 \ $JAR_FILE \ > $REPOSITORY/logs/application.log 2>&1 & From fa0b17cc769189fa7fbcbdabd983419229398193 Mon Sep 17 00:00:00 2001 From: pilltong22 Date: Mon, 5 Jan 2026 17:12:35 +0900 Subject: [PATCH 16/56] Update health-check.sh --- scripts/health-check.sh | 6 ------ 1 file changed, 6 deletions(-) diff --git a/scripts/health-check.sh b/scripts/health-check.sh index d632ebdb..d4a524cc 100644 --- a/scripts/health-check.sh +++ b/scripts/health-check.sh @@ -7,12 +7,6 @@ echo "> [$(date)] 애플리케이션 헬스체크 시작" >> $REPOSITORY/deploy. # 최대 60초 동안 헬스체크 재시도 (Spring Boot 시작 시간 고려) for i in {1..60}; do - # 프로세스 실행 확인 (jar 파일 이름 무관하게 java 프로세스 확인) - if ! pgrep -f 'java.*\.jar' > /dev/null; then - echo "> [$(date)] ERROR: 애플리케이션 프로세스가 실행 중이 아닙니다." >> $REPOSITORY/deploy.log - exit 1 - fi - # HTTP 헬스체크 (Spring Boot Actuator가 있다면 /actuator/health, 없으면 루트 경로) HTTP_STATUS=$(curl -s -o /dev/null -w "%{http_code}" http://localhost:$PORT/actuator/health 2>/dev/null) From 4dff69f03230065a484325f417f0cf28216cdb8b Mon Sep 17 00:00:00 2001 From: pilltong22 Date: Mon, 5 Jan 2026 18:02:35 +0900 Subject: [PATCH 17/56] =?UTF-8?q?debug:=20ValidateService=20=EC=9E=84?= =?UTF-8?q?=EC=8B=9C=20=EB=B9=84=ED=99=9C=EC=84=B1=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- appspec.yml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/appspec.yml b/appspec.yml index f9966ffb..fedeb76c 100644 --- a/appspec.yml +++ b/appspec.yml @@ -27,7 +27,8 @@ hooks: timeout: 120 runas: ec2-user - ValidateService: - - location: scripts/health-check.sh - timeout: 180 - runas: ec2-user + # ValidateService 임시 비활성화 (디버깅용) + # ValidateService: + # - location: scripts/health-check.sh + # timeout: 180 + # runas: ec2-user From 6195604e9d1ffb954afdcc1a25516afbed27cd86 Mon Sep 17 00:00:00 2001 From: pilltong22 Date: Mon, 5 Jan 2026 21:22:20 +0900 Subject: [PATCH 18/56] =?UTF-8?q?=EC=9E=AC=EB=B0=B0=ED=8F=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From b6864fa7fb70169af8a10cce49c2fadbc0a15a37 Mon Sep 17 00:00:00 2001 From: pilltong22 Date: Mon, 5 Jan 2026 22:35:35 +0900 Subject: [PATCH 19/56] =?UTF-8?q?SecurityConfig=20=ED=8C=8C=EC=9D=BC=20?= =?UTF-8?q?=ED=97=AC=EC=8A=A4=EC=B2=B4=ED=81=AC=EC=9A=A9=20=EA=B2=BD?= =?UTF-8?q?=EB=A1=9C=20=ED=97=88=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/werp/sero/security/config/EmployeeSecurityConfig.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/com/werp/sero/security/config/EmployeeSecurityConfig.java b/src/main/java/com/werp/sero/security/config/EmployeeSecurityConfig.java index 0cafdd80..6a587ef9 100644 --- a/src/main/java/com/werp/sero/security/config/EmployeeSecurityConfig.java +++ b/src/main/java/com/werp/sero/security/config/EmployeeSecurityConfig.java @@ -35,6 +35,9 @@ public class EmployeeSecurityConfig { "/swagger-ui/**", "/swagger-resources/**", "/auth/login", + "/actuator/health", // ★ AWS 로드밸런서 헬스체크용 (필수 추가) + "/actuator/**", // (선택) 다른 액추에이터 정보도 허용하려면 추가 + "/health" // (혹시 몰라 기본 경로도 추가) }; From 83cc7d3522150cddaa45a27c2f2a0f3fea39ce94 Mon Sep 17 00:00:00 2001 From: pilltong22 Date: Tue, 6 Jan 2026 00:02:58 +0900 Subject: [PATCH 20/56] =?UTF-8?q?=EC=9E=AC=EB=B0=B0=ED=8F=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../sero/security/config/ClientEmployeeSecurityConfig.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/com/werp/sero/security/config/ClientEmployeeSecurityConfig.java b/src/main/java/com/werp/sero/security/config/ClientEmployeeSecurityConfig.java index 289355bf..d1bcc4a5 100644 --- a/src/main/java/com/werp/sero/security/config/ClientEmployeeSecurityConfig.java +++ b/src/main/java/com/werp/sero/security/config/ClientEmployeeSecurityConfig.java @@ -76,4 +76,7 @@ public SecurityFilterChain clientEmployFilterChain(final HttpSecurity http) thro return http.build(); } + + + } \ No newline at end of file From 05ccf6909baa052e8fa2baf97f45457244e382c3 Mon Sep 17 00:00:00 2001 From: pilltong22 Date: Tue, 6 Jan 2026 00:23:46 +0900 Subject: [PATCH 21/56] =?UTF-8?q?=EB=A1=9C=EB=93=9C=20=EB=B0=B8=EB=9F=B0?= =?UTF-8?q?=EC=84=9C=20=EC=9D=BC=EC=8B=9C=20=ED=95=B4=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../werp/sero/security/config/ClientEmployeeSecurityConfig.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/com/werp/sero/security/config/ClientEmployeeSecurityConfig.java b/src/main/java/com/werp/sero/security/config/ClientEmployeeSecurityConfig.java index d1bcc4a5..130e5de2 100644 --- a/src/main/java/com/werp/sero/security/config/ClientEmployeeSecurityConfig.java +++ b/src/main/java/com/werp/sero/security/config/ClientEmployeeSecurityConfig.java @@ -79,4 +79,5 @@ public SecurityFilterChain clientEmployFilterChain(final HttpSecurity http) thro + } \ No newline at end of file From 0a2c01fa89ca5997ce2b18d0e6bf0e7a5a487e3d Mon Sep 17 00:00:00 2001 From: pilltong22 Date: Tue, 6 Jan 2026 01:01:17 +0900 Subject: [PATCH 22/56] =?UTF-8?q?=EC=9E=AC=EB=B0=B0=ED=8F=AC=20=ED=8A=B8?= =?UTF-8?q?=EB=A6=AC=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../sero/security/config/ClientEmployeeSecurityConfig.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/werp/sero/security/config/ClientEmployeeSecurityConfig.java b/src/main/java/com/werp/sero/security/config/ClientEmployeeSecurityConfig.java index 130e5de2..d238744f 100644 --- a/src/main/java/com/werp/sero/security/config/ClientEmployeeSecurityConfig.java +++ b/src/main/java/com/werp/sero/security/config/ClientEmployeeSecurityConfig.java @@ -74,10 +74,11 @@ public SecurityFilterChain clientEmployFilterChain(final HttpSecurity http) thro ) ; + return http.build(); } - + } \ No newline at end of file From 68d6a2a7d4e81b28270427362a506dedd4d603c1 Mon Sep 17 00:00:00 2001 From: pilltong22 Date: Tue, 6 Jan 2026 11:01:34 +0900 Subject: [PATCH 23/56] =?UTF-8?q?=EC=9A=B4=EC=98=81=20=EB=8F=84=EB=A9=94?= =?UTF-8?q?=EC=9D=B8(sero-erp.cloud)=20CORS=20=ED=97=88=EC=9A=A9=20?= =?UTF-8?q?=EC=84=A4=EC=A0=95=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/werp/sero/config/CorsConfig.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/werp/sero/config/CorsConfig.java b/src/main/java/com/werp/sero/config/CorsConfig.java index e003b495..54b95a24 100644 --- a/src/main/java/com/werp/sero/config/CorsConfig.java +++ b/src/main/java/com/werp/sero/config/CorsConfig.java @@ -16,7 +16,9 @@ public CorsConfigurationSource corsConfigurationSource() { configuration.setAllowedOrigins(List.of( "http://localhost:5173", - "http://sero-f-alb-2092902385.ap-northeast-2.elb.amazonaws.com" + "http://sero-f-alb-2092902385.ap-northeast-2.elb.amazonaws.com", + "http://sero-erp.cloud", + "http://api.sero-erp.cloud" )); configuration.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS")); From 1f5b7ac9dfc3e7ea7e76e3c47fbe5746ea747230 Mon Sep 17 00:00:00 2001 From: pilltong22 Date: Tue, 6 Jan 2026 11:45:00 +0900 Subject: [PATCH 24/56] =?UTF-8?q?=EC=9E=AC=EB=B0=B0=ED=8F=AC=20-elasticbea?= =?UTF-8?q?nstalk=EB=A1=9C=20=EC=A0=84=ED=99=98(=EB=B0=B1=EC=97=94?= =?UTF-8?q?=EB=93=9C)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/werp/sero/config/AsyncConfig.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/com/werp/sero/config/AsyncConfig.java b/src/main/java/com/werp/sero/config/AsyncConfig.java index c6228c4e..e7e20917 100644 --- a/src/main/java/com/werp/sero/config/AsyncConfig.java +++ b/src/main/java/com/werp/sero/config/AsyncConfig.java @@ -7,4 +7,5 @@ @EnableAsync @Configuration public class AsyncConfig { + } \ No newline at end of file From 68f372150e76cdd496a02e7863cf329b275d3c89 Mon Sep 17 00:00:00 2001 From: pilltong22 Date: Tue, 6 Jan 2026 12:00:40 +0900 Subject: [PATCH 25/56] =?UTF-8?q?deploy.yml=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/deploy.yml | 66 ++++++++++++++++-------------------- 1 file changed, 29 insertions(+), 37 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 75c782f3..529d5736 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -1,4 +1,4 @@ -name: Deploy to EC2 with CodeDeploy +name: Deploy to Elastic Beanstalk # GitHub 저장소 읽기 권한 설정 permissions: @@ -32,7 +32,7 @@ jobs: - name: Install envsubst run: sudo apt-get install -y gettext - # 배포용 application.yml 파일을 환경 변수로 생성! + # 배포용 application.yml 파일을 환경 변수로 생성 - name: Create application.yml.template run: | mkdir -p src/main/resources @@ -54,7 +54,7 @@ jobs: properties: hibernate: format_sql: true - + # Redis 설정 (클러스터 + SSL) data: redis: @@ -64,7 +64,7 @@ jobs: ssl: enabled: true - # AWS S3 설정 (spring 하위로 통합됨) + # AWS S3 설정 cloud: aws: s3: @@ -88,7 +88,6 @@ jobs: map-underscore-to-camel-case: true EOL - # envsubst는 환경 변수를 치환해주는 유틸리티로, 템플릿 파일의 ${VARIABLE} 형태의 변수를 실제 환경 변수 값으로 대체 - name: Set Yaml run: | echo "DEBUG: Checking if RDS_PASSWORD is set..." @@ -104,7 +103,6 @@ jobs: SPRING_DATASOURCE_URL: jdbc:mariadb://${{ secrets.RDS_HOSTNAME }}:${{ secrets.RDS_PORT }}/${{ secrets.RDS_DB_NAME }} SPRING_DATASOURCE_USERNAME: ${{ secrets.RDS_USERNAME }} SPRING_DATASOURCE_PASSWORD: ${{ secrets.RDS_PASSWORD }} - # REDIS_HOST는 포트 번호 없이 주소만 입력되어 있어야 합니다. REDIS_HOST: ${{ secrets.REDIS_HOST }} REDIS_PORT: ${{ secrets.REDIS_PORT }} JWT_SECRET: ${{ secrets.JWT_SECRET }} @@ -116,6 +114,8 @@ jobs: AWS_SECRET_KEY: ${{ secrets.AWS_SECRET_KEY }} ################################################# + # CI: 빌드 + ################################################# - name: Build with Gradle run: ./gradlew clean build -x test @@ -132,22 +132,19 @@ jobs: run: echo "CurrentTime=${{steps.current-time.outputs.formattedTime}}" shell: bash - ############################################### - # CodeDeploy 배포 단계 - ############################################### + ################################################# + # CD: Elastic Beanstalk 배포 + ################################################# - # 1. 배포 패키지 생성 (appspec.yml 포함) - - name: Make deployment package + # 1. JAR 파일 이름 확인 및 복사 + - name: Prepare deployment artifact run: | - echo "> 배포 패키지 생성 중..." - zip -r sero-deploy-${{steps.current-time.outputs.formattedTime}}.zip \ - appspec.yml \ - scripts/ \ - build/libs/*.jar \ - -x "*.git*" "build/libs/*plain*" + echo "> JAR 파일 확인" + ls -lh build/libs/ - echo "> 생성된 파일 확인" - ls -lh sero-deploy-${{steps.current-time.outputs.formattedTime}}.zip + # application.jar가 이미 생성되어 있음 (build.gradle에서 설정) + echo "> application.jar 준비 완료" + ls -lh build/libs/application.jar # 2. AWS 자격 증명 설정 - name: Configure AWS credentials @@ -157,21 +154,16 @@ jobs: aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} aws-region: ap-northeast-2 - # 3. S3에 배포 패키지 업로드 - - name: Upload to S3 - run: | - echo "> S3에 배포 패키지 업로드 중..." - aws s3 cp \ - sero-deploy-${{steps.current-time.outputs.formattedTime}}.zip \ - s3://elasticbeanstalk-ap-northeast-2-257394460879/codedeploy/ - - # 4. CodeDeploy 배포 생성 - - name: Deploy with CodeDeploy - run: | - echo "> CodeDeploy 배포 시작..." - aws deploy create-deployment \ - --application-name sero-backend-app \ - --deployment-config-name CodeDeployDefault.AllAtOnce \ - --deployment-group-name sero-backend-dg \ - --s3-location bucket=elasticbeanstalk-ap-northeast-2-257394460879,key=codedeploy/sero-deploy-${{steps.current-time.outputs.formattedTime}}.zip,bundleType=zip \ - --description "GitHub Actions deployment at ${{steps.current-time.outputs.formattedTime}}" \ No newline at end of file + # 3. Elastic Beanstalk에 배포 (JAR 파일만 업로드) + - name: Deploy to Elastic Beanstalk + uses: einaregilsson/beanstalk-deploy@v22 + with: + aws_access_key: ${{ secrets.AWS_ACCESS_KEY_ID }} + aws_secret_key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + application_name: sero-backend + environment_name: sero-backend-env + version_label: sero-${{steps.current-time.outputs.formattedTime}} + region: ap-northeast-2 + deployment_package: build/libs/application.jar + wait_for_deployment: true + wait_for_environment_recovery: 120 From a0a2c06419df00f84084e501d84de3b2a2a68b26 Mon Sep 17 00:00:00 2001 From: pilltong22 Date: Tue, 6 Jan 2026 12:05:23 +0900 Subject: [PATCH 26/56] =?UTF-8?q?deploy=20=EC=9E=AC=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/deploy.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 529d5736..5fa5f4a5 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -160,8 +160,8 @@ jobs: with: aws_access_key: ${{ secrets.AWS_ACCESS_KEY_ID }} aws_secret_key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - application_name: sero-backend - environment_name: sero-backend-env + application_name: sero-b + environment_name: Sero-b-env version_label: sero-${{steps.current-time.outputs.formattedTime}} region: ap-northeast-2 deployment_package: build/libs/application.jar From d1b18df3136444b614a704eefe7ff3adcab9e8f2 Mon Sep 17 00:00:00 2001 From: pilltong22 Date: Tue, 6 Jan 2026 12:19:23 +0900 Subject: [PATCH 27/56] =?UTF-8?q?=EB=98=90=EB=98=90=20=EC=88=98=EC=A0=95?= =?UTF-8?q?=20deploy?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/deploy.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 5fa5f4a5..3913cf24 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -38,7 +38,7 @@ jobs: mkdir -p src/main/resources cat > src/main/resources/application.yml.template <<'EOL' server: - port: 5000 + port: ${PORT} spring: datasource: @@ -100,6 +100,7 @@ jobs: echo "Generated application.yml:" cat src/main/resources/application.yml env: + PORT: '5000' SPRING_DATASOURCE_URL: jdbc:mariadb://${{ secrets.RDS_HOSTNAME }}:${{ secrets.RDS_PORT }}/${{ secrets.RDS_DB_NAME }} SPRING_DATASOURCE_USERNAME: ${{ secrets.RDS_USERNAME }} SPRING_DATASOURCE_PASSWORD: ${{ secrets.RDS_PASSWORD }} From e4dc4e52649d3aa713f81f47d0687b8629a5ad5c Mon Sep 17 00:00:00 2001 From: pilltong22 Date: Tue, 6 Jan 2026 12:31:22 +0900 Subject: [PATCH 28/56] =?UTF-8?q?=ED=8F=AC=ED=8A=B8=208080=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/deploy.yml | 2 +- .platform/nginx.conf | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 3913cf24..ca9ec4f6 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -100,7 +100,7 @@ jobs: echo "Generated application.yml:" cat src/main/resources/application.yml env: - PORT: '5000' + PORT: '8080' SPRING_DATASOURCE_URL: jdbc:mariadb://${{ secrets.RDS_HOSTNAME }}:${{ secrets.RDS_PORT }}/${{ secrets.RDS_DB_NAME }} SPRING_DATASOURCE_USERNAME: ${{ secrets.RDS_USERNAME }} SPRING_DATASOURCE_PASSWORD: ${{ secrets.RDS_PASSWORD }} diff --git a/.platform/nginx.conf b/.platform/nginx.conf index 8dfebfae..97070d83 100644 --- a/.platform/nginx.conf +++ b/.platform/nginx.conf @@ -25,7 +25,7 @@ http { } upstream springboot { - server 127.0.0.1:5000; // 5000번으로 돌고 있는 백엔드 서버를 인지해라! + server 127.0.0.1:8080; // 8080번으로 돌고 있는 백엔드 서버를 인지해라! keepalive 1024; } From 198be152cef513ec9689a8c718766b03ad4848f8 Mon Sep 17 00:00:00 2001 From: pilltong22 Date: Tue, 6 Jan 2026 14:35:42 +0900 Subject: [PATCH 29/56] =?UTF-8?q?RDS=5FHOSTNAME=20-=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../werp/sero/security/config/ClientEmployeeSecurityConfig.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/com/werp/sero/security/config/ClientEmployeeSecurityConfig.java b/src/main/java/com/werp/sero/security/config/ClientEmployeeSecurityConfig.java index d238744f..2f1c1f74 100644 --- a/src/main/java/com/werp/sero/security/config/ClientEmployeeSecurityConfig.java +++ b/src/main/java/com/werp/sero/security/config/ClientEmployeeSecurityConfig.java @@ -75,6 +75,7 @@ public SecurityFilterChain clientEmployFilterChain(final HttpSecurity http) thro ; + return http.build(); } From 0ff0954819f454c9309cac16c66224692fa58bd7 Mon Sep 17 00:00:00 2001 From: pilltong22 Date: Tue, 6 Jan 2026 14:52:24 +0900 Subject: [PATCH 30/56] =?UTF-8?q?=EC=9E=AC=EB=B0=B0=ED=8F=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/werp/sero/security/config/EmployeeSecurityConfig.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/com/werp/sero/security/config/EmployeeSecurityConfig.java b/src/main/java/com/werp/sero/security/config/EmployeeSecurityConfig.java index 6a587ef9..661af8fb 100644 --- a/src/main/java/com/werp/sero/security/config/EmployeeSecurityConfig.java +++ b/src/main/java/com/werp/sero/security/config/EmployeeSecurityConfig.java @@ -90,6 +90,7 @@ public SecurityFilterChain employeeFilterChain(final HttpSecurity http) throws E ) ; + return http.build(); } } From 39d65412ac1abd550bdb1710245410c5d33d7bc4 Mon Sep 17 00:00:00 2001 From: pilltong22 Date: Tue, 6 Jan 2026 15:11:24 +0900 Subject: [PATCH 31/56] =?UTF-8?q?Fix:=20Nginx=20=EC=84=A4=EC=A0=95=20?= =?UTF-8?q?=ED=8F=AC=ED=95=A8=ED=95=9C=20ZIP=20=EB=B0=B0=ED=8F=AC=20?= =?UTF-8?q?=ED=8C=A8=ED=82=A4=EC=A7=80=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - JAR만 배포하던 방식에서 ZIP 패키지로 변경 - .platform/nginx.conf와 .ebextensions/app.config 포함 - 이제 Nginx가 80->8080 프록시 설정을 정상 로드함 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 --- .github/workflows/deploy.yml | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index ca9ec4f6..678d3021 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -137,7 +137,7 @@ jobs: # CD: Elastic Beanstalk 배포 ################################################# - # 1. JAR 파일 이름 확인 및 복사 + # 1. JAR 파일 이름 확인 및 ZIP 패키지 생성 - name: Prepare deployment artifact run: | echo "> JAR 파일 확인" @@ -147,6 +147,16 @@ jobs: echo "> application.jar 준비 완료" ls -lh build/libs/application.jar + # ZIP 패키지 생성 (.platform, .ebextensions 포함) + echo "> ZIP 패키지 생성" + mkdir -p deploy + cp build/libs/application.jar deploy/ + cp -r .platform deploy/ + cp -r .ebextensions deploy/ + cd deploy && zip -r ../application.zip . && cd .. + echo "> ZIP 패키지 생성 완료" + ls -lh application.zip + # 2. AWS 자격 증명 설정 - name: Configure AWS credentials uses: aws-actions/configure-aws-credentials@v4 @@ -165,6 +175,6 @@ jobs: environment_name: Sero-b-env version_label: sero-${{steps.current-time.outputs.formattedTime}} region: ap-northeast-2 - deployment_package: build/libs/application.jar + deployment_package: application.zip wait_for_deployment: true wait_for_environment_recovery: 120 From 7f36378edb688d34f0b0aec98139531ce4fa16bc Mon Sep 17 00:00:00 2001 From: pilltong22 Date: Tue, 6 Jan 2026 16:23:11 +0900 Subject: [PATCH 32/56] =?UTF-8?q?=EC=9E=AC=EB=B0=B0=ED=8F=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/deploy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 678d3021..d9b53708 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -28,7 +28,7 @@ jobs: run: chmod +x ./gradlew shell: bash - # envsubst 설치 + # envsubst 설치! - name: Install envsubst run: sudo apt-get install -y gettext From ff96a7061eacb12ae677b0592684627fe62d3cc8 Mon Sep 17 00:00:00 2001 From: pilltong22 Date: Tue, 6 Jan 2026 16:55:11 +0900 Subject: [PATCH 33/56] =?UTF-8?q?=EC=9E=AC=EB=B0=B0=ED=8F=AC=20(=ED=99=98?= =?UTF-8?q?=EA=B2=BD=EB=B3=80=EC=88=98=20=EC=83=88=EB=A1=9C=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/deploy.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index d9b53708..fdf9f382 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -165,14 +165,14 @@ jobs: aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} aws-region: ap-northeast-2 - # 3. Elastic Beanstalk에 배포 (JAR 파일만 업로드) + # 3. Elastic Beanstalk에 배포 (ZIP 패키지 업로드) - name: Deploy to Elastic Beanstalk uses: einaregilsson/beanstalk-deploy@v22 with: aws_access_key: ${{ secrets.AWS_ACCESS_KEY_ID }} aws_secret_key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} application_name: sero-b - environment_name: Sero-b-env + environment_name: Sero-b-env-v2 version_label: sero-${{steps.current-time.outputs.formattedTime}} region: ap-northeast-2 deployment_package: application.zip From 2e85c5d76f5522f1673d9471bd3bc6b41ab55ee5 Mon Sep 17 00:00:00 2001 From: pilltong22 Date: Tue, 6 Jan 2026 16:58:57 +0900 Subject: [PATCH 34/56] =?UTF-8?q?=EB=B2=84=EC=A0=84=EB=AA=85=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/deploy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index fdf9f382..41f615f6 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -172,7 +172,7 @@ jobs: aws_access_key: ${{ secrets.AWS_ACCESS_KEY_ID }} aws_secret_key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} application_name: sero-b - environment_name: Sero-b-env-v2 + environment_name: Sero-b-env-2 version_label: sero-${{steps.current-time.outputs.formattedTime}} region: ap-northeast-2 deployment_package: application.zip From 3eb9a61f11a732d1566a76092839b56c4a88d496 Mon Sep 17 00:00:00 2001 From: pilltong22 Date: Tue, 6 Jan 2026 17:59:12 +0900 Subject: [PATCH 35/56] =?UTF-8?q?dto=EC=97=90=20imageUrl=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../werp/sero/material/query/dto/MaterialListResponseDTO.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/com/werp/sero/material/query/dto/MaterialListResponseDTO.java b/src/main/java/com/werp/sero/material/query/dto/MaterialListResponseDTO.java index 39a74ef8..853cd8a3 100644 --- a/src/main/java/com/werp/sero/material/query/dto/MaterialListResponseDTO.java +++ b/src/main/java/com/werp/sero/material/query/dto/MaterialListResponseDTO.java @@ -25,5 +25,6 @@ public class MaterialListResponseDTO { private int safetyStock; private Integer cycleTime; private Integer rawMaterialCount; + private String imageUrl; private String createdAt; } From 4636ea5b349cd693f78f14ef6e809b34f800b382 Mon Sep 17 00:00:00 2001 From: pilltong22 <106594632+pilltong22@users.noreply.github.com> Date: Tue, 6 Jan 2026 20:35:45 +0900 Subject: [PATCH 36/56] =?UTF-8?q?fix:=20=EB=B0=B0=ED=8F=AC=EB=90=9C=20?= =?UTF-8?q?=EC=95=A0=ED=94=8C=EB=A6=AC=EC=BC=80=EC=9D=B4=EC=85=98=EC=97=90?= =?UTF-8?q?=EC=84=9C=20s3=20=EB=8B=A4=EC=9A=B4=20=EC=95=88=EB=90=98?= =?UTF-8?q?=EB=8A=94=20=EB=AC=B8=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit dto 에 imageUrl 추가 --- .../werp/sero/material/query/dto/MaterialListResponseDTO.java | 1 + .../com/werp/sero/material/query/dao/MaterialMapper.xml | 1 + 2 files changed, 2 insertions(+) diff --git a/src/main/java/com/werp/sero/material/query/dto/MaterialListResponseDTO.java b/src/main/java/com/werp/sero/material/query/dto/MaterialListResponseDTO.java index 853cd8a3..077f249c 100644 --- a/src/main/java/com/werp/sero/material/query/dto/MaterialListResponseDTO.java +++ b/src/main/java/com/werp/sero/material/query/dto/MaterialListResponseDTO.java @@ -22,6 +22,7 @@ public class MaterialListResponseDTO { private String status; private String baseUnit; private Long unitPrice; + private String imageUrl; private int safetyStock; private Integer cycleTime; private Integer rawMaterialCount; diff --git a/src/main/resources/com/werp/sero/material/query/dao/MaterialMapper.xml b/src/main/resources/com/werp/sero/material/query/dao/MaterialMapper.xml index 301d43f4..881f7247 100644 --- a/src/main/resources/com/werp/sero/material/query/dao/MaterialMapper.xml +++ b/src/main/resources/com/werp/sero/material/query/dao/MaterialMapper.xml @@ -13,6 +13,7 @@ + From 0cde783f16128d471ef92557795fa3d33d390e22 Mon Sep 17 00:00:00 2001 From: pilltong22 <106594632+pilltong22@users.noreply.github.com> Date: Tue, 6 Jan 2026 20:44:20 +0900 Subject: [PATCH 37/56] =?UTF-8?q?DTO=20=EC=9E=AC=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../werp/sero/material/query/dto/MaterialListResponseDTO.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/com/werp/sero/material/query/dto/MaterialListResponseDTO.java b/src/main/java/com/werp/sero/material/query/dto/MaterialListResponseDTO.java index 077f249c..4d0f3764 100644 --- a/src/main/java/com/werp/sero/material/query/dto/MaterialListResponseDTO.java +++ b/src/main/java/com/werp/sero/material/query/dto/MaterialListResponseDTO.java @@ -26,6 +26,5 @@ public class MaterialListResponseDTO { private int safetyStock; private Integer cycleTime; private Integer rawMaterialCount; - private String imageUrl; private String createdAt; } From 543450c390535356c69e5dc926f5ec9d75b0b3d1 Mon Sep 17 00:00:00 2001 From: pilltong22 <106594632+pilltong22@users.noreply.github.com> Date: Wed, 7 Jan 2026 00:59:34 +0900 Subject: [PATCH 38/56] feat: force redeploy to fix imageUrl issue From dc6e194821a869a6653a956742162b148313db2f Mon Sep 17 00:00:00 2001 From: pilltong22 <106594632+pilltong22@users.noreply.github.com> Date: Wed, 7 Jan 2026 01:18:12 +0900 Subject: [PATCH 39/56] debug: add logging to diagnose imageUrl issue --- .../material/query/dao/MaterialMapper.xml | 172 ++++++++++++++++++ .../service/MaterialQueryServiceImpl.java | 15 +- 2 files changed, 186 insertions(+), 1 deletion(-) create mode 100644 BOOT-INF/classes/com/werp/sero/material/query/dao/MaterialMapper.xml diff --git a/BOOT-INF/classes/com/werp/sero/material/query/dao/MaterialMapper.xml b/BOOT-INF/classes/com/werp/sero/material/query/dao/MaterialMapper.xml new file mode 100644 index 00000000..881f7247 --- /dev/null +++ b/BOOT-INF/classes/com/werp/sero/material/query/dao/MaterialMapper.xml @@ -0,0 +1,172 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/java/com/werp/sero/material/query/service/MaterialQueryServiceImpl.java b/src/main/java/com/werp/sero/material/query/service/MaterialQueryServiceImpl.java index 56e3389d..d6f42f4d 100644 --- a/src/main/java/com/werp/sero/material/query/service/MaterialQueryServiceImpl.java +++ b/src/main/java/com/werp/sero/material/query/service/MaterialQueryServiceImpl.java @@ -8,6 +8,7 @@ import com.werp.sero.material.query.dto.MaterialListResponseDTO; import com.werp.sero.material.query.dto.MaterialWithBomResponseDTO; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -17,6 +18,7 @@ /** * 자재 Query Service 구현체 (조회 전용) */ +@Slf4j @Service @RequiredArgsConstructor @Transactional(readOnly = true) @@ -45,7 +47,18 @@ public List getMaterialList( } // 3. 자재 목록 조회 - return materialMapper.findByCondition(type, status, keyword); + List results = materialMapper.findByCondition(type, status, keyword); + + // DEBUG: imageUrl 확인 + if (!results.isEmpty()) { + log.info("===== DEBUG: Material imageUrl check ====="); + log.info("First material ID: {}", results.get(0).getId()); + log.info("First material name: {}", results.get(0).getName()); + log.info("First material imageUrl: {}", results.get(0).getImageUrl()); + log.info("=========================================="); + } + + return results; } @Override From a0a557610da295c37fa779f1c0ce25bf0a05ccba Mon Sep 17 00:00:00 2001 From: pilltong22 <106594632+pilltong22@users.noreply.github.com> Date: Wed, 7 Jan 2026 01:55:22 +0900 Subject: [PATCH 40/56] =?UTF-8?q?=EC=9E=AC=EB=B0=B0=ED=8F=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../material/query/dao/MaterialMapper.xml | 172 ------------------ 1 file changed, 172 deletions(-) delete mode 100644 BOOT-INF/classes/com/werp/sero/material/query/dao/MaterialMapper.xml diff --git a/BOOT-INF/classes/com/werp/sero/material/query/dao/MaterialMapper.xml b/BOOT-INF/classes/com/werp/sero/material/query/dao/MaterialMapper.xml deleted file mode 100644 index 881f7247..00000000 --- a/BOOT-INF/classes/com/werp/sero/material/query/dao/MaterialMapper.xml +++ /dev/null @@ -1,172 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - From 6ee0ab05fb7e57f3f041f8b22061036ce6cbc6ea Mon Sep 17 00:00:00 2001 From: pilltong22 <106594632+pilltong22@users.noreply.github.com> Date: Wed, 7 Jan 2026 02:19:14 +0900 Subject: [PATCH 41/56] debug: use System.out.println for debugging imageUrl --- .../query/service/MaterialQueryServiceImpl.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/werp/sero/material/query/service/MaterialQueryServiceImpl.java b/src/main/java/com/werp/sero/material/query/service/MaterialQueryServiceImpl.java index d6f42f4d..cbbe9722 100644 --- a/src/main/java/com/werp/sero/material/query/service/MaterialQueryServiceImpl.java +++ b/src/main/java/com/werp/sero/material/query/service/MaterialQueryServiceImpl.java @@ -51,11 +51,11 @@ public List getMaterialList( // DEBUG: imageUrl 확인 if (!results.isEmpty()) { - log.info("===== DEBUG: Material imageUrl check ====="); - log.info("First material ID: {}", results.get(0).getId()); - log.info("First material name: {}", results.get(0).getName()); - log.info("First material imageUrl: {}", results.get(0).getImageUrl()); - log.info("=========================================="); + System.out.println("===== DEBUG: Material imageUrl check ====="); + System.out.println("First material ID: " + results.get(0).getId()); + System.out.println("First material name: " + results.get(0).getName()); + System.out.println("First material imageUrl: " + results.get(0).getImageUrl()); + System.out.println("=========================================="); } return results; From 2d75f3665b286418e3e7f3e13f55ce3ce6401a6b Mon Sep 17 00:00:00 2001 From: pilltong22 <106594632+pilltong22@users.noreply.github.com> Date: Wed, 7 Jan 2026 02:28:09 +0900 Subject: [PATCH 42/56] debug: add more field checks to diagnose ResultMap issue --- .../sero/material/query/service/MaterialQueryServiceImpl.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/com/werp/sero/material/query/service/MaterialQueryServiceImpl.java b/src/main/java/com/werp/sero/material/query/service/MaterialQueryServiceImpl.java index cbbe9722..4961ebb0 100644 --- a/src/main/java/com/werp/sero/material/query/service/MaterialQueryServiceImpl.java +++ b/src/main/java/com/werp/sero/material/query/service/MaterialQueryServiceImpl.java @@ -47,7 +47,9 @@ public List getMaterialList( } // 3. 자재 목록 조회 + System.out.println("===== DEBUG: Before MyBatis query ====="); List results = materialMapper.findByCondition(type, status, keyword); + System.out.println("===== DEBUG: After MyBatis query ====="); // DEBUG: imageUrl 확인 if (!results.isEmpty()) { @@ -55,6 +57,8 @@ public List getMaterialList( System.out.println("First material ID: " + results.get(0).getId()); System.out.println("First material name: " + results.get(0).getName()); System.out.println("First material imageUrl: " + results.get(0).getImageUrl()); + System.out.println("First material spec: " + results.get(0).getSpec()); + System.out.println("First material baseUnit: " + results.get(0).getBaseUnit()); System.out.println("=========================================="); } From 2f7f00ee639b147c1089f173eb481be7ffd30b1f Mon Sep 17 00:00:00 2001 From: pilltong22 <106594632+pilltong22@users.noreply.github.com> Date: Wed, 7 Jan 2026 02:28:36 +0900 Subject: [PATCH 43/56] fix: add AS imageUrl alias in SQL query for explicit column mapping --- .../com/werp/sero/material/query/dao/MaterialMapper.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/com/werp/sero/material/query/dao/MaterialMapper.xml b/src/main/resources/com/werp/sero/material/query/dao/MaterialMapper.xml index 881f7247..1c296b6f 100644 --- a/src/main/resources/com/werp/sero/material/query/dao/MaterialMapper.xml +++ b/src/main/resources/com/werp/sero/material/query/dao/MaterialMapper.xml @@ -76,7 +76,7 @@ A.moq, A.cycle_time, A.unit_price, - A.image_url, + A.image_url AS imageUrl, A.conversion_rate, A.safety_stock, A.raw_material_count, From b70c7483e323590175dd6014d5ef7b81fe435932 Mon Sep 17 00:00:00 2001 From: pilltong22 <106594632+pilltong22@users.noreply.github.com> Date: Wed, 7 Jan 2026 02:49:17 +0900 Subject: [PATCH 44/56] fix: add AS imageUrl alias to all SQL queries (findById, findByIdWithBom) --- .../com/werp/sero/material/query/dao/MaterialMapper.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/resources/com/werp/sero/material/query/dao/MaterialMapper.xml b/src/main/resources/com/werp/sero/material/query/dao/MaterialMapper.xml index 1c296b6f..1199dcd4 100644 --- a/src/main/resources/com/werp/sero/material/query/dao/MaterialMapper.xml +++ b/src/main/resources/com/werp/sero/material/query/dao/MaterialMapper.xml @@ -114,7 +114,7 @@ A.moq, A.cycle_time, A.unit_price, - A.image_url, + A.image_url AS imageUrl, A.conversion_rate, A.safety_stock, A.raw_material_count, @@ -156,7 +156,7 @@ A.moq, A.cycle_time, A.unit_price, - A.image_url, + A.image_url AS imageUrl, A.conversion_rate, A.safety_stock, A.raw_material_count, From 162c3e6c60c932809c1d41bed1de1a2766d99fd3 Mon Sep 17 00:00:00 2001 From: pilltong22 <106594632+pilltong22@users.noreply.github.com> Date: Wed, 7 Jan 2026 02:51:57 +0900 Subject: [PATCH 45/56] debug: enable MyBatis SQL logging to see actual query results --- .github/workflows/deploy.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 41f615f6..3ef56911 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -86,6 +86,7 @@ jobs: type-aliases-package: com.werp.sero.**.dto configuration: map-underscore-to-camel-case: true + log-impl: org.apache.ibatis.logging.stdout.StdOutImpl EOL - name: Set Yaml From bcf6fa9b98d3917533da8995400b1b098e69cc34 Mon Sep 17 00:00:00 2001 From: pilltong22 <106594632+pilltong22@users.noreply.github.com> Date: Wed, 7 Jan 2026 03:09:52 +0900 Subject: [PATCH 46/56] =?UTF-8?q?=EC=88=98=EC=A0=95:=20ResultMap=EC=9D=98?= =?UTF-8?q?=20imageUrl=20=EC=BB=AC=EB=9F=BC=20=EB=A7=A4=ED=95=91=EC=9D=84?= =?UTF-8?q?=20image=5Furl=EC=97=90=EC=84=9C=20imageUrl=EB=A1=9C=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD=ED=95=98=EC=97=AC=20SQL=20AS=20=EB=B3=84?= =?UTF-8?q?=EC=B9=AD=EA=B3=BC=20=EC=9D=BC=EC=B9=98=EC=8B=9C=ED=82=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/werp/sero/material/query/dao/MaterialMapper.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/resources/com/werp/sero/material/query/dao/MaterialMapper.xml b/src/main/resources/com/werp/sero/material/query/dao/MaterialMapper.xml index 1199dcd4..a1bd6caf 100644 --- a/src/main/resources/com/werp/sero/material/query/dao/MaterialMapper.xml +++ b/src/main/resources/com/werp/sero/material/query/dao/MaterialMapper.xml @@ -13,7 +13,7 @@ - + @@ -33,7 +33,7 @@ - + From 0ca2e3e798b94efffa1b5e277f6bef39314426a7 Mon Sep 17 00:00:00 2001 From: rosie98 Date: Wed, 7 Jan 2026 10:15:50 +0900 Subject: [PATCH 47/56] =?UTF-8?q?fix:=20#192=20-=20=EA=B2=B0=EC=9E=AC=20?= =?UTF-8?q?=EA=B8=B0=EC=95=88=20=EC=83=81=EC=8B=A0=20=EC=8B=9C,=20LazyInit?= =?UTF-8?q?ializationException=20=EC=97=90=EB=9F=AC=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/controller/ApprovalCommandController.java | 2 +- .../command/application/service/ApprovalCommandService.java | 2 +- .../application/service/ApprovalCommandServiceImpl.java | 4 +++- .../werp/sero/employee/command/domain/aggregate/Employee.java | 4 +--- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/werp/sero/approval/command/application/controller/ApprovalCommandController.java b/src/main/java/com/werp/sero/approval/command/application/controller/ApprovalCommandController.java index 01aab9bf..1e4f4a47 100644 --- a/src/main/java/com/werp/sero/approval/command/application/controller/ApprovalCommandController.java +++ b/src/main/java/com/werp/sero/approval/command/application/controller/ApprovalCommandController.java @@ -26,7 +26,7 @@ public class ApprovalCommandController { @Operation(summary = "결재 상신") @PostMapping(consumes = {MediaType.MULTIPART_FORM_DATA_VALUE}) - public ResponseEntity submitForApproval(@CurrentUser final Employee employee, + public ResponseEntity submitForApproval(@CurrentUser Employee employee, @Valid @RequestPart(name = "requestDTO") final ApprovalCreateRequestDTO requestDTO, @RequestPart(name = "files", required = false) final List files) { return ResponseEntity.ok(approvalCommandService.submitForApproval(employee, requestDTO, files)); diff --git a/src/main/java/com/werp/sero/approval/command/application/service/ApprovalCommandService.java b/src/main/java/com/werp/sero/approval/command/application/service/ApprovalCommandService.java index e6c90066..b25f24cc 100644 --- a/src/main/java/com/werp/sero/approval/command/application/service/ApprovalCommandService.java +++ b/src/main/java/com/werp/sero/approval/command/application/service/ApprovalCommandService.java @@ -9,7 +9,7 @@ import java.util.List; public interface ApprovalCommandService { - ApprovalResponseDTO submitForApproval(final Employee employee, final ApprovalCreateRequestDTO requestDTO, + ApprovalResponseDTO submitForApproval(Employee employee, final ApprovalCreateRequestDTO requestDTO, final List files); void approve(final Employee employee, final int approvalId, final ApprovalDecisionRequestDTO requestDTO); diff --git a/src/main/java/com/werp/sero/approval/command/application/service/ApprovalCommandServiceImpl.java b/src/main/java/com/werp/sero/approval/command/application/service/ApprovalCommandServiceImpl.java index 1dcbaa99..456d2cee 100644 --- a/src/main/java/com/werp/sero/approval/command/application/service/ApprovalCommandServiceImpl.java +++ b/src/main/java/com/werp/sero/approval/command/application/service/ApprovalCommandServiceImpl.java @@ -52,8 +52,10 @@ public class ApprovalCommandServiceImpl implements ApprovalCommandService { @Transactional @Override - public ApprovalResponseDTO submitForApproval(final Employee employee, final ApprovalCreateRequestDTO requestDTO, + public ApprovalResponseDTO submitForApproval(Employee employee, final ApprovalCreateRequestDTO requestDTO, final List files) { + employee = employeeRepository.findById(employee.getId()).orElseThrow(EmployeeNotFoundException::new); + validateDuplicateApproval(requestDTO.getRefCode()); validateApprovalLines(requestDTO.getApprovalLines()); diff --git a/src/main/java/com/werp/sero/employee/command/domain/aggregate/Employee.java b/src/main/java/com/werp/sero/employee/command/domain/aggregate/Employee.java index b0ebb9dc..1c319be0 100644 --- a/src/main/java/com/werp/sero/employee/command/domain/aggregate/Employee.java +++ b/src/main/java/com/werp/sero/employee/command/domain/aggregate/Employee.java @@ -45,9 +45,7 @@ public class Employee { @Column(name = "created_at", nullable = false) private String createdAt; - // ▼▼▼ [핵심 수정 부분] ▼▼▼ - @ManyToOne(fetch = FetchType.LAZY) // 1. 지연 로딩: 필요할 때만 조회 (쿼리 폭탄 방지) + @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "dept_id") - @JsonIgnore // 2. JSON 무시: 직렬화 시 부서 정보를 쳐다보지 않음 (무한 루프 방지) private Department department; } \ No newline at end of file From 7e26d1baaac032aea1e70e49953606509ef315df Mon Sep 17 00:00:00 2001 From: rosie98 Date: Wed, 7 Jan 2026 10:39:46 +0900 Subject: [PATCH 48/56] =?UTF-8?q?fix:=20#194=20-=20=EA=B3=B5=EC=A7=80?= =?UTF-8?q?=EC=82=AC=ED=95=AD=20=EB=93=B1=EB=A1=9D=20=EC=8B=9C,=20LazyInit?= =?UTF-8?q?ializationException=20=EC=97=90=EB=9F=AC=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/controller/NoticeCommandController.java | 2 +- .../command/application/service/NoticeCommandService.java | 2 +- .../application/service/NoticeCommandServiceImpl.java | 7 ++++++- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/werp/sero/notice/command/application/controller/NoticeCommandController.java b/src/main/java/com/werp/sero/notice/command/application/controller/NoticeCommandController.java index eec5724a..2a7b44d5 100644 --- a/src/main/java/com/werp/sero/notice/command/application/controller/NoticeCommandController.java +++ b/src/main/java/com/werp/sero/notice/command/application/controller/NoticeCommandController.java @@ -25,7 +25,7 @@ public class NoticeCommandController { @Operation(summary = "공지사항 등록") @PostMapping(consumes = {MediaType.MULTIPART_FORM_DATA_VALUE}) - public ResponseEntity registerNotice(@CurrentUser final Employee employee, + public ResponseEntity registerNotice(@CurrentUser Employee employee, @Valid @RequestPart(name = "requestDTO") final NoticeCreateRequestDTO requestDTO, @RequestPart(name = "files", required = false) final List files) { final NoticeResponseDTO response = noticeCommandService.registerNotice(employee, requestDTO, files); diff --git a/src/main/java/com/werp/sero/notice/command/application/service/NoticeCommandService.java b/src/main/java/com/werp/sero/notice/command/application/service/NoticeCommandService.java index 119f5049..e639cf88 100644 --- a/src/main/java/com/werp/sero/notice/command/application/service/NoticeCommandService.java +++ b/src/main/java/com/werp/sero/notice/command/application/service/NoticeCommandService.java @@ -8,7 +8,7 @@ import java.util.List; public interface NoticeCommandService { - NoticeResponseDTO registerNotice(final Employee employee, final NoticeCreateRequestDTO requestDTO, + NoticeResponseDTO registerNotice(Employee employee, final NoticeCreateRequestDTO requestDTO, final List files); void deleteNotice(final Employee employee, final int noticeId); diff --git a/src/main/java/com/werp/sero/notice/command/application/service/NoticeCommandServiceImpl.java b/src/main/java/com/werp/sero/notice/command/application/service/NoticeCommandServiceImpl.java index c217c8b1..351ca2ff 100644 --- a/src/main/java/com/werp/sero/notice/command/application/service/NoticeCommandServiceImpl.java +++ b/src/main/java/com/werp/sero/notice/command/application/service/NoticeCommandServiceImpl.java @@ -7,6 +7,8 @@ import com.werp.sero.common.file.S3Uploader; import com.werp.sero.common.util.DateTimeUtils; import com.werp.sero.employee.command.domain.aggregate.Employee; +import com.werp.sero.employee.command.domain.repository.EmployeeRepository; +import com.werp.sero.employee.exception.EmployeeNotFoundException; import com.werp.sero.notice.command.application.dto.NoticeAttachmentResponseDTO; import com.werp.sero.notice.command.application.dto.NoticeCreateRequestDTO; import com.werp.sero.notice.command.application.dto.NoticeResponseDTO; @@ -36,13 +38,16 @@ public class NoticeCommandServiceImpl implements NoticeCommandService { private final S3Uploader s3Uploader; private final FileValidator fileValidator; private final EmployeePermissionRepository employeePermissionRepository; + private final EmployeeRepository employeeRepository; private final CommonCodeManageQueryService commonCodeManageQueryService; @Transactional @Override - public NoticeResponseDTO registerNotice(final Employee employee, final NoticeCreateRequestDTO requestDTO, + public NoticeResponseDTO registerNotice(Employee employee, final NoticeCreateRequestDTO requestDTO, final List files) { + employee = employeeRepository.findById(employee.getId()).orElseThrow(EmployeeNotFoundException::new); + validateCategory(requestDTO.getCategory()); Notice notice = new Notice(requestDTO.getTitle(), requestDTO.getContent(), requestDTO.getCategory(), From 41156ed9fc97a57e38164624531cf3498d2863d5 Mon Sep 17 00:00:00 2001 From: rosie98 Date: Wed, 7 Jan 2026 12:09:28 +0900 Subject: [PATCH 49/56] =?UTF-8?q?fix:=20#198=20-=20Employee=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=20=EC=8B=9C=20department=20LAZY=20=EB=A1=9C=EB=94=A9?= =?UTF-8?q?=20=EB=AC=B8=EC=A0=9C=20=ED=95=B4=EA=B2=B0=20(fetch=20join=20?= =?UTF-8?q?=EC=A0=81=EC=9A=A9)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/service/ApprovalCommandServiceImpl.java | 2 -- .../command/domain/repository/EmployeeRepository.java | 4 +++- .../application/service/NoticeCommandServiceImpl.java | 5 ----- .../sero/security/service/EmployeeUserDetailsService.java | 2 +- 4 files changed, 4 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/werp/sero/approval/command/application/service/ApprovalCommandServiceImpl.java b/src/main/java/com/werp/sero/approval/command/application/service/ApprovalCommandServiceImpl.java index 4ddcf8e8..e8245bf9 100644 --- a/src/main/java/com/werp/sero/approval/command/application/service/ApprovalCommandServiceImpl.java +++ b/src/main/java/com/werp/sero/approval/command/application/service/ApprovalCommandServiceImpl.java @@ -55,8 +55,6 @@ public class ApprovalCommandServiceImpl implements ApprovalCommandService { @Override public ApprovalResponseDTO submitForApproval(Employee employee, final ApprovalCreateRequestDTO requestDTO, final List files) { - employee = employeeRepository.findById(employee.getId()).orElseThrow(EmployeeNotFoundException::new); - validateDuplicateApproval(requestDTO.getRefCode()); validateApprovalLines(requestDTO.getApprovalLines()); diff --git a/src/main/java/com/werp/sero/employee/command/domain/repository/EmployeeRepository.java b/src/main/java/com/werp/sero/employee/command/domain/repository/EmployeeRepository.java index ddfee4a0..e4a75d0a 100644 --- a/src/main/java/com/werp/sero/employee/command/domain/repository/EmployeeRepository.java +++ b/src/main/java/com/werp/sero/employee/command/domain/repository/EmployeeRepository.java @@ -2,12 +2,14 @@ import com.werp.sero.employee.command.domain.aggregate.Employee; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; import java.util.List; import java.util.Optional; public interface EmployeeRepository extends JpaRepository { - Optional findByEmailAndStatus(final String email, final String status); + @Query("SELECT e FROM Employee e LEFT JOIN FETCH e.department WHERE e.email = :email AND e.status = :status") + Optional findByEmailAndStatusWithFetchJoin(final String email, final String status); List findByIdIn(final List employeeIds); } \ No newline at end of file diff --git a/src/main/java/com/werp/sero/notice/command/application/service/NoticeCommandServiceImpl.java b/src/main/java/com/werp/sero/notice/command/application/service/NoticeCommandServiceImpl.java index 351ca2ff..9a953b4b 100644 --- a/src/main/java/com/werp/sero/notice/command/application/service/NoticeCommandServiceImpl.java +++ b/src/main/java/com/werp/sero/notice/command/application/service/NoticeCommandServiceImpl.java @@ -7,8 +7,6 @@ import com.werp.sero.common.file.S3Uploader; import com.werp.sero.common.util.DateTimeUtils; import com.werp.sero.employee.command.domain.aggregate.Employee; -import com.werp.sero.employee.command.domain.repository.EmployeeRepository; -import com.werp.sero.employee.exception.EmployeeNotFoundException; import com.werp.sero.notice.command.application.dto.NoticeAttachmentResponseDTO; import com.werp.sero.notice.command.application.dto.NoticeCreateRequestDTO; import com.werp.sero.notice.command.application.dto.NoticeResponseDTO; @@ -38,7 +36,6 @@ public class NoticeCommandServiceImpl implements NoticeCommandService { private final S3Uploader s3Uploader; private final FileValidator fileValidator; private final EmployeePermissionRepository employeePermissionRepository; - private final EmployeeRepository employeeRepository; private final CommonCodeManageQueryService commonCodeManageQueryService; @@ -46,8 +43,6 @@ public class NoticeCommandServiceImpl implements NoticeCommandService { @Override public NoticeResponseDTO registerNotice(Employee employee, final NoticeCreateRequestDTO requestDTO, final List files) { - employee = employeeRepository.findById(employee.getId()).orElseThrow(EmployeeNotFoundException::new); - validateCategory(requestDTO.getCategory()); Notice notice = new Notice(requestDTO.getTitle(), requestDTO.getContent(), requestDTO.getCategory(), diff --git a/src/main/java/com/werp/sero/security/service/EmployeeUserDetailsService.java b/src/main/java/com/werp/sero/security/service/EmployeeUserDetailsService.java index 6842494c..0a6c30d4 100644 --- a/src/main/java/com/werp/sero/security/service/EmployeeUserDetailsService.java +++ b/src/main/java/com/werp/sero/security/service/EmployeeUserDetailsService.java @@ -21,7 +21,7 @@ public class EmployeeUserDetailsService implements UserDetailsService { @Override public UserDetails loadUserByUsername(final String username) throws UsernameNotFoundException { - final Employee employee = employeeRepository.findByEmailAndStatus(username, "ES_ACT") + final Employee employee = employeeRepository.findByEmailAndStatusWithFetchJoin(username, "ES_ACT") .orElseThrow(EmployeeNotFoundException::new); final List permissions = employeePermissionRepository.findPermissionCodeByEmployee(employee); From cae568e499993bc1b855e2388b13d74a1936479a Mon Sep 17 00:00:00 2001 From: rosie98 Date: Wed, 7 Jan 2026 14:18:56 +0900 Subject: [PATCH 50/56] =?UTF-8?q?fix:=20#204=20-=20=EC=BF=A0=ED=82=A4=20?= =?UTF-8?q?=EC=98=B5=EC=85=98=20=EC=88=98=EC=A0=95(sameSite=EB=A5=BC=20Lax?= =?UTF-8?q?,=20secure=EB=A5=BC=20false=EB=A1=9C=20=EC=88=98=EC=A0=95)=20jo?= =?UTF-8?q?in=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/werp/sero/util/CookieUtil.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/werp/sero/util/CookieUtil.java b/src/main/java/com/werp/sero/util/CookieUtil.java index 3aed3edd..3f5229ec 100644 --- a/src/main/java/com/werp/sero/util/CookieUtil.java +++ b/src/main/java/com/werp/sero/util/CookieUtil.java @@ -15,9 +15,9 @@ public class CookieUtil { public void generateRefreshTokenCookie(final HttpServletResponse response, final JwtToken token) { final ResponseCookie responseCookie = ResponseCookie.from(COOKIE_NAME, token.getToken()) .httpOnly(true) - .sameSite("None") + .sameSite("Lax") .path("/") - .secure(true) + .secure(false) .maxAge(token.getExpirationTime() / 1000) .build(); @@ -27,9 +27,9 @@ public void generateRefreshTokenCookie(final HttpServletResponse response, final public void deleteRefreshTokenCookie(final HttpServletResponse response) { final ResponseCookie responseCookie = ResponseCookie.from(COOKIE_NAME, null) .httpOnly(true) - .sameSite("None") + .sameSite("Lax") .path("/") - .secure(true) + .secure(false) .maxAge(0) .build(); From 9567ac323634d0c7680ce1783eb6085babe3676c Mon Sep 17 00:00:00 2001 From: pilltong22 Date: Wed, 7 Jan 2026 16:23:41 +0900 Subject: [PATCH 51/56] =?UTF-8?q?jwt=20=ED=86=A0=ED=81=B0=20=EB=A7=8C?= =?UTF-8?q?=EB=A3=8C=EC=8B=9C=EA=B0=84=20=EC=88=98=EC=A0=95=20=ED=99=95?= =?UTF-8?q?=EC=9D=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../resources/com/werp/sero/material/query/dao/BomMapper.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/com/werp/sero/material/query/dao/BomMapper.xml b/src/main/resources/com/werp/sero/material/query/dao/BomMapper.xml index 458c3d10..19065843 100644 --- a/src/main/resources/com/werp/sero/material/query/dao/BomMapper.xml +++ b/src/main/resources/com/werp/sero/material/query/dao/BomMapper.xml @@ -17,7 +17,7 @@ - + From 4d6985f9c1314a04e42d1fa668cb2f649e0f5c49 Mon Sep 17 00:00:00 2001 From: rosie98 Date: Thu, 8 Jan 2026 17:16:12 +0900 Subject: [PATCH 52/56] =?UTF-8?q?chore:=20HTTPS=20=EC=A0=81=EC=9A=A9?= =?UTF-8?q?=EC=97=90=20=EB=94=B0=EB=A5=B8=20CORS=20=EC=84=A4=EC=A0=95=20?= =?UTF-8?q?=EB=B0=8F=20=EC=BF=A0=ED=82=A4=20=EC=98=B5=EC=85=98=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/werp/sero/config/CorsConfig.java | 9 ++++----- src/main/java/com/werp/sero/util/CookieUtil.java | 8 ++++---- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/werp/sero/config/CorsConfig.java b/src/main/java/com/werp/sero/config/CorsConfig.java index 54b95a24..ca254e39 100644 --- a/src/main/java/com/werp/sero/config/CorsConfig.java +++ b/src/main/java/com/werp/sero/config/CorsConfig.java @@ -7,6 +7,7 @@ import org.springframework.web.cors.UrlBasedCorsConfigurationSource; import java.util.List; + // @Configuration public class CorsConfig { @@ -15,12 +16,10 @@ public CorsConfigurationSource corsConfigurationSource() { CorsConfiguration configuration = new CorsConfiguration(); configuration.setAllowedOrigins(List.of( - "http://localhost:5173", - "http://sero-f-alb-2092902385.ap-northeast-2.elb.amazonaws.com", - "http://sero-erp.cloud", - "http://api.sero-erp.cloud" + "http://localhost:5173", + "https://sero-erp.cloud" )); - + configuration.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS")); configuration.setAllowedHeaders(List.of("*")); configuration.setAllowCredentials(true); diff --git a/src/main/java/com/werp/sero/util/CookieUtil.java b/src/main/java/com/werp/sero/util/CookieUtil.java index 3f5229ec..3aed3edd 100644 --- a/src/main/java/com/werp/sero/util/CookieUtil.java +++ b/src/main/java/com/werp/sero/util/CookieUtil.java @@ -15,9 +15,9 @@ public class CookieUtil { public void generateRefreshTokenCookie(final HttpServletResponse response, final JwtToken token) { final ResponseCookie responseCookie = ResponseCookie.from(COOKIE_NAME, token.getToken()) .httpOnly(true) - .sameSite("Lax") + .sameSite("None") .path("/") - .secure(false) + .secure(true) .maxAge(token.getExpirationTime() / 1000) .build(); @@ -27,9 +27,9 @@ public void generateRefreshTokenCookie(final HttpServletResponse response, final public void deleteRefreshTokenCookie(final HttpServletResponse response) { final ResponseCookie responseCookie = ResponseCookie.from(COOKIE_NAME, null) .httpOnly(true) - .sameSite("Lax") + .sameSite("None") .path("/") - .secure(false) + .secure(true) .maxAge(0) .build(); From b0d8dbb47d8caab6b5094f9f9b8b642345b00bd4 Mon Sep 17 00:00:00 2001 From: rosie98 Date: Thu, 8 Jan 2026 17:24:55 +0900 Subject: [PATCH 53/56] =?UTF-8?q?fix:=20CORS=20=EC=84=A4=EC=A0=95=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/werp/sero/config/CorsConfig.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/com/werp/sero/config/CorsConfig.java b/src/main/java/com/werp/sero/config/CorsConfig.java index ca254e39..fe8f655a 100644 --- a/src/main/java/com/werp/sero/config/CorsConfig.java +++ b/src/main/java/com/werp/sero/config/CorsConfig.java @@ -17,6 +17,7 @@ public CorsConfigurationSource corsConfigurationSource() { configuration.setAllowedOrigins(List.of( "http://localhost:5173", + "http://sero-f-alb-2092902385.ap-northeast-2.elb.amazonaws.com", "https://sero-erp.cloud" )); From 32a9b85bf075a3a8764f23a5df951bb4d0e3e89c Mon Sep 17 00:00:00 2001 From: pilltong22 Date: Thu, 8 Jan 2026 17:59:44 +0900 Subject: [PATCH 54/56] =?UTF-8?q?whitelist=20=EC=B6=94=EA=B0=80=20(?= =?UTF-8?q?=EB=8B=A4=20=ED=97=88=EC=9A=A9)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/werp/sero/config/CorsConfig.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/werp/sero/config/CorsConfig.java b/src/main/java/com/werp/sero/config/CorsConfig.java index fe8f655a..0b356872 100644 --- a/src/main/java/com/werp/sero/config/CorsConfig.java +++ b/src/main/java/com/werp/sero/config/CorsConfig.java @@ -17,8 +17,13 @@ public CorsConfigurationSource corsConfigurationSource() { configuration.setAllowedOrigins(List.of( "http://localhost:5173", + "https://localhost:5173", "http://sero-f-alb-2092902385.ap-northeast-2.elb.amazonaws.com", - "https://sero-erp.cloud" + "https://sero-f-alb-2092902385.ap-northeast-2.elb.amazonaws.com", + "https://sero-erp.cloud", + "http://sero-erp.cloud", + "http://api.sero-erp.cloud", + "https://api.sero-erp.cloud" )); configuration.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS")); From 2a6b297761f69092b0d677e160bf433d343cab78 Mon Sep 17 00:00:00 2001 From: pilltong22 <106594632+pilltong22@users.noreply.github.com> Date: Fri, 9 Jan 2026 06:48:29 +0900 Subject: [PATCH 55/56] =?UTF-8?q?CookieUtil.java=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/health-check.sh | 32 -------------- scripts/set-permissions.sh | 22 ---------- scripts/start.sh | 43 ------------------- scripts/stop.sh | 38 ---------------- .../java/com/werp/sero/util/CookieUtil.java | 4 +- 5 files changed, 2 insertions(+), 137 deletions(-) delete mode 100644 scripts/health-check.sh delete mode 100644 scripts/set-permissions.sh delete mode 100644 scripts/start.sh delete mode 100644 scripts/stop.sh diff --git a/scripts/health-check.sh b/scripts/health-check.sh deleted file mode 100644 index d4a524cc..00000000 --- a/scripts/health-check.sh +++ /dev/null @@ -1,32 +0,0 @@ -#!/bin/bash - -REPOSITORY=/home/ec2-user/app -PORT=5000 - -echo "> [$(date)] 애플리케이션 헬스체크 시작" >> $REPOSITORY/deploy.log - -# 최대 60초 동안 헬스체크 재시도 (Spring Boot 시작 시간 고려) -for i in {1..60}; do - # HTTP 헬스체크 (Spring Boot Actuator가 있다면 /actuator/health, 없으면 루트 경로) - HTTP_STATUS=$(curl -s -o /dev/null -w "%{http_code}" http://localhost:$PORT/actuator/health 2>/dev/null) - - # Actuator가 없는 경우 루트 경로로 재시도 - if [ "$HTTP_STATUS" == "000" ] || [ "$HTTP_STATUS" == "404" ]; then - HTTP_STATUS=$(curl -s -o /dev/null -w "%{http_code}" http://localhost:$PORT/ 2>/dev/null) - fi - - # 200-299 또는 300-399 응답이면 성공 - if [ "$HTTP_STATUS" -ge 200 ] && [ "$HTTP_STATUS" -lt 400 ]; then - echo "> [$(date)] 헬스체크 성공 (HTTP $HTTP_STATUS)" >> $REPOSITORY/deploy.log - echo "> [$(date)] 배포 완료!" >> $REPOSITORY/deploy.log - exit 0 - fi - - echo "> [$(date)] 헬스체크 재시도 중... ($i/60) - HTTP $HTTP_STATUS" >> $REPOSITORY/deploy.log - sleep 2 -done - -# 60초 동안 성공하지 못하면 실패 -echo "> [$(date)] ERROR: 헬스체크 실패 - 애플리케이션이 정상적으로 시작되지 않았습니다." >> $REPOSITORY/deploy.log -echo "> [$(date)] 로그 확인: tail -n 100 $REPOSITORY/logs/application.log" >> $REPOSITORY/deploy.log -exit 1 diff --git a/scripts/set-permissions.sh b/scripts/set-permissions.sh deleted file mode 100644 index fca5eedf..00000000 --- a/scripts/set-permissions.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/bash - -REPOSITORY=/home/ec2-user/app - -echo "> [$(date)] 파일 권한 설정 시작" >> $REPOSITORY/deploy.log - -# scripts 폴더의 모든 .sh 파일에 실행 권한 부여 -chmod +x $REPOSITORY/scripts/*.sh - -# jar 파일 찾기 -JAR_FILE=$(find $REPOSITORY/build/libs -name "*.jar" ! -name "*plain*" | head -n 1) - -if [ -n "$JAR_FILE" ]; then - chmod +x $JAR_FILE - echo "> [$(date)] JAR 파일 실행 권한 설정: $JAR_FILE" >> $REPOSITORY/deploy.log -else - echo "> [$(date)] WARNING: JAR 파일을 찾을 수 없습니다." >> $REPOSITORY/deploy.log -fi - -echo "> [$(date)] 파일 권한 설정 완료" >> $REPOSITORY/deploy.log - -exit 0 diff --git a/scripts/start.sh b/scripts/start.sh deleted file mode 100644 index beff1f75..00000000 --- a/scripts/start.sh +++ /dev/null @@ -1,43 +0,0 @@ -#!/bin/bash - -REPOSITORY=/home/ec2-user/app - -echo "> [$(date)] 애플리케이션 시작 준비" >> $REPOSITORY/deploy.log - -# JAR 파일 찾기 (plain.jar 제외) -JAR_FILE=$(find $REPOSITORY/build/libs -name "*.jar" ! -name "*plain*" | head -n 1) - -if [ -z "$JAR_FILE" ]; then - echo "> [$(date)] ERROR: JAR 파일을 찾을 수 없습니다." >> $REPOSITORY/deploy.log - exit 1 -fi - -JAR_NAME=$(basename $JAR_FILE) -echo "> [$(date)] 실행할 JAR: $JAR_NAME" >> $REPOSITORY/deploy.log - -# 로그 디렉토리 생성 -mkdir -p $REPOSITORY/logs - -# 애플리케이션 시작 -echo "> [$(date)] 애플리케이션 시작..." >> $REPOSITORY/deploy.log - -nohup java -jar \ - -Dserver.port=5000 \ - $JAR_FILE \ - > $REPOSITORY/logs/application.log 2>&1 & - -NEW_PID=$! -echo "> [$(date)] 애플리케이션 시작됨 (PID: $NEW_PID)" >> $REPOSITORY/deploy.log - -# 프로세스 시작 확인 (최대 10초 대기) -sleep 3 - -if ps -p $NEW_PID > /dev/null 2>&1; then - echo "> [$(date)] 애플리케이션이 정상적으로 시작되었습니다." >> $REPOSITORY/deploy.log - echo $NEW_PID > $REPOSITORY/app.pid - exit 0 -else - echo "> [$(date)] ERROR: 애플리케이션 시작 실패" >> $REPOSITORY/deploy.log - echo "> [$(date)] 로그 확인: tail -n 50 $REPOSITORY/logs/application.log" >> $REPOSITORY/deploy.log - exit 1 -fi diff --git a/scripts/stop.sh b/scripts/stop.sh deleted file mode 100644 index 99804832..00000000 --- a/scripts/stop.sh +++ /dev/null @@ -1,38 +0,0 @@ -#!/bin/bash - -REPOSITORY=/home/ec2-user/app - -echo "> [$(date)] 기존 애플리케이션 종료 시작" >> $REPOSITORY/deploy.log - -# 실행 중인 Spring Boot 애플리케이션 찾기 -CURRENT_PID=$(pgrep -f 'java.*application.jar') - -if [ -z "$CURRENT_PID" ]; then - echo "> [$(date)] 현재 실행 중인 애플리케이션이 없습니다." >> $REPOSITORY/deploy.log -else - echo "> [$(date)] 실행 중인 애플리케이션 PID: $CURRENT_PID" >> $REPOSITORY/deploy.log - echo "> [$(date)] 애플리케이션 종료 중..." >> $REPOSITORY/deploy.log - - # Graceful shutdown (SIGTERM) - kill -15 $CURRENT_PID - - # 프로세스가 종료될 때까지 최대 30초 대기 - for i in {1..30}; do - if ! ps -p $CURRENT_PID > /dev/null 2>&1; then - echo "> [$(date)] 애플리케이션이 정상적으로 종료되었습니다." >> $REPOSITORY/deploy.log - exit 0 - fi - sleep 1 - done - - # 30초 후에도 종료되지 않으면 강제 종료 - if ps -p $CURRENT_PID > /dev/null 2>&1; then - echo "> [$(date)] 강제 종료를 시도합니다." >> $REPOSITORY/deploy.log - kill -9 $CURRENT_PID - sleep 2 - fi - - echo "> [$(date)] 애플리케이션 종료 완료" >> $REPOSITORY/deploy.log -fi - -exit 0 diff --git a/src/main/java/com/werp/sero/util/CookieUtil.java b/src/main/java/com/werp/sero/util/CookieUtil.java index 3aed3edd..6b2cfbac 100644 --- a/src/main/java/com/werp/sero/util/CookieUtil.java +++ b/src/main/java/com/werp/sero/util/CookieUtil.java @@ -17,7 +17,7 @@ public void generateRefreshTokenCookie(final HttpServletResponse response, final .httpOnly(true) .sameSite("None") .path("/") - .secure(true) + .secure(true) // HTTPS 환경에서 SameSite=None은 반드시 Secure=true 필요 .maxAge(token.getExpirationTime() / 1000) .build(); @@ -29,7 +29,7 @@ public void deleteRefreshTokenCookie(final HttpServletResponse response) { .httpOnly(true) .sameSite("None") .path("/") - .secure(true) + .secure(true) // 생성 시와 동일한 설정으로 삭제해야 브라우저가 인식 .maxAge(0) .build(); From 7c4a6c5058a804ebf1810e0736983588c5881fb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=A7=84=ED=98=B8?= Date: Mon, 16 Mar 2026 15:48:14 +0900 Subject: [PATCH 56/56] ci-cd test --- .DS_Store | Bin 0 -> 8196 bytes .github/workflows/deploy.yml | 54 ++++++++++++++++++ Dockerfile | 9 +++ build.gradle | 7 ++- gradlew | 0 settings.gradle | 3 + src/.DS_Store | Bin 0 -> 6148 bytes .../com/werp/sero/HealthCheckController.java | 14 +++++ .../error/exception/BusinessException.java | 2 + .../config/ClientEmployeeSecurityConfig.java | 2 +- .../config/EmployeeSecurityConfig.java | 3 +- 11 files changed, 89 insertions(+), 5 deletions(-) create mode 100644 .DS_Store create mode 100644 .github/workflows/deploy.yml create mode 100644 Dockerfile mode change 100644 => 100755 gradlew create mode 100644 src/.DS_Store create mode 100644 src/main/java/com/werp/sero/HealthCheckController.java diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..ced6b2cde96972d3da35aa0fb935b6bbded7b53c GIT binary patch literal 8196 zcmeHMO=uHA6n>ke-IZ3&L7{?_MNdMlX{&`&3fnXl3L@hAbI@9|-Ow&>c0;l;hY|@M zJm^Kd34(a(MUei0c<|uOQx76|^5oHz(3>9Wo1MvKW;ZFG#Nteud6RkHoA>6+?7Ykt z0F->)9s?Kx01YdV*#T_26rv|JQBrK=3`zyDj}C0YD*(z24u=K%S<*qNGifl{q7pS& z6l#i+nkwvyp-^)i*BQ=WvPC5|2Zdce6y{lBHxwoGj`Qmw92A2}*-8c^14#zR-8}=N zumTPQ!u@^t>sww|_6r5e^(`FJHXbz}e%k&xE9&ii^_5lb-GFYODX49~unKjs1n;2i zB@uiK)%D!VUz=eJv3bgVCz9SMAs%|z(0Qs*1RGo^3Gs~WK9Ayw5PUo*hVRS_ZgKH& zs7^e+Q9?Z98-$-eCJHfg|gpmXG7&_uUI=8V6_3bJ86l_=hXRe;O?G?+L#3 zou3^I?|1vngZ7?acD&D|R`53y`s+h~b@b?hZ8d5Yw%guW71yZ+x!e~emCp3_tD33~ zsEg*R-!Ow>P_N~S)m!A#HQ#rwcE4!da7vA(?6EoD3yO|cs)h!RT|&t1n~rDujl5s? z>{@7RQiXO%)0VPBYir|ElOy{1+(dIkUz-}wVSi$>+0?Y-r_W7aUApI%J^wMG2onuU zNN|{bj@l>K<5tA8*#G(cw5a8oJUP2_o$Vyfo@cW=f@f4+d`bf0?C+aZ&-J|(93>GC zcDN3o!f3ZHxc)L@K8v_K*3rGNU=N@lPl{gHt^Kh4`T<`5h|k3{U~ERuw&0KFpcjT` z0pJ6=!E=U-85-gWl~ah|S2!S|ksS+9gdk@1EM}#`C0Kwtn1{ zz(0Jx&|hu8?;ur;S*H@7WjROlS5y4Tcd?Q}a4jlB6Kn{C xjEC28l+iy7v9B|o!DNd{)L{ARF9Kx#k1~8Ay0IlQJpWrOsg?OZ+`I?4`3;G7^;7@= literal 0 HcmV?d00001 diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml new file mode 100644 index 00000000..279c989c --- /dev/null +++ b/.github/workflows/deploy.yml @@ -0,0 +1,54 @@ +name: Deploy to ECS + +on: + push: + branches: + - main + +jobs: + deploy: + runs-on: ubuntu-latest + + steps: + + - name: Checkout + uses: actions/checkout@v3 + + - name: Setup Java + uses: actions/setup-java@v3 + with: + distribution: temurin + java-version: 17 + + - name: Build JAR + run: ./gradlew build -x test + + - name: Configure AWS credentials + uses: aws-actions/configure-aws-credentials@v2 + with: + aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} + aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + aws-region: ${{ secrets.AWS_REGION }} + + - name: Login to ECR + uses: aws-actions/amazon-ecr-login@v1 + + - name: Build Docker Image + run: docker build -t sero-backend . + + - name: Tag Docker Image + run: | + docker tag sero-backend:latest \ + ${{ secrets.AWS_ACCOUNT_ID }}.dkr.ecr.${{ secrets.AWS_REGION }}.amazonaws.com/sero-backend:latest + + - name: Push Docker Image + run: | + docker push \ + ${{ secrets.AWS_ACCOUNT_ID }}.dkr.ecr.${{ secrets.AWS_REGION }}.amazonaws.com/sero-backend:latest + + - name: Deploy to ECS + run: | + aws ecs update-service \ + --cluster sero-cluster-new \ + --service sero-task-n-service-ksz4njy2 \ + --force-new-deployment diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..4363a8b9 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,9 @@ +FROM eclipse-temurin:17-jre + +WORKDIR /app + +COPY build/libs/*.jar app.jar + +EXPOSE 8080 + +ENTRYPOINT ["java", "-jar", "app.jar"] diff --git a/build.gradle b/build.gradle index d3675823..2217d27f 100644 --- a/build.gradle +++ b/build.gradle @@ -27,10 +27,11 @@ repositories { dependencies { /* Spring boot */ implementation 'org.springframework.boot:spring-boot-starter-web' + implementation 'org.springframework.boot:spring-boot-starter-actuator' /* Mybatis */ implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:3.0.5' - +./gradlew clean build -x test /* JPA */ implementation 'org.springframework.boot:spring-boot-starter-data-jpa' @@ -39,8 +40,8 @@ dependencies { annotationProcessor 'org.projectlombok:lombok' /* Database */ -// runtimeOnly 'com.mysql:mysql-connector-j' - runtimeOnly 'org.mariadb.jdbc:mariadb-java-client' + runtimeOnly 'com.mysql:mysql-connector-j' + // runtimeOnly 'org.mariadb.jdbc:mariadb-java-client' /* Swagger OpenAPI */ implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.8.14' diff --git a/gradlew b/gradlew old mode 100644 new mode 100755 diff --git a/settings.gradle b/settings.gradle index add2273e..122237cf 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1 +1,4 @@ +plugins { + id 'org.gradle.toolchains.foojay-resolver-convention' version '0.10.0' +} rootProject.name = 'sero' \ No newline at end of file diff --git a/src/.DS_Store b/src/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..ed67abd9bfcfa2587ba639235d3a1d901077b435 GIT binary patch literal 6148 zcmeHKJ5Iwu5S;-RmS{{z>4uUb9dsr#9R*S@0KteL#W)h7x5Pm>1E+wqa0MFPd>~$7 zQ6dC0((c=xx3govC_7#v;^}=eAu5O{M-yZjjF`AbsV!eDB+DMl>&fi0YgZ$i{8pDd zdqyo?&<))t&tE*e4!O3g>-n;q!e9NyE18ok@5Q@BOx}rN;CwYlp zhTJgk{_fExugA9CChr)Z4e0AL2U8pd*$keJf3a_kMkz}P~87Rr9bVE;sA3kP5M`rgpOi8V9!@ys8W z7uM|Xm%5y|GK@YH2nA9FwryHS{XfB9X7rMuhQurs2nGI_0-V*edWx6w+WO`7q}G;b w=V)TGu9pD}V=cu%Eyb9~IkKmu@uiHxSB|}*>>_>*2gZkh3KCr?@B<3G17Ds-bN~PV literal 0 HcmV?d00001 diff --git a/src/main/java/com/werp/sero/HealthCheckController.java b/src/main/java/com/werp/sero/HealthCheckController.java new file mode 100644 index 00000000..2ef3c03a --- /dev/null +++ b/src/main/java/com/werp/sero/HealthCheckController.java @@ -0,0 +1,14 @@ +package com.werp.sero; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class HealthCheckController { + + @GetMapping("/") + public ResponseEntity health() { + return ResponseEntity.ok("OK"); + } +} diff --git a/src/main/java/com/werp/sero/common/error/exception/BusinessException.java b/src/main/java/com/werp/sero/common/error/exception/BusinessException.java index 47878bea..9ccbffd0 100644 --- a/src/main/java/com/werp/sero/common/error/exception/BusinessException.java +++ b/src/main/java/com/werp/sero/common/error/exception/BusinessException.java @@ -15,6 +15,8 @@ public BusinessException(final ErrorCode errorCode) { public BusinessException(final ErrorCode errorCode, final String message) { super(message); this.errorCode = errorCode; + + } diff --git a/src/main/java/com/werp/sero/security/config/ClientEmployeeSecurityConfig.java b/src/main/java/com/werp/sero/security/config/ClientEmployeeSecurityConfig.java index 289355bf..9117c98d 100644 --- a/src/main/java/com/werp/sero/security/config/ClientEmployeeSecurityConfig.java +++ b/src/main/java/com/werp/sero/security/config/ClientEmployeeSecurityConfig.java @@ -1,4 +1,4 @@ -package com.werp.sero.security.config; + package com.werp.sero.security.config; import com.werp.sero.security.handler.CustomAccessDeniedHandler; import com.werp.sero.security.handler.CustomAuthenticationEntryPoint; diff --git a/src/main/java/com/werp/sero/security/config/EmployeeSecurityConfig.java b/src/main/java/com/werp/sero/security/config/EmployeeSecurityConfig.java index 0cafdd80..cc9bd1aa 100644 --- a/src/main/java/com/werp/sero/security/config/EmployeeSecurityConfig.java +++ b/src/main/java/com/werp/sero/security/config/EmployeeSecurityConfig.java @@ -35,7 +35,8 @@ public class EmployeeSecurityConfig { "/swagger-ui/**", "/swagger-resources/**", "/auth/login", - + "/actuator/health", + "/", }; private static final String[] AUTHORITY_LIST = {