Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: 디바이스 토큰 업데이트 api 구현 #95

Merged
merged 15 commits into from
Nov 21, 2024

Conversation

kimyu0218
Copy link
Collaborator

@kimyu0218 kimyu0218 commented Nov 12, 2024

Issue Number

close: #84

작업 개요

디바이스 토큰 업데이트 api 구현

작업 사항

디바이스 토큰이 영구적이지 않아서 로그인 외에 별도의 api를 통해 디바이스 토큰을 업데이트 하도록 구현했습니다.
클라이언트에서 디바이스 토큰을 변경하면 /api/member/deviceToken api 호출로 레코드를 변경할 수 있습니다.

고민한 점들(필수 X)

디바이스 토큰 삭제 api를 별도로 파는 게 좋을까요? 새로 api를 만들지, 기존 api를 재사용할지 고민입니다!

public record UpdateDeviceTokenRequest(
        @Schema(description = "deviceToken", requiredMode = Schema.RequiredMode.REQUIRED)
        String deviceToken
) {
    ...
}

스크린샷(필수 X)

여기에 작성하세요

@kimyu0218 kimyu0218 requested a review from songyi00 as a code owner November 12, 2024 23:00
Copy link
Member

@songyi00 songyi00 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

유정 내가 컨텍스트 파악이 덜 되어서ㅠ
�클라이언트에서 업데이트 또는 삭제 API 를 사용하게 되는 트리거가 뭐야?

@kimyu0218
Copy link
Collaborator Author

kimyu0218 commented Nov 13, 2024

@songyi00
PR을 너무 대충 적었구나 ㅋㅋㅠㅠ 이해 안되면 언제든지 말해줘!! 😁😁

디바이스 토큰 = 모바일 디바이스 기기 구분하는 식별자
-> 개인 푸시 알림에 활용

디바이스 토큰이 영구적인 게 아니어서 토큰이 변경될 때마다(앱 재설치, 기기 변경 등) 데이터베이스에 있는 토큰 값을 변경해줘야 해.

그리고 알림을 받다가 너무 알림이 많이 와서 알림을 끈다던지 비활성화 하는 경우가 생기니까 데이터베이스에서 토큰을 삭제해야 해.


원래는

  • updateDeviceToken : 디바이스 토큰이 바뀌었을 때
  • deleteDeviceToken : 알림을 비활성화 했을 때

이렇게 구분해서 작성하려고 했는데 device_token 필드 값을 변경하는 거니까 updateDeviceToken을 그대로 사용해도 될까 싶어서 물어봤어.

지금은 PATCH /api/member/device-token이 디바이스 토큰 값을 변경하고 삭제할 수 있는 유일한 api야. DELETE는 레코드를 삭제할 때 사용하는 거니까 부적절한 것 같기도 해서..!

요약하면 1) DELETE 보단 PATCH가 맞는 것 같은데 2) api가 너무 모호한가 싶어서 물어봤어

@kimyu0218
Copy link
Collaborator Author

얘는 이벤트 아니고 (백엔드가 사용자의 디바이스 토큰 값이 바뀐 걸 알 수 없으니까) 클라이언트에서 api로 알려줘야 해!

Copy link
Collaborator Author

@kimyu0218 kimyu0218 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AppleLoginCommandGoogleLoginCommand가 처음에 만든 dto라 계층별 dto 규칙을 따르고 있지 않았습니다. 각각 request 객체와 toServiceDto(..) 메서드를 만들어 줬습니다. (이 부분은 그냥 무시하셔도 될 것 같아요!!)

Comment on lines +46 to +55
public void update(String memberId, String deviceToken) {
String pattern = makeAnyDatePattern(memberId);
Set<String> keys = redisTemplate.keys(pattern);
if (keys.isEmpty()) {
return;
}
String key = String.valueOf(keys.iterator().next());
Long ttl = redisTemplate.getExpire(key);
redisTemplate.opsForValue().set(key, deviceToken, Duration.ofMillis(ttl));
}
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#100 리뷰 반영

7일 내에 디바이스 토큰이 변경될 일은 없을까?!

memberId가 포함된 키를 조회하고,
새로운 deviceToken 값을 이전 ttl을 걸어 저장합니다.

@@ -22,6 +22,9 @@ public interface MissionMemberRepository extends JpaRepository<MissionMember, Lo
@Query("SELECT mm FROM MissionMember mm JOIN FETCH mm.mission WHERE mm.member.id = :memberId")
List<MissionMember> findAllWithMissionByMemberId(final Long memberId);

@Query("SELECT mm FROM MissionMember mm JOIN FETCH mm.member WHERE mm.mission.id = :missionId")
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#100 리뷰 반영

.getMember().get*()는 N+1 문제가 있을 것 같다고 하셔서 JOIN FETCH 했습니다!! 제가 잘못 이해했으면 편하게 말해주세요 🙌

Comment on lines +188 to +204
@Transactional
public void subscribeToMyMissions(final Long memberId, final String deviceToken) {
List<String> topics = findMySubscribableTopic(memberId);
topics.forEach(topic ->
topicSubscriber.subscribeToTopic(List.of(deviceToken), topic)
);
updateRetryPushMessage(memberId, deviceToken);
}

@Transactional
public void unsubscribeFromMyMissions(final Long memberId, final String deviceToken) {
List<String> topics = findMySubscribableTopic(memberId);
topics.forEach(topic ->
topicSubscriber.unsubscribeFromTopic(List.of(deviceToken), topic)
);
cancelRetryPushMessage(memberId);
}
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

디바이스 토큰을 변경했거나 활성/비활성화했을 때 실행되는 메서드입니다!

  1. 토픽 구독 or 구독 취소
  2. 미션 재시작을 독려해야 하는 경우 redis key-value 수정
  • redis에 저장된 디바이스 토큰 업데이트 (활성화)
  • redis에 저장된 디바이스 토큰 삭제 (비활성화)

Comment on lines +64 to +65
member.updateDeviceToken(command.deviceToken());
member.updatePushActivationStatus(true);
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

디바이스 토큰을 갱신하는 경우, 알림을 활성화하는 것으로 간주했는데 괜찮을까요?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

만약에 모바일에서 푸시 활성 여부랑 상관없이 앱 진입할 때마다 디바이스 토큰 업데이트 API 요청한다고 하면 상태는 안바꾸는게 좋지 않을까?!
모바일에서 분기 태울지 얘기해봐도 좋을 것 같옹

@kimyu0218 kimyu0218 requested a review from songyi00 November 21, 2024 13:00
Copy link
Member

@songyi00 songyi00 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍👍

@kimyu0218 kimyu0218 merged commit 0187ee0 into develop Nov 21, 2024
1 check passed
@kimyu0218 kimyu0218 deleted the feat/#84-fcm-push branch November 21, 2024 16:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

fcm 푸시 알림
2 participants