From dd9851afc02e7541db9e7b200fb5cabde89cf23b Mon Sep 17 00:00:00 2001 From: Shinjongyun Date: Tue, 30 Sep 2025 17:04:25 +0900 Subject: [PATCH 1/5] [Feat] #10 MyPageResponse --- .../domain/user/dto/response/MyPageResponse.java | 9 +++++++++ .../domain/user/service/UserService.java | 15 +++++++++++++++ 2 files changed, 24 insertions(+) create mode 100644 src/main/java/com/WhoIsRoom/WhoIs_Server/domain/user/dto/response/MyPageResponse.java diff --git a/src/main/java/com/WhoIsRoom/WhoIs_Server/domain/user/dto/response/MyPageResponse.java b/src/main/java/com/WhoIsRoom/WhoIs_Server/domain/user/dto/response/MyPageResponse.java new file mode 100644 index 0000000..1dd161d --- /dev/null +++ b/src/main/java/com/WhoIsRoom/WhoIs_Server/domain/user/dto/response/MyPageResponse.java @@ -0,0 +1,9 @@ +package com.WhoIsRoom.WhoIs_Server.domain.user.dto.response; + +import lombok.Builder; +import lombok.Getter; + +@Getter +@Builder +public class MyPageResponse { +} diff --git a/src/main/java/com/WhoIsRoom/WhoIs_Server/domain/user/service/UserService.java b/src/main/java/com/WhoIsRoom/WhoIs_Server/domain/user/service/UserService.java index 7cc4e4d..83fdfb8 100644 --- a/src/main/java/com/WhoIsRoom/WhoIs_Server/domain/user/service/UserService.java +++ b/src/main/java/com/WhoIsRoom/WhoIs_Server/domain/user/service/UserService.java @@ -3,7 +3,9 @@ import com.WhoIsRoom.WhoIs_Server.domain.auth.dto.request.MailRequest; import com.WhoIsRoom.WhoIs_Server.domain.auth.dto.request.PasswordRequest; import com.WhoIsRoom.WhoIs_Server.domain.auth.service.MailService; +import com.WhoIsRoom.WhoIs_Server.domain.club.model.Club; import com.WhoIsRoom.WhoIs_Server.domain.user.dto.request.SignupRequest; +import com.WhoIsRoom.WhoIs_Server.domain.user.dto.response.MyPageResponse; import com.WhoIsRoom.WhoIs_Server.domain.user.model.Role; import com.WhoIsRoom.WhoIs_Server.domain.user.model.User; import com.WhoIsRoom.WhoIs_Server.domain.user.repository.UserRepository; @@ -15,6 +17,8 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.util.List; + @Slf4j @Service @RequiredArgsConstructor @@ -22,6 +26,7 @@ public class UserService { private final UserRepository userRepository; private final PasswordEncoder passwordEncoder; private final MailService mailService; + private final MemberRepositoty memberRepositoty; @Transactional public void signUp(SignupRequest request) { @@ -62,4 +67,14 @@ public void updateMyPassword(Long userId, PasswordRequest request) { } user.setPassword(passwordEncoder.encode(request.getNewPassword())); } + + @Transactional(readOnly = true) + public MyPageResponse getMyPage(Long userId) { + User user = userRepository.findById(userId) + .orElseThrow(() -> new BusinessException(ErrorCode.USER_NOT_FOUND)); + + List clubList = memberRepositoty.findByUserId(); + + + } } From 558b89a9f61e797533cbd1a8ac0a83539c396f65 Mon Sep 17 00:00:00 2001 From: Shinjongyun Date: Tue, 30 Sep 2025 17:39:35 +0900 Subject: [PATCH 2/5] =?UTF-8?q?[Feat]=20#10=20=EB=A7=88=EC=9D=B4=ED=8E=98?= =?UTF-8?q?=EC=9D=B4=EC=A7=80=20=EA=B8=B0=EB=8A=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../member/repository/MemberRepository.java | 10 +++++++++ .../user/controller/UserController.java | 13 ++++++++---- .../user/dto/response/ClubResponse.java | 21 +++++++++++++++++++ .../user/dto/response/MyPageResponse.java | 19 +++++++++++++++++ .../domain/user/service/UserService.java | 9 ++++---- .../CurrentUserIdArgumentResolver.java | 7 +++---- 6 files changed, 67 insertions(+), 12 deletions(-) create mode 100644 src/main/java/com/WhoIsRoom/WhoIs_Server/domain/member/repository/MemberRepository.java create mode 100644 src/main/java/com/WhoIsRoom/WhoIs_Server/domain/user/dto/response/ClubResponse.java diff --git a/src/main/java/com/WhoIsRoom/WhoIs_Server/domain/member/repository/MemberRepository.java b/src/main/java/com/WhoIsRoom/WhoIs_Server/domain/member/repository/MemberRepository.java new file mode 100644 index 0000000..c7d5a07 --- /dev/null +++ b/src/main/java/com/WhoIsRoom/WhoIs_Server/domain/member/repository/MemberRepository.java @@ -0,0 +1,10 @@ +package com.WhoIsRoom.WhoIs_Server.domain.member.repository; + +import com.WhoIsRoom.WhoIs_Server.domain.member.model.Member; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.List; + +public interface MemberRepository extends JpaRepository { + List findByUserId(Long userId); +} diff --git a/src/main/java/com/WhoIsRoom/WhoIs_Server/domain/user/controller/UserController.java b/src/main/java/com/WhoIsRoom/WhoIs_Server/domain/user/controller/UserController.java index 94db5b2..55a12cc 100644 --- a/src/main/java/com/WhoIsRoom/WhoIs_Server/domain/user/controller/UserController.java +++ b/src/main/java/com/WhoIsRoom/WhoIs_Server/domain/user/controller/UserController.java @@ -1,14 +1,13 @@ package com.WhoIsRoom.WhoIs_Server.domain.user.controller; import com.WhoIsRoom.WhoIs_Server.domain.user.dto.request.SignupRequest; +import com.WhoIsRoom.WhoIs_Server.domain.user.dto.response.MyPageResponse; import com.WhoIsRoom.WhoIs_Server.domain.user.service.UserService; +import com.WhoIsRoom.WhoIs_Server.global.common.resolver.CurrentUserId; import com.WhoIsRoom.WhoIs_Server.global.common.response.BaseResponse; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -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 org.springframework.web.bind.annotation.*; @Slf4j @RestController @@ -23,4 +22,10 @@ public BaseResponse signUp(@RequestBody SignupRequest request) { userService.signUp(request); return BaseResponse.ok(null); } + + @GetMapping("/myPage") + public BaseResponse getMyPage(@CurrentUserId Long userId) { + MyPageResponse response = userService.getMyPage(userId); + return BaseResponse.ok(response); + } } diff --git a/src/main/java/com/WhoIsRoom/WhoIs_Server/domain/user/dto/response/ClubResponse.java b/src/main/java/com/WhoIsRoom/WhoIs_Server/domain/user/dto/response/ClubResponse.java new file mode 100644 index 0000000..0da79c8 --- /dev/null +++ b/src/main/java/com/WhoIsRoom/WhoIs_Server/domain/user/dto/response/ClubResponse.java @@ -0,0 +1,21 @@ +package com.WhoIsRoom.WhoIs_Server.domain.user.dto.response; + +import com.WhoIsRoom.WhoIs_Server.domain.club.model.Club; +import lombok.Builder; +import lombok.Getter; + +@Getter +@Builder +public class ClubResponse { + private Long id; + private String name; + + public static ClubResponse from(Club club) { + return ClubResponse.builder() + .id(club.getId()) + .name(club.getName()) + .build(); + } + + +} diff --git a/src/main/java/com/WhoIsRoom/WhoIs_Server/domain/user/dto/response/MyPageResponse.java b/src/main/java/com/WhoIsRoom/WhoIs_Server/domain/user/dto/response/MyPageResponse.java index 1dd161d..56ef1c5 100644 --- a/src/main/java/com/WhoIsRoom/WhoIs_Server/domain/user/dto/response/MyPageResponse.java +++ b/src/main/java/com/WhoIsRoom/WhoIs_Server/domain/user/dto/response/MyPageResponse.java @@ -1,9 +1,28 @@ package com.WhoIsRoom.WhoIs_Server.domain.user.dto.response; +import com.WhoIsRoom.WhoIs_Server.domain.member.model.Member; import lombok.Builder; import lombok.Getter; +import java.util.List; + @Getter @Builder public class MyPageResponse { + private String nickname; + private List clubList; + + public static MyPageResponse from(String nickname, List memberList) { + + List clubList = memberList.stream() + .map(Member::getClub) + .distinct() + .map(ClubResponse::from) + .toList(); + + return MyPageResponse.builder() + .nickname(nickname) + .clubList(clubList) + .build(); + } } diff --git a/src/main/java/com/WhoIsRoom/WhoIs_Server/domain/user/service/UserService.java b/src/main/java/com/WhoIsRoom/WhoIs_Server/domain/user/service/UserService.java index 83fdfb8..72bcec4 100644 --- a/src/main/java/com/WhoIsRoom/WhoIs_Server/domain/user/service/UserService.java +++ b/src/main/java/com/WhoIsRoom/WhoIs_Server/domain/user/service/UserService.java @@ -4,6 +4,8 @@ import com.WhoIsRoom.WhoIs_Server.domain.auth.dto.request.PasswordRequest; import com.WhoIsRoom.WhoIs_Server.domain.auth.service.MailService; import com.WhoIsRoom.WhoIs_Server.domain.club.model.Club; +import com.WhoIsRoom.WhoIs_Server.domain.member.model.Member; +import com.WhoIsRoom.WhoIs_Server.domain.member.repository.MemberRepository; import com.WhoIsRoom.WhoIs_Server.domain.user.dto.request.SignupRequest; import com.WhoIsRoom.WhoIs_Server.domain.user.dto.response.MyPageResponse; import com.WhoIsRoom.WhoIs_Server.domain.user.model.Role; @@ -26,7 +28,7 @@ public class UserService { private final UserRepository userRepository; private final PasswordEncoder passwordEncoder; private final MailService mailService; - private final MemberRepositoty memberRepositoty; + private final MemberRepository memberRepository; @Transactional public void signUp(SignupRequest request) { @@ -73,8 +75,7 @@ public MyPageResponse getMyPage(Long userId) { User user = userRepository.findById(userId) .orElseThrow(() -> new BusinessException(ErrorCode.USER_NOT_FOUND)); - List clubList = memberRepositoty.findByUserId(); - - + List memberList = memberRepository.findByUserId(userId); + return MyPageResponse.from(user.getNickName(), memberList); } } diff --git a/src/main/java/com/WhoIsRoom/WhoIs_Server/global/common/resolver/CurrentUserIdArgumentResolver.java b/src/main/java/com/WhoIsRoom/WhoIs_Server/global/common/resolver/CurrentUserIdArgumentResolver.java index c363b4c..cd36a8c 100644 --- a/src/main/java/com/WhoIsRoom/WhoIs_Server/global/common/resolver/CurrentUserIdArgumentResolver.java +++ b/src/main/java/com/WhoIsRoom/WhoIs_Server/global/common/resolver/CurrentUserIdArgumentResolver.java @@ -1,5 +1,6 @@ package com.WhoIsRoom.WhoIs_Server.global.common.resolver; +import com.WhoIsRoom.WhoIs_Server.domain.auth.model.UserPrincipal; import com.WhoIsRoom.WhoIs_Server.domain.user.repository.UserRepository; import com.WhoIsRoom.WhoIs_Server.global.common.exception.BusinessException; import com.WhoIsRoom.WhoIs_Server.global.common.response.ErrorCode; @@ -29,9 +30,7 @@ public Object resolveArgument(MethodParameter parameter, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception { - String email = (String) SecurityContextHolder.getContext().getAuthentication().getPrincipal(); - return userRepository.findByEmail(email) - .orElseThrow(() -> new BusinessException(ErrorCode.USER_NOT_FOUND)) - .getId(); + UserPrincipal principal = (UserPrincipal) SecurityContextHolder.getContext().getAuthentication().getPrincipal(); + return principal.getUserId(); } } From 945719130ffc6cf8a7bec251debb3910d49b50fc Mon Sep 17 00:00:00 2001 From: Shinjongyun Date: Tue, 30 Sep 2025 18:20:23 +0900 Subject: [PATCH 3/5] =?UTF-8?q?[Feat]=20#10=20=EB=A7=88=EC=9D=B4=ED=8E=98?= =?UTF-8?q?=EC=9D=B4=EC=A7=80=20=EC=88=98=EC=A0=95=20=EA=B8=B0=EB=8A=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../club/repository/ClubRepository.java | 7 ++ .../member/repository/MemberRepository.java | 11 +++ .../user/dto/request/MyPageUpdateRequest.java | 14 +++ .../domain/user/service/UserService.java | 85 +++++++++++++++++++ .../global/common/response/ErrorCode.java | 3 + 5 files changed, 120 insertions(+) create mode 100644 src/main/java/com/WhoIsRoom/WhoIs_Server/domain/club/repository/ClubRepository.java create mode 100644 src/main/java/com/WhoIsRoom/WhoIs_Server/domain/user/dto/request/MyPageUpdateRequest.java diff --git a/src/main/java/com/WhoIsRoom/WhoIs_Server/domain/club/repository/ClubRepository.java b/src/main/java/com/WhoIsRoom/WhoIs_Server/domain/club/repository/ClubRepository.java new file mode 100644 index 0000000..02fb5d2 --- /dev/null +++ b/src/main/java/com/WhoIsRoom/WhoIs_Server/domain/club/repository/ClubRepository.java @@ -0,0 +1,7 @@ +package com.WhoIsRoom.WhoIs_Server.domain.club.repository; + +import com.WhoIsRoom.WhoIs_Server.domain.club.model.Club; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface ClubRepository extends JpaRepository { +} diff --git a/src/main/java/com/WhoIsRoom/WhoIs_Server/domain/member/repository/MemberRepository.java b/src/main/java/com/WhoIsRoom/WhoIs_Server/domain/member/repository/MemberRepository.java index c7d5a07..62a8f25 100644 --- a/src/main/java/com/WhoIsRoom/WhoIs_Server/domain/member/repository/MemberRepository.java +++ b/src/main/java/com/WhoIsRoom/WhoIs_Server/domain/member/repository/MemberRepository.java @@ -2,9 +2,20 @@ import com.WhoIsRoom.WhoIs_Server.domain.member.model.Member; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Modifying; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; +import java.util.Collection; import java.util.List; public interface MemberRepository extends JpaRepository { List findByUserId(Long userId); + // 현재 유저가 속한 clubId 목록만 빠르게 가져오기 + @Query("select m.club.id from Member m where m.user.id = :userId") + List findClubIdsByUserId(@Param("userId") Long userId); + + @Modifying(clearAutomatically = true, flushAutomatically = true) + @Query("delete from Member m where m.user.id = :userId and m.club.id in :clubIds") + void deleteByUserIdAndClubIdIn(@Param("userId") Long userId, @Param("clubIds") Collection clubIds); } diff --git a/src/main/java/com/WhoIsRoom/WhoIs_Server/domain/user/dto/request/MyPageUpdateRequest.java b/src/main/java/com/WhoIsRoom/WhoIs_Server/domain/user/dto/request/MyPageUpdateRequest.java new file mode 100644 index 0000000..8c6da90 --- /dev/null +++ b/src/main/java/com/WhoIsRoom/WhoIs_Server/domain/user/dto/request/MyPageUpdateRequest.java @@ -0,0 +1,14 @@ +package com.WhoIsRoom.WhoIs_Server.domain.user.dto.request; + +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.util.List; + +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class MyPageUpdateRequest { + String nickName; + List clubList; +} diff --git a/src/main/java/com/WhoIsRoom/WhoIs_Server/domain/user/service/UserService.java b/src/main/java/com/WhoIsRoom/WhoIs_Server/domain/user/service/UserService.java index 72bcec4..acd8418 100644 --- a/src/main/java/com/WhoIsRoom/WhoIs_Server/domain/user/service/UserService.java +++ b/src/main/java/com/WhoIsRoom/WhoIs_Server/domain/user/service/UserService.java @@ -4,8 +4,10 @@ import com.WhoIsRoom.WhoIs_Server.domain.auth.dto.request.PasswordRequest; import com.WhoIsRoom.WhoIs_Server.domain.auth.service.MailService; import com.WhoIsRoom.WhoIs_Server.domain.club.model.Club; +import com.WhoIsRoom.WhoIs_Server.domain.club.repository.ClubRepository; import com.WhoIsRoom.WhoIs_Server.domain.member.model.Member; import com.WhoIsRoom.WhoIs_Server.domain.member.repository.MemberRepository; +import com.WhoIsRoom.WhoIs_Server.domain.user.dto.request.MyPageUpdateRequest; import com.WhoIsRoom.WhoIs_Server.domain.user.dto.request.SignupRequest; import com.WhoIsRoom.WhoIs_Server.domain.user.dto.response.MyPageResponse; import com.WhoIsRoom.WhoIs_Server.domain.user.model.Role; @@ -19,7 +21,11 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.util.LinkedHashSet; import java.util.List; +import java.util.Objects; +import java.util.Set; +import java.util.stream.Collectors; @Slf4j @Service @@ -29,6 +35,7 @@ public class UserService { private final PasswordEncoder passwordEncoder; private final MailService mailService; private final MemberRepository memberRepository; + private final ClubRepository clubRepository; @Transactional public void signUp(SignupRequest request) { @@ -78,4 +85,82 @@ public MyPageResponse getMyPage(Long userId) { List memberList = memberRepository.findByUserId(userId); return MyPageResponse.from(user.getNickName(), memberList); } + + @Transactional + public MyPageResponse updateMyPage(Long userId, MyPageUpdateRequest request) { + + User user = userRepository.findById(userId) + .orElseThrow(() -> new BusinessException(ErrorCode.USER_NOT_FOUND)); + + updateUserNickName(user, request.getNickName()); + + updateUserClubs(user, request.getClubList()); + + List updatedMemberList = memberRepository.findByUserId(userId); + return MyPageResponse.from(user.getNickName(), updatedMemberList); + } + + private void updateUserNickName(User user, String newNickName) { + + // 변경 사항이 없으면 아무것도 하지 않음 (최적화) + if (user.getNickName().equals(newNickName)) { + return; + } + + // 닉네임 중복 검사 (자기 자신은 제외되므로 안전함) + if (userRepository.existsByNickName(newNickName)) { + throw new BusinessException(ErrorCode.USER_DUPLICATE_NICKNAME); + } + + user.setNickName(newNickName); + } + + private void updateUserClubs(User user, List newClubIdList) { + // 요청이 null이면 "변경 없음"으로 보고 그대로 리턴하고 싶다면 아래 주석 해제 + // if (newClubIdList == null) return; + + // null이면 빈 리스트로 간주 => 모두 탈퇴 처리 + Set requested = newClubIdList == null ? Set.of() + : newClubIdList.stream() + .filter(Objects::nonNull) + .collect(Collectors.toCollection(LinkedHashSet::new)); // 순서 유지 필요시 + + Long userId = user.getId(); + + // 현재 가입된 clubId 목록 + Set current = new LinkedHashSet<>(memberRepository.findClubIdsByUserId(userId)); + + // 계산: 추가/삭제 집합 + Set toAdd = new LinkedHashSet<>(requested); + toAdd.removeAll(current); + + Set toRemove = new LinkedHashSet<>(current); + toRemove.removeAll(requested); + + // 삭제 먼저 (없으면 no-op) + if (!toRemove.isEmpty()) { + memberRepository.deleteByUserIdAndClubIdIn(userId, toRemove); + } + + // 추가할 Club의 존재성 검증 + if (!toAdd.isEmpty()) { + List clubs = clubRepository.findAllById(toAdd); + + if (clubs.size() != toAdd.size()) { + // 어떤 ID는 존재X + throw new BusinessException(ErrorCode.CLUB_NOT_FOUND); + } + + // Member 엔티티 생성 + List newMembers = clubs.stream() + .map(club -> Member.builder() + .user(user) + .club(club) + .build()) + .toList(); + + // 저장 (유니크 제약 (user_id, club_id) 있어도 toAdd는 중복이 아님) + memberRepository.saveAll(newMembers); + } + } } diff --git a/src/main/java/com/WhoIsRoom/WhoIs_Server/global/common/response/ErrorCode.java b/src/main/java/com/WhoIsRoom/WhoIs_Server/global/common/response/ErrorCode.java index 21891ec..8c543e0 100644 --- a/src/main/java/com/WhoIsRoom/WhoIs_Server/global/common/response/ErrorCode.java +++ b/src/main/java/com/WhoIsRoom/WhoIs_Server/global/common/response/ErrorCode.java @@ -23,6 +23,9 @@ public enum ErrorCode{ USER_DUPLICATE_EMAIL(201, HttpStatus.BAD_REQUEST.value(), "중복된 이메일의 시용자가 있습니다."), USER_DUPLICATE_NICKNAME(202, HttpStatus.BAD_REQUEST.value(), "중복된 닉네임의 사용자가 있습니다."), + // Club + CLUB_NOT_FOUND(300, HttpStatus.NOT_FOUND.value(), "동아리를 찾을 수 없습니다."), + // Auth SECURITY_UNAUTHORIZED(600,HttpStatus.UNAUTHORIZED.value(), "인증 정보가 유효하지 않습니다"), INVALID_TOKEN_TYPE(601, HttpStatus.UNAUTHORIZED.value(), "토큰 타입이 유효하지 않습니다."), From cf3fd82376fb5ca338a3a13994d6371ae2df0a88 Mon Sep 17 00:00:00 2001 From: Shinjongyun Date: Tue, 30 Sep 2025 18:22:21 +0900 Subject: [PATCH 4/5] =?UTF-8?q?[Feat]=20#10=20UserController=20api=20?= =?UTF-8?q?=EC=97=85=EB=8D=B0=EC=9D=B4=ED=8A=B8=20api=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/user/controller/UserController.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/main/java/com/WhoIsRoom/WhoIs_Server/domain/user/controller/UserController.java b/src/main/java/com/WhoIsRoom/WhoIs_Server/domain/user/controller/UserController.java index 55a12cc..d38e165 100644 --- a/src/main/java/com/WhoIsRoom/WhoIs_Server/domain/user/controller/UserController.java +++ b/src/main/java/com/WhoIsRoom/WhoIs_Server/domain/user/controller/UserController.java @@ -1,5 +1,6 @@ package com.WhoIsRoom.WhoIs_Server.domain.user.controller; +import com.WhoIsRoom.WhoIs_Server.domain.user.dto.request.MyPageUpdateRequest; import com.WhoIsRoom.WhoIs_Server.domain.user.dto.request.SignupRequest; import com.WhoIsRoom.WhoIs_Server.domain.user.dto.response.MyPageResponse; import com.WhoIsRoom.WhoIs_Server.domain.user.service.UserService; @@ -28,4 +29,11 @@ public BaseResponse getMyPage(@CurrentUserId Long userId) { MyPageResponse response = userService.getMyPage(userId); return BaseResponse.ok(response); } + + @PatchMapping("/myPage/update") + public BaseResponse updateMyPage(@CurrentUserId Long userId, + @RequestBody MyPageUpdateRequest request) { + MyPageResponse response = userService.updateMyPage(userId, request); + return BaseResponse.ok(response); + } } From 9e4b0ef1c99287801084c271215263865293d76f Mon Sep 17 00:00:00 2001 From: Shinjongyun Date: Tue, 30 Sep 2025 19:34:14 +0900 Subject: [PATCH 5/5] =?UTF-8?q?[Refact]=20#10=20=EB=B9=84=EB=B0=80?= =?UTF-8?q?=EB=B2=88=ED=98=B8=20=EB=B3=80=EA=B2=BD=20users=20=EB=8F=84?= =?UTF-8?q?=EB=A9=94=EC=9D=B8=EC=9C=BC=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/controller/AuthController.java | 7 - .../auth/filter/JwtAuthenticationFilter.java | 3 +- .../user/controller/UserController.java | 8 + .../user/dto/request/MyPageUpdateRequest.java | 6 +- .../user/dto/response/MyPageResponse.java | 4 +- .../domain/user/service/UserService.java | 2 - .../domain/user/service/UserServiceTest.java | 141 ++++++++++++++++++ 7 files changed, 155 insertions(+), 16 deletions(-) create mode 100644 src/test/java/com/WhoIsRoom/WhoIs_Server/domain/user/service/UserServiceTest.java diff --git a/src/main/java/com/WhoIsRoom/WhoIs_Server/domain/auth/controller/AuthController.java b/src/main/java/com/WhoIsRoom/WhoIs_Server/domain/auth/controller/AuthController.java index d02073f..71ac2b0 100644 --- a/src/main/java/com/WhoIsRoom/WhoIs_Server/domain/auth/controller/AuthController.java +++ b/src/main/java/com/WhoIsRoom/WhoIs_Server/domain/auth/controller/AuthController.java @@ -55,11 +55,4 @@ public BaseResponse findPassword(@RequestBody MailRequest request) { userService.sendNewPassword(request); return BaseResponse.ok(null); } - - @PatchMapping("/password") - public BaseResponse updatePassword(@CurrentUserId Long userId, - @RequestBody PasswordRequest request) { - userService.updateMyPassword(userId, request); - return BaseResponse.ok(null); - } } diff --git a/src/main/java/com/WhoIsRoom/WhoIs_Server/domain/auth/filter/JwtAuthenticationFilter.java b/src/main/java/com/WhoIsRoom/WhoIs_Server/domain/auth/filter/JwtAuthenticationFilter.java index 0a884d9..e1ff12d 100644 --- a/src/main/java/com/WhoIsRoom/WhoIs_Server/domain/auth/filter/JwtAuthenticationFilter.java +++ b/src/main/java/com/WhoIsRoom/WhoIs_Server/domain/auth/filter/JwtAuthenticationFilter.java @@ -40,8 +40,7 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter { // 인증을 안해도 되니 토큰이 필요없는 URL들 (에러: 로그인이 필요합니다) public final static List PASS_URIS = Arrays.asList( - "/api/users/signup", - "/api/auth/**" + "/api/users/signup", "/api/auth/**" ); private static final AntPathMatcher ANT = new AntPathMatcher(); diff --git a/src/main/java/com/WhoIsRoom/WhoIs_Server/domain/user/controller/UserController.java b/src/main/java/com/WhoIsRoom/WhoIs_Server/domain/user/controller/UserController.java index d38e165..89daa37 100644 --- a/src/main/java/com/WhoIsRoom/WhoIs_Server/domain/user/controller/UserController.java +++ b/src/main/java/com/WhoIsRoom/WhoIs_Server/domain/user/controller/UserController.java @@ -1,5 +1,6 @@ package com.WhoIsRoom.WhoIs_Server.domain.user.controller; +import com.WhoIsRoom.WhoIs_Server.domain.auth.dto.request.PasswordRequest; import com.WhoIsRoom.WhoIs_Server.domain.user.dto.request.MyPageUpdateRequest; import com.WhoIsRoom.WhoIs_Server.domain.user.dto.request.SignupRequest; import com.WhoIsRoom.WhoIs_Server.domain.user.dto.response.MyPageResponse; @@ -36,4 +37,11 @@ public BaseResponse updateMyPage(@CurrentUserId Long userId, MyPageResponse response = userService.updateMyPage(userId, request); return BaseResponse.ok(response); } + + @PatchMapping("/password") + public BaseResponse updatePassword(@CurrentUserId Long userId, + @RequestBody PasswordRequest request) { + userService.updateMyPassword(userId, request); + return BaseResponse.ok(null); + } } diff --git a/src/main/java/com/WhoIsRoom/WhoIs_Server/domain/user/dto/request/MyPageUpdateRequest.java b/src/main/java/com/WhoIsRoom/WhoIs_Server/domain/user/dto/request/MyPageUpdateRequest.java index 8c6da90..d2feb6c 100644 --- a/src/main/java/com/WhoIsRoom/WhoIs_Server/domain/user/dto/request/MyPageUpdateRequest.java +++ b/src/main/java/com/WhoIsRoom/WhoIs_Server/domain/user/dto/request/MyPageUpdateRequest.java @@ -1,13 +1,13 @@ package com.WhoIsRoom.WhoIs_Server.domain.user.dto.request; -import lombok.AccessLevel; -import lombok.Getter; -import lombok.NoArgsConstructor; +import lombok.*; import java.util.List; @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) +@Builder +@AllArgsConstructor(access = AccessLevel.PRIVATE) public class MyPageUpdateRequest { String nickName; List clubList; diff --git a/src/main/java/com/WhoIsRoom/WhoIs_Server/domain/user/dto/response/MyPageResponse.java b/src/main/java/com/WhoIsRoom/WhoIs_Server/domain/user/dto/response/MyPageResponse.java index 56ef1c5..6787a42 100644 --- a/src/main/java/com/WhoIsRoom/WhoIs_Server/domain/user/dto/response/MyPageResponse.java +++ b/src/main/java/com/WhoIsRoom/WhoIs_Server/domain/user/dto/response/MyPageResponse.java @@ -9,7 +9,7 @@ @Getter @Builder public class MyPageResponse { - private String nickname; + private String nickName; private List clubList; public static MyPageResponse from(String nickname, List memberList) { @@ -21,7 +21,7 @@ public static MyPageResponse from(String nickname, List memberList) { .toList(); return MyPageResponse.builder() - .nickname(nickname) + .nickName(nickname) .clubList(clubList) .build(); } diff --git a/src/main/java/com/WhoIsRoom/WhoIs_Server/domain/user/service/UserService.java b/src/main/java/com/WhoIsRoom/WhoIs_Server/domain/user/service/UserService.java index acd8418..b238c68 100644 --- a/src/main/java/com/WhoIsRoom/WhoIs_Server/domain/user/service/UserService.java +++ b/src/main/java/com/WhoIsRoom/WhoIs_Server/domain/user/service/UserService.java @@ -116,8 +116,6 @@ private void updateUserNickName(User user, String newNickName) { } private void updateUserClubs(User user, List newClubIdList) { - // 요청이 null이면 "변경 없음"으로 보고 그대로 리턴하고 싶다면 아래 주석 해제 - // if (newClubIdList == null) return; // null이면 빈 리스트로 간주 => 모두 탈퇴 처리 Set requested = newClubIdList == null ? Set.of() diff --git a/src/test/java/com/WhoIsRoom/WhoIs_Server/domain/user/service/UserServiceTest.java b/src/test/java/com/WhoIsRoom/WhoIs_Server/domain/user/service/UserServiceTest.java new file mode 100644 index 0000000..dd3aed4 --- /dev/null +++ b/src/test/java/com/WhoIsRoom/WhoIs_Server/domain/user/service/UserServiceTest.java @@ -0,0 +1,141 @@ +package com.WhoIsRoom.WhoIs_Server.domain.user.service; + +import com.WhoIsRoom.WhoIs_Server.domain.club.model.Club; +import com.WhoIsRoom.WhoIs_Server.domain.club.repository.ClubRepository; +import com.WhoIsRoom.WhoIs_Server.domain.member.model.Member; +import com.WhoIsRoom.WhoIs_Server.domain.member.repository.MemberRepository; +import com.WhoIsRoom.WhoIs_Server.domain.user.dto.request.MyPageUpdateRequest; +import com.WhoIsRoom.WhoIs_Server.domain.user.dto.response.MyPageResponse; +import com.WhoIsRoom.WhoIs_Server.domain.user.model.User; +import com.WhoIsRoom.WhoIs_Server.domain.user.repository.UserRepository; + +import lombok.extern.slf4j.Slf4j; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.ArgumentMatchers; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.anyCollection; +import static org.mockito.Mockito.when; + +@Slf4j +@ExtendWith(MockitoExtension.class) +class UserServiceTest { + + @Mock private UserRepository userRepository; + @Mock private ClubRepository clubRepository; + @Mock private MemberRepository memberRepository; + + @InjectMocks + private UserService userService; + + private User user; + private List clubs; + + @BeforeEach + void setUp() { + System.out.println("\n[TEST] ========== setUp =========="); + user = User.builder() + .nickName("조익성") + .email("konkuk@gmail.com") + .password("1234") + .build(); + user.setId(1L); + + Club club1 = Club.builder().name("메이커스팜").build(); club1.setId(1L); + Club club2 = Club.builder().name("목방").build(); club2.setId(2L); + Club club3 = Club.builder().name("건대교지편집위원회").build(); club3.setId(3L); + Club club4 = Club.builder().name("국어국문학과").build(); club4.setId(4L); + + clubs = List.of(club1, club2, club3, club4); + + System.out.println("[TEST] userId=" + user.getId() + ", nick=" + user.getNickName()); + System.out.println("[TEST] clubs=" + clubs.stream() + .map(c -> c.getId() + ":" + c.getName()).toList()); + System.out.println("[TEST] =============================\n"); + } + + @Test + @DisplayName("닉네임과 클럽 목록을 업데이트하고 응답 DTO를 반환한다") + void updateMyPage_success() { + Long userId = user.getId(); + + MyPageUpdateRequest request = MyPageUpdateRequest.builder() + .nickName("조익성") + .clubList(List.of(1L, 2L, 3L, 4L)) + .build(); + + // --- 스텁 + 로그 --- + when(userRepository.findById(userId)) + .thenAnswer(inv -> { + System.out.println("[TEST] userRepository.findById(" + userId + ")"); + return Optional.of(user); + }); + + when(memberRepository.findClubIdsByUserId(userId)) + .thenAnswer(inv -> { + System.out.println("[TEST] memberRepository.findClubIdsByUserId(" + userId + ") -> [2]"); + return List.of(2L); + }); + + when(clubRepository.findAllById(ArgumentMatchers.anyIterable())) + .thenAnswer(invocation -> { + Iterable ids = invocation.getArgument(0); + List idList = new ArrayList<>(); + ids.forEach(idList::add); + System.out.println("[TEST] clubRepository.findAllById called with ids=" + idList); + var result = clubs.stream() + .filter(c -> idList.contains(c.getId())) + .collect(Collectors.toList()); + System.out.println("[TEST] clubRepository.findAllById returns ids=" + + result.stream().map(Club::getId).toList()); + return result; + }); + + when(memberRepository.saveAll(anyCollection())) + .thenAnswer(invocation -> { + @SuppressWarnings("unchecked") + var c = (java.util.Collection) invocation.getArgument(0); + System.out.println("[TEST] memberRepository.saveAll called size=" + c.size() + + ", clubIds=" + c.stream().map(m -> m.getClub().getId()).toList()); + return new ArrayList<>(c); + }); + + when(memberRepository.findByUserId(userId)) + .thenAnswer(inv -> { + System.out.println("[TEST] memberRepository.findByUserId(" + userId + ")"); + var list = clubs.stream() + .map(c -> Member.builder().user(user).club(c).build()) + .collect(Collectors.toList()); + System.out.println("[TEST] memberRepository.findByUserId returns clubIds=" + + list.stream().map(m -> m.getClub().getId()).toList()); + return list; + }); + + // --- 실행 --- + System.out.println("\n[TEST] ===== call userService.updateMyPage ====="); + MyPageResponse response = userService.updateMyPage(userId, request); + System.out.println("[TEST] ===== returned MyPageResponse ====="); + System.out.println("[TEST] resp.nick=" + response.getNickName()); + System.out.println("[TEST] resp.clubs=" + response.getClubList().stream() + .map(c -> c.getId() + ":" + c.getName()).toList()); + System.out.println("[TEST] ===================================\n"); + + // --- 검증 --- + assertThat(response.getNickName()).isEqualTo("조익성"); + assertThat(response.getClubList()).hasSize(4); + assertThat(response.getClubList()) + .extracting("name") + .containsExactlyInAnyOrder("메이커스팜", "목방", "건대교지편집위원회", "국어국문학과"); + } +}