From f1698c7fedcaeb23e23b0746a3cf19b0b08b9fb1 Mon Sep 17 00:00:00 2001 From: itaekyung Date: Fri, 5 Sep 2025 09:41:25 +0900 Subject: [PATCH] =?UTF-8?q?Fix:=20=EC=9C=A0=EC=A0=80=20=EC=A0=95=EB=B3=B4?= =?UTF-8?q?=20=EC=A1=B0=ED=9A=8C=20api=20=EB=AC=BC=20=EA=B4=80=EB=A0=A8=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../user/presentation/UserController.java | 11 ++----- .../member/user/service/UserService.java | 19 +++-------- .../cp_main_be/global/util/TimeUtil.java | 33 +++++++++++++++++++ 3 files changed, 41 insertions(+), 22 deletions(-) create mode 100644 src/main/java/com/example/cp_main_be/global/util/TimeUtil.java diff --git a/src/main/java/com/example/cp_main_be/domain/member/user/presentation/UserController.java b/src/main/java/com/example/cp_main_be/domain/member/user/presentation/UserController.java index 2daf2689..1f41aa31 100644 --- a/src/main/java/com/example/cp_main_be/domain/member/user/presentation/UserController.java +++ b/src/main/java/com/example/cp_main_be/domain/member/user/presentation/UserController.java @@ -8,7 +8,6 @@ import com.example.cp_main_be.domain.member.user.dto.response.UserRegisterResponse; import com.example.cp_main_be.domain.member.user.service.UserService; import com.example.cp_main_be.global.common.ApiResponse; -import com.example.cp_main_be.global.exception.UserNotFoundException; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.validation.Valid; @@ -94,12 +93,8 @@ public ResponseEntity>> getMyGardenIds( @Operation(summary = "유저 정보 조회", description = "유저 정보를 조회합니다") @GetMapping("/{userId}") public ResponseEntity> getUserInfo( - @PathVariable("userId") Long userId) { - // SecurityContextHolder에서 현재 인증된 사용자(UUID)를 가져옴 - User user = - userRepository - .findById(userId) - .orElseThrow(() -> new UserNotFoundException("해당 유저를 찾을 수 없습니다.")); - return ResponseEntity.ok(ApiResponse.success(userService.getUserProfile(user.getId(), userId))); + @PathVariable("userId") Long targetUserId, @AuthenticationPrincipal User user) { + return ResponseEntity.ok( + ApiResponse.success(userService.getUserProfile(user.getId(), targetUserId))); } } diff --git a/src/main/java/com/example/cp_main_be/domain/member/user/service/UserService.java b/src/main/java/com/example/cp_main_be/domain/member/user/service/UserService.java index f031325a..b4425931 100644 --- a/src/main/java/com/example/cp_main_be/domain/member/user/service/UserService.java +++ b/src/main/java/com/example/cp_main_be/domain/member/user/service/UserService.java @@ -16,8 +16,8 @@ import com.example.cp_main_be.domain.social.follow.domain.repository.FollowRepository; import com.example.cp_main_be.global.common.CustomApiException; import com.example.cp_main_be.global.common.ErrorCode; +import com.example.cp_main_be.global.util.TimeUtil; import java.time.LocalDateTime; -import java.time.ZoneId; import java.util.*; import java.util.stream.Collectors; import lombok.RequiredArgsConstructor; @@ -165,10 +165,12 @@ public List getMyGardenIds(User user) { * @return UserProfileResponse DTO */ public UserProfileResponse getUserProfile(Long currentUserId, Long profileUserId) { + // 현재 로그인한 유저 User currentUser = userRepository .findById(currentUserId) // ID로 최신 유저 정보를 조회합니다. .orElseThrow(() -> new CustomApiException(ErrorCode.USER_NOT_FOUND)); + // 프로필 조회할 유저 User profileUser = userRepository .findByIdWithGardensAndAvatars(profileUserId) @@ -208,7 +210,7 @@ public UserProfileResponse getUserProfile(Long currentUserId, Long profileUserId } // 2. 남에게 물 줄 수 있는 남은 횟수 계산 - LocalDateTime startOfWateringDay = getStartOfCurrentWateringDay(); + LocalDateTime startOfWateringDay = TimeUtil.getStartOfCurrentWateringDay(); // 2-1. 프로필 주인이 남에게 물을 줄 수 있는 남은 횟수 (응답 DTO용) int profileUserWateringCount = @@ -237,6 +239,7 @@ public UserProfileResponse getUserProfile(Long currentUserId, Long profileUserId .map( garden -> { // DB를 반복 조회하는 대신, 미리 조회한 Set에서 확인하여 성능을 개선합니다. + // 로그인한 유저가 해당 정원에 물을 아직 안줬고 횟수가 남았다면 true boolean alreadyWateredByMe = wateredGardenIds.contains(garden.getId()); boolean isWateringAbleByMe = leftWaterCountForCurrentUser > 0 && !alreadyWateredByMe; @@ -268,16 +271,4 @@ public UserProfileResponse getUserProfile(Long currentUserId, Long profileUserId .userGardens(userGardens) .build(); } - - // GardenService에 있던 private 메서드를 가져오거나 공통 유틸 클래스로 분리해야 합니다. - private LocalDateTime getStartOfCurrentWateringDay() { - LocalDateTime now = LocalDateTime.now(ZoneId.of("Asia/Seoul")); - LocalDateTime todayNoon = now.toLocalDate().atTime(12, 0); - - if (now.isBefore(todayNoon)) { - return todayNoon.minusDays(1); - } else { - return todayNoon; - } - } } diff --git a/src/main/java/com/example/cp_main_be/global/util/TimeUtil.java b/src/main/java/com/example/cp_main_be/global/util/TimeUtil.java new file mode 100644 index 00000000..87d591d1 --- /dev/null +++ b/src/main/java/com/example/cp_main_be/global/util/TimeUtil.java @@ -0,0 +1,33 @@ +package com.example.cp_main_be.global.util; + +import java.time.LocalDateTime; +import java.time.ZoneId; + +/** 도메인과 관련된 시간 계산을 처리하는 유틸리티 클래스입니다. */ +public final class TimeUtil { + + private static final ZoneId KST = ZoneId.of("Asia/Seoul"); + + private TimeUtil() { + // 유틸리티 클래스는 인스턴스화할 수 없습니다. + } + + /** + * 물주기 주기의 시작 시간을 계산합니다. (매일 정오 12시 초기화) + * + * @return 현재 물주기 주기의 시작 LocalDateTime + */ + public static LocalDateTime getStartOfCurrentWateringDay() { + LocalDateTime now = LocalDateTime.now(KST); + LocalDateTime todayNoon = now.toLocalDate().atTime(12, 0); + + if (now.isBefore(todayNoon)) { + return todayNoon.minusDays(1); // 아직 정오가 안 지났으면, 어제 정오가 시작 시간 + } else { + return todayNoon; // 정오가 지났으면, 오늘 정오가 시작 시간 + } + } + + // 향후 햇빛주기 등 다른 시간 관련 로직도 여기에 추가할 수 있습니다. + // public static LocalDateTime getStartOfCurrentSunlightDay() { ... } +}