Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import me.pinitnotification.interfaces.notification.dto.PushTokenRequest;
import org.springframework.web.bind.annotation.*;

@Deprecated
Copy link

Copilot AI Dec 31, 2025

Choose a reason for hiding this comment

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

문제점:
@deprecated 어노테이션이 since, forRemoval 속성 없이 사용되었습니다.

영향:

  • API 사용자가 언제부터 deprecated 되었는지 알 수 없습니다
  • 향후 제거 계획 여부를 파악할 수 없습니다
  • API 마이그레이션 계획을 수립하기 어렵습니다

수정 제안:
since와 forRemoval 속성을 명시하여 deprecated 정책을 명확히 하세요. 예를 들어, 다음과 같이 작성할 수 있습니다:

  • since: API 버전이나 날짜를 명시
  • forRemoval: 향후 제거 계획이 있는 경우 true로 설정

Copilot generated this review using guidance from repository custom instructions.
@RestController
@RequestMapping("/push")
@Tag(name = "푸시 알림", description = "푸시 구독 및 VAPID 키 관련 API")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package me.pinitnotification.interfaces.notification;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import me.pinitnotification.application.push.PushService;
import me.pinitnotification.domain.member.MemberId;
import me.pinitnotification.interfaces.notification.dto.PushTokenRequest;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/v0/push")
Copy link

Copilot AI Dec 31, 2025

Choose a reason for hiding this comment

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

문제점: API 버전을 "v0"으로 시작하는 것은 일반적이지 않습니다. 통상 API 버전은 v1부터 시작하며, v0는 불안정하거나 실험적인 버전을 의미할 수 있습니다.

영향:

  • API 사용자에게 혼란을 줄 수 있으며, 이 API가 프로덕션 준비가 되지 않았다는 잘못된 인상을 줄 수 있습니다
  • 향후 v1로 마이그레이션 시 불필요한 버전 단계가 추가됩니다

수정 제안:

  • 첫 번째 정식 API 버전은 "/v1/push"로 시작하는 것을 권장합니다
  • 만약 v0가 의도적으로 베타/실험 버전을 의미한다면, @tag description에 이를 명시해야 합니다

Copilot generated this review using guidance from repository custom instructions.
@Tag(name = "푸시 알림", description = "푸시 구독 및 VAPID 키 관련 API")
public class PushNotificationControllerV0 {
Copy link

Copilot AI Dec 31, 2025

Choose a reason for hiding this comment

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

문제점: 기존 PushNotificationController (경로: /push)와 새로운 PushNotificationControllerV0 (경로: /v0/push)가 동시에 존재하여 두 개의 동일한 API 엔드포인트가 공존합니다.

영향:

  • API 사용자가 어떤 엔드포인트를 사용해야 할지 혼란스러울 수 있습니다
  • 두 컨트롤러가 동일한 기능을 제공하므로 유지보수 부담이 증가합니다
  • 기존 /push 엔드포인트의 생명주기(계속 유지할지, 언제 제거할지)가 불명확합니다

수정 제안:

  • 기존 PushNotificationController@Deprecated 어노테이션을 추가하고, 언제 제거될 예정인지 문서화해야 합니다
  • 또는 기존 컨트롤러를 /v0/push로 리다이렉트하도록 변경하는 것을 고려하세요
  • API 문서에 버전 마이그레이션 가이드를 추가하는 것을 권장합니다

Copilot generated this review using guidance from repository custom instructions.
private final PushService pushService;

public PushNotificationControllerV0(PushService pushService) {
this.pushService = pushService;
}

@GetMapping("/vapid")
@Operation(
summary = "VAPID 공개키 조회",
description = "웹 푸시 구독에 사용되는 VAPID 공개키를 반환합니다."
)
@ApiResponses({
@ApiResponse(responseCode = "200", description = "VAPID 공개키",
content = @Content(mediaType = "text/plain", schema = @Schema(implementation = String.class)))
})
public String getVapidPublicKey() {
return pushService.getVapidPublicKey();
}

@GetMapping("/subscribed")
@Operation(
summary = "푸시 구독 상태 조회",
description = "인증된 회원이 푸시 알림을 구독 중인지 여부를 반환합니다."
)
@ApiResponses({
@ApiResponse(responseCode = "200", description = "구독 상태 조회 완료",
content = @Content(mediaType = "text/plain", schema = @Schema(implementation = Boolean.class)))
})
public boolean isSubscribed(
@Parameter(hidden = true) @MemberId Long memberId,
@RequestParam String deviceId) {
return pushService.isSubscribed(memberId, deviceId);
}

@PostMapping("/subscribe")
@Operation(
summary = "푸시 토큰 구독 등록",
description = "인증된 회원의 푸시 토큰을 등록합니다."
)
@ApiResponses({
@ApiResponse(responseCode = "200", description = "구독 등록 완료"),
@ApiResponse(responseCode = "400", description = "토큰이 유효하지 않음", content = @Content)
})
public void subscribe(
@Parameter(hidden = true) @MemberId Long memberId,
@RequestBody PushTokenRequest request) {
pushService.subscribe(memberId, request.deviceId(), request.token());
}

@PostMapping("/unsubscribe")
@Operation(
summary = "푸시 토큰 구독 해지",
description = "인증된 회원의 등록된 푸시 토큰을 삭제합니다."
)
@ApiResponses({
@ApiResponse(responseCode = "200", description = "구독 해지 완료"),
@ApiResponse(responseCode = "400", description = "토큰이 유효하지 않음", content = @Content)
})
public void unsubscribe(
@Parameter(hidden = true) @MemberId Long memberId,
@RequestBody PushTokenRequest request) {
pushService.unsubscribe(memberId, request.deviceId(), request.token());
}


}