From bdbb4b37966aa8f8b10a596547e68b8dfa1212a2 Mon Sep 17 00:00:00 2001 From: Be-HinD Date: Sat, 13 Dec 2025 20:38:05 +0900 Subject: [PATCH] =?UTF-8?q?:recycle:refactor:=20=EC=9C=A0=EC=A0=80=20?= =?UTF-8?q?=ED=94=84=EB=A1=9C=ED=95=84=20=EC=A1=B0=ED=9A=8C=20API=20?= =?UTF-8?q?=EB=A6=AC=ED=8C=A9=ED=86=A0=EB=A7=81=20-=20=EB=A1=9C=EA=B7=B8?= =?UTF-8?q?=EC=9D=B8/=EB=B9=84=EB=A1=9C=EA=B7=B8=EC=9D=B8=EC=97=90=20?= =?UTF-8?q?=EB=94=B0=EB=A5=B8=20=EC=9D=91=EB=8B=B5=20=EB=B6=84=EA=B8=B0=20?= =?UTF-8?q?=EC=B2=98=EB=A6=AC=20-=20=ED=8C=94=EB=A1=9C=EC=9A=B0=20?= =?UTF-8?q?=EC=97=AC=EB=B6=80=20=ED=95=84=EB=93=9C=20=EC=B6=94=EA=B0=80=20?= =?UTF-8?q?=EB=B0=8F=20=EB=A1=9C=EC=A7=81=20=EC=A0=81=EC=9A=A9=20-=20?= =?UTF-8?q?=ED=8C=94=EB=A1=9C=EC=9A=B0=20=EB=A6=AC=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=20transactional(readOnly)=20=EC=A0=81?= =?UTF-8?q?=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../user/application/FollowService.java | 3 +- .../user/application/UserService.java | 20 +++++++++++-- .../dto/response/UserInfoResponse.java | 20 +++++++++++++ .../user/presentation/UserController.java | 28 +++++++++++-------- .../user/presentation/UserControllerDocs.java | 9 ++++-- src/test/http/user/user-api.http | 8 ++++-- 6 files changed, 69 insertions(+), 19 deletions(-) diff --git a/src/main/java/team/wego/wegobackend/user/application/FollowService.java b/src/main/java/team/wego/wegobackend/user/application/FollowService.java index ff68cca..c4b0986 100644 --- a/src/main/java/team/wego/wegobackend/user/application/FollowService.java +++ b/src/main/java/team/wego/wegobackend/user/application/FollowService.java @@ -72,9 +72,10 @@ public void unFollow(String unFollowNickname, Long followerId) { follow.decreaseFollowerCount(); } + @Transactional(readOnly = true) public FollowListResponse followList(Long userId, Long cursor, Integer size) { - if(!userRepository.existsById(userId)) { + if (!userRepository.existsById(userId)) { throw new UserNotFoundException(); } diff --git a/src/main/java/team/wego/wegobackend/user/application/UserService.java b/src/main/java/team/wego/wegobackend/user/application/UserService.java index cb63ed1..d1ff0fd 100644 --- a/src/main/java/team/wego/wegobackend/user/application/UserService.java +++ b/src/main/java/team/wego/wegobackend/user/application/UserService.java @@ -15,6 +15,7 @@ import team.wego.wegobackend.user.domain.User; import team.wego.wegobackend.user.exception.SameNicknameException; import team.wego.wegobackend.user.exception.UserNotFoundException; +import team.wego.wegobackend.user.repository.FollowRepository; import team.wego.wegobackend.user.repository.UserRepository; @Slf4j @@ -24,14 +25,27 @@ public class UserService { private final UserRepository userRepository; + private final FollowRepository followRepository; private final ImageUploadService imageUploadService; @Transactional(readOnly = true) - public UserInfoResponse getProfile(Long userId) { + public UserInfoResponse getProfile(Long loginUserId, Long targetUserId) { - User user = userRepository.findById(userId).orElseThrow(UserNotFoundException::new); + User targetUser = userRepository.findById(targetUserId) + .orElseThrow(UserNotFoundException::new); - return UserInfoResponse.from(user); + // 비로그인 or 본인 조회 + if (loginUserId == null || loginUserId.equals(targetUserId)) { + return UserInfoResponse.from(targetUser); + } + + User loginUser = userRepository.findById(loginUserId) + .orElseThrow(UserNotFoundException::new); + + boolean isFollow = followRepository.existsByFollowerIdAndFolloweeId(loginUserId, + targetUserId); + + return UserInfoResponse.from(targetUser, isFollow); } public UserInfoResponse updateProfileImage(Long userId, MultipartFile file) { diff --git a/src/main/java/team/wego/wegobackend/user/application/dto/response/UserInfoResponse.java b/src/main/java/team/wego/wegobackend/user/application/dto/response/UserInfoResponse.java index 7fb54e6..58b6a99 100644 --- a/src/main/java/team/wego/wegobackend/user/application/dto/response/UserInfoResponse.java +++ b/src/main/java/team/wego/wegobackend/user/application/dto/response/UserInfoResponse.java @@ -37,6 +37,8 @@ public class UserInfoResponse { private Boolean isNotificationEnabled; + private Boolean isFollow; + private LocalDateTime createdAt; public static UserInfoResponse from(User user) { @@ -55,4 +57,22 @@ public static UserInfoResponse from(User user) { .createdAt(user.getCreatedAt()) .build(); } + + public static UserInfoResponse from(User user, Boolean isFollow) { + return UserInfoResponse.builder() + .userId(user.getId()) + .email(user.getEmail()) + .nickName(user.getNickName()) + .mbti(user.getMbti()) + .profileImage(user.getProfileImage()) + .profileMessage(user.getProfileMessage()) + .followeesCnt(user.getFolloweesCnt()) + .followersCnt(user.getFollowersCnt()) + .groupJoinedCnt(user.getGroupJoinedCnt()) + .groupCreatedCnt(user.getGroupCreatedCnt()) + .isNotificationEnabled(user.getNotificationEnabled()) + .isFollow(isFollow) + .createdAt(user.getCreatedAt()) + .build(); + } } diff --git a/src/main/java/team/wego/wegobackend/user/presentation/UserController.java b/src/main/java/team/wego/wegobackend/user/presentation/UserController.java index 582211e..7ccd62b 100644 --- a/src/main/java/team/wego/wegobackend/user/presentation/UserController.java +++ b/src/main/java/team/wego/wegobackend/user/presentation/UserController.java @@ -42,11 +42,17 @@ public class UserController implements UserControllerDocs { /** * 프로필 조회 - * */ + */ @GetMapping("/{userId}") - public ResponseEntity> profile(@PathVariable Long userId) { + public ResponseEntity> profile( + @AuthenticationPrincipal CustomUserDetails userDetails, + @PathVariable Long userId + ) { - UserInfoResponse response = userService.getProfile(userId); + UserInfoResponse response = userService.getProfile( + userDetails == null ? null : userDetails.getId(), + userId + ); return ResponseEntity .status(HttpStatus.OK) @@ -56,7 +62,7 @@ public ResponseEntity> profile(@PathVariable Long /** * 프로필 이미지 변경 - * */ + */ @PatchMapping(value = "/profile-image", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) public ResponseEntity> profileImage( @AuthenticationPrincipal CustomUserDetails userDetails, @@ -72,7 +78,7 @@ public ResponseEntity> profileImage( /** * 프로필 정보 변경 - * */ + */ @PatchMapping("/profile") public ResponseEntity> profileInfo( @AuthenticationPrincipal CustomUserDetails userDetails, @@ -88,7 +94,7 @@ public ResponseEntity> profileInfo( /** * 알림 설정 변경 - * */ + */ @PatchMapping("/notification") public ResponseEntity> changeNotificationConfig( @AuthenticationPrincipal CustomUserDetails userDetails, @@ -105,7 +111,7 @@ public ResponseEntity> changeNotificationConfig( /** * 팔로우 요청 - * */ + */ @PostMapping("/follow") public ResponseEntity> follow( @AuthenticationPrincipal CustomUserDetails userDetails, @@ -121,7 +127,7 @@ public ResponseEntity> follow( /** * 팔로우 취소 - * */ + */ @DeleteMapping("/unfollow") public ResponseEntity> unFollow( @AuthenticationPrincipal CustomUserDetails userDetails, @@ -137,7 +143,7 @@ public ResponseEntity> unFollow( /** * 팔로우 리스트 조회 - * */ + */ @GetMapping("/{userId}/follow") public ResponseEntity> followList( @PathVariable Long userId, //다른 유저 조회를 위한 파라메터 @@ -154,7 +160,7 @@ public ResponseEntity> followList( /** * 이메일 중복검사 - * */ + */ @GetMapping("/email/availability") public ResponseEntity> checkEmailAvailability( @RequestParam("email") String email @@ -169,7 +175,7 @@ public ResponseEntity> checkEmailAvailability( /** * 닉네임 중복검사 - * */ + */ @GetMapping("/nickname/availability") public ResponseEntity> checkNicknameAvailability( @RequestParam("nickname") String nickname diff --git a/src/main/java/team/wego/wegobackend/user/presentation/UserControllerDocs.java b/src/main/java/team/wego/wegobackend/user/presentation/UserControllerDocs.java index da5b21a..461b7dc 100644 --- a/src/main/java/team/wego/wegobackend/user/presentation/UserControllerDocs.java +++ b/src/main/java/team/wego/wegobackend/user/presentation/UserControllerDocs.java @@ -23,8 +23,13 @@ @Tag(name = "유저 API", description = "유저와 관련된 API 리스트 \uD83D\uDC08") public interface UserControllerDocs { - @Operation(summary = "유저 프로필 조회 API", description = "PathVariable로 들어온 userId에 해당하는 유저 프로필에 대한 응답") - ResponseEntity> profile(@PathVariable Long userId); + @Operation(summary = "유저 프로필 조회 API", description = + "PathVariable로 들어온 userId에 해당하는 유저 프로필에 대한 응답 \n" + + "로그인 여부/본인 여부에 따라 팔로우 여부를 null 혹은 true/false로 응답합니다.") + ResponseEntity> profile( + @AuthenticationPrincipal CustomUserDetails userDetails, + @PathVariable Long userId + ); @Operation(summary = "프로필 이미지 변경 API", description = "토큰 주인장 이미지만 변경 가능합니다.") ResponseEntity> profileImage( diff --git a/src/test/http/user/user-api.http b/src/test/http/user/user-api.http index 4231722..ad185ca 100644 --- a/src/test/http/user/user-api.http +++ b/src/test/http/user/user-api.http @@ -21,10 +21,14 @@ Content-Type: application/json client.global.set("accessToken", response.body.data.accessToken); %} -### 유저 정보 조회 +### 유저 정보 조회 (로그인) GET http://localhost:8080/api/v1/users/1 Authorization: Bearer {{accessToken}} +### 유저 정보 조회 (비로그인) +GET http://localhost:8080/api/v1/users/1 + + ### 유저 프로필 이미지 변경 PATCH http://localhost:8080/api/v1/users/profile-image Authorization: Bearer {{accessToken}} @@ -64,7 +68,7 @@ Content-Type: application/json } ### 팔로우 요청 -POST http://localhost:8080/api/v1/users/follow?followNickname=팔로우 대상 +POST http://localhost:8080/api/v1/users/follow?followNickname=user0 Authorization: Bearer {{accessToken}} ### 팔로우 취소