From 744afd7f45173c1c60b714d237244297cf198f4a Mon Sep 17 00:00:00 2001 From: Klaus Date: Mon, 26 Jan 2026 07:16:16 +0900 Subject: [PATCH] =?UTF-8?q?=EC=86=8C=EC=85=9C=20=EB=A1=9C=EA=B7=B8?= =?UTF-8?q?=EC=9D=B8=20=EB=A6=AC=EC=A1=B8=EB=B2=84=20=EB=8F=84=EC=9E=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../sodalive/member/MemberController.kt | 51 ++++++++----------- .../member/social/SocialAuthService.kt | 13 +++++ .../social/SocialAuthServiceResolver.kt | 15 ++++++ .../member/social/google/GoogleAuthService.kt | 14 +++-- .../member/social/kakao/KakaoAuthService.kt | 14 +++-- 5 files changed, 66 insertions(+), 41 deletions(-) create mode 100644 src/main/kotlin/kr/co/vividnext/sodalive/member/social/SocialAuthService.kt create mode 100644 src/main/kotlin/kr/co/vividnext/sodalive/member/social/SocialAuthServiceResolver.kt diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/member/MemberController.kt b/src/main/kotlin/kr/co/vividnext/sodalive/member/MemberController.kt index 3bc333ae..06fa296d 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/member/MemberController.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/member/MemberController.kt @@ -13,8 +13,7 @@ import kr.co.vividnext.sodalive.member.login.LoginResponse import kr.co.vividnext.sodalive.member.login.SocialLoginRequest import kr.co.vividnext.sodalive.member.notification.UpdateNotificationSettingRequest import kr.co.vividnext.sodalive.member.signUp.SignUpRequestV2 -import kr.co.vividnext.sodalive.member.social.google.GoogleAuthService -import kr.co.vividnext.sodalive.member.social.kakao.KakaoAuthService +import kr.co.vividnext.sodalive.member.social.SocialAuthServiceResolver import kr.co.vividnext.sodalive.useraction.ActionType import kr.co.vividnext.sodalive.useraction.UserActionService import org.springframework.data.domain.Pageable @@ -36,8 +35,7 @@ import org.springframework.web.multipart.MultipartFile @RequestMapping("/member") class MemberController( private val service: MemberService, - private val kakaoAuthService: KakaoAuthService, - private val googleAuthService: GoogleAuthService, + private val socialAuthServiceResolver: SocialAuthServiceResolver, private val trackingService: AdTrackingService, private val userActionService: UserActionService, private val messageSource: SodaMessageSource, @@ -345,31 +343,7 @@ class MemberController( @RequestHeader("Authorization") authHeader: String, @RequestBody request: SocialLoginRequest ): ApiResponse { - if (!authHeader.startsWith("Bearer ")) { - throw SodaException(messageKey = "member.social.google_login_failed") - } - - val token = authHeader.substring(7) - val response = googleAuthService.authenticate(token, request.container, request.marketingPid, request.pushToken) - - if (!response.marketingPid.isNullOrBlank()) { - trackingService.saveTrackingHistory( - pid = response.marketingPid, - type = AdTrackingHistoryType.SIGNUP, - memberId = response.memberId - ) - } - - if (response.isNew) { - userActionService.recordAction( - memberId = response.memberId, - isAuth = false, - actionType = ActionType.SIGN_UP - ) - } - - val message = messageSource.getMessage("member.signup.success", langContext.lang) - return ApiResponse.ok(message = message, data = response.loginResponse) + return processSocialLogin(MemberProvider.GOOGLE, authHeader, request) } @PostMapping("/login/kakao") @@ -377,12 +351,27 @@ class MemberController( @RequestHeader("Authorization") authHeader: String, @RequestBody request: SocialLoginRequest ): ApiResponse { + return processSocialLogin(MemberProvider.KAKAO, authHeader, request) + } + + private fun processSocialLogin( + provider: MemberProvider, + authHeader: String, + request: SocialLoginRequest + ): ApiResponse { + val errorKey = when (provider) { + MemberProvider.GOOGLE -> "member.social.google_login_failed" + MemberProvider.KAKAO -> "member.social.kakao_login_failed" + else -> "common.error.bad_request" + } + if (!authHeader.startsWith("Bearer ")) { - throw SodaException(messageKey = "member.social.kakao_login_failed") + throw SodaException(messageKey = errorKey) } val token = authHeader.substring(7) - val response = kakaoAuthService.authenticate(token, request.container, request.marketingPid, request.pushToken) + val authService = socialAuthServiceResolver.resolve(provider) + val response = authService.authenticate(token, request.container, request.marketingPid, request.pushToken) if (!response.marketingPid.isNullOrBlank()) { trackingService.saveTrackingHistory( diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/member/social/SocialAuthService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/member/social/SocialAuthService.kt new file mode 100644 index 00000000..bb500dff --- /dev/null +++ b/src/main/kotlin/kr/co/vividnext/sodalive/member/social/SocialAuthService.kt @@ -0,0 +1,13 @@ +package kr.co.vividnext.sodalive.member.social + +import kr.co.vividnext.sodalive.member.MemberProvider + +interface SocialAuthService { + fun getProvider(): MemberProvider + fun authenticate( + token: String, + container: String, + marketingPid: String?, + pushToken: String? + ): SocialLoginResponse +} diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/member/social/SocialAuthServiceResolver.kt b/src/main/kotlin/kr/co/vividnext/sodalive/member/social/SocialAuthServiceResolver.kt new file mode 100644 index 00000000..f89529fe --- /dev/null +++ b/src/main/kotlin/kr/co/vividnext/sodalive/member/social/SocialAuthServiceResolver.kt @@ -0,0 +1,15 @@ +package kr.co.vividnext.sodalive.member.social + +import kr.co.vividnext.sodalive.member.MemberProvider +import org.springframework.stereotype.Component + +@Component +class SocialAuthServiceResolver( + val services: List +) { + private val serviceMap: Map = services.associateBy { it.getProvider() } + + fun resolve(provider: MemberProvider): SocialAuthService { + return serviceMap[provider] ?: throw IllegalArgumentException("Unsupported social provider: $provider") + } +} diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/member/social/google/GoogleAuthService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/member/social/google/GoogleAuthService.kt index 99530a6a..7d243442 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/member/social/google/GoogleAuthService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/member/social/google/GoogleAuthService.kt @@ -3,8 +3,10 @@ package kr.co.vividnext.sodalive.member.social.google import kr.co.vividnext.sodalive.common.SodaException import kr.co.vividnext.sodalive.jwt.TokenProvider import kr.co.vividnext.sodalive.member.MemberAdapter +import kr.co.vividnext.sodalive.member.MemberProvider import kr.co.vividnext.sodalive.member.MemberService import kr.co.vividnext.sodalive.member.login.LoginResponse +import kr.co.vividnext.sodalive.member.social.SocialAuthService import kr.co.vividnext.sodalive.member.social.SocialLoginResponse import org.springframework.beans.factory.annotation.Value import org.springframework.security.core.context.SecurityContextHolder @@ -18,19 +20,21 @@ class GoogleAuthService( @Value("\${cloud.aws.cloud-front.host}") private val cloudFrontHost: String -) { - fun authenticate( - idToken: String, +) : SocialAuthService { + override fun getProvider(): MemberProvider = MemberProvider.GOOGLE + + override fun authenticate( + token: String, container: String, marketingPid: String?, pushToken: String? ): SocialLoginResponse { - val googleUserInfo = googleService.getUserInfo(idToken) + val googleUserInfo = googleService.getUserInfo(token) ?: throw SodaException(messageKey = "member.social.google_login_failed") val memberResolveResult = memberService.findOrRegister(googleUserInfo, container, marketingPid, pushToken) val member = memberResolveResult.member val principal = MemberAdapter(member) - val authToken = GoogleAuthenticationToken(idToken, principal.authorities) + val authToken = GoogleAuthenticationToken(token, principal.authorities) authToken.setPrincipal(principal) SecurityContextHolder.getContext().authentication = authToken diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/member/social/kakao/KakaoAuthService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/member/social/kakao/KakaoAuthService.kt index ed4cf0c5..bf7c393f 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/member/social/kakao/KakaoAuthService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/member/social/kakao/KakaoAuthService.kt @@ -3,8 +3,10 @@ package kr.co.vividnext.sodalive.member.social.kakao import kr.co.vividnext.sodalive.common.SodaException import kr.co.vividnext.sodalive.jwt.TokenProvider import kr.co.vividnext.sodalive.member.MemberAdapter +import kr.co.vividnext.sodalive.member.MemberProvider import kr.co.vividnext.sodalive.member.MemberService import kr.co.vividnext.sodalive.member.login.LoginResponse +import kr.co.vividnext.sodalive.member.social.SocialAuthService import kr.co.vividnext.sodalive.member.social.SocialLoginResponse import org.springframework.beans.factory.annotation.Value import org.springframework.security.core.context.SecurityContextHolder @@ -18,19 +20,21 @@ class KakaoAuthService( @Value("\${cloud.aws.cloud-front.host}") private val cloudFrontHost: String -) { - fun authenticate( - accessToken: String, +) : SocialAuthService { + override fun getProvider(): MemberProvider = MemberProvider.KAKAO + + override fun authenticate( + token: String, container: String, marketingPid: String?, pushToken: String? ): SocialLoginResponse { - val kakaoUserInfo = kakaoService.getUserInfo(accessToken) + val kakaoUserInfo = kakaoService.getUserInfo(token) ?: throw SodaException(messageKey = "member.social.kakao_login_failed") val memberResolveResult = memberService.findOrRegister(kakaoUserInfo, container, marketingPid, pushToken) val member = memberResolveResult.member val principal = MemberAdapter(member) - val authToken = KakaoAuthenticationToken(accessToken, principal.authorities) + val authToken = KakaoAuthenticationToken(token, principal.authorities) authToken.setPrincipal(principal) SecurityContextHolder.getContext().authentication = authToken