Skip to content

Commit 9a5515e

Browse files
feat: 사용자별 다중 디바이스 알림 전송 기능 추가 및 리팩토링 (#128)
* [BOOK-408] feat: apis - deviceId값을 통한 다중기기 알림기능 개발(#127) * [BOOK-408] feat: apis - deviceId값을 통한 다중기기 알림기능 개발(#127) * [BOOK-408] feat: batch - deviceId값을 통한 다중기기 알림기능 개발(#127) * [BOOK-408] feat: domain - deviceId값을 통한 다중기기 알림기능 개발(#127) * [BOOK-408] feat: infra - deviceId값을 통한 다중기기 알림기능 개발(#127) * [BOOK-408] chore: batch - 사용하지 않는 import문 제거 * [BOOK-408] refactor: apis, infra, domain - 중복된 VO 제거 * [BOOK-408] refactor: domain - Device 클래스 구조를 재정비하고, 데이터 처리를 개선하기 위해 DeviceVO를 도입 * [BOOK-408] refactor: domain, infra - User 객체 대신 userId를 사용하도록 Notification 모델 수정 및 알림 관리를 위한 NotificationDomainService 도입 * [BOOK-408] chore: domain - ReadingRecordDomainService에 관한 TODO 주석처리 * [BOOK-408] refactor: batch, domain - FcmNotificationJobConfig를 NotificationService로 리팩토링하고, 알림 전송 로직을 분리하여 코드 가독성 및 유지보수성 향상 * [BOOK-408] fix: domain - 누락된 중괄호 추가 * [BOOK-408] chore: batch - InfraConfig에 AOP, SENTRY 추가 * [BOOK-408] chore: infra - dev 환경에서만 flyway를 비활성화 하도록 변경 * [BOOK-408] refactor: infra - resolve build error (#128) --------- Co-authored-by: DongHoon Lee <[email protected]>
1 parent 84ffad8 commit 9a5515e

File tree

37 files changed

+584
-398
lines changed

37 files changed

+584
-398
lines changed

apis/src/main/kotlin/org/yapp/apis/auth/dto/response/UserIdResponse.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package org.yapp.apis.auth.dto.response
22

33
import io.swagger.v3.oas.annotations.media.Schema
4-
import org.yapp.domain.token.RefreshToken.UserId
4+
import org.yapp.domain.user.User
55
import java.util.*
66

77
@Schema(
@@ -13,7 +13,7 @@ data class UserIdResponse(
1313
val userId: UUID
1414
) {
1515
companion object {
16-
fun from(userId: UserId): UserIdResponse {
16+
fun from(userId: User.Id): UserIdResponse {
1717
return UserIdResponse(userId.value)
1818
}
1919
}

apis/src/main/kotlin/org/yapp/apis/user/controller/UserController.kt

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import jakarta.validation.Valid
44
import org.springframework.http.ResponseEntity
55
import org.springframework.security.core.annotation.AuthenticationPrincipal
66
import org.springframework.web.bind.annotation.*
7-
import org.yapp.apis.user.dto.request.FcmTokenRequest
7+
import org.yapp.apis.user.dto.request.DeviceRequest
88
import org.yapp.apis.user.dto.request.NotificationSettingsRequest
99
import org.yapp.apis.user.dto.request.TermsAgreementRequest
1010
import org.yapp.apis.user.dto.response.UserProfileResponse
@@ -42,12 +42,12 @@ class UserController(
4242
return ResponseEntity.ok(userProfile)
4343
}
4444

45-
@PutMapping("/me/fcm-token")
46-
override fun updateFcmToken(
45+
@PutMapping("/me/devices")
46+
override fun registerDevice(
4747
@AuthenticationPrincipal userId: UUID,
48-
@Valid @RequestBody request: FcmTokenRequest
48+
@Valid @RequestBody request: DeviceRequest
4949
): ResponseEntity<UserProfileResponse> {
50-
val userProfile = userUseCase.updateFcmToken(userId, request)
50+
val userProfile = userUseCase.registerDevice(userId, request)
5151
return ResponseEntity.ok(userProfile)
5252
}
5353
}

apis/src/main/kotlin/org/yapp/apis/user/controller/UserControllerApi.kt

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import org.springframework.web.bind.annotation.GetMapping
1414
import org.springframework.web.bind.annotation.PutMapping
1515
import org.springframework.web.bind.annotation.RequestBody
1616
import org.springframework.web.bind.annotation.RequestMapping
17-
import org.yapp.apis.user.dto.request.FcmTokenRequest
17+
import org.yapp.apis.user.dto.request.DeviceRequest
1818
import org.yapp.apis.user.dto.request.NotificationSettingsRequest
1919
import org.yapp.apis.user.dto.request.TermsAgreementRequest
2020
import org.yapp.apis.user.dto.response.UserProfileResponse
@@ -122,14 +122,14 @@ interface UserControllerApi {
122122
): ResponseEntity<UserProfileResponse>
123123

124124
@Operation(
125-
summary = "FCM 토큰 등록",
126-
description = "사용자의 FCM 토큰을 등록합니다."
125+
summary = "디바이스 등록",
126+
description = "사용자의 디바이스를 등록합니다. 이미 등록된 디바이스인 경우 FCM 토큰을 업데이트합니다."
127127
)
128128
@ApiResponses(
129129
value = [
130130
ApiResponse(
131131
responseCode = "200",
132-
description = "FCM 토큰 등록 성공",
132+
description = "디바이스 등록 또는 업데이트 성공",
133133
content = [Content(schema = Schema(implementation = UserProfileResponse::class))]
134134
),
135135
ApiResponse(
@@ -149,9 +149,9 @@ interface UserControllerApi {
149149
)
150150
]
151151
)
152-
@PutMapping("/me/fcm-token")
153-
fun updateFcmToken(
152+
@PutMapping("/me/devices")
153+
fun registerDevice(
154154
@Parameter(hidden = true) @AuthenticationPrincipal userId: UUID,
155-
@Valid @RequestBody @Parameter(description = "FCM 토큰 요청 객체") request: FcmTokenRequest
155+
@Valid @RequestBody @Parameter(description = "디바이스 정보 요청 객체") request: DeviceRequest
156156
): ResponseEntity<UserProfileResponse>
157157
}

apis/src/main/kotlin/org/yapp/apis/user/dto/request/FcmTokenRequest.kt renamed to apis/src/main/kotlin/org/yapp/apis/user/dto/request/DeviceRequest.kt

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,18 @@ import io.swagger.v3.oas.annotations.media.Schema
44
import jakarta.validation.constraints.NotBlank
55

66
@Schema(
7-
name = "FcmTokenRequest",
8-
description = "DTO for FCM token update requests"
7+
name = "DeviceRequest",
8+
description = "DTO for device update requests"
99
)
10-
data class FcmTokenRequest private constructor(
10+
data class DeviceRequest private constructor(
11+
@field:Schema(
12+
description = "디바이스 아이디",
13+
example = "c8a9d7d0-4f6a-4b1a-8f0a-9d8e7f6a4b1a",
14+
required = true
15+
)
16+
@field:NotBlank(message = "디바이스 아이디는 필수입니다.")
17+
val deviceId: String? = null,
18+
1119
@field:Schema(
1220
description = "FCM 토큰",
1321
example = "epGzIKlHScicTBrbt26pFG:APA91bG-ZPD-KMJyS-JOiflEPUIVvrp8l9DFBN2dlNG8IHw8mFlkAPok7dVPFJR4phc9061KPztkAIjBJaryZLnv6vIJXNGQsykzDcok3wFC9LrsC-F_aKY",
@@ -16,5 +24,6 @@ data class FcmTokenRequest private constructor(
1624
@field:NotBlank(message = "FCM 토큰은 필수입니다.")
1725
val fcmToken: String? = null
1826
) {
27+
fun validDeviceId(): String = deviceId!!.trim()
1928
fun validFcmToken(): String = fcmToken!!.trim()
2029
}

apis/src/main/kotlin/org/yapp/apis/user/service/UserService.kt

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,21 @@ package org.yapp.apis.user.service
33
import jakarta.validation.Valid
44
import org.yapp.apis.auth.exception.AuthErrorCode
55
import org.yapp.apis.auth.exception.AuthException
6-
import org.yapp.apis.user.dto.request.FcmTokenRequest
6+
import org.yapp.apis.user.dto.request.DeviceRequest
77
import org.yapp.apis.user.dto.request.FindUserIdentityRequest
88
import org.yapp.apis.user.dto.request.NotificationSettingsRequest
99
import org.yapp.apis.user.dto.request.TermsAgreementRequest
1010
import org.yapp.apis.user.dto.response.UserAuthInfoResponse
1111
import org.yapp.apis.user.dto.response.UserProfileResponse
12+
import org.yapp.domain.device.DeviceDomainService
1213
import org.yapp.domain.user.UserDomainService
1314
import org.yapp.globalutils.annotation.ApplicationService
1415
import java.util.*
1516

1617
@ApplicationService
1718
class UserService(
18-
private val userDomainService: UserDomainService
19+
private val userDomainService: UserDomainService,
20+
private val deviceDomainService: DeviceDomainService
1921
) {
2022
fun findUserProfileByUserId(userId: UUID): UserProfileResponse {
2123
val userProfile = userDomainService.findUserProfileById(userId)
@@ -45,9 +47,10 @@ class UserService(
4547
return UserProfileResponse.from(updatedUserProfile)
4648
}
4749

48-
fun updateFcmToken(userId: UUID, @Valid request: FcmTokenRequest): UserProfileResponse {
50+
fun registerDevice(userId: UUID, @Valid request: DeviceRequest): UserProfileResponse {
4951
validateUserExists(userId)
50-
val updatedUserProfile = userDomainService.updateFcmToken(userId, request.validFcmToken())
51-
return UserProfileResponse.from(updatedUserProfile)
52+
deviceDomainService.findOrCreateDevice(userId, request.validDeviceId(), request.validFcmToken())
53+
val userProfile = userDomainService.findUserProfileById(userId)
54+
return UserProfileResponse.from(userProfile)
5255
}
5356
}

apis/src/main/kotlin/org/yapp/apis/user/usecase/UserUseCase.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package org.yapp.apis.user.usecase
22

33
import org.springframework.transaction.annotation.Transactional
4-
import org.yapp.apis.user.dto.request.FcmTokenRequest
4+
import org.yapp.apis.user.dto.request.DeviceRequest
55
import org.yapp.apis.user.dto.request.NotificationSettingsRequest
66
import org.yapp.apis.user.dto.request.TermsAgreementRequest
77
import org.yapp.apis.user.dto.response.UserProfileResponse
@@ -29,7 +29,7 @@ class UserUseCase(
2929
}
3030

3131
@Transactional
32-
fun updateFcmToken(userId: UUID, request: FcmTokenRequest): UserProfileResponse {
33-
return userService.updateFcmToken(userId, request)
32+
fun registerDevice(userId: UUID, request: DeviceRequest): UserProfileResponse {
33+
return userService.registerDevice(userId, request)
3434
}
3535
}

batch/src/main/kotlin/org/yapp/batch/config/InfraConfig.kt

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,9 @@ import org.yapp.infra.InfraBaseConfigGroup
77
@Configuration(proxyBeanMethods = false)
88
@EnableInfraBaseConfig(
99
[
10-
InfraBaseConfigGroup.JPA
10+
InfraBaseConfigGroup.JPA,
11+
InfraBaseConfigGroup.AOP,
12+
InfraBaseConfigGroup.SENTRY
1113
]
1214
)
13-
class InfraConfig {
14-
}
15+
class InfraConfig

0 commit comments

Comments
 (0)