From c610ba7b3407b495403efb159619c3e6658bfc2a Mon Sep 17 00:00:00 2001 From: hs12 Date: Mon, 30 Jun 2025 13:09:17 +0900 Subject: [PATCH 01/38] =?UTF-8?q?[remove]=20:=20=EB=B0=B0=ED=8F=AC=20?= =?UTF-8?q?=EC=8A=A4=ED=81=AC=EB=A6=BD=ED=8A=B8=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/cd.yml | 83 ---------------------------------------- 1 file changed, 83 deletions(-) delete mode 100644 .github/workflows/cd.yml diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml deleted file mode 100644 index 93dfa74e..00000000 --- a/.github/workflows/cd.yml +++ /dev/null @@ -1,83 +0,0 @@ -name: CD Backend - -on: - push: - branches: [ "main", "dev" ] - -permissions: - contents: read - -jobs: - build: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - # 자바 버전 설정 - - name: Set up JDK 17 - uses: actions/setup-java@v3 - with: - java-version: '17' - distribution: 'temurin' - - # yml 파일 생성 - - name: Generate application-core.yml - run: | - mkdir -p ./core/src/main/resources - echo "${{ secrets.APPLICATION_CORE }}" | base64 -d > ./core/src/main/resources/application-core.yml - - # firebase json 파일 생성 - - name : Generate firebase_account.json - run: | - mkdir -p ./core/src/main/resources/firebase - echo "${{ secrets.FIREBASE_ACCOUNT }}" | base64 -d > ./core/src/main/resources/firebase/firebase_account.json - - # gradle 권한 부여 - - name: Grant execute permission for gradlew - run: chmod +x ./gradlew - shell: bash - - # 빌드 시 캐시 적용 - - name: Gradle Caching - uses: actions/cache@v3 - with: - path: | - ~/.gradle/caches - ~/.gradle/wrapper - key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} - restore-keys: | - ${{ runner.os }}-gradle- - - # 빌드 - - name: Build with Gradle - run: ./gradlew build -x test - - - # 도커 허브 로그인 - - name: Docker Hub Login - uses: docker/login-action@v2 - with: - username: ${{ secrets.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_TOKEN }} - - - # 도커 이미지 빌드 및 푸시 - - name: docker image build and push - run: | - docker build -f Dockerfile -t ${{ secrets.DOCKERHUB_USERNAME }}/${{ secrets.DOCKERHUB_APP_NAME }} . - docker push ${{ secrets.DOCKERHUB_USERNAME }}/${{ secrets.DOCKERHUB_APP_NAME }} - - # 서버 백그라운드 실행 - - name: pull image and run container - uses: appleboy/ssh-action@master - with: - host: ${{ secrets.EC2_HOST }} - username: ${{ secrets.EC2_USERNAME }} - key: ${{ secrets.EC2_KEY }} - port: ${{ secrets.EC2_PORT }} - script: | - cd compose - docker rm -f $(docker ps -qa) - docker pull ${{ secrets.DOCKERHUB_USERNAME }}/${{ secrets.DOCKERHUB_APP_NAME }} - docker-compose up -d - docker system prune -f \ No newline at end of file From dfc1af21c27fac3441b94d953f874feed5876f35 Mon Sep 17 00:00:00 2001 From: hs12 Date: Mon, 30 Jun 2025 13:09:33 +0900 Subject: [PATCH 02/38] =?UTF-8?q?[remove]=20:=20dummy=20sql=20=ED=8C=8C?= =?UTF-8?q?=EC=9D=BC=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- insert_auction_dummy_data.sql | 22 ---------------------- insert_product_dummy_data.sql | 19 ------------------- insert_product_image_dummy_data.sql | 19 ------------------- 3 files changed, 60 deletions(-) delete mode 100644 insert_auction_dummy_data.sql delete mode 100644 insert_product_dummy_data.sql delete mode 100644 insert_product_image_dummy_data.sql diff --git a/insert_auction_dummy_data.sql b/insert_auction_dummy_data.sql deleted file mode 100644 index 718ab2af..00000000 --- a/insert_auction_dummy_data.sql +++ /dev/null @@ -1,22 +0,0 @@ -DELIMITER $$ - -DROP PROCEDURE IF EXISTS insert_auction_dummy_data; -CREATE PROCEDURE insert_auction_dummy_data() - -BEGIN - DECLARE i INT DEFAULT 0; - WHILE i < 3000 DO - INSERT INTO auction - (created_at, updated_at, bidding_count, bookmark_count, current_bidding_price, end_date, init_price, auction_status, title, trade_method, dong, gu, si, buyer_id, product_id, seller_id, buy_price) - VALUES - (NOW(), NOW(), FLOOR(RAND() * 10), FLOOR(RAND() * 10), 3000, '2024-04-07', 3000, 'BIDDING', '에어팟 거의 새거', 'DIRECT', '동선동', '성북구', '서울시', NULL, 1 + i, 2, NULL); - SET i = i + 1; - END WHILE; -END$$ - -DELIMITER ; - -CALL insert_auction_dummy_data(); - -# ALTER TABLE auction AUTO_INCREMENT = 1; -# DELETE FROM auction WHERE auction_id >= 1; diff --git a/insert_product_dummy_data.sql b/insert_product_dummy_data.sql deleted file mode 100644 index c5916d46..00000000 --- a/insert_product_dummy_data.sql +++ /dev/null @@ -1,19 +0,0 @@ -DELIMITER $$ - -DROP PROCEDURE IF EXISTS insert_product_dummy_data; -CREATE PROCEDURE insert_product_dummy_data() - -BEGIN - DECLARE i INT DEFAULT 0; - WHILE i < 3000 DO - INSERT INTO product (created_at, updated_at, description, purchase_time, status, product_category_id) - VALUES (NOW(), NOW(), '애플 에어팟 맛집입니다^^', 'UNDER_ONE_MONTH', 'CLEAN', 1); - SET i = i + 1; - END WHILE; -END$$ - -DELIMITER ; -CALL insert_product_dummy_data(); - -# ALTER TABLE product AUTO_INCREMENT = 1; -# DELETE FROM product WHERE product_id >= 1; diff --git a/insert_product_image_dummy_data.sql b/insert_product_image_dummy_data.sql deleted file mode 100644 index df07f2eb..00000000 --- a/insert_product_image_dummy_data.sql +++ /dev/null @@ -1,19 +0,0 @@ -DELIMITER $$ - -DROP PROCEDURE IF EXISTS insert_product_image_dummy_data; -CREATE PROCEDURE insert_product_image_dummy_data() - -BEGIN - DECLARE i INT DEFAULT 0; - WHILE i < 3000 DO - INSERT INTO product_image (created_at, updated_at, image_url, product_id) - VALUES (NOW(), NOW(), "image_url_string", i + 1); - SET i = i + 1; - END WHILE; -END$$ - -DELIMITER ; -CALL insert_product_image_dummy_data(); - -# ALTER TABLE product_image AUTO_INCREMENT = 1; -# DELETE FROM product_image WHERE product_image_id >= 1; From f353875d83ab4913bdbe9d5341fbcee40841a7d6 Mon Sep 17 00:00:00 2001 From: hs12 Date: Mon, 30 Jun 2025 13:10:02 +0900 Subject: [PATCH 03/38] =?UTF-8?q?[remove]=20:=20=EC=95=8C=EB=A6=BC=20?= =?UTF-8?q?=EA=B4=80=EB=A0=A8=20=ED=8C=8C=EC=9D=BC=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/NotificationApiController.java | 71 ----------- .../NotificationApiControllerTest.java | 120 ------------------ .../notification/dto/NotificationMapper.java | 29 ----- .../dto/request/SaveFCMTokenRequest.java | 19 --- .../CountUserNotificationsResponse.java | 10 -- .../dto/response/NotificationResponse.java | 31 ----- .../exception/NotificationErrorCode.java | 17 --- .../repository/NotificationRepository.java | 18 --- .../service/NotificationCleanupService.java | 24 ---- .../domain/service/FCMServiceTest.java | 61 --------- 10 files changed, 400 deletions(-) delete mode 100644 api/src/main/java/dev/handsup/notification/controller/NotificationApiController.java delete mode 100644 api/src/test/java/dev/handsup/notification/controller/NotificationApiControllerTest.java delete mode 100644 core/src/main/java/dev/handsup/notification/dto/NotificationMapper.java delete mode 100644 core/src/main/java/dev/handsup/notification/dto/request/SaveFCMTokenRequest.java delete mode 100644 core/src/main/java/dev/handsup/notification/dto/response/CountUserNotificationsResponse.java delete mode 100644 core/src/main/java/dev/handsup/notification/dto/response/NotificationResponse.java delete mode 100644 core/src/main/java/dev/handsup/notification/exception/NotificationErrorCode.java delete mode 100644 core/src/main/java/dev/handsup/notification/repository/NotificationRepository.java delete mode 100644 core/src/main/java/dev/handsup/notification/service/NotificationCleanupService.java delete mode 100644 core/src/test/java/dev/handsup/notification/domain/service/FCMServiceTest.java diff --git a/api/src/main/java/dev/handsup/notification/controller/NotificationApiController.java b/api/src/main/java/dev/handsup/notification/controller/NotificationApiController.java deleted file mode 100644 index 832c6d3f..00000000 --- a/api/src/main/java/dev/handsup/notification/controller/NotificationApiController.java +++ /dev/null @@ -1,71 +0,0 @@ -package dev.handsup.notification.controller; - -import org.springframework.data.domain.Pageable; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -import dev.handsup.auth.jwt.JwtAuthorization; -import dev.handsup.common.dto.PageResponse; -import dev.handsup.notification.dto.request.SaveFCMTokenRequest; -import dev.handsup.notification.dto.response.CountUserNotificationsResponse; -import dev.handsup.notification.dto.response.NotificationResponse; -import dev.handsup.notification.service.FCMService; -import dev.handsup.notification.service.NotificationService; -import dev.handsup.user.domain.User; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.tags.Tag; -import lombok.RequiredArgsConstructor; - -@Tag(name = "알림 API") -@RequestMapping("/api/notifications") -@RestController -@RequiredArgsConstructor -public class NotificationApiController { - - private final NotificationService notificationService; - private final FCMService fcmService; - - @PostMapping("/fcm-tokens") - @Operation(summary = "FCM 토큰 저장 API", description = "사용자의 Email, FCM 토큰을 key, value 로 저장한다") - @ApiResponse(useReturnTypeSchema = true) - public ResponseEntity saveFCMToken( - @Parameter(hidden = true) @JwtAuthorization User user, - @RequestBody SaveFCMTokenRequest request - ) { - fcmService.saveFcmToken(user.getEmail(), request); - return ResponseEntity.ok(HttpStatus.OK); - } - - @GetMapping("/count") - @Operation(summary = "미확인 알림 수 조회 API", description = "특정 사용자의 확인하지 않은 알림 수를 조회한다") - @ApiResponse(useReturnTypeSchema = true) - public ResponseEntity countUserNotifications( - @Parameter(hidden = true) @JwtAuthorization User user - ) { - long readNotificationCount = user.getReadNotificationCount(); - long notificationsCount = notificationService.countNotificationsByUserEmail(user.getEmail()); - CountUserNotificationsResponse response = CountUserNotificationsResponse.from( - notificationsCount - readNotificationCount - ); - return ResponseEntity.ok(response); - } - - @GetMapping() - @Operation(summary = "알림 전체 조회 API", description = "특정 사용자가 받은 알림을 최근 생성 순으로 전체 조회한다") - @ApiResponse(useReturnTypeSchema = true) - public ResponseEntity> getUserReviewLabels( - @Parameter(hidden = true) @JwtAuthorization User user, - Pageable pageable - ) { - PageResponse response = notificationService.getNotifications(user, pageable); - return ResponseEntity.ok(response); - } - -} diff --git a/api/src/test/java/dev/handsup/notification/controller/NotificationApiControllerTest.java b/api/src/test/java/dev/handsup/notification/controller/NotificationApiControllerTest.java deleted file mode 100644 index e4021074..00000000 --- a/api/src/test/java/dev/handsup/notification/controller/NotificationApiControllerTest.java +++ /dev/null @@ -1,120 +0,0 @@ -package dev.handsup.notification.controller; - -import static org.springframework.http.HttpHeaders.*; -import static org.springframework.http.MediaType.*; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; - -import java.util.List; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.data.domain.PageRequest; -import org.springframework.test.util.ReflectionTestUtils; - -import dev.handsup.auction.domain.Auction; -import dev.handsup.auction.repository.auction.AuctionRepository; -import dev.handsup.auction.repository.product.ProductCategoryRepository; -import dev.handsup.auth.service.JwtProvider; -import dev.handsup.common.support.ApiTestSupport; -import dev.handsup.fixture.AuctionFixture; -import dev.handsup.fixture.UserFixture; -import dev.handsup.notification.domain.Notification; -import dev.handsup.notification.domain.NotificationType; -import dev.handsup.notification.dto.request.SaveFCMTokenRequest; -import dev.handsup.notification.repository.NotificationRepository; -import dev.handsup.user.domain.User; -import dev.handsup.user.repository.UserRepository; - -@DisplayName("[Notification 통합 테스트]") -class NotificationApiControllerTest extends ApiTestSupport { - - @Autowired - private NotificationRepository notificationRepository; - @Autowired - private AuctionRepository auctionRepository; - @Autowired - private ProductCategoryRepository productCategoryRepository; - @Autowired - private UserRepository userRepository; - @Autowired - private JwtProvider jwtProvider; - - private User receiver; - private String receiverAccessToken; - - @BeforeEach - void setUp() { - receiver = UserFixture.user2(); - ReflectionTestUtils.setField(receiver, "readNotificationCount", 1); - userRepository.save(receiver); - receiverAccessToken = jwtProvider.createAccessToken(receiver.getId()); - - Auction auction = AuctionFixture.auction(receiver); - productCategoryRepository.save(auction.getProduct().getProductCategory()); - auctionRepository.save(auction); - - Notification notification1 = Notification.of( - user.getEmail(), - receiver.getEmail(), - NotificationType.BOOKMARK.getContent(), - NotificationType.BOOKMARK, - auction - ); - Notification notification2 = Notification.of( - user.getEmail(), - receiver.getEmail(), - NotificationType.CHAT.getContent(), - NotificationType.CHAT, - auction - ); - Notification notification3 = Notification.of( - user.getEmail(), - receiver.getEmail(), - NotificationType.PURCHASE_WINNING.getContent(), - NotificationType.PURCHASE_WINNING, - auction - ); - notificationRepository.saveAll(List.of(notification1, notification2, notification3)); - } - - @Test - @DisplayName("FCM 토큰을 저장에 성공하면 HttpSatus.Ok 를 받는다") - void saveFCMToken() throws Exception { - SaveFCMTokenRequest request = SaveFCMTokenRequest.from("fcmToken123"); - - mockMvc.perform(post("/api/notifications/fcm-tokens") - .contentType(APPLICATION_JSON) - .header(AUTHORIZATION, "Bearer " + accessToken) - .content(toJson(request))) - .andExpect(status().isOk()); - } - - @Test - @DisplayName("사용자의 미확인 알림 수를 조회한다") - void countUserNotifications() throws Exception { - mockMvc.perform(get("/api/notifications/count") - .header(AUTHORIZATION, "Bearer " + receiverAccessToken)) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.count").value(2)); - } - - @Test - @DisplayName("사용자가 받은 전체 알림을 최근 생성 순으로 조회한다") - void getUserReviewLabels() throws Exception { - PageRequest pageRequest = PageRequest.of(0, 5); - - mockMvc.perform(get("/api/notifications") - .header(AUTHORIZATION, "Bearer " + receiverAccessToken) - .contentType(APPLICATION_JSON) - .content(toJson(pageRequest)) - ) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.content.size()").value(3)) - .andExpect(jsonPath("$.content[0].content").value(NotificationType.PURCHASE_WINNING.getContent())) - .andExpect(jsonPath("$.content[1].content").value(NotificationType.CHAT.getContent())) - .andExpect(jsonPath("$.content[2].content").value(NotificationType.BOOKMARK.getContent())); - } -} diff --git a/core/src/main/java/dev/handsup/notification/dto/NotificationMapper.java b/core/src/main/java/dev/handsup/notification/dto/NotificationMapper.java deleted file mode 100644 index 61298030..00000000 --- a/core/src/main/java/dev/handsup/notification/dto/NotificationMapper.java +++ /dev/null @@ -1,29 +0,0 @@ -package dev.handsup.notification.dto; - -import static lombok.AccessLevel.*; - -import dev.handsup.notification.domain.NotificationType; -import dev.handsup.notification.dto.response.NotificationResponse; -import lombok.NoArgsConstructor; - -@NoArgsConstructor(access = PRIVATE) -public class NotificationMapper { - - public static NotificationResponse toNotificationResponse( - Long notificationId, - NotificationType notificationType, - String content, - String senderProfileImageUrl, - Long auctionId, - String auctionImageUrl - ) { - return NotificationResponse.of( - notificationId, - notificationType, - content, - senderProfileImageUrl, - auctionId, - auctionImageUrl - ); - } -} diff --git a/core/src/main/java/dev/handsup/notification/dto/request/SaveFCMTokenRequest.java b/core/src/main/java/dev/handsup/notification/dto/request/SaveFCMTokenRequest.java deleted file mode 100644 index de7370f9..00000000 --- a/core/src/main/java/dev/handsup/notification/dto/request/SaveFCMTokenRequest.java +++ /dev/null @@ -1,19 +0,0 @@ -package dev.handsup.notification.dto.request; - -import static lombok.AccessLevel.*; - -import jakarta.validation.constraints.NotNull; -import lombok.Builder; - -@Builder(access = PRIVATE) -public record SaveFCMTokenRequest( - - @NotNull(message = "fcmToken 은 null일 수 없습니다.") - String fcmToken -) { - public static SaveFCMTokenRequest from(String fcmToken) { - return SaveFCMTokenRequest.builder() - .fcmToken(fcmToken) - .build(); - } -} diff --git a/core/src/main/java/dev/handsup/notification/dto/response/CountUserNotificationsResponse.java b/core/src/main/java/dev/handsup/notification/dto/response/CountUserNotificationsResponse.java deleted file mode 100644 index 8d592d62..00000000 --- a/core/src/main/java/dev/handsup/notification/dto/response/CountUserNotificationsResponse.java +++ /dev/null @@ -1,10 +0,0 @@ -package dev.handsup.notification.dto.response; - -public record CountUserNotificationsResponse( - - long count -) { - public static CountUserNotificationsResponse from(long count) { - return new CountUserNotificationsResponse(count); - } -} diff --git a/core/src/main/java/dev/handsup/notification/dto/response/NotificationResponse.java b/core/src/main/java/dev/handsup/notification/dto/response/NotificationResponse.java deleted file mode 100644 index 700ff276..00000000 --- a/core/src/main/java/dev/handsup/notification/dto/response/NotificationResponse.java +++ /dev/null @@ -1,31 +0,0 @@ -package dev.handsup.notification.dto.response; - -import dev.handsup.notification.domain.NotificationType; - -public record NotificationResponse( - - Long notificationId, - NotificationType notificationType, - String content, - String senderProfileImageUrl, - Long auctionId, - String auctionImageUrl -) { - public static NotificationResponse of( - Long notificationId, - NotificationType notificationType, - String content, - String senderProfileImageUrl, - Long auctionId, - String auctionImageUrl - ) { - return new NotificationResponse( - notificationId, - notificationType, - content, - senderProfileImageUrl, - auctionId, - auctionImageUrl - ); - } -} diff --git a/core/src/main/java/dev/handsup/notification/exception/NotificationErrorCode.java b/core/src/main/java/dev/handsup/notification/exception/NotificationErrorCode.java deleted file mode 100644 index ee41e94e..00000000 --- a/core/src/main/java/dev/handsup/notification/exception/NotificationErrorCode.java +++ /dev/null @@ -1,17 +0,0 @@ -package dev.handsup.notification.exception; - -import dev.handsup.common.exception.ErrorCode; -import lombok.Getter; -import lombok.RequiredArgsConstructor; - -@Getter -@RequiredArgsConstructor -public enum NotificationErrorCode implements ErrorCode { - - FAILED_TO_SEND_FIREBASE_MESSAGE("FIREBASE 의 메시지 전송에 실패했습니다.", "NOTIF_001"), - FAILED_TO_SEND_MESSAGE("메시지 전송에 실패했습니다.", "NOTIF_002"), - NOT_FOUND_FCM_TOKEN("FCMTokenRepository 에 해당 FCM토큰이 존재하지 않습니다.", "NOTIF_003"); - - private final String message; - private final String code; -} diff --git a/core/src/main/java/dev/handsup/notification/repository/NotificationRepository.java b/core/src/main/java/dev/handsup/notification/repository/NotificationRepository.java deleted file mode 100644 index 1079fca1..00000000 --- a/core/src/main/java/dev/handsup/notification/repository/NotificationRepository.java +++ /dev/null @@ -1,18 +0,0 @@ -package dev.handsup.notification.repository; - -import java.time.LocalDateTime; - -import org.springframework.data.domain.Pageable; -import org.springframework.data.domain.Slice; -import org.springframework.data.jpa.repository.JpaRepository; - -import dev.handsup.notification.domain.Notification; - -public interface NotificationRepository extends JpaRepository { - - long countByReceiverEmail(String receiverEmail); - - Slice findByReceiverEmailOrderByCreatedAtDesc(String receiverEmail, Pageable pageable); - - void deleteByCreatedAtBefore(LocalDateTime dateTime); -} diff --git a/core/src/main/java/dev/handsup/notification/service/NotificationCleanupService.java b/core/src/main/java/dev/handsup/notification/service/NotificationCleanupService.java deleted file mode 100644 index eb439ebd..00000000 --- a/core/src/main/java/dev/handsup/notification/service/NotificationCleanupService.java +++ /dev/null @@ -1,24 +0,0 @@ -package dev.handsup.notification.service; - -import java.time.LocalDateTime; - -import org.springframework.scheduling.annotation.Scheduled; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import dev.handsup.notification.repository.NotificationRepository; -import lombok.RequiredArgsConstructor; - -@Service -@RequiredArgsConstructor -public class NotificationCleanupService { - - private final NotificationRepository notificationRepository; - - // 매일 자정에 실행 - @Transactional - @Scheduled(cron = "0 0 0 * * ?") - public void deleteOldNotifications() { - notificationRepository.deleteByCreatedAtBefore(LocalDateTime.now().minusWeeks(2)); - } -} diff --git a/core/src/test/java/dev/handsup/notification/domain/service/FCMServiceTest.java b/core/src/test/java/dev/handsup/notification/domain/service/FCMServiceTest.java deleted file mode 100644 index 48d7dfa8..00000000 --- a/core/src/test/java/dev/handsup/notification/domain/service/FCMServiceTest.java +++ /dev/null @@ -1,61 +0,0 @@ -package dev.handsup.notification.domain.service; - -import static org.mockito.ArgumentMatchers.*; -import static org.mockito.BDDMockito.*; - -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; - -import com.google.firebase.messaging.FirebaseMessaging; -import com.google.firebase.messaging.FirebaseMessagingException; - -import dev.handsup.auction.domain.Auction; -import dev.handsup.fixture.AuctionFixture; -import dev.handsup.fixture.UserFixture; -import dev.handsup.notification.domain.NotificationType; -import dev.handsup.notification.repository.FCMTokenRepository; -import dev.handsup.notification.service.FCMService; -import dev.handsup.notification.service.NotificationService; -import dev.handsup.user.domain.User; - -@DisplayName("[FCM 알림 서비스 테스트]") -@ExtendWith(MockitoExtension.class) -class FCMServiceTest { - - private final User receiver = UserFixture.user1(); - private final Auction auction = AuctionFixture.auction(); - @Mock - private FCMTokenRepository fcmTokenRepository; - @Mock - private FirebaseMessaging firebaseMessaging; - @Mock - private NotificationService notificationService; - @InjectMocks - private FCMService fcmService; - - @Test - @DisplayName("메시지를 성공적으로 보낸다]") - void sendMessageSuccessTest() throws FirebaseMessagingException { - // given - String receiverEmail = receiver.getEmail(); - String fcmToken = "fcmToken123"; - given(fcmTokenRepository.getFcmToken(receiverEmail)).willReturn(fcmToken); - - // when - fcmService.sendMessage( - "senderEmail", - "senderNickname", - receiverEmail, - NotificationType.BOOKMARK, - auction - ); - - // then - verify(firebaseMessaging, times(1)).send(any()); - } - -} From d58baa3b33fb05ac30c3c0ca1b95495cf99a1824 Mon Sep 17 00:00:00 2001 From: hs12 Date: Mon, 30 Jun 2025 13:10:58 +0900 Subject: [PATCH 04/38] =?UTF-8?q?[chore]=20:=20application.yml=20=EC=95=8C?= =?UTF-8?q?=EB=A6=BC=20=EA=B2=BD=EB=A1=9C=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/src/test/resources/application.yml | 3 --- core/src/test/resources/application.yml | 3 --- 2 files changed, 6 deletions(-) diff --git a/api/src/test/resources/application.yml b/api/src/test/resources/application.yml index 060e11e0..0de398ff 100644 --- a/api/src/test/resources/application.yml +++ b/api/src/test/resources/application.yml @@ -24,6 +24,3 @@ cloud: bucket: s3-bucket-name stack: auto: false - -fcm: - certification: firebase/firebase_account.json diff --git a/core/src/test/resources/application.yml b/core/src/test/resources/application.yml index 060e11e0..0de398ff 100644 --- a/core/src/test/resources/application.yml +++ b/core/src/test/resources/application.yml @@ -24,6 +24,3 @@ cloud: bucket: s3-bucket-name stack: auto: false - -fcm: - certification: firebase/firebase_account.json From 6dbd72ed9e30ae64495efeeda2ffd95ea634ef42 Mon Sep 17 00:00:00 2001 From: hs12 Date: Mon, 30 Jun 2025 13:11:21 +0900 Subject: [PATCH 05/38] =?UTF-8?q?[chore]=20:=20=EC=83=88=20json=20?= =?UTF-8?q?=ED=8C=8C=EC=9D=BC=20gitignore=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 50eb0168..1366d5f7 100644 --- a/.gitignore +++ b/.gitignore @@ -45,3 +45,4 @@ core/src/main/resources/application-core-prod.yml /core/src/test/resources/firebase/firebase_account.json /api/src/test/resources/firebase/firebase_account.json /core/src/main/resources/application-core-local.yml +/core/src/main/resources/firebase/serviceAccountKey.json From c25c8669c0ec251226927c84fc8aa5ccee88e91b Mon Sep 17 00:00:00 2001 From: hs12 Date: Mon, 30 Jun 2025 13:12:58 +0900 Subject: [PATCH 06/38] =?UTF-8?q?[feat]=20:=20=EA=B8=B0=EC=A1=B4=20?= =?UTF-8?q?=EC=95=8C=EB=A6=BC=20=EC=82=AD=EC=A0=9C=20=EB=B0=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/controller/AuthApiController.java | 3 --- .../controller/BiddingApiControllerTest.java | 6 +----- .../controller/BookmarkApiControllerTest.java | 6 +----- .../controller/CommentApiControllerTest.java | 5 +---- .../bookmark/service/BookmarkService.java | 16 ---------------- .../handsup/chat/service/ChatMessageService.java | 16 ---------------- .../handsup/comment/service/CommentService.java | 15 --------------- .../bidding/service/BiddingServiceTest.java | 4 ++-- .../bookmark/service/BookmarkServiceTest.java | 4 +--- .../chat/repository/ChatRoomRepositoryTest.java | 6 +++--- .../comment/service/CommentServiceTest.java | 4 +--- 11 files changed, 10 insertions(+), 75 deletions(-) diff --git a/api/src/main/java/dev/handsup/auth/controller/AuthApiController.java b/api/src/main/java/dev/handsup/auth/controller/AuthApiController.java index 7c999749..c5aec2ef 100644 --- a/api/src/main/java/dev/handsup/auth/controller/AuthApiController.java +++ b/api/src/main/java/dev/handsup/auth/controller/AuthApiController.java @@ -17,7 +17,6 @@ import dev.handsup.auth.dto.response.TokenReIssueResponse; import dev.handsup.auth.jwt.JwtAuthorization; import dev.handsup.auth.service.AuthService; -import dev.handsup.notification.service.FCMService; import dev.handsup.user.domain.User; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; @@ -35,7 +34,6 @@ public class AuthApiController { private final AuthService authService; - private final FCMService fcmService; @NoAuth @PostMapping("/login") @@ -60,7 +58,6 @@ public ResponseEntity login( public ResponseEntity logout( @Parameter(hidden = true) @JwtAuthorization User user ) { - fcmService.deleteFcmToken(user.getEmail()); return ResponseEntity.ok(HttpStatus.OK); } diff --git a/api/src/test/java/dev/handsup/bidding/controller/BiddingApiControllerTest.java b/api/src/test/java/dev/handsup/bidding/controller/BiddingApiControllerTest.java index 61fb1844..ea8b878c 100644 --- a/api/src/test/java/dev/handsup/bidding/controller/BiddingApiControllerTest.java +++ b/api/src/test/java/dev/handsup/bidding/controller/BiddingApiControllerTest.java @@ -32,7 +32,6 @@ import dev.handsup.fixture.AuctionFixture; import dev.handsup.fixture.BiddingFixture; import dev.handsup.fixture.UserFixture; -import dev.handsup.notification.repository.FCMTokenRepository; import dev.handsup.user.domain.User; import dev.handsup.user.repository.UserRepository; @@ -56,8 +55,7 @@ class BiddingApiControllerTest extends ApiTestSupport { private AuctionService auctionService; @Autowired private JwtProvider jwtProvider; - @Autowired - private FCMTokenRepository fcmTokenRepository; + @BeforeEach void setUp() { @@ -170,7 +168,6 @@ void getTop3BidsForAuctionTest() throws Exception { @Test void completeTrading() throws Exception { //given - fcmTokenRepository.saveFcmToken(bidder.getEmail(), "fcmToken123"); ReflectionTestUtils.setField(auction1, "status", AuctionStatus.TRADING); //변경 감지 Bidding bidding = BiddingFixture.bidding(bidder, auction1, TradingStatus.PROGRESSING); biddingRepository.save(bidding); @@ -204,7 +201,6 @@ void completeTrading_fails() throws Exception { @Test void cancelTrading() throws Exception { //given - fcmTokenRepository.saveFcmToken(bidder.getEmail(), "fcmToken123"); Bidding waitingBidding1 = BiddingFixture.bidding(bidder, auction1, TradingStatus.WAITING, 200000); Bidding waitingBidding2 = BiddingFixture.bidding(bidder, auction1, TradingStatus.WAITING, 300000); Bidding anotherAuctionBidding = BiddingFixture.bidding(bidder, auction2, TradingStatus.WAITING, 400000); diff --git a/api/src/test/java/dev/handsup/bookmark/controller/BookmarkApiControllerTest.java b/api/src/test/java/dev/handsup/bookmark/controller/BookmarkApiControllerTest.java index 721f4b7e..9e2073d7 100644 --- a/api/src/test/java/dev/handsup/bookmark/controller/BookmarkApiControllerTest.java +++ b/api/src/test/java/dev/handsup/bookmark/controller/BookmarkApiControllerTest.java @@ -23,7 +23,6 @@ import dev.handsup.fixture.AuctionFixture; import dev.handsup.fixture.BookmarkFixture; import dev.handsup.fixture.UserFixture; -import dev.handsup.notification.repository.FCMTokenRepository; import dev.handsup.user.domain.User; @DisplayName("[Bookmark 통합 테스트]") @@ -37,8 +36,7 @@ class BookmarkApiControllerTest extends ApiTestSupport { private AuctionRepository auctionRepository; @Autowired private ProductCategoryRepository productCategoryRepository; - @Autowired - private FCMTokenRepository fcmTokenRepository; + @BeforeEach void setUp() { @@ -54,8 +52,6 @@ void setUp() { @Test @DisplayName("[북마크를 추가할 수 있다.]") void addBookmark() throws Exception { - // fcm 토큰 저장, seller 는 receiver - fcmTokenRepository.saveFcmToken(seller.getEmail(), "fcmToken123"); mockMvc.perform(post("/api/auctions/bookmarks/{auctionId}", auction.getId()) .contentType(APPLICATION_JSON) diff --git a/api/src/test/java/dev/handsup/comment/controller/CommentApiControllerTest.java b/api/src/test/java/dev/handsup/comment/controller/CommentApiControllerTest.java index ad1e68b7..833584c7 100644 --- a/api/src/test/java/dev/handsup/comment/controller/CommentApiControllerTest.java +++ b/api/src/test/java/dev/handsup/comment/controller/CommentApiControllerTest.java @@ -24,7 +24,6 @@ import dev.handsup.fixture.CommentFixture; import dev.handsup.fixture.ProductFixture; import dev.handsup.fixture.UserFixture; -import dev.handsup.notification.repository.FCMTokenRepository; import dev.handsup.user.domain.User; @DisplayName("[Comment 통합 테스트]") @@ -36,8 +35,7 @@ class CommentApiControllerTest extends ApiTestSupport { private ProductCategory productCategory; @Autowired private CommentRepository commentRepository; - @Autowired - private FCMTokenRepository fcmTokenRepository; + @BeforeEach void setUp() { @@ -50,7 +48,6 @@ void setUp() { @DisplayName("[댓글을 등록할 수 있다.]") @Test void registerComment() throws Exception { - fcmTokenRepository.saveFcmToken(seller.getEmail(), "fcmToken123"); RegisterCommentRequest request = RegisterCommentRequest.of("와"); mockMvc.perform(post("/api/auctions/{auctionId}/comments", auction.getId()) diff --git a/core/src/main/java/dev/handsup/bookmark/service/BookmarkService.java b/core/src/main/java/dev/handsup/bookmark/service/BookmarkService.java index 61dc2c80..55300782 100644 --- a/core/src/main/java/dev/handsup/bookmark/service/BookmarkService.java +++ b/core/src/main/java/dev/handsup/bookmark/service/BookmarkService.java @@ -21,8 +21,6 @@ import dev.handsup.common.dto.PageResponse; import dev.handsup.common.exception.NotFoundException; import dev.handsup.common.exception.ValidationException; -import dev.handsup.notification.domain.NotificationType; -import dev.handsup.notification.service.FCMService; import dev.handsup.user.domain.User; import lombok.RequiredArgsConstructor; @@ -32,7 +30,6 @@ public class BookmarkService { private final BookmarkRepository bookmarkRepository; private final AuctionRepository auctionRepository; - private final FCMService fcmService; @Transactional public EditBookmarkResponse addBookmark(User user, Long auctionId) { @@ -44,22 +41,9 @@ public EditBookmarkResponse addBookmark(User user, Long auctionId) { bookmarkRepository.save(bookmark); - // user 는 sender - sendMessage(user, auction); - return BookmarkMapper.toEditBookmarkResponse(auction.getBookmarkCount()); } - private void sendMessage(User user, Auction auction) { - fcmService.sendMessage( - user.getEmail(), - user.getNickname(), - auction.getSeller().getEmail(), - NotificationType.BOOKMARK, - auction - ); - } - private void validateSelfBookmark(User user, Auction auction) { if (Objects.equals(auction.getSeller().getId(), user.getId())) { throw new ValidationException(BookmarkErrorCode.NOT_ALLOW_SELF_BOOKMARK); diff --git a/core/src/main/java/dev/handsup/chat/service/ChatMessageService.java b/core/src/main/java/dev/handsup/chat/service/ChatMessageService.java index 4fcf2251..b4f99f8b 100644 --- a/core/src/main/java/dev/handsup/chat/service/ChatMessageService.java +++ b/core/src/main/java/dev/handsup/chat/service/ChatMessageService.java @@ -15,8 +15,6 @@ import dev.handsup.chat.repository.ChatMessageRepository; import dev.handsup.chat.repository.ChatRoomRepository; import dev.handsup.common.exception.NotFoundException; -import dev.handsup.notification.domain.NotificationType; -import dev.handsup.notification.service.FCMService; import dev.handsup.user.domain.User; import dev.handsup.user.exception.UserErrorCode; import dev.handsup.user.repository.UserRepository; @@ -30,7 +28,6 @@ public class ChatMessageService { private final ChatMessageRepository chatMessageRepository; private final UserRepository userRepository; private final AuctionRepository auctionRepository; - private final FCMService fcmService; @Transactional public ChatMessageResponse registerChatMessage(Long chatRoomId, ChatMessageRequest request) { @@ -38,22 +35,9 @@ public ChatMessageResponse registerChatMessage(Long chatRoomId, ChatMessageReque ChatMessage chatMessage = ChatMessageMapper.toChatMessage(chatRoom, request); ChatMessage savedChatMessage = chatMessageRepository.save(chatMessage); - User sender = getUserById(request.senderId()); - sendMessage(sender, chatRoom.getReceiver(sender), chatRoom); - return ChatMessageMapper.toChatMessageResponse(savedChatMessage); } - private void sendMessage(User sender, User receiver, ChatRoom chatRoom) { - fcmService.sendMessage( - sender.getEmail(), - sender.getNickname(), - receiver.getEmail(), - NotificationType.BOOKMARK, - getAuctionById(chatRoom.getAuctionId()) - ); - } - private ChatRoom getChatRoomById(Long chatRoomId) { return chatRoomRepository.findById(chatRoomId) .orElseThrow(() -> new NotFoundException(ChatRoomErrorCode.NOT_FOUND_CHAT_ROOM)); diff --git a/core/src/main/java/dev/handsup/comment/service/CommentService.java b/core/src/main/java/dev/handsup/comment/service/CommentService.java index a89daf9d..3ffa3aeb 100644 --- a/core/src/main/java/dev/handsup/comment/service/CommentService.java +++ b/core/src/main/java/dev/handsup/comment/service/CommentService.java @@ -16,8 +16,6 @@ import dev.handsup.common.dto.CommonMapper; import dev.handsup.common.dto.PageResponse; import dev.handsup.common.exception.NotFoundException; -import dev.handsup.notification.domain.NotificationType; -import dev.handsup.notification.service.FCMService; import dev.handsup.user.domain.User; import lombok.RequiredArgsConstructor; @@ -27,7 +25,6 @@ public class CommentService { private final AuctionRepository auctionRepository; private final CommentRepository commentRepository; - private final FCMService fcmService; @Transactional public CommentResponse registerAuctionComment(Long auctionId, RegisterCommentRequest request, User user) { @@ -36,21 +33,9 @@ public CommentResponse registerAuctionComment(Long auctionId, RegisterCommentReq auction.validateIfCommentAvailable(); Comment comment = commentRepository.save(CommentMapper.toComment(request, auction, user)); - sendMessage(user, auction); - return CommentMapper.toCommentResponse(comment); } - private void sendMessage(User user, Auction auction) { - fcmService.sendMessage( - user.getEmail(), - user.getNickname(), - auction.getSeller().getEmail(), - NotificationType.COMMENT, - auction - ); - } - @Transactional(readOnly = true) public PageResponse getAuctionComments(Long auctionId, Pageable pageable) { Auction auction = getAuctionById(auctionId); diff --git a/core/src/test/java/dev/handsup/bidding/service/BiddingServiceTest.java b/core/src/test/java/dev/handsup/bidding/service/BiddingServiceTest.java index 23ea7d2e..f2d01069 100644 --- a/core/src/test/java/dev/handsup/bidding/service/BiddingServiceTest.java +++ b/core/src/test/java/dev/handsup/bidding/service/BiddingServiceTest.java @@ -35,7 +35,7 @@ import dev.handsup.fixture.AuctionFixture; import dev.handsup.fixture.BiddingFixture; import dev.handsup.fixture.UserFixture; -import dev.handsup.notification.service.FCMService; +import dev.handsup.notification.service.NotificationSender; import dev.handsup.user.domain.User; @ExtendWith(MockitoExtension.class) @@ -52,7 +52,7 @@ class BiddingServiceTest { @Mock private AuctionRepository auctionRepository; @Mock - private FCMService fcmService; + private NotificationSender notificationSender; @InjectMocks private BiddingService biddingService; diff --git a/core/src/test/java/dev/handsup/bookmark/service/BookmarkServiceTest.java b/core/src/test/java/dev/handsup/bookmark/service/BookmarkServiceTest.java index 32f2055d..3ee9621b 100644 --- a/core/src/test/java/dev/handsup/bookmark/service/BookmarkServiceTest.java +++ b/core/src/test/java/dev/handsup/bookmark/service/BookmarkServiceTest.java @@ -29,7 +29,6 @@ import dev.handsup.fixture.AuctionFixture; import dev.handsup.fixture.BookmarkFixture; import dev.handsup.fixture.UserFixture; -import dev.handsup.notification.service.FCMService; import dev.handsup.user.domain.User; @DisplayName("[BookmarkService 테스트]") @@ -42,8 +41,7 @@ class BookmarkServiceTest { private AuctionRepository auctionRepository; @Mock private BookmarkRepository bookmarkRepository; - @Mock - private FCMService fcmService; + @InjectMocks private BookmarkService bookmarkService; diff --git a/core/src/test/java/dev/handsup/chat/repository/ChatRoomRepositoryTest.java b/core/src/test/java/dev/handsup/chat/repository/ChatRoomRepositoryTest.java index d4672b74..25f6fd71 100644 --- a/core/src/test/java/dev/handsup/chat/repository/ChatRoomRepositoryTest.java +++ b/core/src/test/java/dev/handsup/chat/repository/ChatRoomRepositoryTest.java @@ -84,9 +84,9 @@ void findChatRoomsByUser() { assertAll( () -> assertThat(chatRoomSlice).hasSize(3), () -> assertThat(chatRoomSlice.hasNext()).isFalse(), - () -> assertThat(chatRooms.get(0)).isEqualTo(chatRoom1), - () -> assertThat(chatRooms.get(1)).isEqualTo(chatRoom2), - () -> assertThat(chatRooms.get(2)).isEqualTo(chatRoom3) + () -> assertThat(chatRooms.get(0).getId()).isEqualTo(chatRoom1.getId()), + () -> assertThat(chatRooms.get(1).getId()).isEqualTo(chatRoom2.getId()), + () -> assertThat(chatRooms.get(2).getId()).isEqualTo(chatRoom3.getId()) ); } } diff --git a/core/src/test/java/dev/handsup/comment/service/CommentServiceTest.java b/core/src/test/java/dev/handsup/comment/service/CommentServiceTest.java index 44ff83e3..c98c296f 100644 --- a/core/src/test/java/dev/handsup/comment/service/CommentServiceTest.java +++ b/core/src/test/java/dev/handsup/comment/service/CommentServiceTest.java @@ -27,7 +27,6 @@ import dev.handsup.fixture.AuctionFixture; import dev.handsup.fixture.CommentFixture; import dev.handsup.fixture.UserFixture; -import dev.handsup.notification.service.FCMService; import dev.handsup.user.domain.User; @DisplayName("[댓글 서비스 테스트]") @@ -40,8 +39,7 @@ class CommentServiceTest { private AuctionRepository auctionRepository; @Mock private CommentRepository commentRepository; - @Mock - private FCMService fcmService; + @InjectMocks private CommentService commentService; From 3bbe13e1268c3064068958aa3c5fbfb6fc6e13c1 Mon Sep 17 00:00:00 2001 From: hs12 Date: Mon, 30 Jun 2025 13:13:25 +0900 Subject: [PATCH 07/38] =?UTF-8?q?[feat]=20:=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20=EC=97=94=ED=8B=B0=ED=8B=B0=20=EC=BB=AC=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../handsup/review/controller/ReviewApiControllerTest.java | 4 ---- core/src/main/java/dev/handsup/user/domain/User.java | 7 ------- .../dev/handsup/user/dto/response/UserDetailResponse.java | 2 -- 3 files changed, 13 deletions(-) diff --git a/api/src/test/java/dev/handsup/review/controller/ReviewApiControllerTest.java b/api/src/test/java/dev/handsup/review/controller/ReviewApiControllerTest.java index 9e0da3fb..80da1f6d 100644 --- a/api/src/test/java/dev/handsup/review/controller/ReviewApiControllerTest.java +++ b/api/src/test/java/dev/handsup/review/controller/ReviewApiControllerTest.java @@ -32,7 +32,6 @@ import dev.handsup.fixture.AuctionFixture; import dev.handsup.fixture.ReviewFixture; import dev.handsup.fixture.ReviewLabelFixture; -import dev.handsup.notification.repository.FCMTokenRepository; import dev.handsup.review.domain.Review; import dev.handsup.review.domain.ReviewLabel; import dev.handsup.review.domain.ReviewLabelValue; @@ -68,8 +67,6 @@ class ReviewApiControllerTest extends ApiTestSupport { private BiddingService biddingService; @Autowired private UserRepository userRepository; - @Autowired - private FCMTokenRepository fcmTokenRepository; @BeforeEach void setUp() { @@ -83,7 +80,6 @@ void setUp() { @DisplayName("[리뷰 등록 API] 작성자가 경매에 대한 리뷰를 등록한다") void registerReviewTest() throws Exception { // given - fcmTokenRepository.saveFcmToken(auction.getSeller().getEmail(), "fcmToken123"); ReflectionTestUtils.setField(auction, "status", AuctionStatus.TRADING); Long auctionId = auction.getId(); int beforeSellerScore = auction.getSeller().getScore(); diff --git a/core/src/main/java/dev/handsup/user/domain/User.java b/core/src/main/java/dev/handsup/user/domain/User.java index 491dac17..a6eeed3e 100644 --- a/core/src/main/java/dev/handsup/user/domain/User.java +++ b/core/src/main/java/dev/handsup/user/domain/User.java @@ -48,8 +48,6 @@ public class User extends TimeBaseEntity { @Column(name = "profile_image_url") private String profileImageUrl; - @Column(name = "report_count", nullable = false) - private int reportCount = 0; @Column(name = "read_notification_count", nullable = false) private long readNotificationCount = 0; @@ -134,11 +132,6 @@ private void validateUser( Assert.isTrue(matcher.matches(), NON_VALIDATED_EMAIL.getMessage()); } - //== 비즈니스 메서드==// - public void updateReadNotificationCount(long readNotificationCount) { - this.readNotificationCount = readNotificationCount; - } - public void operateScore(int evaluationScore) { score += evaluationScore; diff --git a/core/src/main/java/dev/handsup/user/dto/response/UserDetailResponse.java b/core/src/main/java/dev/handsup/user/dto/response/UserDetailResponse.java index b56f2a8d..92098158 100644 --- a/core/src/main/java/dev/handsup/user/dto/response/UserDetailResponse.java +++ b/core/src/main/java/dev/handsup/user/dto/response/UserDetailResponse.java @@ -11,7 +11,6 @@ public record UserDetailResponse( int score, Address address, String profileImageUrl, - int reportCount, long readNotificationCount ) { public static UserDetailResponse of(User user) { @@ -23,7 +22,6 @@ public static UserDetailResponse of(User user) { user.getScore(), user.getAddress(), user.getProfileImageUrl(), - user.getReportCount(), user.getReadNotificationCount() ); } From 6da68335d345c12f00c95405ed75fe4cc1576dd1 Mon Sep 17 00:00:00 2001 From: hs12 Date: Mon, 30 Jun 2025 13:13:55 +0900 Subject: [PATCH 08/38] =?UTF-8?q?[chore]=20:=20FCM=20=EC=84=A4=EC=A0=95=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dev/handsup/common/config/FCMConfig.java | 33 ++++++++----------- 1 file changed, 13 insertions(+), 20 deletions(-) diff --git a/core/src/main/java/dev/handsup/common/config/FCMConfig.java b/core/src/main/java/dev/handsup/common/config/FCMConfig.java index ebd71340..6af9bfeb 100644 --- a/core/src/main/java/dev/handsup/common/config/FCMConfig.java +++ b/core/src/main/java/dev/handsup/common/config/FCMConfig.java @@ -1,11 +1,7 @@ package dev.handsup.common.config; import java.io.IOException; -import java.io.InputStream; -import javax.annotation.PostConstruct; - -import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.ClassPathResource; @@ -15,28 +11,25 @@ import com.google.firebase.FirebaseOptions; import com.google.firebase.messaging.FirebaseMessaging; +import jakarta.annotation.PostConstruct; import lombok.extern.slf4j.Slf4j; -@Slf4j @Configuration -public class FCMConfig { - - @Value("${fcm.certification}") - private String googleApplicationCredentials; +@Slf4j +public class FcmConfig { + private static final String FIREBASE_KEY_PATH = "firebase/serviceAccountKey.json"; @PostConstruct - public void initialize() throws IOException { - ClassPathResource resource = new ClassPathResource(googleApplicationCredentials); - - try (InputStream inputStream = resource.getInputStream()) { + public void initialize() { + try { + GoogleCredentials googleCredentials = GoogleCredentials + .fromStream(new ClassPathResource(FIREBASE_KEY_PATH).getInputStream()); FirebaseOptions options = FirebaseOptions.builder() - .setCredentials(GoogleCredentials.fromStream(inputStream)) + .setCredentials(googleCredentials) .build(); - - if (FirebaseApp.getApps().isEmpty()) { - FirebaseApp.initializeApp(options); - log.info("FirebaseApp initialization complete"); - } + FirebaseApp.initializeApp(options); + } catch (IOException e) { + log.error(e.getMessage()); } } @@ -44,4 +37,4 @@ public void initialize() throws IOException { public FirebaseMessaging firebaseMessaging() { return FirebaseMessaging.getInstance(); } -} +} \ No newline at end of file From 3ca5af89a05ec6fc5d18aec180c09c51d75a6d74 Mon Sep 17 00:00:00 2001 From: hs12 Date: Mon, 30 Jun 2025 13:14:47 +0900 Subject: [PATCH 09/38] =?UTF-8?q?[feat]=20:=20=EC=83=88=20=EC=95=8C?= =?UTF-8?q?=EB=A6=BC=20=EC=97=94=ED=8B=B0=ED=8B=B0=20=EC=B6=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../notification/domain/Notification.java | 72 ++++++++----------- .../notification/domain/NotificationType.java | 11 +-- 2 files changed, 36 insertions(+), 47 deletions(-) diff --git a/core/src/main/java/dev/handsup/notification/domain/Notification.java b/core/src/main/java/dev/handsup/notification/domain/Notification.java index ecd99964..d19d14dd 100644 --- a/core/src/main/java/dev/handsup/notification/domain/Notification.java +++ b/core/src/main/java/dev/handsup/notification/domain/Notification.java @@ -1,28 +1,23 @@ package dev.handsup.notification.domain; -import static jakarta.persistence.ConstraintMode.*; -import static jakarta.persistence.EnumType.*; -import static jakarta.persistence.FetchType.*; import static jakarta.persistence.GenerationType.*; import static lombok.AccessLevel.*; -import dev.handsup.auction.domain.Auction; import dev.handsup.common.entity.TimeBaseEntity; import jakarta.persistence.Column; import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; import jakarta.persistence.Enumerated; -import jakarta.persistence.ForeignKey; import jakarta.persistence.GeneratedValue; import jakarta.persistence.Id; -import jakarta.persistence.JoinColumn; -import jakarta.persistence.ManyToOne; +import lombok.AccessLevel; import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; @Entity -@Getter @NoArgsConstructor(access = PROTECTED) +@Getter public class Notification extends TimeBaseEntity { @Id @@ -30,54 +25,47 @@ public class Notification extends TimeBaseEntity { @Column(name = "notification_id") private Long id; - @Column(name = "sender_email", nullable = false) - private String senderEmail; + @Column(name = "receiver_id") + private Long receiverId; - @Column(name = "receiver_email", nullable = false) - private String receiverEmail; + @Column(name = "sender_id") + private Long senderId; - @Column(name = "content", nullable = false) - private String content; + @Column(name = "auction_id") + private Long auctionId; - @Column(name = "type", nullable = false) - @Enumerated(STRING) + @Column(name = "type") + @Enumerated(EnumType.STRING) private NotificationType type; - @ManyToOne(fetch = LAZY) - @JoinColumn(name = "auction_id", - nullable = false, - foreignKey = @ForeignKey(NO_CONSTRAINT)) - private Auction auction; + @Column(name = "content") + private String content; - @Builder - private Notification( - String senderEmail, - String receiverEmail, - String content, - NotificationType type, - Auction auction - ) { - this.senderEmail = senderEmail; - this.receiverEmail = receiverEmail; - this.content = content; + @Column(name = "is_read") + private boolean isRead = false; + + @Builder(access = AccessLevel.PRIVATE) + private Notification(Long receiverId, Long senderId, Long auctionId, NotificationType type, String content) { + this.receiverId = receiverId; + this.senderId = senderId; + this.auctionId = auctionId; this.type = type; - this.auction = auction; + this.content = content; } public static Notification of( - String senderEmail, - String receiverEmail, - String content, + Long receiverId, + Long senderId, + Long auctionId, NotificationType type, - Auction auction + String content ) { return Notification.builder() - .senderEmail(senderEmail) - .receiverEmail(receiverEmail) - .content(content) + .receiverId(receiverId) + .senderId(senderId) + .auctionId(auctionId) .type(type) - .auction(auction) + .content(content) .build(); } - } diff --git a/core/src/main/java/dev/handsup/notification/domain/NotificationType.java b/core/src/main/java/dev/handsup/notification/domain/NotificationType.java index d8049c93..b1f294be 100644 --- a/core/src/main/java/dev/handsup/notification/domain/NotificationType.java +++ b/core/src/main/java/dev/handsup/notification/domain/NotificationType.java @@ -8,11 +8,12 @@ public enum NotificationType { CHAT("채팅 알림", "님이 회원님과의 채팅방에서 속삭이고 있어요."), - COMMENT("자신의 경매의 댓글 알림 알림", "님이 회원님의 경매 물품에서 얘기하고 있어요."), - BOOKMARK("자신의 경매의 북마크 알림", "님이 회원님의 경매 물품을 관심있어 해요."), - PURCHASE_WINNING("구매 입찰의 낙찰 알림", "입찰하신 물품이 낙찰되었습니다."), - CANCELED_PURCHASE_TRADING("구매 입찰의 거래 취소 알림", "거래가 취소되었습니다."), - COMPLETED_PURCHASE_TRADING("구매 입찰의 거래 완료 알림", "거래가 완료되었습니다."); + COMMENT("경매 댓글 알림", "님이 회원님의 경매 물품에서 얘기하고 있어요."), + BOOKMARK("경매 북마크 알림", "님이 회원님의 경매 물품을 관심있어 해요."), + BIDDING_CREATED("입찰 알림", "님이 회원님 경매에 입찰하였습니다."), + PURCHASE_WINNING("낙찰 알림", "입찰하신 물품이 낙찰되었습니다."), + CANCELED_PURCHASE_TRADING("거래 취소 알림", "거래가 취소되었습니다."), + COMPLETED_PURCHASE_TRADING("거래 완료 알림", "거래가 완료되었습니다."); private final String title; private final String content; From 0d9cc860a62883aa68be013b6eea6d09cdb686ce Mon Sep 17 00:00:00 2001 From: hs12 Date: Mon, 30 Jun 2025 13:15:24 +0900 Subject: [PATCH 10/38] =?UTF-8?q?[feat]=20:=20FCM=20=ED=86=A0=ED=81=B0=20?= =?UTF-8?q?=EC=A0=80=EC=9E=A5=20=EA=B5=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/FCMController.java | 34 +++++++++++++++++ .../repository/FCMTokenRepository.java | 24 ++++++------ .../notification/service/FCMService.java | 38 +++++++------------ 3 files changed, 60 insertions(+), 36 deletions(-) create mode 100644 api/src/main/java/dev/handsup/notification/controller/FCMController.java diff --git a/api/src/main/java/dev/handsup/notification/controller/FCMController.java b/api/src/main/java/dev/handsup/notification/controller/FCMController.java new file mode 100644 index 00000000..f1a54b79 --- /dev/null +++ b/api/src/main/java/dev/handsup/notification/controller/FCMController.java @@ -0,0 +1,34 @@ +package dev.handsup.notification.controller; + +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; + +import dev.handsup.auth.jwt.JwtAuthorization; +import dev.handsup.notification.dto.SaveFCMTokenRequest; +import dev.handsup.notification.service.FCMService; +import dev.handsup.user.domain.User; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; + +@RestController +@RequiredArgsConstructor +public class FCMController { + private final FCMService fcmService; + + @PostMapping("/api/fcm-tokens") + @Operation(summary = "FCM 토큰 저장 API", description = "{사용자 아이디 : FCM 토큰}을 redis에 저장") + @ApiResponse(useReturnTypeSchema = true) + public ResponseEntity saveFCMToken( + @Parameter(hidden = true) @JwtAuthorization User user, + @RequestBody @Valid SaveFCMTokenRequest request + ) { + fcmService.saveFcmToken(user.getId(), request.fcmToken()); + return ResponseEntity.ok(HttpStatus.OK); + } +} diff --git a/core/src/main/java/dev/handsup/notification/repository/FCMTokenRepository.java b/core/src/main/java/dev/handsup/notification/repository/FCMTokenRepository.java index dfdf40dc..a405f622 100644 --- a/core/src/main/java/dev/handsup/notification/repository/FCMTokenRepository.java +++ b/core/src/main/java/dev/handsup/notification/repository/FCMTokenRepository.java @@ -9,22 +9,24 @@ @Component public class FCMTokenRepository { - private final StringRedisTemplate tokenRedisTemplate; + private static final String PREFIX = "fcmToken:"; - public void saveFcmToken(String receiverEmail, String fcmToken) { - tokenRedisTemplate.opsForValue() - .set(receiverEmail, fcmToken); + private final StringRedisTemplate redisTemplate; + + public void saveFcmToken(Long userId, String fcmToken) { + redisTemplate.opsForValue() + .set(PREFIX + userId, fcmToken); } - public String getFcmToken(String email) { - return tokenRedisTemplate.opsForValue().get(email); + public String getFcmToken(Long userId) { + return redisTemplate.opsForValue().get(PREFIX + userId); } - public void deleteFcmToken(String email) { - tokenRedisTemplate.delete(email); + public void deleteFcmToken(Long userId) { + redisTemplate.delete(PREFIX + userId); } - public boolean hasKey(String email) { - return Boolean.TRUE.equals(tokenRedisTemplate.hasKey(email)); + public boolean hasKey(Long userId) { + return redisTemplate.hasKey(PREFIX + userId); } -} +} \ No newline at end of file diff --git a/core/src/main/java/dev/handsup/notification/service/FCMService.java b/core/src/main/java/dev/handsup/notification/service/FCMService.java index ace0e1a5..9a9e8034 100644 --- a/core/src/main/java/dev/handsup/notification/service/FCMService.java +++ b/core/src/main/java/dev/handsup/notification/service/FCMService.java @@ -7,10 +7,8 @@ import com.google.firebase.messaging.Message; import com.google.firebase.messaging.Notification; -import dev.handsup.auction.domain.Auction; import dev.handsup.common.exception.ValidationException; import dev.handsup.notification.domain.NotificationType; -import dev.handsup.notification.dto.request.SaveFCMTokenRequest; import dev.handsup.notification.repository.FCMTokenRepository; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -19,19 +17,17 @@ @RequiredArgsConstructor @Service public class FCMService { - private final FCMTokenRepository fcmTokenRepository; private final FirebaseMessaging firebaseMessaging; - private final NotificationService notificationService; - public void sendMessage( - String senderEmail, + public void sendNotification( + Long senderId, String senderNickname, - String receiverEmail, - NotificationType notificationType, - Auction auction + Long receiverId, + Long auctionId, + NotificationType notificationType ) { - String fcmToken = fcmTokenRepository.getFcmToken(receiverEmail); + String fcmToken = fcmTokenRepository.getFcmToken(receiverId); if (fcmToken == null) { return; } @@ -49,31 +45,23 @@ public void sendMessage( .setToken(fcmToken) .build(); - send(message, receiverEmail); - - notificationService.saveNotification( - senderEmail, - receiverEmail, - senderNickname + notificationType.getContent(), - notificationType, - auction - ); + send(message, receiverId); } - private void send(Message message, String receiverEmail) { + private void send(Message message, Long receiverId) { try { firebaseMessaging.send(message); - log.info("Sent message: {}, to: {}", message, receiverEmail); + log.info("Sent message: {}, to: {}", message, receiverId); } catch (FirebaseMessagingException e) { throw new ValidationException(e.getMessage()); } } - public void saveFcmToken(String userEmail, SaveFCMTokenRequest request) { - fcmTokenRepository.saveFcmToken(userEmail, request.fcmToken()); + public void saveFcmToken(Long userId, String fcmToken) { + fcmTokenRepository.saveFcmToken(userId, fcmToken); } - public void deleteFcmToken(String email) { - fcmTokenRepository.deleteFcmToken(email); + public void deleteFcmToken(Long userId) { + fcmTokenRepository.deleteFcmToken(userId); } } From a40c94f35aa9e3fa3a55b8741d071b849a78242a Mon Sep 17 00:00:00 2001 From: hs12 Date: Mon, 30 Jun 2025 13:16:10 +0900 Subject: [PATCH 11/38] =?UTF-8?q?[feat]=20:=20=EC=9E=85=EC=B0=B0=20?= =?UTF-8?q?=EC=95=8C=EB=A6=BC=20=EC=B6=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bidding/service/BiddingService.java | 26 +++++++------------ .../notification/dto/SaveFCMTokenRequest.java | 18 +++++++++++++ .../service/NotificationSender.java | 24 +++++++++++++++++ .../repository/BiddingConcurrencyTest.java | 3 ++- 4 files changed, 53 insertions(+), 18 deletions(-) create mode 100644 core/src/main/java/dev/handsup/notification/dto/SaveFCMTokenRequest.java create mode 100644 core/src/main/java/dev/handsup/notification/service/NotificationSender.java diff --git a/core/src/main/java/dev/handsup/bidding/service/BiddingService.java b/core/src/main/java/dev/handsup/bidding/service/BiddingService.java index 3992a003..2b7eb55c 100644 --- a/core/src/main/java/dev/handsup/bidding/service/BiddingService.java +++ b/core/src/main/java/dev/handsup/bidding/service/BiddingService.java @@ -21,7 +21,7 @@ import dev.handsup.common.exception.ValidationException; import dev.handsup.common.redisson.DistributeLock; import dev.handsup.notification.domain.NotificationType; -import dev.handsup.notification.service.FCMService; +import dev.handsup.notification.service.NotificationSender; import dev.handsup.user.domain.User; import lombok.RequiredArgsConstructor; @@ -32,7 +32,7 @@ public class BiddingService { private final BiddingRepository biddingRepository; private final BiddingQueryRepository biddingQueryRepository; private final AuctionRepository auctionRepository; - private final FCMService fcmService; + private final NotificationSender notificationSender; @Transactional @DistributeLock(key = "'auction_' + #auctionId") // auctionId 값을 추출하여 락 키로 사용 @@ -43,6 +43,7 @@ public BiddingResponse registerBidding(RegisterBiddingRequest request, Long auct auction.updateCurrentBiddingPrice(request.biddingPrice()); // 경매 입찰 최고가 갱신 auction.increaseBiddingCount(); // 경매 입찰 수 + 1 Bidding bidding = BiddingMapper.toBidding(request.biddingPrice(), auction, bidder); + sendBiddingNotification(bidder,auction); //알림 전송 return BiddingMapper.toBiddingResponse(biddingRepository.save(bidding)); } @@ -64,7 +65,6 @@ public BiddingResponse completeTrading(Long biddingId, User user) { bidding.getAuction().updateAuctionStatusCompleted(); bidding.getAuction().updateBuyer(bidding.getBidder()); bidding.getAuction().updateBuyPrice(bidding.getBiddingPrice()); - sendMessage(user, bidding, NotificationType.COMPLETED_PURCHASE_TRADING); return BiddingMapper.toBiddingResponse(bidding); } @@ -79,12 +79,6 @@ public BiddingResponse cancelTrading(Long biddingId, User user) { .orElseThrow(() -> new NotFoundException(BiddingErrorCode.NOT_FOUND_NEXT_BIDDING)); nextBidding.updateTradingStatusPreparing(); // 다음 입찰 준비중 상태로 변경 - // 현재 입찰자 거래 취소 알림 - sendMessage(user, bidding, NotificationType.CANCELED_PURCHASE_TRADING); - - // 다음 입찰자 낙찰 알림 - sendMessage(user, nextBidding, NotificationType.PURCHASE_WINNING); - return BiddingMapper.toBiddingResponse(bidding); } @@ -114,14 +108,12 @@ private Auction getAuctionById(Long auctionId) { .orElseThrow(() -> new NotFoundException(AuctionErrorCode.NOT_FOUND_AUCTION)); } - private void sendMessage(User seller, Bidding bidding, NotificationType completedPurchaseTrading) { - fcmService.sendMessage( - seller.getEmail(), - seller.getNickname(), - bidding.getBidder().getEmail(), - completedPurchaseTrading, - bidding.getAuction() + private void sendBiddingNotification(User bidder, Auction auction) { + notificationSender.sendNotification( + bidder, + auction.getSeller(), + auction, + NotificationType.BIDDING_CREATED ); } - } diff --git a/core/src/main/java/dev/handsup/notification/dto/SaveFCMTokenRequest.java b/core/src/main/java/dev/handsup/notification/dto/SaveFCMTokenRequest.java new file mode 100644 index 00000000..4c8bed19 --- /dev/null +++ b/core/src/main/java/dev/handsup/notification/dto/SaveFCMTokenRequest.java @@ -0,0 +1,18 @@ +package dev.handsup.notification.dto; + +import static lombok.AccessLevel.*; + +import jakarta.validation.constraints.NotEmpty; +import lombok.Builder; + +@Builder(access = PRIVATE) +public record SaveFCMTokenRequest( + @NotEmpty(message = "fcmToken을 입력해주세요.") + String fcmToken +) { + public static SaveFCMTokenRequest from(String fcmToken) { + return SaveFCMTokenRequest.builder() + .fcmToken(fcmToken) + .build(); + } +} \ No newline at end of file diff --git a/core/src/main/java/dev/handsup/notification/service/NotificationSender.java b/core/src/main/java/dev/handsup/notification/service/NotificationSender.java new file mode 100644 index 00000000..a4086c4a --- /dev/null +++ b/core/src/main/java/dev/handsup/notification/service/NotificationSender.java @@ -0,0 +1,24 @@ +package dev.handsup.notification.service; + +import org.springframework.stereotype.Service; + +import dev.handsup.auction.domain.Auction; +import dev.handsup.notification.domain.NotificationType; +import dev.handsup.user.domain.User; +import lombok.RequiredArgsConstructor; + +@Service +@RequiredArgsConstructor +public class NotificationSender { + private final FCMService fcmService; + + public void sendNotification(User sender, User receiver, Auction auction, NotificationType type) { + fcmService.sendNotification( + sender.getId(), + sender.getNickname(), + receiver.getId(), + auction.getId(), + type + ); + } +} diff --git a/core/src/test/java/dev/handsup/bidding/repository/BiddingConcurrencyTest.java b/core/src/test/java/dev/handsup/bidding/repository/BiddingConcurrencyTest.java index faa2028d..1dabb068 100644 --- a/core/src/test/java/dev/handsup/bidding/repository/BiddingConcurrencyTest.java +++ b/core/src/test/java/dev/handsup/bidding/repository/BiddingConcurrencyTest.java @@ -19,6 +19,7 @@ import dev.handsup.auction.repository.product.ProductCategoryRepository; import dev.handsup.bidding.dto.request.RegisterBiddingRequest; import dev.handsup.bidding.service.BiddingService; +import dev.handsup.common.config.FcmConfig; import dev.handsup.config.TestAuditingConfig; import dev.handsup.fixture.AuctionFixture; import dev.handsup.fixture.UserFixture; @@ -29,7 +30,7 @@ @SpringBootTest @Slf4j -@Import(TestAuditingConfig.class) +@Import({TestAuditingConfig.class, FcmConfig.class}) class BiddingConcurrencyTest extends TestContainerSupport { private Auction auction; From c38eb132582df8272b5e65905e07b14d729b70c8 Mon Sep 17 00:00:00 2001 From: hs12 Date: Mon, 30 Jun 2025 13:16:31 +0900 Subject: [PATCH 12/38] =?UTF-8?q?[chore]=20:=20=EC=9E=85=EC=B0=B0=20?= =?UTF-8?q?=EC=95=8C=EB=A6=BC=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=9C=84?= =?UTF-8?q?=ED=95=9C=20Http=20test=20=ED=8C=8C=EC=9D=BC=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- core/src/test/http/bidding.http | 11 +++++++++++ core/src/test/http/user.http | 9 +++++++++ 2 files changed, 20 insertions(+) create mode 100644 core/src/test/http/bidding.http diff --git a/core/src/test/http/bidding.http b/core/src/test/http/bidding.http new file mode 100644 index 00000000..44435068 --- /dev/null +++ b/core/src/test/http/bidding.http @@ -0,0 +1,11 @@ + + +### +### 입찰 등록 +POST http://localhost:8080/api/auctions/1/bids +Content-Type: application/json +Authorization: Bearer eyJ0eXBlIjoiand0IiwiYWxnIjoiSFMyNTYifQ.eyJ1c2VySWQiOjIsImlhdCI6MTc1MTIwMDE0NywiZXhwIjoyMDY2NTYwMTQ3fQ.iRr1DCdtZlu1_--DSjENedXSzLwBiL4vcjMAgTBk8hI + +{ + "biddingPrice": 198000 +} \ No newline at end of file diff --git a/core/src/test/http/user.http b/core/src/test/http/user.http index 27d36e13..9d0eb7b7 100644 --- a/core/src/test/http/user.http +++ b/core/src/test/http/user.http @@ -5,4 +5,13 @@ Content-Type: application/json { "email": "user1@email.com", "password": "testpw1!" +} + +### 로그인 요청 (user2) +POST http://localhost:8080/api/auth/login +Content-Type: application/json + +{ +"email": "user2@email.com", +"password": "testpw2!" } \ No newline at end of file From 22b794b260b800958e56621ae118841e17e8ad17 Mon Sep 17 00:00:00 2001 From: hs12 Date: Mon, 30 Jun 2025 14:01:08 +0900 Subject: [PATCH 13/38] =?UTF-8?q?[refactor]=20:=20=ED=83=80=EC=9E=85?= =?UTF-8?q?=EC=97=90=20=EB=94=B0=EB=A5=B8=20=EB=A9=94=EC=8B=9C=EC=A7=80=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=20enum=EC=97=90=20=EC=B1=85=EC=9E=84=20?= =?UTF-8?q?=EC=9C=84=EC=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dev/handsup/notification/domain/NotificationType.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/core/src/main/java/dev/handsup/notification/domain/NotificationType.java b/core/src/main/java/dev/handsup/notification/domain/NotificationType.java index b1f294be..65e9cdb3 100644 --- a/core/src/main/java/dev/handsup/notification/domain/NotificationType.java +++ b/core/src/main/java/dev/handsup/notification/domain/NotificationType.java @@ -17,4 +17,11 @@ public enum NotificationType { private final String title; private final String content; + + public String processContent(String senderNickname) { + if (this == PURCHASE_WINNING || this == CANCELED_PURCHASE_TRADING) { + return this.content; + } + return senderNickname + this.content; + } } From 1f252700135a1c1575deed986fa3ebf2a2e73661 Mon Sep 17 00:00:00 2001 From: hs12 Date: Mon, 30 Jun 2025 14:01:55 +0900 Subject: [PATCH 14/38] =?UTF-8?q?[feat]=20:=20=EC=95=8C=EB=A6=BC=20?= =?UTF-8?q?=EC=A0=80=EC=9E=A5=20=EB=A1=9C=EC=A7=81=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../repository/NotificationRepository.java | 8 ++ .../service/NotificationService.java | 74 ++----------------- 2 files changed, 16 insertions(+), 66 deletions(-) create mode 100644 core/src/main/java/dev/handsup/notification/repository/NotificationRepository.java diff --git a/core/src/main/java/dev/handsup/notification/repository/NotificationRepository.java b/core/src/main/java/dev/handsup/notification/repository/NotificationRepository.java new file mode 100644 index 00000000..9271aa49 --- /dev/null +++ b/core/src/main/java/dev/handsup/notification/repository/NotificationRepository.java @@ -0,0 +1,8 @@ +package dev.handsup.notification.repository; + +import org.springframework.data.jpa.repository.JpaRepository; + +import dev.handsup.notification.domain.Notification; + +public interface NotificationRepository extends JpaRepository { +} diff --git a/core/src/main/java/dev/handsup/notification/service/NotificationService.java b/core/src/main/java/dev/handsup/notification/service/NotificationService.java index 0b3eec5a..1813f15b 100644 --- a/core/src/main/java/dev/handsup/notification/service/NotificationService.java +++ b/core/src/main/java/dev/handsup/notification/service/NotificationService.java @@ -1,86 +1,28 @@ package dev.handsup.notification.service; -import org.springframework.data.domain.Pageable; -import org.springframework.data.domain.Slice; import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import dev.handsup.auction.domain.Auction; -import dev.handsup.auction.exception.AuctionErrorCode; -import dev.handsup.auction.repository.auction.AuctionRepository; -import dev.handsup.common.dto.CommonMapper; -import dev.handsup.common.dto.PageResponse; -import dev.handsup.common.exception.NotFoundException; import dev.handsup.notification.domain.Notification; import dev.handsup.notification.domain.NotificationType; -import dev.handsup.notification.dto.NotificationMapper; -import dev.handsup.notification.dto.response.NotificationResponse; import dev.handsup.notification.repository.NotificationRepository; import dev.handsup.user.domain.User; -import dev.handsup.user.exception.UserErrorCode; -import dev.handsup.user.repository.UserRepository; +import jakarta.transaction.Transactional; import lombok.RequiredArgsConstructor; -@RequiredArgsConstructor @Service +@RequiredArgsConstructor public class NotificationService { - private final NotificationRepository notificationRepository; - private final UserRepository userRepository; - private final AuctionRepository auctionRepository; - - public long countNotificationsByUserEmail(String userEmail) { - return notificationRepository.countByReceiverEmail(userEmail); - } @Transactional - public void saveNotification( - String senderEmail, - String receiverEmail, - String content, - NotificationType notificationType, - Auction auction - ) { + public void saveNotification(User sender, User receiver, Long auctionId, String content, NotificationType type){ Notification notification = Notification.of( - senderEmail, receiverEmail, content, notificationType, auction + receiver.getId(), + sender.getId(), + auctionId, + type, + content ); - notificationRepository.save(notification); } - - @Transactional - public PageResponse getNotifications(User user, Pageable pageable) { - Slice notificationResponsePage = notificationRepository - .findByReceiverEmailOrderByCreatedAtDesc(user.getEmail(), pageable) - .map(notification -> { - String senderEmail = notification.getSenderEmail(); - String senderProfileImageUrl = getUserByEmail(senderEmail).getProfileImageUrl(); - Auction auction = getAuctionById(notification.getAuction().getId()); - - return NotificationMapper.toNotificationResponse( - notification.getId(), - notification.getType(), - notification.getContent(), - senderProfileImageUrl, - auction.getId(), - auction.getProduct().getImages().get(0).getImageUrl() - ); - }); - - // 사용자의 읽은 알림 수 갱신 - user.updateReadNotificationCount(notificationResponsePage.getContent().size()); - userRepository.save(user); - - return CommonMapper.toPageResponse(notificationResponsePage); - } - - private User getUserByEmail(String email) { - return userRepository.findByEmail(email) - .orElseThrow(() -> new NotFoundException(UserErrorCode.NOT_FOUND_BY_EMAIL)); - } - - private Auction getAuctionById(Long auctionId) { - return auctionRepository.findById(auctionId) - .orElseThrow(() -> new NotFoundException(AuctionErrorCode.NOT_FOUND_AUCTION)); - } } From b68a989ce5f6f80f9f8720b8ac0143616b945eab Mon Sep 17 00:00:00 2001 From: hs12 Date: Mon, 30 Jun 2025 14:02:31 +0900 Subject: [PATCH 15/38] =?UTF-8?q?[refactor]=20:=20=EC=95=8C=EB=A6=BC=20?= =?UTF-8?q?=EC=A0=80=EC=9E=A5=20=ED=98=B8=EC=B6=9C=20NotificationSender?= =?UTF-8?q?=EC=97=90=20=EC=9C=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dev/handsup/bidding/service/BiddingService.java | 2 +- .../dev/handsup/notification/service/FCMService.java | 11 ++--------- .../notification/service/NotificationSender.java | 12 ++++++------ 3 files changed, 9 insertions(+), 16 deletions(-) diff --git a/core/src/main/java/dev/handsup/bidding/service/BiddingService.java b/core/src/main/java/dev/handsup/bidding/service/BiddingService.java index 2b7eb55c..a9350cf8 100644 --- a/core/src/main/java/dev/handsup/bidding/service/BiddingService.java +++ b/core/src/main/java/dev/handsup/bidding/service/BiddingService.java @@ -112,7 +112,7 @@ private void sendBiddingNotification(User bidder, Auction auction) { notificationSender.sendNotification( bidder, auction.getSeller(), - auction, + auction.getId(), NotificationType.BIDDING_CREATED ); } diff --git a/core/src/main/java/dev/handsup/notification/service/FCMService.java b/core/src/main/java/dev/handsup/notification/service/FCMService.java index 9a9e8034..248ec7e8 100644 --- a/core/src/main/java/dev/handsup/notification/service/FCMService.java +++ b/core/src/main/java/dev/handsup/notification/service/FCMService.java @@ -21,10 +21,8 @@ public class FCMService { private final FirebaseMessaging firebaseMessaging; public void sendNotification( - Long senderId, - String senderNickname, Long receiverId, - Long auctionId, + String content, NotificationType notificationType ) { String fcmToken = fcmTokenRepository.getFcmToken(receiverId); @@ -32,15 +30,10 @@ public void sendNotification( return; } - if (notificationType.equals(NotificationType.CANCELED_PURCHASE_TRADING) || - notificationType.equals(NotificationType.PURCHASE_WINNING)) { - senderNickname = ""; - } - Message message = Message.builder() .setNotification(Notification.builder() .setTitle(notificationType.getTitle()) - .setBody(senderNickname + notificationType.getContent()) + .setBody(content) .build()) .setToken(fcmToken) .build(); diff --git a/core/src/main/java/dev/handsup/notification/service/NotificationSender.java b/core/src/main/java/dev/handsup/notification/service/NotificationSender.java index a4086c4a..00d98340 100644 --- a/core/src/main/java/dev/handsup/notification/service/NotificationSender.java +++ b/core/src/main/java/dev/handsup/notification/service/NotificationSender.java @@ -2,7 +2,6 @@ import org.springframework.stereotype.Service; -import dev.handsup.auction.domain.Auction; import dev.handsup.notification.domain.NotificationType; import dev.handsup.user.domain.User; import lombok.RequiredArgsConstructor; @@ -10,15 +9,16 @@ @Service @RequiredArgsConstructor public class NotificationSender { + private final NotificationService notificationService; private final FCMService fcmService; - public void sendNotification(User sender, User receiver, Auction auction, NotificationType type) { + public void sendNotification(User sender, User receiver, Long auctionId, NotificationType notificationType) { + String content = notificationType.processContent(sender.getNickname()); fcmService.sendNotification( - sender.getId(), - sender.getNickname(), receiver.getId(), - auction.getId(), - type + content, + notificationType ); + notificationService.saveNotification(sender,receiver,auctionId,content,notificationType); } } From b38d17446a7055140a2cd0b52b601e54386fc4f2 Mon Sep 17 00:00:00 2001 From: hs12 Date: Mon, 30 Jun 2025 14:12:03 +0900 Subject: [PATCH 16/38] =?UTF-8?q?[chore]=20:=20http=20=ED=8C=8C=EC=9D=BC?= =?UTF-8?q?=20gitignore=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + core/src/test/http/auction.http | 21 --------- core/src/test/http/bidding.http | 11 ----- core/src/test/http/home.http | 4 -- core/src/test/http/recommend.http | 18 ------- core/src/test/http/search.http | 78 ------------------------------- core/src/test/http/user.http | 17 ------- 7 files changed, 1 insertion(+), 149 deletions(-) delete mode 100644 core/src/test/http/auction.http delete mode 100644 core/src/test/http/bidding.http delete mode 100644 core/src/test/http/home.http delete mode 100644 core/src/test/http/recommend.http delete mode 100644 core/src/test/http/search.http delete mode 100644 core/src/test/http/user.http diff --git a/.gitignore b/.gitignore index 1366d5f7..7f10d69d 100644 --- a/.gitignore +++ b/.gitignore @@ -46,3 +46,4 @@ core/src/main/resources/application-core-prod.yml /api/src/test/resources/firebase/firebase_account.json /core/src/main/resources/application-core-local.yml /core/src/main/resources/firebase/serviceAccountKey.json +/core/src/test/http diff --git a/core/src/test/http/auction.http b/core/src/test/http/auction.http deleted file mode 100644 index 4b9c2203..00000000 --- a/core/src/test/http/auction.http +++ /dev/null @@ -1,21 +0,0 @@ -### GET request to example server -POST http://localhost:8080/api/auctions -Content-Type: application/json -Authorization: Bearer eyJ0eXBlIjoiand0IiwiYWxnIjoiSFMyNTYifQ.eyJ1c2VySWQiOjEsImlhdCI6MTc0OTk4ODQ3NiwiZXhwIjoyMDY1MzQ4NDc2fQ._I9ddh2ADiTV6aIitn19RRkW2sglpkRbRMZtlqC7xeM - -{ - "title": "에어팟 거의 새거", - "productCategory": "디지털 기기", - "initPrice": 3000, - "endDate": "2024-02-17", - "productStatus": "깨끗해요", - "purchaseTime": "6개월 이하", - "description": "거의 새거임", - "tradeMethod": "직거래", - "imageUrls": [ - "https://s3.ap-northeast-2.amazonaws.com/handsup-bucket/images/f2ed3069-3c65-4cb5-97dc-2f24a64ca103.jpg" - ], - "si": "서울시", - "gu": "성북구", - "dong": "동선동" -} \ No newline at end of file diff --git a/core/src/test/http/bidding.http b/core/src/test/http/bidding.http deleted file mode 100644 index 44435068..00000000 --- a/core/src/test/http/bidding.http +++ /dev/null @@ -1,11 +0,0 @@ - - -### -### 입찰 등록 -POST http://localhost:8080/api/auctions/1/bids -Content-Type: application/json -Authorization: Bearer eyJ0eXBlIjoiand0IiwiYWxnIjoiSFMyNTYifQ.eyJ1c2VySWQiOjIsImlhdCI6MTc1MTIwMDE0NywiZXhwIjoyMDY2NTYwMTQ3fQ.iRr1DCdtZlu1_--DSjENedXSzLwBiL4vcjMAgTBk8hI - -{ - "biddingPrice": 198000 -} \ No newline at end of file diff --git a/core/src/test/http/home.http b/core/src/test/http/home.http deleted file mode 100644 index b40ef5d9..00000000 --- a/core/src/test/http/home.http +++ /dev/null @@ -1,4 +0,0 @@ -### 경매 추천 - 지역 필터(서울시 관악구 봉천동) -### 최근생성, 마감일, 입찰수, 북마크수 -GET http://localhost:8080/api/auctions/recommend?page=0&size=10&sort=최근생성&si=서울시&gu=관악구&dong=봉천동 -Content-Type: application/json \ No newline at end of file diff --git a/core/src/test/http/recommend.http b/core/src/test/http/recommend.http deleted file mode 100644 index ba1b05fd..00000000 --- a/core/src/test/http/recommend.http +++ /dev/null @@ -1,18 +0,0 @@ -### 경매 추천 -GET http://localhost:8080/api/auctions/recommend?si=서울시&gu=강남구&dong=역삼동&page=0&size=10&sort=북마크수 - - -### 경매 조건 추천 ver2 -GET http://localhost:8080/api/v2/auctions/recommend?si=서울시&gu=강남구&dong=역삼동&page=0&size=10&sort=북마크수 - -### 경매 카테고리 추천 ver1 -GET http://localhost:8080/api/auctions/recommend/category?page=0&size=10 -Content-Type: application/json -Authorization: Bearer eyJ0eXBlIjoiand0IiwiYWxnIjoiSFMyNTYifQ.eyJ1c2VySWQiOjEsImlhdCI6MTc0OTk4ODQ3NiwiZXhwIjoyMDY1MzQ4NDc2fQ._I9ddh2ADiTV6aIitn19RRkW2sglpkRbRMZtlqC7xeM - -### 경매 카테고리 추천 ver2 -GET http://localhost:8080/api/v2/auctions/recommend/category?page=0&size=10 -Content-Type: application/json -Authorization: Bearer eyJ0eXBlIjoiand0IiwiYWxnIjoiSFMyNTYifQ.eyJ1c2VySWQiOjEsImlhdCI6MTc0OTk4ODQ3NiwiZXhwIjoyMDY1MzQ4NDc2fQ._I9ddh2ADiTV6aIitn19RRkW2sglpkRbRMZtlqC7xeM - - diff --git a/core/src/test/http/search.http b/core/src/test/http/search.http deleted file mode 100644 index b14d6903..00000000 --- a/core/src/test/http/search.http +++ /dev/null @@ -1,78 +0,0 @@ -### 기본 검색 (키워드만) -POST http://localhost:8080/api/auctions/search?page=0&size=10&sort=최신순 -Content-Type: application/json - -{ - "keyword": "에어팟" -} - -### - - - -### 카테고리, 거래방식 등 복합 검색 예시 -POST http://localhost:8080/api/auctions/search?page=0&size=10&sort=최신순 -Content-Type: application/json - -{ - "keyword": "에어팟", -"productCategory": "디지털 기기", - "si": "서울시", - "gu": "강남구", - "dong": "역삼동" -} - -### 카테고리, 거래방식 등 복합 검색 예시 -POST http://localhost:8080/api/auctions/search?page=0&size=10&sort=최신순 -Content-Type: application/json - -{ - "keyword": "에어팟", - "productCategory": "디지털 기기", - "si": "서울시", - "gu": "강남구", - "dong": "역삼동" -} - -### 카테고리, 거래방식 등 복합 검색 예시 -POST http://localhost:8080/api/v2/auctions/search?page=0&size=10&sort=최신순 -Content-Type: application/json - -{ - "keyword": "에어팟", - "productCategory": "디지털 기기", - "si": "서울시", - "gu": "강남구", - "dong": "역삼동" -} - -### - -### 북마크순 정렬 검색 -POST http://localhost:8080/api/auctions/search?page=0&size=10&sort=북마크수 -Content-Type: application/json - -{ - "keyword": "에어팟" -} - -### - -### 마감일 임박순 + 카테고리 -POST http://localhost:8080/api/auctions/search?page=0&size=10&sort=마감일 -Content-Type: application/json - -{ - "keyword": "청소기", - "productCategory": "APPLIANCES" -} - -### - -### 검색결과 없는 경우(키워드 없음) -POST http://localhost:8080/api/auctions/search?page=0&size=10 -Content-Type: application/json - -{ - "keyword": "존재하지않는상품명" -} \ No newline at end of file diff --git a/core/src/test/http/user.http b/core/src/test/http/user.http deleted file mode 100644 index 9d0eb7b7..00000000 --- a/core/src/test/http/user.http +++ /dev/null @@ -1,17 +0,0 @@ -### 로그인 요청 (user1) -POST http://localhost:8080/api/auth/login -Content-Type: application/json - -{ - "email": "user1@email.com", - "password": "testpw1!" -} - -### 로그인 요청 (user2) -POST http://localhost:8080/api/auth/login -Content-Type: application/json - -{ -"email": "user2@email.com", -"password": "testpw2!" -} \ No newline at end of file From aad4bc3892136253e8adb712fe7be62bb9badb0c Mon Sep 17 00:00:00 2001 From: hs12 Date: Mon, 30 Jun 2025 14:48:13 +0900 Subject: [PATCH 17/38] =?UTF-8?q?[feat]=20:=20=EC=95=8C=EB=A6=BC=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1,=20=EC=A1=B0=ED=9A=8C=20=EC=B6=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/NotificationController.java | 33 +++++++++++++++++++ .../notification/domain/Notification.java | 6 ++-- .../notification/dto/NotificationMapper.java | 23 +++++++++++++ .../dto/NotificationResponse.java | 11 +++++++ .../repository/NotificationRepository.java | 3 ++ .../service/NotificationService.java | 21 ++++++++++-- 6 files changed, 91 insertions(+), 6 deletions(-) create mode 100644 api/src/main/java/dev/handsup/notification/controller/NotificationController.java create mode 100644 core/src/main/java/dev/handsup/notification/dto/NotificationMapper.java create mode 100644 core/src/main/java/dev/handsup/notification/dto/NotificationResponse.java diff --git a/api/src/main/java/dev/handsup/notification/controller/NotificationController.java b/api/src/main/java/dev/handsup/notification/controller/NotificationController.java new file mode 100644 index 00000000..3b31e6ad --- /dev/null +++ b/api/src/main/java/dev/handsup/notification/controller/NotificationController.java @@ -0,0 +1,33 @@ +package dev.handsup.notification.controller; + +import org.springframework.data.domain.Pageable; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +import dev.handsup.auth.jwt.JwtAuthorization; +import dev.handsup.common.dto.PageResponse; +import dev.handsup.notification.dto.NotificationResponse; +import dev.handsup.notification.service.NotificationService; +import dev.handsup.user.domain.User; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import lombok.RequiredArgsConstructor; + +@RestController +@RequiredArgsConstructor +public class NotificationController { + private final NotificationService notificationService; + + @GetMapping("/api/notifications") + @Operation(summary = "알림 전체 조회 API", description = "특정 사용자가 받은 알림을 최근 생성 순으로 전체 조회한다") + @ApiResponse(useReturnTypeSchema = true) + public ResponseEntity> getUserNotifications( + @Parameter(hidden = true) @JwtAuthorization User user, + Pageable pageable + ) { + PageResponse response = notificationService.getNotifications(user, pageable); + return ResponseEntity.ok(response); + } +} diff --git a/core/src/main/java/dev/handsup/notification/domain/Notification.java b/core/src/main/java/dev/handsup/notification/domain/Notification.java index d19d14dd..137427d3 100644 --- a/core/src/main/java/dev/handsup/notification/domain/Notification.java +++ b/core/src/main/java/dev/handsup/notification/domain/Notification.java @@ -57,15 +57,15 @@ public static Notification of( Long receiverId, Long senderId, Long auctionId, - NotificationType type, - String content + String content, + NotificationType type ) { return Notification.builder() .receiverId(receiverId) .senderId(senderId) .auctionId(auctionId) - .type(type) .content(content) + .type(type) .build(); } } diff --git a/core/src/main/java/dev/handsup/notification/dto/NotificationMapper.java b/core/src/main/java/dev/handsup/notification/dto/NotificationMapper.java new file mode 100644 index 00000000..a593b83a --- /dev/null +++ b/core/src/main/java/dev/handsup/notification/dto/NotificationMapper.java @@ -0,0 +1,23 @@ +package dev.handsup.notification.dto; + +import dev.handsup.notification.domain.Notification; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; + +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public class NotificationMapper { + + public static NotificationResponse toNotificationResponse( + Notification notification + ) { + return new NotificationResponse( + notification.getId(), + notification.getReceiverId(), + notification.getSenderId(), + notification.getAuctionId(), + notification.getType().getTitle(), + notification.getContent(), + notification.getCreatedAt().toString() + ); + } +} diff --git a/core/src/main/java/dev/handsup/notification/dto/NotificationResponse.java b/core/src/main/java/dev/handsup/notification/dto/NotificationResponse.java new file mode 100644 index 00000000..3a31c9e3 --- /dev/null +++ b/core/src/main/java/dev/handsup/notification/dto/NotificationResponse.java @@ -0,0 +1,11 @@ +package dev.handsup.notification.dto; + +public record NotificationResponse( + Long notificationId, + Long receiverId, + Long senderId, + Long auctionId, + String type, + String content, + String createdAt +) { } \ No newline at end of file diff --git a/core/src/main/java/dev/handsup/notification/repository/NotificationRepository.java b/core/src/main/java/dev/handsup/notification/repository/NotificationRepository.java index 9271aa49..9a35c7e2 100644 --- a/core/src/main/java/dev/handsup/notification/repository/NotificationRepository.java +++ b/core/src/main/java/dev/handsup/notification/repository/NotificationRepository.java @@ -1,8 +1,11 @@ package dev.handsup.notification.repository; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Slice; import org.springframework.data.jpa.repository.JpaRepository; import dev.handsup.notification.domain.Notification; public interface NotificationRepository extends JpaRepository { + Slice findByReceiverIdOrderByCreatedAtDesc(Long receiverId, Pageable pageable); } diff --git a/core/src/main/java/dev/handsup/notification/service/NotificationService.java b/core/src/main/java/dev/handsup/notification/service/NotificationService.java index 1813f15b..cfc33771 100644 --- a/core/src/main/java/dev/handsup/notification/service/NotificationService.java +++ b/core/src/main/java/dev/handsup/notification/service/NotificationService.java @@ -1,12 +1,18 @@ package dev.handsup.notification.service; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Slice; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import dev.handsup.common.dto.CommonMapper; +import dev.handsup.common.dto.PageResponse; import dev.handsup.notification.domain.Notification; import dev.handsup.notification.domain.NotificationType; +import dev.handsup.notification.dto.NotificationMapper; +import dev.handsup.notification.dto.NotificationResponse; import dev.handsup.notification.repository.NotificationRepository; import dev.handsup.user.domain.User; -import jakarta.transaction.Transactional; import lombok.RequiredArgsConstructor; @Service @@ -20,9 +26,18 @@ public void saveNotification(User sender, User receiver, Long auctionId, String receiver.getId(), sender.getId(), auctionId, - type, - content + content, + type ); notificationRepository.save(notification); } + + @Transactional(readOnly = true) + public PageResponse getNotifications(User user, Pageable pageable) { + Slice notificationResponsePage = notificationRepository + .findByReceiverIdOrderByCreatedAtDesc(user.getId(), pageable) + .map(NotificationMapper::toNotificationResponse); + + return CommonMapper.toPageResponse(notificationResponsePage); + } } From b78dd1575a9660298ec31a2cb4f1d7b443950cc0 Mon Sep 17 00:00:00 2001 From: hs12 Date: Mon, 30 Jun 2025 14:48:35 +0900 Subject: [PATCH 18/38] =?UTF-8?q?[refactor]=20:=20=EC=82=AC=EC=9A=A9?= =?UTF-8?q?=ED=95=98=EC=A7=80=20=EC=95=8A=EB=8A=94=20=EC=9D=98=EC=A1=B4?= =?UTF-8?q?=EC=84=B1=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/dev/handsup/auction/service/AuctionService.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/core/src/main/java/dev/handsup/auction/service/AuctionService.java b/core/src/main/java/dev/handsup/auction/service/AuctionService.java index 1f7219b6..054f9cad 100644 --- a/core/src/main/java/dev/handsup/auction/service/AuctionService.java +++ b/core/src/main/java/dev/handsup/auction/service/AuctionService.java @@ -11,7 +11,6 @@ import dev.handsup.auction.exception.AuctionErrorCode; import dev.handsup.auction.repository.auction.AuctionRepository; import dev.handsup.auction.repository.auction.AuctionSearchRepository; -import dev.handsup.auction.repository.product.PreferredProductCategoryRepository; import dev.handsup.auction.repository.product.ProductCategoryRepository; import dev.handsup.common.exception.NotFoundException; import dev.handsup.search.dto.AuctionSearchMapper; @@ -25,7 +24,6 @@ public class AuctionService { private final AuctionRepository auctionRepository; private final AuctionSearchRepository auctionSearchRepository; private final ProductCategoryRepository productCategoryRepository; - private final PreferredProductCategoryRepository preferredProductCategoryRepository; public AuctionDetailResponse registerAuction(RegisterAuctionRequest request, User user) { ProductCategory productCategory = getProductCategoryByValue(request.productCategory()); From d42bc5379f2dd9671cddadda9013a5b1aa21bd6b Mon Sep 17 00:00:00 2001 From: hs12 Date: Mon, 30 Jun 2025 15:09:09 +0900 Subject: [PATCH 19/38] =?UTF-8?q?[feat]=20:=20=EB=A1=9C=EA=B7=B8=EC=95=84?= =?UTF-8?q?=EC=9B=83=20=EC=8B=9C=20fcm=20=ED=86=A0=ED=81=B0=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/dev/handsup/auth/controller/AuthApiController.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/api/src/main/java/dev/handsup/auth/controller/AuthApiController.java b/api/src/main/java/dev/handsup/auth/controller/AuthApiController.java index c5aec2ef..be53d2e3 100644 --- a/api/src/main/java/dev/handsup/auth/controller/AuthApiController.java +++ b/api/src/main/java/dev/handsup/auth/controller/AuthApiController.java @@ -17,6 +17,7 @@ import dev.handsup.auth.dto.response.TokenReIssueResponse; import dev.handsup.auth.jwt.JwtAuthorization; import dev.handsup.auth.service.AuthService; +import dev.handsup.notification.service.FCMService; import dev.handsup.user.domain.User; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; @@ -34,6 +35,7 @@ public class AuthApiController { private final AuthService authService; + private final FCMService fcmService; @NoAuth @PostMapping("/login") @@ -58,6 +60,7 @@ public ResponseEntity login( public ResponseEntity logout( @Parameter(hidden = true) @JwtAuthorization User user ) { + fcmService.deleteFcmToken(user.getId()); return ResponseEntity.ok(HttpStatus.OK); } From ef47ef6cc41e078b055301bb0641204a72b8ba70 Mon Sep 17 00:00:00 2001 From: hs12 Date: Mon, 30 Jun 2025 15:11:09 +0900 Subject: [PATCH 20/38] =?UTF-8?q?[chore]=20:=20FirebaseApp=20=EC=A4=91?= =?UTF-8?q?=EB=B3=B5=20=EC=83=9D=EC=84=B1=20=EB=B0=A9=EC=A7=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- core/src/main/java/dev/handsup/common/config/FCMConfig.java | 1 + 1 file changed, 1 insertion(+) diff --git a/core/src/main/java/dev/handsup/common/config/FCMConfig.java b/core/src/main/java/dev/handsup/common/config/FCMConfig.java index 6af9bfeb..9b2a37f7 100644 --- a/core/src/main/java/dev/handsup/common/config/FCMConfig.java +++ b/core/src/main/java/dev/handsup/common/config/FCMConfig.java @@ -21,6 +21,7 @@ public class FcmConfig { @PostConstruct public void initialize() { + if (!FirebaseApp.getApps().isEmpty()) return; try { GoogleCredentials googleCredentials = GoogleCredentials .fromStream(new ClassPathResource(FIREBASE_KEY_PATH).getInputStream()); From 7cdf0d6527ec010a3a8da586e2703da428abf726 Mon Sep 17 00:00:00 2001 From: hs12 Date: Mon, 30 Jun 2025 15:17:52 +0900 Subject: [PATCH 21/38] =?UTF-8?q?[feat]=20:=20fcm=20token=20ttl=20?= =?UTF-8?q?=EB=B6=80=EC=97=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../handsup/chat/service/ChatMessageService.java | 14 -------------- .../repository/FCMTokenRepository.java | 8 ++++++-- 2 files changed, 6 insertions(+), 16 deletions(-) diff --git a/core/src/main/java/dev/handsup/chat/service/ChatMessageService.java b/core/src/main/java/dev/handsup/chat/service/ChatMessageService.java index b4f99f8b..39050ce0 100644 --- a/core/src/main/java/dev/handsup/chat/service/ChatMessageService.java +++ b/core/src/main/java/dev/handsup/chat/service/ChatMessageService.java @@ -3,8 +3,6 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import dev.handsup.auction.domain.Auction; -import dev.handsup.auction.exception.AuctionErrorCode; import dev.handsup.auction.repository.auction.AuctionRepository; import dev.handsup.chat.domain.ChatMessage; import dev.handsup.chat.domain.ChatRoom; @@ -15,8 +13,6 @@ import dev.handsup.chat.repository.ChatMessageRepository; import dev.handsup.chat.repository.ChatRoomRepository; import dev.handsup.common.exception.NotFoundException; -import dev.handsup.user.domain.User; -import dev.handsup.user.exception.UserErrorCode; import dev.handsup.user.repository.UserRepository; import lombok.RequiredArgsConstructor; @@ -42,14 +38,4 @@ private ChatRoom getChatRoomById(Long chatRoomId) { return chatRoomRepository.findById(chatRoomId) .orElseThrow(() -> new NotFoundException(ChatRoomErrorCode.NOT_FOUND_CHAT_ROOM)); } - - private User getUserById(Long userId) { - return userRepository.findById(userId) - .orElseThrow(() -> new NotFoundException(UserErrorCode.NOT_FOUND_USER)); - } - - public Auction getAuctionById(Long auctionId) { - return auctionRepository.findById(auctionId) - .orElseThrow(() -> new NotFoundException(AuctionErrorCode.NOT_FOUND_AUCTION)); - } } diff --git a/core/src/main/java/dev/handsup/notification/repository/FCMTokenRepository.java b/core/src/main/java/dev/handsup/notification/repository/FCMTokenRepository.java index a405f622..fe260685 100644 --- a/core/src/main/java/dev/handsup/notification/repository/FCMTokenRepository.java +++ b/core/src/main/java/dev/handsup/notification/repository/FCMTokenRepository.java @@ -1,5 +1,7 @@ package dev.handsup.notification.repository; +import java.util.concurrent.TimeUnit; + import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Component; @@ -14,8 +16,10 @@ public class FCMTokenRepository { private final StringRedisTemplate redisTemplate; public void saveFcmToken(Long userId, String fcmToken) { - redisTemplate.opsForValue() - .set(PREFIX + userId, fcmToken); + if (!hasKey(userId)){ + redisTemplate.opsForValue() + .set(PREFIX + userId, fcmToken, 3000, TimeUnit.DAYS); + } } public String getFcmToken(Long userId) { From 74c634924dad953fd8dcab1a52e5697f693a1408 Mon Sep 17 00:00:00 2001 From: hs12 Date: Mon, 30 Jun 2025 15:28:10 +0900 Subject: [PATCH 22/38] =?UTF-8?q?[chore]=20:=20ci=20=EC=8A=A4=ED=81=AC?= =?UTF-8?q?=EB=A6=BD=ED=8A=B8=20firebase=20=EA=B2=BD=EB=A1=9C=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/ci.yml | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 486b9136..de2c597f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -30,12 +30,7 @@ jobs: - name : Generate firebase_account.json run: | mkdir -p ./core/src/main/resources/firebase - echo "${{ secrets.FIREBASE_ACCOUNT }}" | base64 -d > ./core/src/main/resources/firebase/firebase_account.json - mkdir -p ./core/src/test/resources/firebase - echo "${{ secrets.FIREBASE_ACCOUNT }}" | base64 -d > ./core/src/test/resources/firebase/firebase_account.json - mkdir -p ./api/src/test/resources/firebase - echo "${{ secrets.FIREBASE_ACCOUNT }}" | base64 -d > ./api/src/test/resources/firebase/firebase_account.json - + echo "${{ secrets.FIREBASE_KEY }}" > ./core/src/main/resources/firebase/serviceAccountKey.json # gradle 권한 부여 - name: Grant execute permission for gradlew run: chmod +x ./gradlew From 6ed0f6ffca1c03d5c4313cfb0bb94cbd9f0b0a96 Mon Sep 17 00:00:00 2001 From: hs12 Date: Mon, 30 Jun 2025 15:39:23 +0900 Subject: [PATCH 23/38] =?UTF-8?q?[chore]=20:=20ci=20=EC=8A=A4=ED=81=AC?= =?UTF-8?q?=EB=A6=BD=ED=8A=B8=20=EC=9E=84=EC=8B=9C=20trigger=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index de2c597f..d15d5c66 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -3,6 +3,8 @@ name: CI Backend on: pull_request: branches: ["main", "dev"] + push: + branches: [ "**" ] permissions: contents: read From 2e21e0cc96e113b0ad27c67ad68555331651eb2d Mon Sep 17 00:00:00 2001 From: hs12 Date: Mon, 30 Jun 2025 15:41:33 +0900 Subject: [PATCH 24/38] =?UTF-8?q?[style]=20:=20=EC=BD=94=EB=93=9C=20?= =?UTF-8?q?=EB=A6=AC=ED=8F=AC=EB=A9=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auction/dto/mapper/AuctionMapper.java | 2 +- .../auction/AuctionSearchRepository.java | 26 +++++++++---------- .../auction/scheduler/AuctionScheduler.java | 2 +- .../bidding/service/BiddingService.java | 2 +- .../dto/NotificationResponse.java | 3 ++- .../repository/FCMTokenRepository.java | 2 +- .../service/NotificationSender.java | 4 +-- .../service/NotificationService.java | 2 +- .../handsup/search/domain/AuctionSearch.java | 2 +- .../search/dto/AuctionSearchMapper.java | 4 +-- .../handsup/search/service/SearchService.java | 1 - .../java/dev/handsup/user/domain/User.java | 1 - 12 files changed, 25 insertions(+), 26 deletions(-) diff --git a/core/src/main/java/dev/handsup/auction/dto/mapper/AuctionMapper.java b/core/src/main/java/dev/handsup/auction/dto/mapper/AuctionMapper.java index 2b50f514..a40aa6b6 100644 --- a/core/src/main/java/dev/handsup/auction/dto/mapper/AuctionMapper.java +++ b/core/src/main/java/dev/handsup/auction/dto/mapper/AuctionMapper.java @@ -76,7 +76,7 @@ public static AuctionDetailResponse toAuctionDetailResponse(Auction auction) { } public static AuctionSearchResponse toAuctionSearchResponse(Auction auction) { - boolean isProgress = auction.getStatus()== AuctionStatus.BIDDING; + boolean isProgress = auction.getStatus() == AuctionStatus.BIDDING; return AuctionSearchResponse.of( auction.getId(), auction.getTitle(), diff --git a/core/src/main/java/dev/handsup/auction/repository/auction/AuctionSearchRepository.java b/core/src/main/java/dev/handsup/auction/repository/auction/AuctionSearchRepository.java index 51c7b2da..b0aa1d9e 100644 --- a/core/src/main/java/dev/handsup/auction/repository/auction/AuctionSearchRepository.java +++ b/core/src/main/java/dev/handsup/auction/repository/auction/AuctionSearchRepository.java @@ -13,19 +13,19 @@ public interface AuctionSearchRepository extends JpaRepository searchAuctions(AuctionSearchCondition condition, Pageable pageable) { Slice auctionResponsePage = auctionRepository diff --git a/core/src/main/java/dev/handsup/user/domain/User.java b/core/src/main/java/dev/handsup/user/domain/User.java index a6eeed3e..aa3bf636 100644 --- a/core/src/main/java/dev/handsup/user/domain/User.java +++ b/core/src/main/java/dev/handsup/user/domain/User.java @@ -48,7 +48,6 @@ public class User extends TimeBaseEntity { @Column(name = "profile_image_url") private String profileImageUrl; - @Column(name = "read_notification_count", nullable = false) private long readNotificationCount = 0; From c9a0a9f7d5594d07f68ab6f70dd62861dc5e5e8b Mon Sep 17 00:00:00 2001 From: hs12 Date: Mon, 30 Jun 2025 15:42:20 +0900 Subject: [PATCH 25/38] =?UTF-8?q?[chore]=20:=20ci=20=EC=8A=A4=ED=81=AC?= =?UTF-8?q?=EB=A6=BD=ED=8A=B8=20=EC=9E=84=EC=8B=9C=20=ED=8A=B8=EB=A6=AC?= =?UTF-8?q?=EA=B1=B0=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/ci.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d15d5c66..de2c597f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -3,8 +3,6 @@ name: CI Backend on: pull_request: branches: ["main", "dev"] - push: - branches: [ "**" ] permissions: contents: read From 314e8b6846f06e66a894b5c84f248bef6960fb2b Mon Sep 17 00:00:00 2001 From: hs12 Date: Mon, 30 Jun 2025 16:14:44 +0900 Subject: [PATCH 26/38] =?UTF-8?q?[fix]=20:=20=EC=9E=84=EC=8B=9C=EB=A1=9C?= =?UTF-8?q?=20=ED=8C=8C=EC=9D=BC=EB=AA=85=20=EB=B3=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dev/handsup/auth/controller/AuthApiController.java | 4 ++-- .../handsup/notification/controller/FCMController.java | 8 ++++---- .../common/config/{FCMConfig.java => FcmConfigTmp.java} | 5 +++-- ...veFCMTokenRequest.java => SaveFcmTokenRequestTmp.java} | 6 +++--- ...FCMTokenRepository.java => FcmTokenRepositoryTmp.java} | 2 +- .../service/{FCMService.java => FcmServiceTmp.java} | 6 +++--- .../handsup/notification/service/NotificationSender.java | 2 +- .../bidding/repository/BiddingConcurrencyTest.java | 4 ++-- 8 files changed, 19 insertions(+), 18 deletions(-) rename core/src/main/java/dev/handsup/common/config/{FCMConfig.java => FcmConfigTmp.java} (93%) rename core/src/main/java/dev/handsup/notification/dto/{SaveFCMTokenRequest.java => SaveFcmTokenRequestTmp.java} (67%) rename core/src/main/java/dev/handsup/notification/repository/{FCMTokenRepository.java => FcmTokenRepositoryTmp.java} (95%) rename core/src/main/java/dev/handsup/notification/service/{FCMService.java => FcmServiceTmp.java} (90%) diff --git a/api/src/main/java/dev/handsup/auth/controller/AuthApiController.java b/api/src/main/java/dev/handsup/auth/controller/AuthApiController.java index be53d2e3..aa03b152 100644 --- a/api/src/main/java/dev/handsup/auth/controller/AuthApiController.java +++ b/api/src/main/java/dev/handsup/auth/controller/AuthApiController.java @@ -17,7 +17,7 @@ import dev.handsup.auth.dto.response.TokenReIssueResponse; import dev.handsup.auth.jwt.JwtAuthorization; import dev.handsup.auth.service.AuthService; -import dev.handsup.notification.service.FCMService; +import dev.handsup.notification.service.FcmServiceTmp; import dev.handsup.user.domain.User; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; @@ -35,7 +35,7 @@ public class AuthApiController { private final AuthService authService; - private final FCMService fcmService; + private final FcmServiceTmp fcmService; @NoAuth @PostMapping("/login") diff --git a/api/src/main/java/dev/handsup/notification/controller/FCMController.java b/api/src/main/java/dev/handsup/notification/controller/FCMController.java index f1a54b79..901d0ee7 100644 --- a/api/src/main/java/dev/handsup/notification/controller/FCMController.java +++ b/api/src/main/java/dev/handsup/notification/controller/FCMController.java @@ -7,8 +7,8 @@ import org.springframework.web.bind.annotation.RestController; import dev.handsup.auth.jwt.JwtAuthorization; -import dev.handsup.notification.dto.SaveFCMTokenRequest; -import dev.handsup.notification.service.FCMService; +import dev.handsup.notification.dto.SaveFcmTokenRequestTmp; +import dev.handsup.notification.service.FcmServiceTmp; import dev.handsup.user.domain.User; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; @@ -19,14 +19,14 @@ @RestController @RequiredArgsConstructor public class FCMController { - private final FCMService fcmService; + private final FcmServiceTmp fcmService; @PostMapping("/api/fcm-tokens") @Operation(summary = "FCM 토큰 저장 API", description = "{사용자 아이디 : FCM 토큰}을 redis에 저장") @ApiResponse(useReturnTypeSchema = true) public ResponseEntity saveFCMToken( @Parameter(hidden = true) @JwtAuthorization User user, - @RequestBody @Valid SaveFCMTokenRequest request + @RequestBody @Valid SaveFcmTokenRequestTmp request ) { fcmService.saveFcmToken(user.getId(), request.fcmToken()); return ResponseEntity.ok(HttpStatus.OK); diff --git a/core/src/main/java/dev/handsup/common/config/FCMConfig.java b/core/src/main/java/dev/handsup/common/config/FcmConfigTmp.java similarity index 93% rename from core/src/main/java/dev/handsup/common/config/FCMConfig.java rename to core/src/main/java/dev/handsup/common/config/FcmConfigTmp.java index 9b2a37f7..525d4278 100644 --- a/core/src/main/java/dev/handsup/common/config/FCMConfig.java +++ b/core/src/main/java/dev/handsup/common/config/FcmConfigTmp.java @@ -16,12 +16,13 @@ @Configuration @Slf4j -public class FcmConfig { +public class FcmConfigTmp { private static final String FIREBASE_KEY_PATH = "firebase/serviceAccountKey.json"; @PostConstruct public void initialize() { - if (!FirebaseApp.getApps().isEmpty()) return; + if (!FirebaseApp.getApps().isEmpty()) + return; try { GoogleCredentials googleCredentials = GoogleCredentials .fromStream(new ClassPathResource(FIREBASE_KEY_PATH).getInputStream()); diff --git a/core/src/main/java/dev/handsup/notification/dto/SaveFCMTokenRequest.java b/core/src/main/java/dev/handsup/notification/dto/SaveFcmTokenRequestTmp.java similarity index 67% rename from core/src/main/java/dev/handsup/notification/dto/SaveFCMTokenRequest.java rename to core/src/main/java/dev/handsup/notification/dto/SaveFcmTokenRequestTmp.java index 4c8bed19..b7063fa9 100644 --- a/core/src/main/java/dev/handsup/notification/dto/SaveFCMTokenRequest.java +++ b/core/src/main/java/dev/handsup/notification/dto/SaveFcmTokenRequestTmp.java @@ -6,12 +6,12 @@ import lombok.Builder; @Builder(access = PRIVATE) -public record SaveFCMTokenRequest( +public record SaveFcmTokenRequestTmp( @NotEmpty(message = "fcmToken을 입력해주세요.") String fcmToken ) { - public static SaveFCMTokenRequest from(String fcmToken) { - return SaveFCMTokenRequest.builder() + public static SaveFcmTokenRequestTmp from(String fcmToken) { + return SaveFcmTokenRequestTmp.builder() .fcmToken(fcmToken) .build(); } diff --git a/core/src/main/java/dev/handsup/notification/repository/FCMTokenRepository.java b/core/src/main/java/dev/handsup/notification/repository/FcmTokenRepositoryTmp.java similarity index 95% rename from core/src/main/java/dev/handsup/notification/repository/FCMTokenRepository.java rename to core/src/main/java/dev/handsup/notification/repository/FcmTokenRepositoryTmp.java index 9beeff04..11851428 100644 --- a/core/src/main/java/dev/handsup/notification/repository/FCMTokenRepository.java +++ b/core/src/main/java/dev/handsup/notification/repository/FcmTokenRepositoryTmp.java @@ -9,7 +9,7 @@ @RequiredArgsConstructor @Component -public class FCMTokenRepository { +public class FcmTokenRepositoryTmp { private static final String PREFIX = "fcmToken:"; diff --git a/core/src/main/java/dev/handsup/notification/service/FCMService.java b/core/src/main/java/dev/handsup/notification/service/FcmServiceTmp.java similarity index 90% rename from core/src/main/java/dev/handsup/notification/service/FCMService.java rename to core/src/main/java/dev/handsup/notification/service/FcmServiceTmp.java index 248ec7e8..b7208c97 100644 --- a/core/src/main/java/dev/handsup/notification/service/FCMService.java +++ b/core/src/main/java/dev/handsup/notification/service/FcmServiceTmp.java @@ -9,15 +9,15 @@ import dev.handsup.common.exception.ValidationException; import dev.handsup.notification.domain.NotificationType; -import dev.handsup.notification.repository.FCMTokenRepository; +import dev.handsup.notification.repository.FcmTokenRepositoryTmp; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @Slf4j @RequiredArgsConstructor @Service -public class FCMService { - private final FCMTokenRepository fcmTokenRepository; +public class FcmServiceTmp { + private final FcmTokenRepositoryTmp fcmTokenRepository; private final FirebaseMessaging firebaseMessaging; public void sendNotification( diff --git a/core/src/main/java/dev/handsup/notification/service/NotificationSender.java b/core/src/main/java/dev/handsup/notification/service/NotificationSender.java index 1375e63e..f7ee94b2 100644 --- a/core/src/main/java/dev/handsup/notification/service/NotificationSender.java +++ b/core/src/main/java/dev/handsup/notification/service/NotificationSender.java @@ -10,7 +10,7 @@ @RequiredArgsConstructor public class NotificationSender { private final NotificationService notificationService; - private final FCMService fcmService; + private final FcmServiceTmp fcmService; public void sendNotification(User sender, User receiver, Long auctionId, NotificationType notificationType) { String content = notificationType.processContent(sender.getNickname()); diff --git a/core/src/test/java/dev/handsup/bidding/repository/BiddingConcurrencyTest.java b/core/src/test/java/dev/handsup/bidding/repository/BiddingConcurrencyTest.java index 1dabb068..c220c73e 100644 --- a/core/src/test/java/dev/handsup/bidding/repository/BiddingConcurrencyTest.java +++ b/core/src/test/java/dev/handsup/bidding/repository/BiddingConcurrencyTest.java @@ -19,7 +19,7 @@ import dev.handsup.auction.repository.product.ProductCategoryRepository; import dev.handsup.bidding.dto.request.RegisterBiddingRequest; import dev.handsup.bidding.service.BiddingService; -import dev.handsup.common.config.FcmConfig; +import dev.handsup.common.config.FcmConfigTmp; import dev.handsup.config.TestAuditingConfig; import dev.handsup.fixture.AuctionFixture; import dev.handsup.fixture.UserFixture; @@ -30,7 +30,7 @@ @SpringBootTest @Slf4j -@Import({TestAuditingConfig.class, FcmConfig.class}) +@Import({TestAuditingConfig.class, FcmConfigTmp.class}) class BiddingConcurrencyTest extends TestContainerSupport { private Auction auction; From dbf7f92b040d8623fddbeea470f7ec4c6ca7ebba Mon Sep 17 00:00:00 2001 From: hs12 Date: Mon, 30 Jun 2025 16:15:50 +0900 Subject: [PATCH 27/38] =?UTF-8?q?[fix]=20:=20=EC=9E=84=EC=8B=9C=EB=A1=9C?= =?UTF-8?q?=20=ED=8C=8C=EC=9D=BC=EB=AA=85=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/{FCMController.java => FcmControllerTmp.java} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename api/src/main/java/dev/handsup/notification/controller/{FCMController.java => FcmControllerTmp.java} (97%) diff --git a/api/src/main/java/dev/handsup/notification/controller/FCMController.java b/api/src/main/java/dev/handsup/notification/controller/FcmControllerTmp.java similarity index 97% rename from api/src/main/java/dev/handsup/notification/controller/FCMController.java rename to api/src/main/java/dev/handsup/notification/controller/FcmControllerTmp.java index 901d0ee7..fe95e0e2 100644 --- a/api/src/main/java/dev/handsup/notification/controller/FCMController.java +++ b/api/src/main/java/dev/handsup/notification/controller/FcmControllerTmp.java @@ -18,7 +18,7 @@ @RestController @RequiredArgsConstructor -public class FCMController { +public class FcmControllerTmp { private final FcmServiceTmp fcmService; @PostMapping("/api/fcm-tokens") From ff069f661dbadbd4d1233f4650709790f4388417 Mon Sep 17 00:00:00 2001 From: hs12 Date: Mon, 30 Jun 2025 16:22:39 +0900 Subject: [PATCH 28/38] =?UTF-8?q?[fix]=20:=20=ED=8C=8C=EC=9D=BC=EB=AA=85?= =?UTF-8?q?=20=EC=9B=90=EB=B3=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dev/handsup/auth/controller/AuthApiController.java | 4 ++-- .../{FcmControllerTmp.java => FcmController.java} | 10 +++++----- .../config/{FcmConfigTmp.java => FcmConfig.java} | 2 +- ...cmTokenRequestTmp.java => SaveFcmTokenRequest.java} | 6 +++--- ...TokenRepositoryTmp.java => FcmTokenRepository.java} | 2 +- .../service/{FcmServiceTmp.java => FcmService.java} | 6 +++--- .../notification/service/NotificationSender.java | 2 +- .../bidding/repository/BiddingConcurrencyTest.java | 4 ++-- 8 files changed, 18 insertions(+), 18 deletions(-) rename api/src/main/java/dev/handsup/notification/controller/{FcmControllerTmp.java => FcmController.java} (81%) rename core/src/main/java/dev/handsup/common/config/{FcmConfigTmp.java => FcmConfig.java} (97%) rename core/src/main/java/dev/handsup/notification/dto/{SaveFcmTokenRequestTmp.java => SaveFcmTokenRequest.java} (67%) rename core/src/main/java/dev/handsup/notification/repository/{FcmTokenRepositoryTmp.java => FcmTokenRepository.java} (95%) rename core/src/main/java/dev/handsup/notification/service/{FcmServiceTmp.java => FcmService.java} (90%) diff --git a/api/src/main/java/dev/handsup/auth/controller/AuthApiController.java b/api/src/main/java/dev/handsup/auth/controller/AuthApiController.java index aa03b152..558ef250 100644 --- a/api/src/main/java/dev/handsup/auth/controller/AuthApiController.java +++ b/api/src/main/java/dev/handsup/auth/controller/AuthApiController.java @@ -17,7 +17,7 @@ import dev.handsup.auth.dto.response.TokenReIssueResponse; import dev.handsup.auth.jwt.JwtAuthorization; import dev.handsup.auth.service.AuthService; -import dev.handsup.notification.service.FcmServiceTmp; +import dev.handsup.notification.service.FcmService; import dev.handsup.user.domain.User; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; @@ -35,7 +35,7 @@ public class AuthApiController { private final AuthService authService; - private final FcmServiceTmp fcmService; + private final FcmService fcmService; @NoAuth @PostMapping("/login") diff --git a/api/src/main/java/dev/handsup/notification/controller/FcmControllerTmp.java b/api/src/main/java/dev/handsup/notification/controller/FcmController.java similarity index 81% rename from api/src/main/java/dev/handsup/notification/controller/FcmControllerTmp.java rename to api/src/main/java/dev/handsup/notification/controller/FcmController.java index fe95e0e2..969cf3e4 100644 --- a/api/src/main/java/dev/handsup/notification/controller/FcmControllerTmp.java +++ b/api/src/main/java/dev/handsup/notification/controller/FcmController.java @@ -7,8 +7,8 @@ import org.springframework.web.bind.annotation.RestController; import dev.handsup.auth.jwt.JwtAuthorization; -import dev.handsup.notification.dto.SaveFcmTokenRequestTmp; -import dev.handsup.notification.service.FcmServiceTmp; +import dev.handsup.notification.dto.SaveFcmTokenRequest; +import dev.handsup.notification.service.FcmService; import dev.handsup.user.domain.User; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; @@ -18,15 +18,15 @@ @RestController @RequiredArgsConstructor -public class FcmControllerTmp { - private final FcmServiceTmp fcmService; +public class FcmController { + private final FcmService fcmService; @PostMapping("/api/fcm-tokens") @Operation(summary = "FCM 토큰 저장 API", description = "{사용자 아이디 : FCM 토큰}을 redis에 저장") @ApiResponse(useReturnTypeSchema = true) public ResponseEntity saveFCMToken( @Parameter(hidden = true) @JwtAuthorization User user, - @RequestBody @Valid SaveFcmTokenRequestTmp request + @RequestBody @Valid SaveFcmTokenRequest request ) { fcmService.saveFcmToken(user.getId(), request.fcmToken()); return ResponseEntity.ok(HttpStatus.OK); diff --git a/core/src/main/java/dev/handsup/common/config/FcmConfigTmp.java b/core/src/main/java/dev/handsup/common/config/FcmConfig.java similarity index 97% rename from core/src/main/java/dev/handsup/common/config/FcmConfigTmp.java rename to core/src/main/java/dev/handsup/common/config/FcmConfig.java index 525d4278..dd218a55 100644 --- a/core/src/main/java/dev/handsup/common/config/FcmConfigTmp.java +++ b/core/src/main/java/dev/handsup/common/config/FcmConfig.java @@ -16,7 +16,7 @@ @Configuration @Slf4j -public class FcmConfigTmp { +public class FcmConfig { private static final String FIREBASE_KEY_PATH = "firebase/serviceAccountKey.json"; @PostConstruct diff --git a/core/src/main/java/dev/handsup/notification/dto/SaveFcmTokenRequestTmp.java b/core/src/main/java/dev/handsup/notification/dto/SaveFcmTokenRequest.java similarity index 67% rename from core/src/main/java/dev/handsup/notification/dto/SaveFcmTokenRequestTmp.java rename to core/src/main/java/dev/handsup/notification/dto/SaveFcmTokenRequest.java index b7063fa9..784d1f79 100644 --- a/core/src/main/java/dev/handsup/notification/dto/SaveFcmTokenRequestTmp.java +++ b/core/src/main/java/dev/handsup/notification/dto/SaveFcmTokenRequest.java @@ -6,12 +6,12 @@ import lombok.Builder; @Builder(access = PRIVATE) -public record SaveFcmTokenRequestTmp( +public record SaveFcmTokenRequest( @NotEmpty(message = "fcmToken을 입력해주세요.") String fcmToken ) { - public static SaveFcmTokenRequestTmp from(String fcmToken) { - return SaveFcmTokenRequestTmp.builder() + public static SaveFcmTokenRequest from(String fcmToken) { + return SaveFcmTokenRequest.builder() .fcmToken(fcmToken) .build(); } diff --git a/core/src/main/java/dev/handsup/notification/repository/FcmTokenRepositoryTmp.java b/core/src/main/java/dev/handsup/notification/repository/FcmTokenRepository.java similarity index 95% rename from core/src/main/java/dev/handsup/notification/repository/FcmTokenRepositoryTmp.java rename to core/src/main/java/dev/handsup/notification/repository/FcmTokenRepository.java index 11851428..3039b3a6 100644 --- a/core/src/main/java/dev/handsup/notification/repository/FcmTokenRepositoryTmp.java +++ b/core/src/main/java/dev/handsup/notification/repository/FcmTokenRepository.java @@ -9,7 +9,7 @@ @RequiredArgsConstructor @Component -public class FcmTokenRepositoryTmp { +public class FcmTokenRepository { private static final String PREFIX = "fcmToken:"; diff --git a/core/src/main/java/dev/handsup/notification/service/FcmServiceTmp.java b/core/src/main/java/dev/handsup/notification/service/FcmService.java similarity index 90% rename from core/src/main/java/dev/handsup/notification/service/FcmServiceTmp.java rename to core/src/main/java/dev/handsup/notification/service/FcmService.java index b7208c97..bc79c809 100644 --- a/core/src/main/java/dev/handsup/notification/service/FcmServiceTmp.java +++ b/core/src/main/java/dev/handsup/notification/service/FcmService.java @@ -9,15 +9,15 @@ import dev.handsup.common.exception.ValidationException; import dev.handsup.notification.domain.NotificationType; -import dev.handsup.notification.repository.FcmTokenRepositoryTmp; +import dev.handsup.notification.repository.FcmTokenRepository; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @Slf4j @RequiredArgsConstructor @Service -public class FcmServiceTmp { - private final FcmTokenRepositoryTmp fcmTokenRepository; +public class FcmService { + private final FcmTokenRepository fcmTokenRepository; private final FirebaseMessaging firebaseMessaging; public void sendNotification( diff --git a/core/src/main/java/dev/handsup/notification/service/NotificationSender.java b/core/src/main/java/dev/handsup/notification/service/NotificationSender.java index f7ee94b2..c5a816a8 100644 --- a/core/src/main/java/dev/handsup/notification/service/NotificationSender.java +++ b/core/src/main/java/dev/handsup/notification/service/NotificationSender.java @@ -10,7 +10,7 @@ @RequiredArgsConstructor public class NotificationSender { private final NotificationService notificationService; - private final FcmServiceTmp fcmService; + private final FcmService fcmService; public void sendNotification(User sender, User receiver, Long auctionId, NotificationType notificationType) { String content = notificationType.processContent(sender.getNickname()); diff --git a/core/src/test/java/dev/handsup/bidding/repository/BiddingConcurrencyTest.java b/core/src/test/java/dev/handsup/bidding/repository/BiddingConcurrencyTest.java index c220c73e..1dabb068 100644 --- a/core/src/test/java/dev/handsup/bidding/repository/BiddingConcurrencyTest.java +++ b/core/src/test/java/dev/handsup/bidding/repository/BiddingConcurrencyTest.java @@ -19,7 +19,7 @@ import dev.handsup.auction.repository.product.ProductCategoryRepository; import dev.handsup.bidding.dto.request.RegisterBiddingRequest; import dev.handsup.bidding.service.BiddingService; -import dev.handsup.common.config.FcmConfigTmp; +import dev.handsup.common.config.FcmConfig; import dev.handsup.config.TestAuditingConfig; import dev.handsup.fixture.AuctionFixture; import dev.handsup.fixture.UserFixture; @@ -30,7 +30,7 @@ @SpringBootTest @Slf4j -@Import({TestAuditingConfig.class, FcmConfigTmp.class}) +@Import({TestAuditingConfig.class, FcmConfig.class}) class BiddingConcurrencyTest extends TestContainerSupport { private Auction auction; From ba98826b80b0144492f5e4a533a8bc5f3b6200c4 Mon Sep 17 00:00:00 2001 From: hs12 Date: Mon, 30 Jun 2025 16:34:51 +0900 Subject: [PATCH 29/38] =?UTF-8?q?[remove]=20:=20=EB=B6=88=ED=95=84?= =?UTF-8?q?=EC=9A=94=ED=95=9C=20json=20=ED=8C=8C=EC=9D=BC=20gitignore?= =?UTF-8?q?=EC=97=90=EC=84=9C=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/ci.yml | 2 +- .gitignore | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index de2c597f..4238f656 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -27,7 +27,7 @@ jobs: distribution: 'temurin' # firebase json 파일 생성 - - name : Generate firebase_account.json + - name : Generate serviceAccountKey.json run: | mkdir -p ./core/src/main/resources/firebase echo "${{ secrets.FIREBASE_KEY }}" > ./core/src/main/resources/firebase/serviceAccountKey.json diff --git a/.gitignore b/.gitignore index 7f10d69d..0c305aeb 100644 --- a/.gitignore +++ b/.gitignore @@ -41,9 +41,6 @@ out/ core/src/main/resources/application-core-prod.yml /api/src/main/resources/application.yml /core/src/main/generated/ -/core/src/main/resources/firebase/firebase_account.json -/core/src/test/resources/firebase/firebase_account.json -/api/src/test/resources/firebase/firebase_account.json /core/src/main/resources/application-core-local.yml /core/src/main/resources/firebase/serviceAccountKey.json /core/src/test/http From 94af207b15ac8eb2c45f3b23696cf35b809d0624 Mon Sep 17 00:00:00 2001 From: hs12 Date: Mon, 30 Jun 2025 16:56:27 +0900 Subject: [PATCH 30/38] =?UTF-8?q?[fix]=20:=20test=20=EA=B2=BD=EB=A1=9C?= =?UTF-8?q?=EC=97=90=20json=20=ED=8C=8C=EC=9D=BC=20=EC=B6=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/ci.yml | 5 +++++ api/src/test/resources/application.yml | 2 ++ .../src/main/java/dev/handsup/common/config/FcmConfig.java | 7 +++++-- core/src/test/resources/application.yml | 2 ++ 4 files changed, 14 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4238f656..128a4874 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -30,7 +30,12 @@ jobs: - name : Generate serviceAccountKey.json run: | mkdir -p ./core/src/main/resources/firebase + mkdir -p ./core/src/test/resources/firebase + mkdir -p ./api/src/test/resources/firebase echo "${{ secrets.FIREBASE_KEY }}" > ./core/src/main/resources/firebase/serviceAccountKey.json + echo "${{ secrets.FIREBASE_KEY }}" > ./core/src/test/resources/firebase/serviceAccountKey.json + echo "${{ secrets.FIREBASE_KEY }}" > ./api/src/test/resources/firebase/serviceAccountKey.json + # gradle 권한 부여 - name: Grant execute permission for gradlew run: chmod +x ./gradlew diff --git a/api/src/test/resources/application.yml b/api/src/test/resources/application.yml index 0de398ff..abb62451 100644 --- a/api/src/test/resources/application.yml +++ b/api/src/test/resources/application.yml @@ -24,3 +24,5 @@ cloud: bucket: s3-bucket-name stack: auto: false +fcm: + key: firebase/serviceAccountKey.json \ No newline at end of file diff --git a/core/src/main/java/dev/handsup/common/config/FcmConfig.java b/core/src/main/java/dev/handsup/common/config/FcmConfig.java index dd218a55..9ce05371 100644 --- a/core/src/main/java/dev/handsup/common/config/FcmConfig.java +++ b/core/src/main/java/dev/handsup/common/config/FcmConfig.java @@ -2,6 +2,7 @@ import java.io.IOException; +import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.ClassPathResource; @@ -17,7 +18,9 @@ @Configuration @Slf4j public class FcmConfig { - private static final String FIREBASE_KEY_PATH = "firebase/serviceAccountKey.json"; + + @Value("${fcm.key}") + private String FIREBASE_KEY_PATH; @PostConstruct public void initialize() { @@ -39,4 +42,4 @@ public void initialize() { public FirebaseMessaging firebaseMessaging() { return FirebaseMessaging.getInstance(); } -} \ No newline at end of file +} diff --git a/core/src/test/resources/application.yml b/core/src/test/resources/application.yml index 0de398ff..abb62451 100644 --- a/core/src/test/resources/application.yml +++ b/core/src/test/resources/application.yml @@ -24,3 +24,5 @@ cloud: bucket: s3-bucket-name stack: auto: false +fcm: + key: firebase/serviceAccountKey.json \ No newline at end of file From 14fe3be5a55cb1437779d643af9f49a8055e0ed9 Mon Sep 17 00:00:00 2001 From: hs12 Date: Mon, 30 Jun 2025 17:38:19 +0900 Subject: [PATCH 31/38] =?UTF-8?q?[fix]=20:=20=EC=84=A4=EC=A0=95=20?= =?UTF-8?q?=EC=9B=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/ci.yml | 8 ++------ api/src/test/resources/application.yml | 4 +--- .../main/java/dev/handsup/common/config/FcmConfig.java | 7 ++----- core/src/test/resources/application.yml | 4 +--- 4 files changed, 6 insertions(+), 17 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 128a4874..773a6f43 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -2,7 +2,7 @@ name: CI Backend on: pull_request: - branches: ["main", "dev"] + branches: [ "main", "dev" ] permissions: contents: read @@ -27,14 +27,10 @@ jobs: distribution: 'temurin' # firebase json 파일 생성 - - name : Generate serviceAccountKey.json + - name: Generate serviceAccountKey.json run: | mkdir -p ./core/src/main/resources/firebase - mkdir -p ./core/src/test/resources/firebase - mkdir -p ./api/src/test/resources/firebase echo "${{ secrets.FIREBASE_KEY }}" > ./core/src/main/resources/firebase/serviceAccountKey.json - echo "${{ secrets.FIREBASE_KEY }}" > ./core/src/test/resources/firebase/serviceAccountKey.json - echo "${{ secrets.FIREBASE_KEY }}" > ./api/src/test/resources/firebase/serviceAccountKey.json # gradle 권한 부여 - name: Grant execute permission for gradlew diff --git a/api/src/test/resources/application.yml b/api/src/test/resources/application.yml index abb62451..6991e513 100644 --- a/api/src/test/resources/application.yml +++ b/api/src/test/resources/application.yml @@ -23,6 +23,4 @@ cloud: s3: bucket: s3-bucket-name stack: - auto: false -fcm: - key: firebase/serviceAccountKey.json \ No newline at end of file + auto: false \ No newline at end of file diff --git a/core/src/main/java/dev/handsup/common/config/FcmConfig.java b/core/src/main/java/dev/handsup/common/config/FcmConfig.java index 9ce05371..dd218a55 100644 --- a/core/src/main/java/dev/handsup/common/config/FcmConfig.java +++ b/core/src/main/java/dev/handsup/common/config/FcmConfig.java @@ -2,7 +2,6 @@ import java.io.IOException; -import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.ClassPathResource; @@ -18,9 +17,7 @@ @Configuration @Slf4j public class FcmConfig { - - @Value("${fcm.key}") - private String FIREBASE_KEY_PATH; + private static final String FIREBASE_KEY_PATH = "firebase/serviceAccountKey.json"; @PostConstruct public void initialize() { @@ -42,4 +39,4 @@ public void initialize() { public FirebaseMessaging firebaseMessaging() { return FirebaseMessaging.getInstance(); } -} +} \ No newline at end of file diff --git a/core/src/test/resources/application.yml b/core/src/test/resources/application.yml index abb62451..6991e513 100644 --- a/core/src/test/resources/application.yml +++ b/core/src/test/resources/application.yml @@ -23,6 +23,4 @@ cloud: s3: bucket: s3-bucket-name stack: - auto: false -fcm: - key: firebase/serviceAccountKey.json \ No newline at end of file + auto: false \ No newline at end of file From 2d190f0d18748c4de08a72b91fe24fcb5fcc52c4 Mon Sep 17 00:00:00 2001 From: hs12 Date: Mon, 30 Jun 2025 17:49:37 +0900 Subject: [PATCH 32/38] =?UTF-8?q?[chore]=20:=20json=20=ED=8C=8C=EC=9D=BC?= =?UTF-8?q?=20=EC=A1=B4=EC=9E=AC=EC=97=AC=EB=B6=80=20=ED=99=95=EC=9D=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/ci.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 773a6f43..bca3ae7b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -32,7 +32,11 @@ jobs: mkdir -p ./core/src/main/resources/firebase echo "${{ secrets.FIREBASE_KEY }}" > ./core/src/main/resources/firebase/serviceAccountKey.json - # gradle 권한 부여 + - name: Check serviceAccountKey.json existence + run: ls -al ./core/build/resources/main/firebase/ + + + # gradle 권한 부여 - name: Grant execute permission for gradlew run: chmod +x ./gradlew shell: bash From 0c3a4414988c60d06c97f43acf6e39e1488efb5f Mon Sep 17 00:00:00 2001 From: hs12 Date: Mon, 30 Jun 2025 17:56:52 +0900 Subject: [PATCH 33/38] =?UTF-8?q?[chore]=20:=20json=20=EC=A1=B4=EC=9E=AC?= =?UTF-8?q?=EC=97=AC=EB=B6=80=ED=99=95=EC=9D=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/ci.yml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bca3ae7b..23ce996c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -32,10 +32,6 @@ jobs: mkdir -p ./core/src/main/resources/firebase echo "${{ secrets.FIREBASE_KEY }}" > ./core/src/main/resources/firebase/serviceAccountKey.json - - name: Check serviceAccountKey.json existence - run: ls -al ./core/build/resources/main/firebase/ - - # gradle 권한 부여 - name: Grant execute permission for gradlew run: chmod +x ./gradlew @@ -56,6 +52,9 @@ jobs: - name: Build with Gradle run: ./gradlew build + - name: Check serviceAccountKey.json existence + run: ls -al ./core/build/resources/main/firebase/ + # 테스트 결과 PR 코멘트에 등록 - name: Register the test results as PR comments uses: EnricoMi/publish-unit-test-result-action@v2 From 982882719eeb4e51188440fe525f1bb6cd1a5efb Mon Sep 17 00:00:00 2001 From: hs12 Date: Mon, 30 Jun 2025 18:02:02 +0900 Subject: [PATCH 34/38] =?UTF-8?q?[chore]=20:=20=EB=94=94=EC=BD=94=EB=94=A9?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/ci.yml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 23ce996c..4755927c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -30,7 +30,7 @@ jobs: - name: Generate serviceAccountKey.json run: | mkdir -p ./core/src/main/resources/firebase - echo "${{ secrets.FIREBASE_KEY }}" > ./core/src/main/resources/firebase/serviceAccountKey.json + echo "${{ secrets.FIREBASE_ACCOUNT }}" | base64 -d > ./core/src/main/resources/firebase/serviceAccountKey.json # gradle 권한 부여 - name: Grant execute permission for gradlew @@ -52,9 +52,6 @@ jobs: - name: Build with Gradle run: ./gradlew build - - name: Check serviceAccountKey.json existence - run: ls -al ./core/build/resources/main/firebase/ - # 테스트 결과 PR 코멘트에 등록 - name: Register the test results as PR comments uses: EnricoMi/publish-unit-test-result-action@v2 From d9f91315dd5d9cae7a8b6e8f1ba9c291dcf469e1 Mon Sep 17 00:00:00 2001 From: hs12 Date: Mon, 30 Jun 2025 18:22:05 +0900 Subject: [PATCH 35/38] =?UTF-8?q?[chore]=20:=20=ED=85=8C=EC=8A=A4=ED=8A=B8?= =?UTF-8?q?=20=EA=B2=BD=EB=A1=9C=EC=97=90=20json=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/ci.yml | 4 ++++ api/src/test/resources/application.yml | 4 +++- .../src/main/java/dev/handsup/common/config/FcmConfig.java | 7 ++++--- core/src/test/resources/application.yml | 4 +++- 4 files changed, 14 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4755927c..7b16be21 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,6 +31,10 @@ jobs: run: | mkdir -p ./core/src/main/resources/firebase echo "${{ secrets.FIREBASE_ACCOUNT }}" | base64 -d > ./core/src/main/resources/firebase/serviceAccountKey.json + mkdir -p ./core/src/test/resources/firebase + echo "${{ secrets.FIREBASE_ACCOUNT }}" | base64 -d > ./core/src/test/resources/firebase/serviceAccountKey.json + mkdir -p ./api/src/test/resources/firebase + echo "${{ secrets.FIREBASE_ACCOUNT }}" | base64 -d > ./api/src/test/resources/firebase/serviceAccountKey.json # gradle 권한 부여 - name: Grant execute permission for gradlew diff --git a/api/src/test/resources/application.yml b/api/src/test/resources/application.yml index 6991e513..abb62451 100644 --- a/api/src/test/resources/application.yml +++ b/api/src/test/resources/application.yml @@ -23,4 +23,6 @@ cloud: s3: bucket: s3-bucket-name stack: - auto: false \ No newline at end of file + auto: false +fcm: + key: firebase/serviceAccountKey.json \ No newline at end of file diff --git a/core/src/main/java/dev/handsup/common/config/FcmConfig.java b/core/src/main/java/dev/handsup/common/config/FcmConfig.java index dd218a55..8af17800 100644 --- a/core/src/main/java/dev/handsup/common/config/FcmConfig.java +++ b/core/src/main/java/dev/handsup/common/config/FcmConfig.java @@ -2,6 +2,7 @@ import java.io.IOException; +import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.ClassPathResource; @@ -17,15 +18,15 @@ @Configuration @Slf4j public class FcmConfig { - private static final String FIREBASE_KEY_PATH = "firebase/serviceAccountKey.json"; - + @Value("${fcm.key:firebase/serviceAccountKey.json}") + private String firebase_key_path; @PostConstruct public void initialize() { if (!FirebaseApp.getApps().isEmpty()) return; try { GoogleCredentials googleCredentials = GoogleCredentials - .fromStream(new ClassPathResource(FIREBASE_KEY_PATH).getInputStream()); + .fromStream(new ClassPathResource(firebase_key_path).getInputStream()); FirebaseOptions options = FirebaseOptions.builder() .setCredentials(googleCredentials) .build(); diff --git a/core/src/test/resources/application.yml b/core/src/test/resources/application.yml index 6991e513..abb62451 100644 --- a/core/src/test/resources/application.yml +++ b/core/src/test/resources/application.yml @@ -23,4 +23,6 @@ cloud: s3: bucket: s3-bucket-name stack: - auto: false \ No newline at end of file + auto: false +fcm: + key: firebase/serviceAccountKey.json \ No newline at end of file From 753db17d9a8123162810180af9a83d1d9978cf97 Mon Sep 17 00:00:00 2001 From: hs12 Date: Mon, 30 Jun 2025 18:28:50 +0900 Subject: [PATCH 36/38] =?UTF-8?q?[chore]=20:=20=EC=8B=9C=ED=81=AC=EB=A6=BF?= =?UTF-8?q?=ED=82=A4=EB=AA=85=20=EC=A0=9C=EB=8C=80=EB=A1=9C=20=EC=9E=85?= =?UTF-8?q?=EB=A0=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7b16be21..ae8c2eb2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -30,11 +30,11 @@ jobs: - name: Generate serviceAccountKey.json run: | mkdir -p ./core/src/main/resources/firebase - echo "${{ secrets.FIREBASE_ACCOUNT }}" | base64 -d > ./core/src/main/resources/firebase/serviceAccountKey.json + echo "${{ secrets.FIREBASE_KEY }}" | base64 -d > ./core/src/main/resources/firebase/serviceAccountKey.json mkdir -p ./core/src/test/resources/firebase - echo "${{ secrets.FIREBASE_ACCOUNT }}" | base64 -d > ./core/src/test/resources/firebase/serviceAccountKey.json + echo "${{ secrets.FIREBASE_KEY }}" | base64 -d > ./core/src/test/resources/firebase/serviceAccountKey.json mkdir -p ./api/src/test/resources/firebase - echo "${{ secrets.FIREBASE_ACCOUNT }}" | base64 -d > ./api/src/test/resources/firebase/serviceAccountKey.json + echo "${{ secrets.FIREBASE_KEY }}" | base64 -d > ./api/src/test/resources/firebase/serviceAccountKey.json # gradle 권한 부여 - name: Grant execute permission for gradlew From 22823a016b3bffef8b6f3eb629e115eea094e1a4 Mon Sep 17 00:00:00 2001 From: hs12 Date: Mon, 30 Jun 2025 19:38:54 +0900 Subject: [PATCH 37/38] =?UTF-8?q?[chore]=20:=20test=20=EA=B2=BD=EB=A1=9C?= =?UTF-8?q?=EC=97=90=20=EA=BC=AD=20=ED=95=84=EC=9A=94=ED=95=9C=EC=A7=80=20?= =?UTF-8?q?=ED=99=95=EC=9D=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/ci.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ae8c2eb2..baa0fef3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,10 +31,10 @@ jobs: run: | mkdir -p ./core/src/main/resources/firebase echo "${{ secrets.FIREBASE_KEY }}" | base64 -d > ./core/src/main/resources/firebase/serviceAccountKey.json - mkdir -p ./core/src/test/resources/firebase - echo "${{ secrets.FIREBASE_KEY }}" | base64 -d > ./core/src/test/resources/firebase/serviceAccountKey.json - mkdir -p ./api/src/test/resources/firebase - echo "${{ secrets.FIREBASE_KEY }}" | base64 -d > ./api/src/test/resources/firebase/serviceAccountKey.json +# mkdir -p ./core/src/test/resources/firebase +# echo "${{ secrets.FIREBASE_KEY }}" | base64 -d > ./core/src/test/resources/firebase/serviceAccountKey.json +# mkdir -p ./api/src/test/resources/firebase +# echo "${{ secrets.FIREBASE_KEY }}" | base64 -d > ./api/src/test/resources/firebase/serviceAccountKey.json # gradle 권한 부여 - name: Grant execute permission for gradlew From 3ef9f246ba00b2c99a73a07e4f914dccb5a5c634 Mon Sep 17 00:00:00 2001 From: hs12 Date: Mon, 30 Jun 2025 19:44:32 +0900 Subject: [PATCH 38/38] =?UTF-8?q?[chore]=20:=20test=20=EA=B2=BD=EB=A1=9C?= =?UTF-8?q?=EC=97=90=20=EA=BC=AD=20json=20=ED=95=84=EC=9A=94=ED=95=9C?= =?UTF-8?q?=EC=A7=80=20=ED=99=95=EC=9D=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/src/test/resources/application.yml | 4 +--- core/src/main/java/dev/handsup/common/config/FcmConfig.java | 6 ++---- core/src/test/resources/application.yml | 4 +--- 3 files changed, 4 insertions(+), 10 deletions(-) diff --git a/api/src/test/resources/application.yml b/api/src/test/resources/application.yml index abb62451..6991e513 100644 --- a/api/src/test/resources/application.yml +++ b/api/src/test/resources/application.yml @@ -23,6 +23,4 @@ cloud: s3: bucket: s3-bucket-name stack: - auto: false -fcm: - key: firebase/serviceAccountKey.json \ No newline at end of file + auto: false \ No newline at end of file diff --git a/core/src/main/java/dev/handsup/common/config/FcmConfig.java b/core/src/main/java/dev/handsup/common/config/FcmConfig.java index 8af17800..2a809fa8 100644 --- a/core/src/main/java/dev/handsup/common/config/FcmConfig.java +++ b/core/src/main/java/dev/handsup/common/config/FcmConfig.java @@ -2,7 +2,6 @@ import java.io.IOException; -import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.ClassPathResource; @@ -18,15 +17,14 @@ @Configuration @Slf4j public class FcmConfig { - @Value("${fcm.key:firebase/serviceAccountKey.json}") - private String firebase_key_path; + private static final String FIREBASE_KEY_PATH = "firebase/serviceAccountKey.json"; @PostConstruct public void initialize() { if (!FirebaseApp.getApps().isEmpty()) return; try { GoogleCredentials googleCredentials = GoogleCredentials - .fromStream(new ClassPathResource(firebase_key_path).getInputStream()); + .fromStream(new ClassPathResource(FIREBASE_KEY_PATH).getInputStream()); FirebaseOptions options = FirebaseOptions.builder() .setCredentials(googleCredentials) .build(); diff --git a/core/src/test/resources/application.yml b/core/src/test/resources/application.yml index abb62451..6991e513 100644 --- a/core/src/test/resources/application.yml +++ b/core/src/test/resources/application.yml @@ -23,6 +23,4 @@ cloud: s3: bucket: s3-bucket-name stack: - auto: false -fcm: - key: firebase/serviceAccountKey.json \ No newline at end of file + auto: false \ No newline at end of file