Skip to content

Commit 94ef14a

Browse files
committed
fix: 디바이스 토큰 저장
- device_id + member_id가 중복저장되는 문제 해결 - device_id에 device_type이 저장되는 문제 해
1 parent 87b8b8e commit 94ef14a

File tree

2 files changed

+112
-3
lines changed

2 files changed

+112
-3
lines changed

tuk-api/src/main/kotlin/nexters/tuk/application/device/DeviceService.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ class DeviceService(
1717
memberId: Long,
1818
command: DeviceCommand.UpdateDeviceToken,
1919
): DeviceResponse.UpdateDeviceToken {
20-
val deviceToken = command.deviceInfo.deviceToken ?: throw IllegalArgumentException("디바이스 토큰은 필수 정보입니다.")
20+
val deviceToken =
21+
command.deviceInfo.deviceToken ?: throw IllegalArgumentException("디바이스 토큰은 필수 정보입니다.")
2122

2223
val device = deviceRepository.findByDeviceIdAndMemberId(
2324
deviceId = command.deviceInfo.deviceId,
@@ -31,7 +32,7 @@ class DeviceService(
3132
device
3233
} ?: deviceRepository.save(
3334
Device.new(
34-
deviceId = command.deviceInfo.deviceType,
35+
deviceId = command.deviceInfo.deviceId,
3536
deviceToken = deviceToken,
3637
appVersion = command.deviceInfo.appVersion,
3738
osVersion = command.deviceInfo.osVersion,

tuk-api/src/test/kotlin/nexters/tuk/application/device/DeviceServiceIntegrationTest.kt

Lines changed: 109 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package nexters.tuk.application.device
22

33
import nexters.tuk.application.device.dto.request.DeviceCommand
4+
import nexters.tuk.domain.device.DeviceRepository
45
import nexters.tuk.fixtures.createDeviceInfoFixture
56
import org.assertj.core.api.Assertions.assertThat
67
import org.junit.jupiter.api.Assertions.assertAll
@@ -13,6 +14,7 @@ import org.springframework.test.context.jdbc.Sql
1314
@SpringBootTest
1415
class DeviceServiceIntegrationTest @Autowired constructor(
1516
private val deviceService: DeviceService,
17+
private val deviceRepository: DeviceRepository,
1618
) {
1719
@Test
1820
fun `디바이스 토큰을 정상적으로 저장한다`() {
@@ -40,21 +42,127 @@ class DeviceServiceIntegrationTest @Autowired constructor(
4042
val deviceInfo = createDeviceInfoFixture()
4143
val updateDeviceInfo = createDeviceInfoFixture(deviceToken = "updateDeviceToken")
4244

43-
deviceService.updateDeviceToken(
45+
val firstResult = deviceService.updateDeviceToken(
4446
memberId = memberId,
4547
command = DeviceCommand.UpdateDeviceToken(deviceInfo)
4648
)
4749

50+
val countAfterFirstInsert = deviceRepository.count()
51+
4852
// when
4953
val actual = deviceService.updateDeviceToken(
5054
memberId = memberId,
5155
command = DeviceCommand.UpdateDeviceToken(updateDeviceInfo)
5256
)
5357

58+
val countAfterUpdate = deviceRepository.count()
59+
val deviceFromDb = deviceRepository.findByDeviceIdAndMemberId(deviceInfo.deviceId, memberId)
60+
5461
// then
5562
assertAll(
5663
{ assertThat(actual.deviceToken).isEqualTo(updateDeviceInfo.deviceToken) },
5764
{ assertThat(actual.memberId).isEqualTo(memberId) },
65+
{ assertThat(actual.deviceId).isEqualTo(firstResult.deviceId) }, // 같은 디바이스 ID 확인
66+
{ assertThat(countAfterFirstInsert).isEqualTo(1L) }, // 첫 번째 저장 후 1개
67+
{ assertThat(countAfterUpdate).isEqualTo(1L) }, // 업데이트 후에도 여전히 1개 (새로 생성되지 않음)
68+
{ assertThat(deviceFromDb?.deviceToken).isEqualTo(updateDeviceInfo.deviceToken) }, // DB에서 직접 확인
69+
)
70+
}
71+
72+
@Test
73+
fun `같은 memberId와 deviceId로 여러 번 호출하면 계속 업데이트된다`() {
74+
// given
75+
val memberId = 1L
76+
val deviceInfo = createDeviceInfoFixture()
77+
78+
// when & then - 첫 번째 저장
79+
val firstResult = deviceService.updateDeviceToken(
80+
memberId = memberId,
81+
command = DeviceCommand.UpdateDeviceToken(deviceInfo)
82+
)
83+
84+
assertThat(deviceRepository.count()).isEqualTo(1L)
85+
assertThat(firstResult.deviceToken).isEqualTo(deviceInfo.deviceToken)
86+
87+
// when & then - 두 번째 업데이트
88+
val updatedInfo1 = createDeviceInfoFixture(deviceToken = "token2")
89+
val secondResult = deviceService.updateDeviceToken(
90+
memberId = memberId,
91+
command = DeviceCommand.UpdateDeviceToken(updatedInfo1)
92+
)
93+
94+
assertThat(deviceRepository.count()).isEqualTo(1L) // 여전히 1개
95+
assertThat(secondResult.deviceToken).isEqualTo("token2")
96+
assertThat(secondResult.deviceId).isEqualTo(firstResult.deviceId)
97+
98+
// when & then - 세 번째 업데이트
99+
val updatedInfo2 = createDeviceInfoFixture(deviceToken = "token3", appVersion = "2.0")
100+
val thirdResult = deviceService.updateDeviceToken(
101+
memberId = memberId,
102+
command = DeviceCommand.UpdateDeviceToken(updatedInfo2)
103+
)
104+
105+
assertThat(deviceRepository.count()).isEqualTo(1L) // 여전히 1개
106+
assertThat(thirdResult.deviceToken).isEqualTo("token3")
107+
assertThat(thirdResult.deviceId).isEqualTo(firstResult.deviceId)
108+
109+
// DB에서 직접 확인
110+
val finalDeviceFromDb = deviceRepository.findByDeviceIdAndMemberId(deviceInfo.deviceId, memberId)
111+
assertThat(finalDeviceFromDb?.deviceToken).isEqualTo("token3")
112+
}
113+
114+
@Test
115+
fun `다른 memberId는 별도의 디바이스로 저장된다`() {
116+
// given
117+
val memberId1 = 1L
118+
val memberId2 = 2L
119+
val deviceInfo = createDeviceInfoFixture()
120+
121+
// when
122+
val result1 = deviceService.updateDeviceToken(
123+
memberId = memberId1,
124+
command = DeviceCommand.UpdateDeviceToken(deviceInfo)
125+
)
126+
127+
val result2 = deviceService.updateDeviceToken(
128+
memberId = memberId2,
129+
command = DeviceCommand.UpdateDeviceToken(deviceInfo)
130+
)
131+
132+
// then
133+
assertAll(
134+
{ assertThat(deviceRepository.count()).isEqualTo(2L) }, // 2개 디바이스
135+
{ assertThat(result1.memberId).isEqualTo(memberId1) },
136+
{ assertThat(result2.memberId).isEqualTo(memberId2) },
137+
{ assertThat(result1.deviceId).isEqualTo(result2.deviceId) }, // 같은 deviceId
138+
{ assertThat(result1.deviceToken).isEqualTo(result2.deviceToken) }, // 같은 토큰
139+
)
140+
}
141+
142+
@Test
143+
fun `다른 deviceId는 별도의 디바이스로 저장된다`() {
144+
// given
145+
val memberId = 1L
146+
val deviceInfo1 = createDeviceInfoFixture(deviceId = "device1")
147+
val deviceInfo2 = createDeviceInfoFixture(deviceId = "device2")
148+
149+
// when
150+
val result1 = deviceService.updateDeviceToken(
151+
memberId = memberId,
152+
command = DeviceCommand.UpdateDeviceToken(deviceInfo1)
153+
)
154+
155+
val result2 = deviceService.updateDeviceToken(
156+
memberId = memberId,
157+
command = DeviceCommand.UpdateDeviceToken(deviceInfo2)
158+
)
159+
160+
// then
161+
assertAll(
162+
{ assertThat(deviceRepository.count()).isEqualTo(2L) }, // 2개 디바이스
163+
{ assertThat(result1.memberId).isEqualTo(result2.memberId) }, // 같은 memberId
164+
{ assertThat(result1.deviceId).isEqualTo("device1") },
165+
{ assertThat(result2.deviceId).isEqualTo("device2") },
58166
)
59167
}
60168
}

0 commit comments

Comments
 (0)