From 7aab5173cf7d02c34ad23cfefaf6118579034118 Mon Sep 17 00:00:00 2001 From: DongHoon Lee Date: Mon, 10 Mar 2025 00:36:08 +0900 Subject: [PATCH 01/15] =?UTF-8?q?[#315]=20refactor:=20dto=20=ED=8C=A8?= =?UTF-8?q?=ED=82=A4=EC=A7=80=20application=20=ED=8C=A8=ED=82=A4=EC=A7=80?= =?UTF-8?q?=20=ED=95=98=EC=9C=84=EB=A1=9C=20=EC=9D=B4=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/beat/domain/member/api/MemberApi.java | 4 ++-- .../java/com/beat/domain/member/api/MemberController.java | 6 +++--- .../domain/member/application/AuthenticationService.java | 5 ++--- .../beat/domain/member/application/SocialLoginService.java | 5 ++--- .../{ => application}/dto/AccessTokenGenerateResponse.java | 2 +- .../member/{ => application}/dto/LoginSuccessResponse.java | 2 +- .../member/{ => application}/dto/MemberLoginResponse.java | 2 +- 7 files changed, 12 insertions(+), 14 deletions(-) rename src/main/java/com/beat/domain/member/{ => application}/dto/AccessTokenGenerateResponse.java (81%) rename src/main/java/com/beat/domain/member/{ => application}/dto/LoginSuccessResponse.java (87%) rename src/main/java/com/beat/domain/member/{ => application}/dto/MemberLoginResponse.java (85%) diff --git a/src/main/java/com/beat/domain/member/api/MemberApi.java b/src/main/java/com/beat/domain/member/api/MemberApi.java index 1f2335b9..d5209b75 100644 --- a/src/main/java/com/beat/domain/member/api/MemberApi.java +++ b/src/main/java/com/beat/domain/member/api/MemberApi.java @@ -5,8 +5,8 @@ import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestParam; -import com.beat.domain.member.dto.AccessTokenGenerateResponse; -import com.beat.domain.member.dto.MemberLoginResponse; +import com.beat.domain.member.application.dto.AccessTokenGenerateResponse; +import com.beat.domain.member.application.dto.MemberLoginResponse; import com.beat.global.auth.annotation.CurrentMember; import com.beat.global.auth.client.dto.MemberLoginRequest; import com.beat.global.common.dto.ErrorResponse; diff --git a/src/main/java/com/beat/domain/member/api/MemberController.java b/src/main/java/com/beat/domain/member/api/MemberController.java index ba4206b0..0bd9847a 100644 --- a/src/main/java/com/beat/domain/member/api/MemberController.java +++ b/src/main/java/com/beat/domain/member/api/MemberController.java @@ -12,9 +12,9 @@ import com.beat.domain.member.application.AuthenticationService; import com.beat.domain.member.application.SocialLoginService; -import com.beat.domain.member.dto.AccessTokenGenerateResponse; -import com.beat.domain.member.dto.LoginSuccessResponse; -import com.beat.domain.member.dto.MemberLoginResponse; +import com.beat.domain.member.application.dto.AccessTokenGenerateResponse; +import com.beat.domain.member.application.dto.LoginSuccessResponse; +import com.beat.domain.member.application.dto.MemberLoginResponse; import com.beat.domain.member.exception.MemberSuccessCode; import com.beat.global.auth.annotation.CurrentMember; import com.beat.global.auth.client.dto.MemberLoginRequest; diff --git a/src/main/java/com/beat/domain/member/application/AuthenticationService.java b/src/main/java/com/beat/domain/member/application/AuthenticationService.java index 5984d7fb..26013ce8 100644 --- a/src/main/java/com/beat/domain/member/application/AuthenticationService.java +++ b/src/main/java/com/beat/domain/member/application/AuthenticationService.java @@ -1,7 +1,7 @@ package com.beat.domain.member.application; -import com.beat.domain.member.dto.AccessTokenGenerateResponse; -import com.beat.domain.member.dto.LoginSuccessResponse; +import com.beat.domain.member.application.dto.AccessTokenGenerateResponse; +import com.beat.domain.member.application.dto.LoginSuccessResponse; import com.beat.domain.user.domain.Role; import com.beat.domain.user.domain.Users; import com.beat.global.auth.client.dto.MemberInfoResponse; @@ -30,7 +30,6 @@ @Service @RequiredArgsConstructor public class AuthenticationService { - private static final String BEARER_PREFIX = "Bearer "; private final JwtTokenProvider jwtTokenProvider; private final TokenService tokenService; diff --git a/src/main/java/com/beat/domain/member/application/SocialLoginService.java b/src/main/java/com/beat/domain/member/application/SocialLoginService.java index 36b304c9..dcf8947a 100644 --- a/src/main/java/com/beat/domain/member/application/SocialLoginService.java +++ b/src/main/java/com/beat/domain/member/application/SocialLoginService.java @@ -2,11 +2,10 @@ import com.beat.domain.member.domain.Member; import com.beat.domain.member.domain.SocialType; -import com.beat.domain.member.dto.LoginSuccessResponse; +import com.beat.domain.member.application.dto.LoginSuccessResponse; import com.beat.domain.member.exception.MemberErrorCode; import com.beat.domain.member.port.in.MemberUseCase; import com.beat.domain.user.domain.Users; -import com.beat.domain.user.port.in.UserUseCase; import com.beat.global.auth.client.application.KakaoSocialService; import com.beat.global.auth.client.application.SocialService; import com.beat.global.auth.client.dto.MemberInfoResponse; @@ -116,4 +115,4 @@ private Long findOrRegisterMember(final MemberInfoResponse memberInfoResponse) { return memberRegistrationService.registerMemberWithUserInfo(memberInfoResponse); } -} \ No newline at end of file +} diff --git a/src/main/java/com/beat/domain/member/dto/AccessTokenGenerateResponse.java b/src/main/java/com/beat/domain/member/application/dto/AccessTokenGenerateResponse.java similarity index 81% rename from src/main/java/com/beat/domain/member/dto/AccessTokenGenerateResponse.java rename to src/main/java/com/beat/domain/member/application/dto/AccessTokenGenerateResponse.java index db4be892..ba1ac893 100644 --- a/src/main/java/com/beat/domain/member/dto/AccessTokenGenerateResponse.java +++ b/src/main/java/com/beat/domain/member/application/dto/AccessTokenGenerateResponse.java @@ -1,4 +1,4 @@ -package com.beat.domain.member.dto; +package com.beat.domain.member.application.dto; public record AccessTokenGenerateResponse( String accessToken diff --git a/src/main/java/com/beat/domain/member/dto/LoginSuccessResponse.java b/src/main/java/com/beat/domain/member/application/dto/LoginSuccessResponse.java similarity index 87% rename from src/main/java/com/beat/domain/member/dto/LoginSuccessResponse.java rename to src/main/java/com/beat/domain/member/application/dto/LoginSuccessResponse.java index e8f19d22..d2e0de6d 100644 --- a/src/main/java/com/beat/domain/member/dto/LoginSuccessResponse.java +++ b/src/main/java/com/beat/domain/member/application/dto/LoginSuccessResponse.java @@ -1,4 +1,4 @@ -package com.beat.domain.member.dto; +package com.beat.domain.member.application.dto; public record LoginSuccessResponse( String accessToken, diff --git a/src/main/java/com/beat/domain/member/dto/MemberLoginResponse.java b/src/main/java/com/beat/domain/member/application/dto/MemberLoginResponse.java similarity index 85% rename from src/main/java/com/beat/domain/member/dto/MemberLoginResponse.java rename to src/main/java/com/beat/domain/member/application/dto/MemberLoginResponse.java index 38b67af2..b4a519a1 100644 --- a/src/main/java/com/beat/domain/member/dto/MemberLoginResponse.java +++ b/src/main/java/com/beat/domain/member/application/dto/MemberLoginResponse.java @@ -1,4 +1,4 @@ -package com.beat.domain.member.dto; +package com.beat.domain.member.application.dto; public record MemberLoginResponse( String accessToken, From 3fe3d08701e4692ce61ee06163fae9675e437404 Mon Sep 17 00:00:00 2001 From: DongHoon Lee Date: Mon, 10 Mar 2025 00:37:50 +0900 Subject: [PATCH 02/15] =?UTF-8?q?[#315]=20refactor:=20=EC=9D=91=EB=8B=B5?= =?UTF-8?q?=20dto=20response=20=ED=8C=A8=ED=82=A4=EC=A7=80=EB=A1=9C=20?= =?UTF-8?q?=EC=9D=B4=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/beat/domain/member/api/MemberApi.java | 4 ++-- .../java/com/beat/domain/member/api/MemberController.java | 6 +++--- .../domain/member/application/AuthenticationService.java | 4 ++-- .../beat/domain/member/application/SocialLoginService.java | 2 +- .../dto/{ => response}/AccessTokenGenerateResponse.java | 2 +- .../dto/{ => response}/LoginSuccessResponse.java | 2 +- .../application/dto/{ => response}/MemberLoginResponse.java | 2 +- 7 files changed, 11 insertions(+), 11 deletions(-) rename src/main/java/com/beat/domain/member/application/dto/{ => response}/AccessTokenGenerateResponse.java (78%) rename src/main/java/com/beat/domain/member/application/dto/{ => response}/LoginSuccessResponse.java (85%) rename src/main/java/com/beat/domain/member/application/dto/{ => response}/MemberLoginResponse.java (82%) diff --git a/src/main/java/com/beat/domain/member/api/MemberApi.java b/src/main/java/com/beat/domain/member/api/MemberApi.java index d5209b75..25bb3a81 100644 --- a/src/main/java/com/beat/domain/member/api/MemberApi.java +++ b/src/main/java/com/beat/domain/member/api/MemberApi.java @@ -5,8 +5,8 @@ import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestParam; -import com.beat.domain.member.application.dto.AccessTokenGenerateResponse; -import com.beat.domain.member.application.dto.MemberLoginResponse; +import com.beat.domain.member.application.dto.response.AccessTokenGenerateResponse; +import com.beat.domain.member.application.dto.response.MemberLoginResponse; import com.beat.global.auth.annotation.CurrentMember; import com.beat.global.auth.client.dto.MemberLoginRequest; import com.beat.global.common.dto.ErrorResponse; diff --git a/src/main/java/com/beat/domain/member/api/MemberController.java b/src/main/java/com/beat/domain/member/api/MemberController.java index 0bd9847a..309ba2e0 100644 --- a/src/main/java/com/beat/domain/member/api/MemberController.java +++ b/src/main/java/com/beat/domain/member/api/MemberController.java @@ -12,9 +12,9 @@ import com.beat.domain.member.application.AuthenticationService; import com.beat.domain.member.application.SocialLoginService; -import com.beat.domain.member.application.dto.AccessTokenGenerateResponse; -import com.beat.domain.member.application.dto.LoginSuccessResponse; -import com.beat.domain.member.application.dto.MemberLoginResponse; +import com.beat.domain.member.application.dto.response.AccessTokenGenerateResponse; +import com.beat.domain.member.application.dto.response.LoginSuccessResponse; +import com.beat.domain.member.application.dto.response.MemberLoginResponse; import com.beat.domain.member.exception.MemberSuccessCode; import com.beat.global.auth.annotation.CurrentMember; import com.beat.global.auth.client.dto.MemberLoginRequest; diff --git a/src/main/java/com/beat/domain/member/application/AuthenticationService.java b/src/main/java/com/beat/domain/member/application/AuthenticationService.java index 26013ce8..94469954 100644 --- a/src/main/java/com/beat/domain/member/application/AuthenticationService.java +++ b/src/main/java/com/beat/domain/member/application/AuthenticationService.java @@ -1,7 +1,7 @@ package com.beat.domain.member.application; -import com.beat.domain.member.application.dto.AccessTokenGenerateResponse; -import com.beat.domain.member.application.dto.LoginSuccessResponse; +import com.beat.domain.member.application.dto.response.AccessTokenGenerateResponse; +import com.beat.domain.member.application.dto.response.LoginSuccessResponse; import com.beat.domain.user.domain.Role; import com.beat.domain.user.domain.Users; import com.beat.global.auth.client.dto.MemberInfoResponse; diff --git a/src/main/java/com/beat/domain/member/application/SocialLoginService.java b/src/main/java/com/beat/domain/member/application/SocialLoginService.java index dcf8947a..8c12b8f7 100644 --- a/src/main/java/com/beat/domain/member/application/SocialLoginService.java +++ b/src/main/java/com/beat/domain/member/application/SocialLoginService.java @@ -2,7 +2,7 @@ import com.beat.domain.member.domain.Member; import com.beat.domain.member.domain.SocialType; -import com.beat.domain.member.application.dto.LoginSuccessResponse; +import com.beat.domain.member.application.dto.response.LoginSuccessResponse; import com.beat.domain.member.exception.MemberErrorCode; import com.beat.domain.member.port.in.MemberUseCase; import com.beat.domain.user.domain.Users; diff --git a/src/main/java/com/beat/domain/member/application/dto/AccessTokenGenerateResponse.java b/src/main/java/com/beat/domain/member/application/dto/response/AccessTokenGenerateResponse.java similarity index 78% rename from src/main/java/com/beat/domain/member/application/dto/AccessTokenGenerateResponse.java rename to src/main/java/com/beat/domain/member/application/dto/response/AccessTokenGenerateResponse.java index ba1ac893..7d99fc9f 100644 --- a/src/main/java/com/beat/domain/member/application/dto/AccessTokenGenerateResponse.java +++ b/src/main/java/com/beat/domain/member/application/dto/response/AccessTokenGenerateResponse.java @@ -1,4 +1,4 @@ -package com.beat.domain.member.application.dto; +package com.beat.domain.member.application.dto.response; public record AccessTokenGenerateResponse( String accessToken diff --git a/src/main/java/com/beat/domain/member/application/dto/LoginSuccessResponse.java b/src/main/java/com/beat/domain/member/application/dto/response/LoginSuccessResponse.java similarity index 85% rename from src/main/java/com/beat/domain/member/application/dto/LoginSuccessResponse.java rename to src/main/java/com/beat/domain/member/application/dto/response/LoginSuccessResponse.java index d2e0de6d..9c037adf 100644 --- a/src/main/java/com/beat/domain/member/application/dto/LoginSuccessResponse.java +++ b/src/main/java/com/beat/domain/member/application/dto/response/LoginSuccessResponse.java @@ -1,4 +1,4 @@ -package com.beat.domain.member.application.dto; +package com.beat.domain.member.application.dto.response; public record LoginSuccessResponse( String accessToken, diff --git a/src/main/java/com/beat/domain/member/application/dto/MemberLoginResponse.java b/src/main/java/com/beat/domain/member/application/dto/response/MemberLoginResponse.java similarity index 82% rename from src/main/java/com/beat/domain/member/application/dto/MemberLoginResponse.java rename to src/main/java/com/beat/domain/member/application/dto/response/MemberLoginResponse.java index b4a519a1..e4be92c5 100644 --- a/src/main/java/com/beat/domain/member/application/dto/MemberLoginResponse.java +++ b/src/main/java/com/beat/domain/member/application/dto/response/MemberLoginResponse.java @@ -1,4 +1,4 @@ -package com.beat.domain.member.application.dto; +package com.beat.domain.member.application.dto.response; public record MemberLoginResponse( String accessToken, From 7ea24d89ddaf7eaf42f100e7139cdf62b1744950 Mon Sep 17 00:00:00 2001 From: DongHoon Lee Date: Mon, 10 Mar 2025 09:44:14 +0900 Subject: [PATCH 03/15] =?UTF-8?q?[#315]=20chore(build.gradle):=20slack=20w?= =?UTF-8?q?ebhook=20=EB=B0=8F=20@ConfigurationProperties=EC=9D=84=20?= =?UTF-8?q?=EC=82=AC=EC=9A=A9=ED=95=98=EA=B8=B0=20=EC=9C=84=ED=95=9C=20?= =?UTF-8?q?=EC=9D=98=EC=A1=B4=EC=84=B1=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/build.gradle b/build.gradle index 41b4fc21..4f8a9592 100644 --- a/build.gradle +++ b/build.gradle @@ -106,6 +106,12 @@ dependencies { // AOP implementation 'org.springframework.boot:spring-boot-starter-aop' + + // Slack Webhook + implementation 'com.slack.api:slack-api-client:1.45.3' + + // @ConfigurationProperties auto bean register + annotationProcessor "org.springframework.boot:spring-boot-configuration-processor" } jar { From 82dbafd69a01ed347f395c9d136c4b51a6820da5 Mon Sep 17 00:00:00 2001 From: DongHoon Lee Date: Mon, 10 Mar 2025 09:45:23 +0900 Subject: [PATCH 04/15] =?UTF-8?q?[#315]=20chore:=20slack=20=EC=9B=B9?= =?UTF-8?q?=ED=9B=85=20=EA=B2=BD=EB=A1=9C=20=EB=B0=8F=20=EC=8A=A4=EB=A0=88?= =?UTF-8?q?=EB=93=9C=20=ED=92=80=20=EC=82=AC=EC=9D=B4=EC=A6=88=20=EC=84=A4?= =?UTF-8?q?=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/resources/application-dev.yml | 8 ++++++++ src/main/resources/application-prod.yml | 8 ++++++++ 2 files changed, 16 insertions(+) diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml index b7fe1bc4..afcf2920 100644 --- a/src/main/resources/application-dev.yml +++ b/src/main/resources/application-dev.yml @@ -114,3 +114,11 @@ springdoc: operations-sorter: alpha display-request-duration: true urls-primary-name: general + +slack: + webhook: + url: ${DEV_SLACK_WEBHOOK_URL} + +thread-pool: + core-size: 2 + thread-name-prefix: executor- diff --git a/src/main/resources/application-prod.yml b/src/main/resources/application-prod.yml index 403f2df8..74166219 100644 --- a/src/main/resources/application-prod.yml +++ b/src/main/resources/application-prod.yml @@ -113,3 +113,11 @@ springdoc: operations-sorter: alpha display-request-duration: true urls-primary-name: general + +slack: + webhook: + url: ${PROD_SLACK_WEBHOOK_URL} + +thread-pool: + core-size: 2 + thread-name-prefix: executor- From df20e9ac807b964b9e614502a1282b22f86bfedd Mon Sep 17 00:00:00 2001 From: DongHoon Lee Date: Mon, 10 Mar 2025 09:47:37 +0900 Subject: [PATCH 05/15] =?UTF-8?q?[#315]=20feat(MemberRegistrationService):?= =?UTF-8?q?=20=ED=9A=8C=EC=9B=90=EA=B0=80=EC=9E=85=20=EC=9D=B4=EB=B2=A4?= =?UTF-8?q?=ED=8A=B8=EB=A5=BC=20=EB=B3=B4=EB=82=B4=EB=8A=94=20publisher=20?= =?UTF-8?q?=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/beat/BeatApplication.java | 2 ++ .../member/application/MemberRegistrationService.java | 8 ++++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/beat/BeatApplication.java b/src/main/java/com/beat/BeatApplication.java index 3dc74923..7dfb7785 100644 --- a/src/main/java/com/beat/BeatApplication.java +++ b/src/main/java/com/beat/BeatApplication.java @@ -3,6 +3,7 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.ImportAutoConfiguration; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.context.properties.ConfigurationPropertiesScan; import org.springframework.cloud.openfeign.EnableFeignClients; import org.springframework.cloud.openfeign.FeignAutoConfiguration; import org.springframework.context.annotation.EnableAspectJAutoProxy; @@ -14,6 +15,7 @@ @EnableScheduling @EnableAsync @EnableAspectJAutoProxy +@ConfigurationPropertiesScan @ImportAutoConfiguration({FeignAutoConfiguration.class}) public class BeatApplication { diff --git a/src/main/java/com/beat/domain/member/application/MemberRegistrationService.java b/src/main/java/com/beat/domain/member/application/MemberRegistrationService.java index 5f19fc65..d2f3b7d5 100644 --- a/src/main/java/com/beat/domain/member/application/MemberRegistrationService.java +++ b/src/main/java/com/beat/domain/member/application/MemberRegistrationService.java @@ -1,5 +1,6 @@ package com.beat.domain.member.application; +import com.beat.domain.member.application.dto.event.MemberRegisteredEvent; import com.beat.domain.member.dao.MemberRepository; import com.beat.domain.member.domain.Member; import com.beat.domain.user.dao.UserRepository; @@ -10,6 +11,7 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.context.ApplicationEventPublisher; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -18,6 +20,7 @@ @RequiredArgsConstructor public class MemberRegistrationService { + private final ApplicationEventPublisher eventPublisher; private final UserRepository userRepository; private final MemberRepository memberRepository; @@ -41,9 +44,10 @@ public Long registerMemberWithUserInfo(final MemberInfoResponse memberInfoRespon ); memberRepository.save(member); - log.info("Member registered with memberId: {}, role: {}", member.getId(), users.getRole()); + eventPublisher.publishEvent(new MemberRegisteredEvent(member.getNickname())); + return member.getId(); } -} \ No newline at end of file +} From 472394ae7f1dcf54bf106b767453913ccc63dc79 Mon Sep 17 00:00:00 2001 From: DongHoon Lee Date: Mon, 10 Mar 2025 09:48:25 +0900 Subject: [PATCH 06/15] =?UTF-8?q?[#315]=20feat(MemberRegisteredEvent):=20?= =?UTF-8?q?=ED=9A=8C=EC=9B=90=EA=B0=80=EC=9E=85=20=EC=8B=9C=20=EC=9D=B4?= =?UTF-8?q?=EB=B2=A4=ED=8A=B8=EB=A1=9C=20=EC=9C=A0=EC=A0=80=EC=9D=98=20?= =?UTF-8?q?=EB=8B=89=EB=84=A4=EC=9E=84=EC=9D=84=20=EB=8B=B4=EB=8A=94=20DTO?= =?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 --- .../member/application/dto/event/MemberRegisteredEvent.java | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 src/main/java/com/beat/domain/member/application/dto/event/MemberRegisteredEvent.java diff --git a/src/main/java/com/beat/domain/member/application/dto/event/MemberRegisteredEvent.java b/src/main/java/com/beat/domain/member/application/dto/event/MemberRegisteredEvent.java new file mode 100644 index 00000000..acbfa714 --- /dev/null +++ b/src/main/java/com/beat/domain/member/application/dto/event/MemberRegisteredEvent.java @@ -0,0 +1,6 @@ +package com.beat.domain.member.application.dto.event; + +public record MemberRegisteredEvent( + String nickname +) { +} From e1c6b84cabe70f2c088a45f0da9fc6a75a1264b0 Mon Sep 17 00:00:00 2001 From: DongHoon Lee Date: Mon, 10 Mar 2025 09:51:11 +0900 Subject: [PATCH 07/15] =?UTF-8?q?[#315]=20feat(MemberRegisteredEventListen?= =?UTF-8?q?er):=20=ED=9A=8C=EC=9B=90=EA=B0=80=EC=9E=85=20=EC=9D=B4?= =?UTF-8?q?=EB=B2=A4=ED=8A=B8=EB=A5=BC=20=EB=B0=9B=EC=95=84=EC=84=9C=20?= =?UTF-8?q?=EB=B9=84=EB=8F=99=EA=B8=B0=EB=A1=9C=20=EC=8A=AC=EB=9E=99=20?= =?UTF-8?q?=EC=84=9C=EB=B9=84=EC=8A=A4=EB=A1=9C=20=EC=9A=94=EC=B2=AD?= =?UTF-8?q?=EC=9D=84=20=EB=B3=B4=EB=82=B4=EB=8A=94=20=EC=9D=B4=EB=B2=A4?= =?UTF-8?q?=ED=8A=B8=EB=A6=AC=EC=8A=A4=EB=84=88=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../event/MemberRegisteredEventListener.java | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 src/main/java/com/beat/global/external/notification/slack/event/MemberRegisteredEventListener.java diff --git a/src/main/java/com/beat/global/external/notification/slack/event/MemberRegisteredEventListener.java b/src/main/java/com/beat/global/external/notification/slack/event/MemberRegisteredEventListener.java new file mode 100644 index 00000000..61651fe2 --- /dev/null +++ b/src/main/java/com/beat/global/external/notification/slack/event/MemberRegisteredEventListener.java @@ -0,0 +1,41 @@ +package com.beat.global.external.notification.slack.event; + +import java.util.HashMap; +import java.util.Map; + +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Component; +import org.springframework.transaction.event.TransactionPhase; +import org.springframework.transaction.event.TransactionalEventListener; + +import com.beat.domain.member.application.dto.event.MemberRegisteredEvent; +import com.beat.domain.member.port.in.MemberUseCase; +import com.beat.global.external.notification.slack.application.SlackService; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Component +@RequiredArgsConstructor +public class MemberRegisteredEventListener { + private static final String TEXT_KEY = "text"; + private static final String WELCOME_MESSAGE = "번째 유저가 회원가입했습니다 - "; + private static final String SLACK_TRANSFER_ERROR = "Slack 전송 실패"; + + private final MemberUseCase memberUseCase; + private final SlackService slackService; + + @Async("taskExecutor") + @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT) + public void sendSlackNotification(MemberRegisteredEvent event) { + Map payload = new HashMap<>(); + payload.put(TEXT_KEY, memberUseCase.countMembers() + WELCOME_MESSAGE + event.nickname()); + + try { + slackService.sendMessage(payload); + } catch (Exception e) { + throw new RuntimeException(SLACK_TRANSFER_ERROR); + } + } +} From 503ac2b0a95d5b7642fee6f028bcb008b042ba98 Mon Sep 17 00:00:00 2001 From: DongHoon Lee Date: Mon, 10 Mar 2025 09:51:56 +0900 Subject: [PATCH 08/15] =?UTF-8?q?[#315]=20feat:=20openFeign=EC=9D=84=20?= =?UTF-8?q?=EC=9D=B4=EC=9A=A9=ED=95=B4=20slack=20webhook=20URL=EB=A1=9C=20?= =?UTF-8?q?=EC=9A=94=EC=B2=AD=EC=9D=84=20=EB=B3=B4=EB=82=B4=EB=8A=94=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../slack/application/SlackClient.java | 15 +++++++++++++++ .../slack/application/SlackService.java | 18 ++++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 src/main/java/com/beat/global/external/notification/slack/application/SlackClient.java create mode 100644 src/main/java/com/beat/global/external/notification/slack/application/SlackService.java diff --git a/src/main/java/com/beat/global/external/notification/slack/application/SlackClient.java b/src/main/java/com/beat/global/external/notification/slack/application/SlackClient.java new file mode 100644 index 00000000..754d70a4 --- /dev/null +++ b/src/main/java/com/beat/global/external/notification/slack/application/SlackClient.java @@ -0,0 +1,15 @@ +package com.beat.global.external.notification.slack.application; + +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.http.MediaType; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; + +import java.util.Map; + +@FeignClient(name = "slackClient", url = "${slack.webhook.url}") +public interface SlackClient { + + @PostMapping(consumes = MediaType.APPLICATION_JSON_VALUE) + void sendMessage(@RequestBody Map payload); +} diff --git a/src/main/java/com/beat/global/external/notification/slack/application/SlackService.java b/src/main/java/com/beat/global/external/notification/slack/application/SlackService.java new file mode 100644 index 00000000..77e98fd4 --- /dev/null +++ b/src/main/java/com/beat/global/external/notification/slack/application/SlackService.java @@ -0,0 +1,18 @@ +package com.beat.global.external.notification.slack.application; + +import java.util.Map; + +import org.springframework.stereotype.Service; + +import lombok.RequiredArgsConstructor; + +@Service +@RequiredArgsConstructor +public class SlackService { + + private final SlackClient slackClient; + + public void sendMessage(Map payload) { + slackClient.sendMessage(payload); + } +} From f5653b452b88e8b9cc85cf683116e1dd393ccbee Mon Sep 17 00:00:00 2001 From: DongHoon Lee Date: Mon, 10 Mar 2025 09:52:40 +0900 Subject: [PATCH 09/15] =?UTF-8?q?[#315]=20feat:=20=ED=9A=8C=EC=9B=90?= =?UTF-8?q?=EA=B0=80=EC=9E=85=20=EC=9C=A0=EC=A0=80=20=EC=88=98=EB=A5=BC=20?= =?UTF-8?q?=EC=B8=A1=EC=A0=95=ED=95=98=EB=8A=94=20=EC=84=9C=EB=B9=84?= =?UTF-8?q?=EC=8A=A4=20=EB=A1=9C=EC=A7=81=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../beat/domain/member/application/MemberService.java | 9 ++++++++- .../com/beat/domain/member/port/in/MemberUseCase.java | 2 ++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/beat/domain/member/application/MemberService.java b/src/main/java/com/beat/domain/member/application/MemberService.java index 5fdb3a4b..2765589b 100644 --- a/src/main/java/com/beat/domain/member/application/MemberService.java +++ b/src/main/java/com/beat/domain/member/application/MemberService.java @@ -43,6 +43,7 @@ public Member findMemberBySocialIdAndSocialType(final Long socialId, final Socia .orElseThrow(() -> new NotFoundException(MemberErrorCode.MEMBER_NOT_FOUND)); } + @Override @Transactional public void deleteUser(final Long id) { Users users = userRepository.findById(id) @@ -50,4 +51,10 @@ public void deleteUser(final Long id) { userRepository.delete(users); } -} \ No newline at end of file + + @Override + @Transactional(readOnly = true) + public long countMembers() { + return memberRepository.count(); + } +} diff --git a/src/main/java/com/beat/domain/member/port/in/MemberUseCase.java b/src/main/java/com/beat/domain/member/port/in/MemberUseCase.java index 328a2f2f..36b19a34 100644 --- a/src/main/java/com/beat/domain/member/port/in/MemberUseCase.java +++ b/src/main/java/com/beat/domain/member/port/in/MemberUseCase.java @@ -11,4 +11,6 @@ public interface MemberUseCase { Member findMemberBySocialIdAndSocialType(Long socialId, SocialType socialType); void deleteUser(Long id); + + long countMembers(); } From 227660a8c5d083318d81dbaa2a4cfcaa7fb78a87 Mon Sep 17 00:00:00 2001 From: DongHoon Lee Date: Mon, 10 Mar 2025 09:53:08 +0900 Subject: [PATCH 10/15] =?UTF-8?q?[#315]=20feat(GlobalAsyncExceptionHandler?= =?UTF-8?q?):=20=EB=B9=84=EB=8F=99=EA=B8=B0=20=EC=98=88=EC=99=B8=20?= =?UTF-8?q?=ED=95=B8=EB=93=A4=EB=9F=AC=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../handler/GlobalAsyncExceptionHandler.java | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 src/main/java/com/beat/global/common/handler/GlobalAsyncExceptionHandler.java diff --git a/src/main/java/com/beat/global/common/handler/GlobalAsyncExceptionHandler.java b/src/main/java/com/beat/global/common/handler/GlobalAsyncExceptionHandler.java new file mode 100644 index 00000000..8d0ed18d --- /dev/null +++ b/src/main/java/com/beat/global/common/handler/GlobalAsyncExceptionHandler.java @@ -0,0 +1,27 @@ +package com.beat.global.common.handler; + +import java.lang.reflect.Method; + +import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler; +import org.springframework.lang.NonNull; +import org.springframework.lang.Nullable; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class GlobalAsyncExceptionHandler implements AsyncUncaughtExceptionHandler { + + @Override + public void handleUncaughtException(@NonNull Throwable ex, @NonNull Method method, @Nullable Object... params) { + if (params == null) { + log.error("비동기 작업 중 예외 발생! Method: [{}], Params: [null], Exception: [{}]", + method.getName(), ex.getMessage(), ex); + return; + } + + String paramValues = java.util.Arrays.toString(params); + + log.error("비동기 작업 중 예외 발생! Method: [{}], Params: [{}], Exception: [{}]", + method.getName(), paramValues, ex.getMessage(), ex); + } +} From f358757e428ba60b1e598e6df7ff4757dcd191cd Mon Sep 17 00:00:00 2001 From: DongHoon Lee Date: Mon, 10 Mar 2025 09:53:57 +0900 Subject: [PATCH 11/15] =?UTF-8?q?[#315]=20feat(AsyncThreadConfig):=20?= =?UTF-8?q?=EC=8A=A4=EB=A0=88=EB=93=9C=20=ED=92=80=20=EA=B4=80=EB=A0=A8=20?= =?UTF-8?q?Config=20=ED=81=B4=EB=9E=98=EC=8A=A4=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/config/AsyncThreadConfig.java | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 src/main/java/com/beat/global/common/config/AsyncThreadConfig.java diff --git a/src/main/java/com/beat/global/common/config/AsyncThreadConfig.java b/src/main/java/com/beat/global/common/config/AsyncThreadConfig.java new file mode 100644 index 00000000..8bf61512 --- /dev/null +++ b/src/main/java/com/beat/global/common/config/AsyncThreadConfig.java @@ -0,0 +1,40 @@ +package com.beat.global.common.config; + +import java.util.concurrent.Executor; +import java.util.concurrent.ThreadPoolExecutor; + +import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.AsyncConfigurer; +import org.springframework.scheduling.annotation.EnableAsync; +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; +import org.springframework.security.concurrent.DelegatingSecurityContextExecutor; + +import com.beat.global.common.handler.GlobalAsyncExceptionHandler; + +import lombok.RequiredArgsConstructor; + +@Configuration +@EnableAsync +@RequiredArgsConstructor +public class AsyncThreadConfig implements AsyncConfigurer { + private final ThreadPoolProperties threadPoolProperties; + + @Override + @Bean(name = "taskExecutor") + public Executor getAsyncExecutor() { + ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); + executor.setCorePoolSize(threadPoolProperties.getCoreSize()); + executor.setThreadNamePrefix(threadPoolProperties.getThreadNamePrefix()); + executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); + executor.initialize(); + return new DelegatingSecurityContextExecutor(executor.getThreadPoolExecutor()); + } + + @Override + @Bean + public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() { + return new GlobalAsyncExceptionHandler(); + } +} From 97ec4c764bcef0aab89204bf1b0064eef2cdf6c7 Mon Sep 17 00:00:00 2001 From: DongHoon Lee Date: Mon, 10 Mar 2025 09:54:39 +0900 Subject: [PATCH 12/15] =?UTF-8?q?[#315]=20feat(ThreadPoolProperties):=20?= =?UTF-8?q?=EC=8A=A4=EB=A0=88=EB=93=9C=20coreSize,=20namePrefix=EB=A5=BC?= =?UTF-8?q?=20=EA=B4=80=EB=A6=AC=ED=95=98=EB=8A=94=20ConfigurationProperti?= =?UTF-8?q?es=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../global/common/config/ThreadPoolProperties.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 src/main/java/com/beat/global/common/config/ThreadPoolProperties.java diff --git a/src/main/java/com/beat/global/common/config/ThreadPoolProperties.java b/src/main/java/com/beat/global/common/config/ThreadPoolProperties.java new file mode 100644 index 00000000..5d896fe0 --- /dev/null +++ b/src/main/java/com/beat/global/common/config/ThreadPoolProperties.java @@ -0,0 +1,14 @@ +package com.beat.global.common.config; + +import org.springframework.boot.context.properties.ConfigurationProperties; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@ConfigurationProperties(prefix = "thread-pool") +@RequiredArgsConstructor +@Getter +public class ThreadPoolProperties { + private final int coreSize; + private final String threadNamePrefix; +} From 09ac9559b7b8456b8ddab7ff2476fbb1c14528b5 Mon Sep 17 00:00:00 2001 From: DongHoon Lee Date: Mon, 10 Mar 2025 10:42:53 +0900 Subject: [PATCH 13/15] =?UTF-8?q?[#315]=20chore(MemberRegisteredEventListe?= =?UTF-8?q?ner):=20=ED=99=98=EC=98=81=20=EB=A9=94=EC=8B=9C=EC=A7=80=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../notification/slack/event/MemberRegisteredEventListener.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/beat/global/external/notification/slack/event/MemberRegisteredEventListener.java b/src/main/java/com/beat/global/external/notification/slack/event/MemberRegisteredEventListener.java index 61651fe2..8f0c9ff3 100644 --- a/src/main/java/com/beat/global/external/notification/slack/event/MemberRegisteredEventListener.java +++ b/src/main/java/com/beat/global/external/notification/slack/event/MemberRegisteredEventListener.java @@ -20,7 +20,7 @@ @RequiredArgsConstructor public class MemberRegisteredEventListener { private static final String TEXT_KEY = "text"; - private static final String WELCOME_MESSAGE = "번째 유저가 회원가입했습니다 - "; + private static final String WELCOME_MESSAGE = "번째 유저가 회원가입했띠예 🎉🎉 - "; private static final String SLACK_TRANSFER_ERROR = "Slack 전송 실패"; private final MemberUseCase memberUseCase; From 1a1dcc27007d1143ae2fee5d6b59984cd7f920b0 Mon Sep 17 00:00:00 2001 From: DongHoon Lee Date: Mon, 10 Mar 2025 14:29:02 +0900 Subject: [PATCH 14/15] =?UTF-8?q?[#315]=20chore(GlobalAsyncExceptionHandle?= =?UTF-8?q?r):=20import=EB=AC=B8=20=EC=B5=9C=EC=A0=81=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../global/common/handler/GlobalAsyncExceptionHandler.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/beat/global/common/handler/GlobalAsyncExceptionHandler.java b/src/main/java/com/beat/global/common/handler/GlobalAsyncExceptionHandler.java index 8d0ed18d..481041a2 100644 --- a/src/main/java/com/beat/global/common/handler/GlobalAsyncExceptionHandler.java +++ b/src/main/java/com/beat/global/common/handler/GlobalAsyncExceptionHandler.java @@ -1,6 +1,7 @@ package com.beat.global.common.handler; import java.lang.reflect.Method; +import java.util.Arrays; import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler; import org.springframework.lang.NonNull; @@ -19,7 +20,7 @@ public void handleUncaughtException(@NonNull Throwable ex, @NonNull Method metho return; } - String paramValues = java.util.Arrays.toString(params); + String paramValues = Arrays.toString(params); log.error("비동기 작업 중 예외 발생! Method: [{}], Params: [{}], Exception: [{}]", method.getName(), paramValues, ex.getMessage(), ex); From 2ccdb4a3521168ebd9b4a628f6306eebbf164342 Mon Sep 17 00:00:00 2001 From: DongHoon Lee Date: Mon, 10 Mar 2025 15:01:06 +0900 Subject: [PATCH 15/15] =?UTF-8?q?[#315]=20chore(JwtAuthenticationFilter):?= =?UTF-8?q?=20=ED=86=A0=ED=81=B0=20=EC=97=86=EB=8A=94=20API=20=EC=9A=94?= =?UTF-8?q?=EC=B2=AD=20=EB=A1=9C=EA=B9=85=20=EB=A0=88=EB=B2=A8=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../beat/global/auth/jwt/filter/JwtAuthenticationFilter.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/beat/global/auth/jwt/filter/JwtAuthenticationFilter.java b/src/main/java/com/beat/global/auth/jwt/filter/JwtAuthenticationFilter.java index 9177cca6..be49bd3e 100644 --- a/src/main/java/com/beat/global/auth/jwt/filter/JwtAuthenticationFilter.java +++ b/src/main/java/com/beat/global/auth/jwt/filter/JwtAuthenticationFilter.java @@ -42,7 +42,7 @@ protected void doFilterInternal(@NonNull HttpServletRequest request, final String token = getJwtFromRequest(request); if (!StringUtils.hasText(token)) { - log.info("JWT Token not found in request header. Assuming guest access or public API request."); + log.debug("JWT Token not found in request header. Assuming guest access or public API request."); filterChain.doFilter(request, response); return; } @@ -109,4 +109,4 @@ private String getJwtFromRequest(HttpServletRequest request) { } return null; } -} \ No newline at end of file +}