From 208863a3715274abc9a3554fab16b5b0add3d122 Mon Sep 17 00:00:00 2001 From: JangIkhwan Date: Sat, 3 Jan 2026 16:19:53 +0900 Subject: [PATCH 01/28] =?UTF-8?q?[Feat!]=20#159=20=ED=94=84=EB=A1=9C?= =?UTF-8?q?=ED=95=84=20=EC=88=98=EC=A0=95=20API=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - BREAKING CHANGE : 프로필 수정 API를 삭제. 프론트에서는 프로필 수정 기능을 제거해야함 --- .../domain/user/controller/UserController.java | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/src/main/java/com/kuit/findyou/domain/user/controller/UserController.java b/src/main/java/com/kuit/findyou/domain/user/controller/UserController.java index 91d49d89..ed75644c 100644 --- a/src/main/java/com/kuit/findyou/domain/user/controller/UserController.java +++ b/src/main/java/com/kuit/findyou/domain/user/controller/UserController.java @@ -142,21 +142,6 @@ public BaseResponse deleteInterestAnimal(@Parameter(hidden = true) @LoginU return BaseResponse.ok(null); } - @Operation( - summary = "프로필 이미지 변경 API", - description = "프로필 이미지 변경을 수행합니다. 기본이미지는 enum값 이름으로 저장, 사용자 업로드 이미지는 cdn url로 저장됩니다." - ) - @CustomExceptionDescription(CHANGE_PROFILE_IMAGE) - @PreAuthorize("hasRole('ROLE_USER')") - @PatchMapping(value = "/me/profile-image", consumes = MULTIPART_FORM_DATA_VALUE) - public BaseResponse changeProfileImage( - @LoginUserId Long userId, - @Valid @ModelAttribute ChangeProfileImageRequest req - ) { - userServiceFacade.changeProfileImage(userId, req); - return BaseResponse.ok(null); - } - @Operation( summary = "신고 내역 조회 API", description = """ From 24630a06966b479d59f6a99bbd3e22e6cdc699a8 Mon Sep 17 00:00:00 2001 From: JangIkhwan Date: Sun, 4 Jan 2026 20:15:23 +0900 Subject: [PATCH 02/28] =?UTF-8?q?[Test]=20#159=20=ED=94=84=EB=A1=9C?= =?UTF-8?q?=ED=95=84=20=EC=88=98=EC=A0=95=20API=20=EA=B4=80=EB=A0=A8=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=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 --- .../user/controller/UserControllerTest.java | 218 ------------------ 1 file changed, 218 deletions(-) diff --git a/src/test/java/com/kuit/findyou/domain/user/controller/UserControllerTest.java b/src/test/java/com/kuit/findyou/domain/user/controller/UserControllerTest.java index 53751a44..ca415431 100644 --- a/src/test/java/com/kuit/findyou/domain/user/controller/UserControllerTest.java +++ b/src/test/java/com/kuit/findyou/domain/user/controller/UserControllerTest.java @@ -497,116 +497,6 @@ void shouldSucceedToDeleteInterestAnimal_WhenItDoesNotExist() { assertThat(interestReportRepository.existsByReportIdAndUserId(report.getId(), user.getId())).isFalse(); } - @Test - @DisplayName("기본 이미지로 변경 성공") - void changeProfileImage_Default_Success() { - // given - User user = testInitializer.createTestUser(); - String token = jwtUtil.createAccessJwt(user.getId(), user.getRole()); - - // when & then - given() - .header("Authorization", "Bearer " + token) - .contentType(ContentType.MULTIPART) - .multiPart(multipartText("defaultProfileImageName", "chick")) - .when() - .patch("/api/v2/users/me/profile-image") - .then() - .statusCode(200) - .body("code", equalTo(SUCCESS.getCode())) - .body("message", equalTo(SUCCESS.getMessage())) - .body("data", nullValue()); - - User updated = userRepository.findById(user.getId()).orElseThrow(); - assertThat(updated.getProfileImageUrl()).isEqualTo("chick"); - } - - @Test - @DisplayName("파일 업로드로 변경 성공") - void changeProfileImage_File_Success() { - // given - User user = testInitializer.createTestUser(); - String token = jwtUtil.createAccessJwt(user.getId(), user.getRole()); - - // when & then - given() - .header("Authorization", "Bearer " + token) - .contentType(ContentType.MULTIPART) - .multiPart("profileImageFile", "p.jpg", "fake".getBytes(), "image/jpeg") - .when() - .patch("/api/v2/users/me/profile-image") - .then() - .statusCode(200) - .body("code", equalTo(SUCCESS.getCode())) - .body("message", equalTo(SUCCESS.getMessage())) - .body("data", nullValue()); - - User updated = userRepository.findById(user.getId()).orElseThrow(); - assertThat(updated.getProfileImageUrl()).startsWith("base-url"); - assertThat(updated.getProfileImageUrl()).endsWith("_p.jpg"); - } - - @Test - @DisplayName("둘 다 제공(파일+기본명) → 400") - void changeProfileImage_BothProvided_BadRequest() { - // given - User user = testInitializer.createTestUser(); - String token = jwtUtil.createAccessJwt(user.getId(), user.getRole()); - - given() - .header("Authorization", "Bearer " + token) - .contentType(ContentType.MULTIPART) - .multiPart(multipartText("defaultProfileImageName", "puppy")) - .multiPart("profileImageFile", "p.jpg", "fake".getBytes(), "image/jpeg") - .when() - .patch("/api/v2/users/me/profile-image") - .then() - .statusCode(200) - .body("success", equalTo(false)) - .body("code", equalTo(400)) - .body("message", equalTo("Invalid request")); - } - - @Test - @DisplayName("둘 다 제공 X → 400") - void changeProfileImage_NoneProvided_BadRequest() { - // given - User user = testInitializer.createTestUser(); - String token = jwtUtil.createAccessJwt(user.getId(), user.getRole()); - - given() - .header("Authorization", "Bearer " + token) - .contentType(ContentType.MULTIPART) - .multiPart("dummy", "dummy") - .when() - .patch("/api/v2/users/me/profile-image") - .then() - .statusCode(200) - .body("success", equalTo(false)) - .body("code", equalTo(400)) - .body("message", equalTo("Invalid request")); - } - - @Test - @DisplayName("잘못된 기본이미지 이름 → 400") - void changeProfileImage_InvalidDefaultName_BadRequest() { - // given - User user = testInitializer.createTestUser(); - String token = jwtUtil.createAccessJwt(user.getId(), user.getRole()); - - given() - .header("Authorization", "Bearer " + token) - .contentType(ContentType.MULTIPART) - .multiPart(multipartText("defaultProfileImageName", "cat")) - .when() - .patch("/api/v2/users/me/profile-image") - .then() - .statusCode(200) - .body("success", equalTo(false)) - .body("code", equalTo(BAD_REQUEST.getCode())) - .body("message", equalTo("Invalid request")); - } - @Test @DisplayName("사용자가 신고한 내역이 있다면 리턴한다.") void shouldReturnUserReports_WhenTheyExist() { @@ -687,93 +577,6 @@ void shouldReturnProfile_WhenUserExists() { // then assertThat(response.nickname()).isEqualTo(nickname); - assertThat(response.profileImage()).isEqualTo(profileImage); - } - - @Test - @DisplayName("프로필 이미지 변경 후, 마이페이지 조회 시 변경된 URL이 반환") - void changeProfileImage_and_VerifyWithMypageApi() { - User user = testInitializer.createTestUser(); - String token = jwtUtil.createAccessJwt(user.getId(), user.getRole()); - - when(s3Client.putObject(any(PutObjectRequest.class), any(RequestBody.class))) - .thenReturn(PutObjectResponse.builder().build()); - - // === 프로필 이미지 변경 API 호출 === - given() - .header("Authorization", "Bearer " + token) - .contentType(ContentType.MULTIPART) - .multiPart("profileImageFile", "p.jpg", "fake".getBytes(), "image/jpeg") - .when() - .patch("/api/v2/users/me/profile-image") - .then() - .statusCode(200) - .body("success", equalTo(true)); - - // === 마이페이지 조회 API 호출 === - String profileImageUrl = given() - .header("Authorization", "Bearer " + token) - .when() - .get("/api/v2/users/me") // 마이페이지 조회 API - .then() - .log().all() - .statusCode(200) - .extract() - .jsonPath() - .getString("data.profileImage"); - - // === 반환된 URL이 CDN 주소 형식을 따르는지 확인 === - assertThat(profileImageUrl).startsWith("base-url"); - } - - @Test - @DisplayName("프로필 - 기본이미지 -> 업로드 변경 시, 삭제 호출 없음") - void changeProfileImage_DefaultToUploaded_NoDelete() { - User user = testInitializer.createUserWithDefaultProfileImage(PUPPY); - - String token = jwtUtil.createAccessJwt(user.getId(), user.getRole()); - - when(s3Client.putObject(any(PutObjectRequest.class), any(RequestBody.class))) - .thenReturn(PutObjectResponse.builder().build()); - - given() - .header("Authorization", "Bearer " + token) - .contentType(ContentType.MULTIPART) - .multiPart("profileImageFile", "p.jpg", "fake".getBytes(), "image/jpeg") - .when() - .patch("/api/v2/users/me/profile-image") - .then() - .statusCode(200) - .body("success", equalTo(true)); - - verify(s3Client, times(0)).deleteObject(any(DeleteObjectRequest.class)); - } - - @Test - @DisplayName("프로필 - 업로드된 파일 -> 새 업로드 변경 시, 기존 파일 삭제 호출됨") - void changeProfileImage_FileToFile_DeleteOldFile() { - // given - //기존 프로필 이미지 존재 - User user = testInitializer.createUserWithUploadedProfileImage("base-url/old_profile.jpg"); - String token = jwtUtil.createAccessJwt(user.getId(), user.getRole()); - - when(s3Client.putObject(any(PutObjectRequest.class), any(RequestBody.class))) - .thenReturn(PutObjectResponse.builder().build()); - - // when - //새 프로필 업로드 - given() - .header("Authorization", "Bearer " + token) - .contentType(ContentType.MULTIPART) - .multiPart("profileImageFile", "new.jpg", "fake".getBytes(), "image/jpeg") - .when() - .patch("/api/v2/users/me/profile-image") - .then() - .statusCode(200) - .body("success", equalTo(true)); - - // then - verify(s3Client, times(1)).deleteObject(any(DeleteObjectRequest.class)); } @Test @@ -869,27 +672,6 @@ void shouldDenyRequest_WhenGuestDeletesAccount(){ .body("message", equalTo(FORBIDDEN.getMessage())); } - @Test - @DisplayName("비회원은 프로필 이미지를 변경할 수 없다") - void shouldDenyRequest_WhenGuestChangesProfileImage() { - // given - User guest = testInitializer.createTestGuest(); - String token = jwtUtil.createAccessJwt(guest.getId(), guest.getRole()); - - // when & then - given() - .header("Authorization", "Bearer " + token) - .contentType(ContentType.MULTIPART) - .multiPart(multipartText("defaultProfileImageName", "chick")) - .when() - .patch("/api/v2/users/me/profile-image") - .then() - .statusCode(403) - .body("success", equalTo(FORBIDDEN.getSuccess())) - .body("code", equalTo(FORBIDDEN.getCode())) - .body("message", equalTo(FORBIDDEN.getMessage())); - } - @Test @DisplayName("게스트는 게스트로 조회된다") void checkGuest_shouldReturnTrue_WhenGuest() { From bcc35d541c39c4d42ebab7981891118bafb0fe7e Mon Sep 17 00:00:00 2001 From: JangIkhwan Date: Sun, 4 Jan 2026 20:15:56 +0900 Subject: [PATCH 03/28] =?UTF-8?q?[Feat]=20#159=20UserServiceFacade?= =?UTF-8?q?=EC=97=90=EC=84=9C=20changeProfileImage=20=EB=A9=94=EC=84=9C?= =?UTF-8?q?=EB=93=9C=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/user/service/facade/UserServiceFacade.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/main/java/com/kuit/findyou/domain/user/service/facade/UserServiceFacade.java b/src/main/java/com/kuit/findyou/domain/user/service/facade/UserServiceFacade.java index 324cd754..8136655c 100644 --- a/src/main/java/com/kuit/findyou/domain/user/service/facade/UserServiceFacade.java +++ b/src/main/java/com/kuit/findyou/domain/user/service/facade/UserServiceFacade.java @@ -3,13 +3,11 @@ import com.kuit.findyou.domain.report.dto.response.CardResponseDTO; import com.kuit.findyou.domain.user.dto.response.CheckGuestResponse; import com.kuit.findyou.domain.user.dto.response.GetUserProfileResponse; -import com.kuit.findyou.domain.user.dto.request.ChangeProfileImageRequest; import com.kuit.findyou.domain.user.dto.request.CheckDuplicateNicknameRequest; import com.kuit.findyou.domain.user.dto.request.RegisterUserRequest; import com.kuit.findyou.domain.user.dto.response.CheckDuplicateNicknameResponse; import com.kuit.findyou.domain.user.dto.response.RegisterUserResponse; import com.kuit.findyou.domain.user.service.change_nickname.ChangeNicknameService; -import com.kuit.findyou.domain.user.service.change_profileImage.ChangeProfileImageService; import com.kuit.findyou.domain.user.service.delete.DeleteUserService; import com.kuit.findyou.domain.user.service.interest_report.InterestReportService; import com.kuit.findyou.domain.user.service.query.QueryUserService; @@ -28,7 +26,6 @@ public class UserServiceFacade { private final QueryUserService queryUserService; private final ChangeNicknameService changeNicknameService; private final DeleteUserService deleteUserService; - private final ChangeProfileImageService changeProfileImageService; private final UserReportService userReportService; public CardResponseDTO retrieveViewedAnimals(Long lastId, Long userId) { @@ -63,8 +60,6 @@ public void deleteUser(Long userId) { deleteUserService.deleteUser(userId); } - public void changeProfileImage(Long userId, ChangeProfileImageRequest request){ changeProfileImageService.changeProfileImage(userId, request); } - public CardResponseDTO retrieveUserReports(Long userId, Long lastId){ return userReportService.retrieveUserReports(userId, lastId, 20); } From 7915494d3798154f3ffeecde7e03abee99af6441 Mon Sep 17 00:00:00 2001 From: JangIkhwan Date: Sun, 4 Jan 2026 20:16:22 +0900 Subject: [PATCH 04/28] =?UTF-8?q?[Feat]=20#159=20=ED=94=84=EB=A1=9C?= =?UTF-8?q?=ED=95=84=20=EC=88=98=EC=A0=95=20=EC=84=9C=EB=B9=84=EC=8A=A4=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ChangeProfileImageService.java | 7 -- .../ChangeProfileImageServiceImpl.java | 75 ------------------- 2 files changed, 82 deletions(-) delete mode 100644 src/main/java/com/kuit/findyou/domain/user/service/change_profileImage/ChangeProfileImageService.java delete mode 100644 src/main/java/com/kuit/findyou/domain/user/service/change_profileImage/ChangeProfileImageServiceImpl.java diff --git a/src/main/java/com/kuit/findyou/domain/user/service/change_profileImage/ChangeProfileImageService.java b/src/main/java/com/kuit/findyou/domain/user/service/change_profileImage/ChangeProfileImageService.java deleted file mode 100644 index bf093d26..00000000 --- a/src/main/java/com/kuit/findyou/domain/user/service/change_profileImage/ChangeProfileImageService.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.kuit.findyou.domain.user.service.change_profileImage; - -import com.kuit.findyou.domain.user.dto.request.ChangeProfileImageRequest; - -public interface ChangeProfileImageService { - void changeProfileImage(Long userId, ChangeProfileImageRequest request); -} diff --git a/src/main/java/com/kuit/findyou/domain/user/service/change_profileImage/ChangeProfileImageServiceImpl.java b/src/main/java/com/kuit/findyou/domain/user/service/change_profileImage/ChangeProfileImageServiceImpl.java deleted file mode 100644 index f3a2d885..00000000 --- a/src/main/java/com/kuit/findyou/domain/user/service/change_profileImage/ChangeProfileImageServiceImpl.java +++ /dev/null @@ -1,75 +0,0 @@ -package com.kuit.findyou.domain.user.service.change_profileImage; - -import com.kuit.findyou.domain.user.constant.DefaultProfileImage; -import com.kuit.findyou.domain.user.dto.request.ChangeProfileImageRequest; -import com.kuit.findyou.domain.user.model.User; -import com.kuit.findyou.domain.user.repository.UserRepository; -import com.kuit.findyou.global.common.exception.CustomException; -import com.kuit.findyou.global.infrastructure.FileUploadingFailedException; -import com.kuit.findyou.global.infrastructure.ImageUploader; -import jakarta.persistence.EntityNotFoundException; -import jakarta.transaction.Transactional; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; - -import java.net.URI; -import java.net.URISyntaxException; -import java.util.Arrays; - -import static com.kuit.findyou.global.common.response.status.BaseExceptionResponseStatus.*; - -@Slf4j -@Service -@RequiredArgsConstructor -public class ChangeProfileImageServiceImpl implements ChangeProfileImageService { - private final UserRepository userRepository; - private final ImageUploader imageUploader; - - - @Override - @Transactional - public void changeProfileImage(Long userId, ChangeProfileImageRequest request) { - try { - User user = userRepository.getReferenceById(userId); - - String toSave; - if (request.profileImageFile() != null) { - try { - toSave = imageUploader.upload(request.profileImageFile()); - } catch (FileUploadingFailedException e) { - throw new CustomException(IMAGE_UPLOAD_FAILED); - } - } else { - //enum 이름을 소문자로 저장 - toSave = Arrays.stream(DefaultProfileImage.values()) - .filter(v -> v.getName().equalsIgnoreCase(request.defaultProfileImageName())) - .findFirst() - .orElseThrow(() -> new CustomException(BAD_REQUEST)) - .getName(); - } - String oldImageUrl = user.getProfileImageUrl(); - user.changeProfileImage(toSave); - if (isUploadedFile(oldImageUrl)) { - String imageKey = extractImageKeyFromUrl(oldImageUrl); - imageUploader.delete(imageKey); - } - }catch (EntityNotFoundException e) { - throw new CustomException(USER_NOT_FOUND); - } - } - - private boolean isUploadedFile(String url) { - if (url == null) return false; - return Arrays.stream(DefaultProfileImage.values()) - .noneMatch(defaultImage -> defaultImage.getName().equalsIgnoreCase(url)); - } - - private String extractImageKeyFromUrl(String url) { - try { - return new URI(url).getPath().substring(1); - } catch (URISyntaxException e) { - throw new CustomException(BAD_REQUEST); - } - } -} From b429e266b639fa3ee1a818bd4858942bc936f1db Mon Sep 17 00:00:00 2001 From: JangIkhwan Date: Sun, 4 Jan 2026 20:16:31 +0900 Subject: [PATCH 05/28] =?UTF-8?q?[Test]=20#159=20=ED=94=84=EB=A1=9C?= =?UTF-8?q?=ED=95=84=20=EC=88=98=EC=A0=95=20=EC=84=9C=EB=B9=84=EC=8A=A4=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=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 --- .../ChangeProfileImageServiceTest.java | 102 ------------------ 1 file changed, 102 deletions(-) delete mode 100644 src/test/java/com/kuit/findyou/domain/user/service/ChangeProfileImageServiceTest.java diff --git a/src/test/java/com/kuit/findyou/domain/user/service/ChangeProfileImageServiceTest.java b/src/test/java/com/kuit/findyou/domain/user/service/ChangeProfileImageServiceTest.java deleted file mode 100644 index beda325b..00000000 --- a/src/test/java/com/kuit/findyou/domain/user/service/ChangeProfileImageServiceTest.java +++ /dev/null @@ -1,102 +0,0 @@ -package com.kuit.findyou.domain.user.service; - -import com.kuit.findyou.domain.user.dto.request.ChangeProfileImageRequest; -import com.kuit.findyou.domain.user.model.Role; -import com.kuit.findyou.domain.user.model.User; -import com.kuit.findyou.domain.user.repository.UserRepository; -import com.kuit.findyou.domain.user.service.change_profileImage.ChangeProfileImageServiceImpl; -import com.kuit.findyou.global.common.exception.CustomException; -import com.kuit.findyou.global.infrastructure.FileUploadingFailedException; -import com.kuit.findyou.global.infrastructure.ImageUploader; -import jakarta.persistence.EntityNotFoundException; -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 org.springframework.mock.web.MockMultipartFile; - -import static com.kuit.findyou.global.common.response.status.BaseExceptionResponseStatus.IMAGE_UPLOAD_FAILED; -import static com.kuit.findyou.global.common.response.status.BaseExceptionResponseStatus.USER_NOT_FOUND; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.when; - -@ExtendWith(MockitoExtension.class) -public class ChangeProfileImageServiceTest { - @InjectMocks - ChangeProfileImageServiceImpl service; - @Mock - UserRepository userRepository; - @Mock - ImageUploader imageUploader; - - @Test - @DisplayName("기본 프로필(enum)로 변경 성공") - void changeToDefaultProfileImage_Success() { - // given - User user = User.builder() - .id(1L).name("유저").role(Role.USER).deviceId("1234").build(); - - when(userRepository.getReferenceById(1L)).thenReturn(user); - - ChangeProfileImageRequest req = new ChangeProfileImageRequest(null, "chick"); - - // when - service.changeProfileImage(1L, req); - - // then - assertThat(user.getProfileImageUrl()).isEqualTo("chick"); - } - - @Test - @DisplayName("파일 업로드로 변경 성공") - void changeToUploadedImage_Success() { - // given - User user = User.builder() - .id(1L).name("유저").role(Role.USER).deviceId("dev").build(); - - when(userRepository.getReferenceById(1L)).thenReturn(user); - when(imageUploader.upload(any())).thenReturn("https://cdn.test/uploaded.jpg"); - - MockMultipartFile file = new MockMultipartFile( - "profileImageFile", "p.jpg", "image/jpeg", "x".getBytes()); - ChangeProfileImageRequest req = new ChangeProfileImageRequest(file, null); - - // when - service.changeProfileImage(1L, req); - - // then - assertThat(user.getProfileImageUrl()).isEqualTo("https://cdn.test/uploaded.jpg"); - } - - @Test - @DisplayName("존재하지 않는 사용자이면 USER_NOT_FOUND") - void userNotFound_Throws() { - when(userRepository.getReferenceById(99L)).thenThrow(new EntityNotFoundException()); - ChangeProfileImageRequest req = new ChangeProfileImageRequest(null, "puppy"); - - assertThatThrownBy(() -> service.changeProfileImage(99L, req)) - .isInstanceOf(CustomException.class) - .hasMessageContaining(USER_NOT_FOUND.getMessage()); - } - - @Test - @DisplayName("이미지 업로드 실패 시 IMAGE_UPLOAD_FAILED") - void uploadFailed_Throws() { - User user = User.builder() - .id(1L).name("유저").role(Role.USER).deviceId("1234").build(); - when(userRepository.getReferenceById(1L)).thenReturn(user); - when(imageUploader.upload(any())).thenThrow(new FileUploadingFailedException("S3 업로드 실패")); - - MockMultipartFile file = new MockMultipartFile( - "profileImageFile", "p.jpg", "image/jpeg", "x".getBytes()); - ChangeProfileImageRequest req = new ChangeProfileImageRequest(file, null); - - assertThatThrownBy(() -> service.changeProfileImage(1L, req)) - .isInstanceOf(CustomException.class) - .hasMessageContaining(IMAGE_UPLOAD_FAILED.getMessage()); - } -} From 6275e008464c75ce526c201b3b3e0cfb6be6f71d Mon Sep 17 00:00:00 2001 From: JangIkhwan Date: Sun, 4 Jan 2026 20:17:40 +0900 Subject: [PATCH 06/28] =?UTF-8?q?[Feat!]=20#159=20=ED=94=84=EB=A1=9C?= =?UTF-8?q?=ED=95=84=20=EC=A1=B0=ED=9A=8C=20API=EC=9D=98=20=EC=9D=91?= =?UTF-8?q?=EB=8B=B5=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - BREAKING CHANGE : 응답에서 profileImage 필드를 삭제. 프론트에서 수정 필요 --- .../domain/user/dto/response/GetUserProfileResponse.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/main/java/com/kuit/findyou/domain/user/dto/response/GetUserProfileResponse.java b/src/main/java/com/kuit/findyou/domain/user/dto/response/GetUserProfileResponse.java index 81edb438..96f99403 100644 --- a/src/main/java/com/kuit/findyou/domain/user/dto/response/GetUserProfileResponse.java +++ b/src/main/java/com/kuit/findyou/domain/user/dto/response/GetUserProfileResponse.java @@ -5,8 +5,6 @@ @Schema(description = "마이페이지 프로필 조회 API 응답 DTO ") public record GetUserProfileResponse( @Schema(description = "닉네임", example = "유저1") - String nickname, - @Schema(description = "프로필 이미지", example = "image.png") - String profileImage + String nickname ) { } From fa0e3f444ce7fed10cf0a76b301801f3c9e7b748 Mon Sep 17 00:00:00 2001 From: JangIkhwan Date: Sun, 4 Jan 2026 20:18:33 +0900 Subject: [PATCH 07/28] =?UTF-8?q?[Feat]=20#159=20getUserProfile=20?= =?UTF-8?q?=EB=A9=94=EC=84=9C=EB=93=9C=EC=97=90=EC=84=9C=20=EC=9D=91?= =?UTF-8?q?=EB=8B=B5=20=EC=83=9D=EC=84=B1=EB=AC=B8=EC=9D=84=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 - 생성자의 인자에서 프로필 이미지를 제거 --- .../findyou/domain/user/service/query/QueryUserServiceImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/kuit/findyou/domain/user/service/query/QueryUserServiceImpl.java b/src/main/java/com/kuit/findyou/domain/user/service/query/QueryUserServiceImpl.java index 523205fa..fd3927f9 100644 --- a/src/main/java/com/kuit/findyou/domain/user/service/query/QueryUserServiceImpl.java +++ b/src/main/java/com/kuit/findyou/domain/user/service/query/QueryUserServiceImpl.java @@ -28,7 +28,7 @@ public CheckDuplicateNicknameResponse checkDuplicateNickname(CheckDuplicateNickn @Override public GetUserProfileResponse getUserProfile(Long userId) { User user = userRepository.getReferenceById(userId); - return new GetUserProfileResponse(user.getName(), user.getProfileImageUrl()); + return new GetUserProfileResponse(user.getName()); } @Override From 070b45ff3743cb8c19dfd1636eb0ca98e57336e7 Mon Sep 17 00:00:00 2001 From: JangIkhwan Date: Sun, 4 Jan 2026 20:19:07 +0900 Subject: [PATCH 08/28] =?UTF-8?q?[Test]=20#159=20getUserProfile=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=EC=97=90=20=EB=94=B0=EB=9D=BC=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 불필요한 모킹을 제거 --- .../domain/user/service/query/QueryUserServiceTest.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/test/java/com/kuit/findyou/domain/user/service/query/QueryUserServiceTest.java b/src/test/java/com/kuit/findyou/domain/user/service/query/QueryUserServiceTest.java index 9226a370..f16e0d40 100644 --- a/src/test/java/com/kuit/findyou/domain/user/service/query/QueryUserServiceTest.java +++ b/src/test/java/com/kuit/findyou/domain/user/service/query/QueryUserServiceTest.java @@ -27,17 +27,14 @@ void shouldReturnUserProfile_WhenUserExists(){ // given final long userId = 1L; final String name = "name"; - final String profileImage = "default"; User mockUser = mock(User.class); when(userRepository.getReferenceById(anyLong())).thenReturn(mockUser); when(mockUser.getName()).thenReturn(name); - when(mockUser.getProfileImageUrl()).thenReturn(profileImage); // when GetUserProfileResponse userProfile = queryUserService.getUserProfile(userId); // then assertThat(userProfile.nickname()).isEqualTo(name); - assertThat(userProfile.profileImage()).isEqualTo(profileImage); } } \ No newline at end of file From ee0182262d8d45330f10941b867732b5a13ca278 Mon Sep 17 00:00:00 2001 From: JangIkhwan Date: Sun, 4 Jan 2026 20:21:53 +0900 Subject: [PATCH 09/28] =?UTF-8?q?[Test]=20#159=20TestInitializer=EC=97=90?= =?UTF-8?q?=EC=84=9C=20=EB=B6=88=ED=95=84=EC=9A=94=ED=95=9C=20=EB=A9=94?= =?UTF-8?q?=EC=84=9C=EB=93=9C=EB=A5=BC=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../global/common/util/TestInitializer.java | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/src/test/java/com/kuit/findyou/global/common/util/TestInitializer.java b/src/test/java/com/kuit/findyou/global/common/util/TestInitializer.java index 59f26dff..705e9eea 100644 --- a/src/test/java/com/kuit/findyou/global/common/util/TestInitializer.java +++ b/src/test/java/com/kuit/findyou/global/common/util/TestInitializer.java @@ -404,23 +404,6 @@ public void createTestCities() { sigunguRepository.save(Sigungu.builder().name("해운대구").sido(busan).build()); } - public User createUserWithDefaultProfileImage(DefaultProfileImage img) { - User user = createTestUser(); - user.changeProfileImage(img.getName()); - return userRepository.save(user); - } - - public User createUserWithUploadedProfileImage(String imageUrl) { - User user = User.builder() - .name("홍길동") - .role(Role.USER) - .deviceId("device-uploaded") - .profileImageUrl(imageUrl) - .build(); - - return userRepository.save(user); - } - public User createTestGuest() { User user = User.builder() .name("게스트") From bd75f6dad6c8be8624f251b44feb3854f39df4ae Mon Sep 17 00:00:00 2001 From: JangIkhwan Date: Sun, 4 Jan 2026 20:22:51 +0900 Subject: [PATCH 10/28] =?UTF-8?q?[Feat]=20#159=20User=20=EC=97=94=ED=8B=B0?= =?UTF-8?q?=ED=8B=B0=EC=97=90=EC=84=9C=20=ED=94=84=EB=A1=9C=ED=95=84=20?= =?UTF-8?q?=EC=9D=B4=EB=AF=B8=EC=A7=80=20=EC=88=98=EC=A0=95=ED=95=98?= =?UTF-8?q?=EB=8A=94=20changeProfileImage=20=EB=A9=94=EC=84=9C=EB=93=9C=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/kuit/findyou/domain/user/model/User.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/com/kuit/findyou/domain/user/model/User.java b/src/main/java/com/kuit/findyou/domain/user/model/User.java index 962345f4..495cd18a 100644 --- a/src/main/java/com/kuit/findyou/domain/user/model/User.java +++ b/src/main/java/com/kuit/findyou/domain/user/model/User.java @@ -119,5 +119,4 @@ public boolean isGuest(){ public void changeNickname(String newNickname) { this.name = newNickname; } - public void changeProfileImage(String newImage) {this.profileImageUrl = newImage;} } From f8f332b4eb3812614a0ee79eaa68bf8968d6e34e Mon Sep 17 00:00:00 2001 From: JangIkhwan Date: Sun, 4 Jan 2026 20:24:07 +0900 Subject: [PATCH 11/28] =?UTF-8?q?[Test]=20#159=20UserRepositoryTest?= =?UTF-8?q?=EC=97=90=EC=84=9C=20=EB=B6=88=ED=95=84=EC=9A=94=ED=95=9C=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=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 --- .../user/repository/UserRepositoryTest.java | 40 ------------------- 1 file changed, 40 deletions(-) diff --git a/src/test/java/com/kuit/findyou/domain/user/repository/UserRepositoryTest.java b/src/test/java/com/kuit/findyou/domain/user/repository/UserRepositoryTest.java index 32fa2d8d..78be189e 100644 --- a/src/test/java/com/kuit/findyou/domain/user/repository/UserRepositoryTest.java +++ b/src/test/java/com/kuit/findyou/domain/user/repository/UserRepositoryTest.java @@ -225,44 +225,4 @@ private User createUser(String name, Role role, Long kakaoId, String deviceId) { .build(); return userRepository.save(build); } - - @Test - @DisplayName("더티체킹으로 기본 프로필 이미지(enum 문자열) 저장") - void dirtyChecking_SaveDefaultProfileName() { - // given - User user = userRepository.save(User.builder() - .name("유저") - .role(Role.USER) - .deviceId("dev-1") - .build()); - - // when - user.changeProfileImage("puppy"); - em.flush(); - em.clear(); - - // then - User found = userRepository.findById(user.getId()).orElseThrow(); - assertThat(found.getProfileImageUrl()).isEqualTo("puppy"); - } - - @Test - @DisplayName("더티체킹으로 CDN URL이 저장") - void dirtyChecking_SaveCdnUrl() { - // given - User user = userRepository.save(User.builder() - .name("유저") - .role(Role.USER) - .deviceId("dev-2") - .build()); - - // when - user.changeProfileImage("https://cdn.example/profile.jpg"); - em.flush(); - em.clear(); - - // then - User found = userRepository.findById(user.getId()).orElseThrow(); - assertThat(found.getProfileImageUrl()).isEqualTo("https://cdn.example/profile.jpg"); - } } \ No newline at end of file From 3689b0ed667ff8f557408c45704122d91f58e8f4 Mon Sep 17 00:00:00 2001 From: JangIkhwan Date: Sun, 4 Jan 2026 20:42:47 +0900 Subject: [PATCH 12/28] =?UTF-8?q?[Feat!]=20#159=20=ED=9A=8C=EC=9B=90?= =?UTF-8?q?=EC=A0=95=EB=B3=B4=20=EB=93=B1=EB=A1=9D=20API=20=EC=9A=94?= =?UTF-8?q?=EC=B2=AD=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - BREAKING CHANGE : 요청에서 profileImageFile과 defaultProfileImageName 제거. 프론트 수정 필요. --- .../domain/user/controller/UserController.java | 2 +- .../user/dto/request/RegisterUserRequest.java | 13 ------------- 2 files changed, 1 insertion(+), 14 deletions(-) diff --git a/src/main/java/com/kuit/findyou/domain/user/controller/UserController.java b/src/main/java/com/kuit/findyou/domain/user/controller/UserController.java index ed75644c..18a79c79 100644 --- a/src/main/java/com/kuit/findyou/domain/user/controller/UserController.java +++ b/src/main/java/com/kuit/findyou/domain/user/controller/UserController.java @@ -73,7 +73,7 @@ public BaseResponse retrieveViewedAnimals ( ) @CustomExceptionDescription(REGISTER_USER) @PostMapping(consumes = MULTIPART_FORM_DATA_VALUE) - public BaseResponse registerUser(@ModelAttribute RegisterUserRequest request){ + public BaseResponse registerUser(@RequestBody RegisterUserRequest request){ log.info("[registerUser] kakaoId = {}", request.kakaoId()); return new BaseResponse<>(userServiceFacade.registerUser(request)); } diff --git a/src/main/java/com/kuit/findyou/domain/user/dto/request/RegisterUserRequest.java b/src/main/java/com/kuit/findyou/domain/user/dto/request/RegisterUserRequest.java index b9861154..57de8b1c 100644 --- a/src/main/java/com/kuit/findyou/domain/user/dto/request/RegisterUserRequest.java +++ b/src/main/java/com/kuit/findyou/domain/user/dto/request/RegisterUserRequest.java @@ -9,19 +9,6 @@ """ ) @Builder public record RegisterUserRequest( - @Schema(description = """ - 사용자 지정 프로필 이미지 파일 (기본 프로필을 사용하지 않을 경우 업로드) - """, - type = "string", - format = "binary", - nullable = true) - MultipartFile profileImageFile, - @Schema(description = """ - 기본 프로필 이미지 이름 (profileImageFile이 없을 경우 선택) - """, - example = "default", - nullable = true) - String defaultProfileImageName, @Schema(description = "회원 닉네임", example = "찾아유", required = true) From a98befda5bc4b9f453d3e1eb04b0de44982cbf1c Mon Sep 17 00:00:00 2001 From: JangIkhwan Date: Sun, 4 Jan 2026 20:47:37 +0900 Subject: [PATCH 13/28] =?UTF-8?q?[Docs]=20#159=20=ED=9A=8C=EC=9B=90?= =?UTF-8?q?=EC=A0=95=EB=B3=B4=20=EB=93=B1=EB=A1=9D=20API=20=EB=AA=85?= =?UTF-8?q?=EC=84=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kuit/findyou/domain/user/controller/UserController.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/main/java/com/kuit/findyou/domain/user/controller/UserController.java b/src/main/java/com/kuit/findyou/domain/user/controller/UserController.java index 18a79c79..7e35ddec 100644 --- a/src/main/java/com/kuit/findyou/domain/user/controller/UserController.java +++ b/src/main/java/com/kuit/findyou/domain/user/controller/UserController.java @@ -65,10 +65,7 @@ public BaseResponse retrieveViewedAnimals ( @Operation( summary = "회원정보 등록 API", description = """ - 회원 정보를 등록합니다. 회원 등록에 성공하면 유저 정보(식별자와 닉네임)와 엑세스 토큰을 얻을 수 있습니다. \n - **[중요] profileImageFile과 defaultProfileImageName 중 하나만 선택해야 합니다.** \n - - profileImageFile을 업로드하면 defaultProfileImageName은 무시됩니다. \n - - 둘 다 null이면 에러가 발생합니다. + 회원 정보를 등록합니다. 회원 등록에 성공하면 유저 정보(식별자와 닉네임)와 엑세스 토큰을 얻을 수 있습니다. """ ) @CustomExceptionDescription(REGISTER_USER) From 663f4e279460c60f4b64914422af13851c731082 Mon Sep 17 00:00:00 2001 From: JangIkhwan Date: Sun, 4 Jan 2026 21:03:07 +0900 Subject: [PATCH 14/28] =?UTF-8?q?[Feat!]=20#159=20=ED=9A=8C=EC=9B=90?= =?UTF-8?q?=EC=A0=95=EB=B3=B4=20=EB=93=B1=EB=A1=9D=20API=EC=97=90=EC=84=9C?= =?UTF-8?q?=20=EC=9A=94=EC=B2=AD=20=EB=B0=94=EB=94=94=EB=A5=BC=20multipart?= =?UTF-8?q?=EA=B0=80=20=EC=95=84=EB=8B=88=EB=9D=BC=20json=20=ED=98=95?= =?UTF-8?q?=ED=83=9C=EB=A1=9C=20=EB=B0=9B=EB=8F=84=EB=A1=9D=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 - BREAKING CHANGE : 프론트 수정 필요 --- .../kuit/findyou/domain/user/controller/UserController.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/com/kuit/findyou/domain/user/controller/UserController.java b/src/main/java/com/kuit/findyou/domain/user/controller/UserController.java index 7e35ddec..7f9c9b1e 100644 --- a/src/main/java/com/kuit/findyou/domain/user/controller/UserController.java +++ b/src/main/java/com/kuit/findyou/domain/user/controller/UserController.java @@ -25,7 +25,6 @@ import lombok.extern.slf4j.Slf4j; import static com.kuit.findyou.global.common.swagger.SwaggerResponseDescription.*; -import static org.springframework.http.MediaType.MULTIPART_FORM_DATA_VALUE; @Slf4j @RestController @@ -69,7 +68,7 @@ public BaseResponse retrieveViewedAnimals ( """ ) @CustomExceptionDescription(REGISTER_USER) - @PostMapping(consumes = MULTIPART_FORM_DATA_VALUE) + @PostMapping public BaseResponse registerUser(@RequestBody RegisterUserRequest request){ log.info("[registerUser] kakaoId = {}", request.kakaoId()); return new BaseResponse<>(userServiceFacade.registerUser(request)); From cc10edbcaac9a4c644390bad36dac2bb784b3ce5 Mon Sep 17 00:00:00 2001 From: JangIkhwan Date: Sun, 4 Jan 2026 21:04:09 +0900 Subject: [PATCH 15/28] =?UTF-8?q?[Test]=20#159=20=ED=9A=8C=EC=9B=90?= =?UTF-8?q?=EC=A0=95=EB=B3=B4=20=EB=93=B1=EB=A1=9D=20API=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../user/controller/UserControllerTest.java | 24 +++++++------------ 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/src/test/java/com/kuit/findyou/domain/user/controller/UserControllerTest.java b/src/test/java/com/kuit/findyou/domain/user/controller/UserControllerTest.java index ca415431..34459292 100644 --- a/src/test/java/com/kuit/findyou/domain/user/controller/UserControllerTest.java +++ b/src/test/java/com/kuit/findyou/domain/user/controller/UserControllerTest.java @@ -5,6 +5,7 @@ import com.kuit.findyou.domain.report.model.WitnessReport; import com.kuit.findyou.domain.report.repository.InterestReportRepository; import com.kuit.findyou.domain.user.dto.request.CheckDuplicateNicknameRequest; +import com.kuit.findyou.domain.user.dto.request.RegisterUserRequest; import com.kuit.findyou.domain.user.dto.response.CheckDuplicateNicknameResponse; import com.kuit.findyou.domain.user.dto.response.CheckGuestResponse; import com.kuit.findyou.domain.user.dto.response.GetUserProfileResponse; @@ -29,23 +30,16 @@ import org.springframework.context.annotation.Import; import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.bean.override.mockito.MockitoBean; -import software.amazon.awssdk.core.sync.RequestBody; import software.amazon.awssdk.services.s3.S3Client; -import software.amazon.awssdk.services.s3.model.DeleteObjectRequest; -import software.amazon.awssdk.services.s3.model.PutObjectRequest; -import software.amazon.awssdk.services.s3.model.PutObjectResponse; import java.time.LocalDate; import java.util.Map; -import static com.kuit.findyou.domain.user.constant.DefaultProfileImage.PUPPY; import static com.kuit.findyou.global.common.response.status.BaseExceptionResponseStatus.*; -import static com.kuit.findyou.global.common.util.RestAssuredUtils.multipartText; import static io.restassured.RestAssured.given; import static org.assertj.core.api.Assertions.assertThat; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.nullValue; -import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.*; @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @@ -122,16 +116,16 @@ void retrieveViewedAnimals() { @Test void should_Succeed_When_registerAnyoneWhoFirstLoggedIn() { // given - final String NICKNAME = "유저1"; + String nickname = "유저1"; + Long kakaoId = 123456L; + String deviceId= "device-01"; // when RegisterUserResponse response = given() -// .log().all() - .contentType(ContentType.MULTIPART) - .multiPart(multipartText("defaultProfileImageName", "default")) - .multiPart(multipartText("nickname", NICKNAME)) - .multiPart(multipartText("kakaoId", "123456")) - .multiPart(multipartText("deviceId", "device-001")) + .log().all() + .contentType(ContentType.JSON) + .accept(ContentType.JSON) + .body(new RegisterUserRequest(nickname, kakaoId, deviceId)) .when() .post("/api/v2/users") .then() @@ -143,7 +137,7 @@ void should_Succeed_When_registerAnyoneWhoFirstLoggedIn() { // then Role role = jwtUtil.getRole(response.accessToken()); - assertThat(response.nickname()).isEqualTo(NICKNAME); + assertThat(response.nickname()).isEqualTo(nickname); assertThat(role).isEqualTo(Role.USER); } From c0f611a753d2c325e93b3c18d60730f2217d9f20 Mon Sep 17 00:00:00 2001 From: JangIkhwan Date: Sun, 4 Jan 2026 21:09:59 +0900 Subject: [PATCH 16/28] =?UTF-8?q?[Feat]=20#159=20=ED=9A=8C=EC=9B=90?= =?UTF-8?q?=EC=A0=95=EB=B3=B4=20=EB=93=B1=EB=A1=9D=20=EC=84=9C=EB=B9=84?= =?UTF-8?q?=EC=8A=A4=20=EB=A1=9C=EC=A7=81=EC=97=90=EC=84=9C=20=ED=94=84?= =?UTF-8?q?=EB=A1=9C=ED=95=84=20=EC=9D=B4=EB=AF=B8=EC=A7=80=20=EA=B4=80?= =?UTF-8?q?=EB=A0=A8=20=EB=82=B4=EC=9A=A9=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kuit/findyou/domain/user/model/User.java | 5 +- .../register/RegisterUserServiceImpl.java | 53 ++----------------- 2 files changed, 4 insertions(+), 54 deletions(-) diff --git a/src/main/java/com/kuit/findyou/domain/user/model/User.java b/src/main/java/com/kuit/findyou/domain/user/model/User.java index 495cd18a..04c01d27 100644 --- a/src/main/java/com/kuit/findyou/domain/user/model/User.java +++ b/src/main/java/com/kuit/findyou/domain/user/model/User.java @@ -11,8 +11,6 @@ import com.kuit.findyou.global.common.model.BaseEntity; import jakarta.persistence.*; import lombok.*; -import org.hibernate.annotations.SQLDelete; -import org.hibernate.annotations.SQLRestriction; import java.util.ArrayList; import java.util.List; @@ -100,7 +98,7 @@ public void addInterestReport(InterestReport interestReport) { public void addSubscribe(Subscribe subscribe) { subscribes.add(subscribe); } public void setFcmToken(FcmToken fcmToken) {this.fcmToken = fcmToken;} - public void upgradeToMember(Long kakaoId, String nickname, String profileImageUrl){ + public void upgradeToMember(Long kakaoId, String nickname){ // 비회원이어야 회원이 될 수 있음 if(this.role != Role.GUEST){ throw new CustomException(ALREADY_REGISTERED_USER); @@ -108,7 +106,6 @@ public void upgradeToMember(Long kakaoId, String nickname, String profileImageUr this.kakaoId = kakaoId; this.name = nickname; - this.profileImageUrl = profileImageUrl; this.role = Role.USER; } diff --git a/src/main/java/com/kuit/findyou/domain/user/service/register/RegisterUserServiceImpl.java b/src/main/java/com/kuit/findyou/domain/user/service/register/RegisterUserServiceImpl.java index 55f1f2d0..04fff97b 100644 --- a/src/main/java/com/kuit/findyou/domain/user/service/register/RegisterUserServiceImpl.java +++ b/src/main/java/com/kuit/findyou/domain/user/service/register/RegisterUserServiceImpl.java @@ -1,19 +1,16 @@ package com.kuit.findyou.domain.user.service.register; -import com.kuit.findyou.domain.user.constant.DefaultProfileImage; import com.kuit.findyou.domain.user.dto.request.RegisterUserRequest; import com.kuit.findyou.domain.user.dto.response.RegisterUserResponse; import com.kuit.findyou.domain.user.model.Role; import com.kuit.findyou.domain.user.model.User; import com.kuit.findyou.domain.user.repository.UserRepository; import com.kuit.findyou.global.common.exception.CustomException; -import com.kuit.findyou.global.infrastructure.FileUploadingFailedException; import com.kuit.findyou.global.infrastructure.ImageUploader; import com.kuit.findyou.global.jwt.util.JwtUtil; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; -import org.springframework.web.multipart.MultipartFile; import static com.kuit.findyou.global.common.response.status.BaseExceptionResponseStatus.*; @@ -22,7 +19,6 @@ @Service public class RegisterUserServiceImpl implements RegisterUserService { private final UserRepository userRepository; - private final ImageUploader imageUploader; private final JwtUtil jwtUtil; @Override @@ -33,18 +29,15 @@ public RegisterUserResponse registerUser(RegisterUserRequest request) { throw new CustomException(ALREADY_REGISTERED_USER); } - // 비회원이었는지 확인한 후에 회원 정보 저장 - String profileImageUrl = getProfileImageUrl(request); - User user = userRepository.findByDeviceId(request.deviceId()) .map(existing -> { log.info("[registerUser] user with deviceId {} alreay exists", request.deviceId()); - existing.upgradeToMember(request.kakaoId(), request.nickname(), profileImageUrl); + existing.upgradeToMember(request.kakaoId(), request.nickname()); return existing; }) .orElseGet(()->{ log.info("[registerUser] user not found"); - return mapToUser(request, profileImageUrl); + return mapToUser(request); }); User save = userRepository.save(user); @@ -54,52 +47,12 @@ public RegisterUserResponse registerUser(RegisterUserRequest request) { return new RegisterUserResponse(save.getId(), save.getName(), accessToken); } - private User mapToUser(RegisterUserRequest request, String profileImageUrl) { + private User mapToUser(RegisterUserRequest request) { return User.builder() .kakaoId(request.kakaoId()) .name(request.nickname()) - .profileImageUrl(profileImageUrl) .role(Role.USER) .deviceId(request.deviceId()) .build(); } - - private String getProfileImageUrl(RegisterUserRequest request) { - // 프로필 이미지 설정 관련 검증 - MultipartFile profileImage = request.profileImageFile(); - String defaultProfileImageName = request.defaultProfileImageName(); - - if(validateProfileImage(profileImage, defaultProfileImageName)){ - // 요청이 잘못되었음 - throw new CustomException(BAD_REQUEST); - } - - // 인프라에 이미지 업로드 - if(!isEmptyProfileImageFile(profileImage)){ - try{ - return imageUploader.upload(profileImage); - } - catch (FileUploadingFailedException e){ - throw new CustomException(IMAGE_UPLOAD_FAILED); - } - } - - // 기본 이미지 이름 반환 - return defaultProfileImageName; - } - - private boolean validateProfileImage(MultipartFile profileFile, String defaultName) { - // 둘 다 잘못된 값이거나, 둘 다 올바른 값이면 잘못된 요청으로 간주 - boolean invalidName = isInvalidDefaultProfileImageName(defaultName); - boolean emptyFile = isEmptyProfileImageFile(profileFile); - return invalidName && emptyFile || !invalidName && !emptyFile; - } - - private boolean isInvalidDefaultProfileImageName(String name) { - return name == null || !DefaultProfileImage.validate(name); - } - - private boolean isEmptyProfileImageFile(MultipartFile file) { - return file == null || file.isEmpty(); - } } From 0ad89bb92c846cf55644595998244c88502f577f Mon Sep 17 00:00:00 2001 From: JangIkhwan Date: Sun, 4 Jan 2026 21:12:24 +0900 Subject: [PATCH 17/28] =?UTF-8?q?[Test]=20#159=20UserServiceTest=EC=97=90?= =?UTF-8?q?=EC=84=9C=20=ED=9A=8C=EC=9B=90=EC=A0=95=EB=B3=B4=20=EB=93=B1?= =?UTF-8?q?=EB=A1=9D=20=EA=B4=80=EB=A0=A8=20=ED=85=8C=EC=8A=A4=ED=8A=B8=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 --- .../domain/user/service/UserServiceTest.java | 104 +----------------- 1 file changed, 5 insertions(+), 99 deletions(-) diff --git a/src/test/java/com/kuit/findyou/domain/user/service/UserServiceTest.java b/src/test/java/com/kuit/findyou/domain/user/service/UserServiceTest.java index 0e97f9c9..9aeac3e2 100644 --- a/src/test/java/com/kuit/findyou/domain/user/service/UserServiceTest.java +++ b/src/test/java/com/kuit/findyou/domain/user/service/UserServiceTest.java @@ -6,8 +6,6 @@ import com.kuit.findyou.domain.user.repository.UserRepository; import com.kuit.findyou.domain.user.service.register.RegisterUserServiceImpl; import com.kuit.findyou.global.common.exception.CustomException; -import com.kuit.findyou.global.infrastructure.FileUploadingFailedException; -import com.kuit.findyou.global.infrastructure.ImageUploader; import com.kuit.findyou.global.jwt.util.JwtUtil; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -15,7 +13,6 @@ import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; -import org.springframework.mock.web.MockMultipartFile; import java.util.Optional; @@ -33,8 +30,6 @@ class UserServiceTest { @Mock private UserRepository userRepository; @Mock - private ImageUploader imageUploader; - @Mock private JwtUtil jwtUtil; @DisplayName("처음 로그인한 사용자가 회원등록을 하면 성공한다") @@ -44,7 +39,7 @@ void should_Succeed_When_AnyoneWhoFirstLoggedInRegister(){ final Long USER_ID = 1L; final String ACCESS_TOKEN = "accessToken"; - RegisterUserRequest request = getRegisterUserRequestWithoutImage(); + RegisterUserRequest request = getRegisterUserRequest(); when(userRepository.findByKakaoId(request.kakaoId())).thenReturn(Optional.empty()); when(userRepository.findByDeviceId(request.deviceId())).thenReturn(Optional.empty()); @@ -64,10 +59,8 @@ void should_Succeed_When_AnyoneWhoFirstLoggedInRegister(){ assertThat(response.accessToken()).isEqualTo(ACCESS_TOKEN); } - private static RegisterUserRequest getRegisterUserRequestWithoutImage() { + private static RegisterUserRequest getRegisterUserRequest() { RegisterUserRequest request = RegisterUserRequest.builder() - .profileImageFile(null) - .defaultProfileImageName("default") .nickname("유저1") .kakaoId(1234L) .deviceId("1234") @@ -82,7 +75,7 @@ void should_Succeed_When_GuestRegister(){ final Long USER_ID = 1L; final String ACCESS_TOKEN = "accessToken"; - RegisterUserRequest request = getRegisterUserRequestWithImage(); + RegisterUserRequest request = getRegisterUserRequest(); User user = mock(User.class); @@ -93,8 +86,6 @@ void should_Succeed_When_GuestRegister(){ .name(request.nickname()) .build()); - when(imageUploader.upload(any())).thenReturn("image-url"); - when(jwtUtil.createAccessJwt(any(), any())).thenReturn(ACCESS_TOKEN); // when @@ -105,7 +96,7 @@ void should_Succeed_When_GuestRegister(){ assertThat(response.nickname()).isEqualTo(request.nickname()); assertThat(response.accessToken()).isEqualTo(ACCESS_TOKEN); - verify(user).upgradeToMember(eq(request.kakaoId()), eq(request.nickname()), eq("image-url")); + verify(user).upgradeToMember(eq(request.kakaoId()), eq(request.nickname())); } @DisplayName("이미 가입한 회원이 회원등록을 하면 예외를 발생시킨다") @@ -114,7 +105,7 @@ void should_ThrowException_When_ExistingUserRegister(){ // given final Long USER_ID = 1L; - RegisterUserRequest request = getRegisterUserRequestWithoutImage(); + RegisterUserRequest request = getRegisterUserRequest(); User user = User.builder() .id(USER_ID) @@ -128,89 +119,4 @@ void should_ThrowException_When_ExistingUserRegister(){ .isInstanceOf(CustomException.class) .hasMessageContaining(ALREADY_REGISTERED_USER.getMessage()); } - - @DisplayName("올바르지 않은 기본 프로필로 요청하면 예외가 발생한다") - @Test - void should_ThrowException_When_RequestContainsInvalidDefaultProfile(){ - // given - RegisterUserRequest request = getRegisterUserRequestWithWrongDefaultImageName(); - - when(userRepository.findByKakaoId(request.kakaoId())).thenReturn(Optional.empty()); - - // when - // then - assertThatThrownBy(() -> userService.registerUser(request)) - .isInstanceOf(CustomException.class) - .hasMessageContaining(BAD_REQUEST.getMessage()); - } - - private static RegisterUserRequest getRegisterUserRequestWithWrongDefaultImageName() { - RegisterUserRequest request = RegisterUserRequest.builder() - .profileImageFile(null) - .defaultProfileImageName("default-image") - .nickname("유저1") - .kakaoId(1234L) - .deviceId("1234") - .build(); - return request; - } - - @DisplayName("프로필 관련 내용 없이 요청하면 예외가 발생한다") - @Test - void should_ThrowException_When_RequestDoesNotContainProfile(){ - // given - RegisterUserRequest request = getRegisterUserRequestWithoutProfile(); - - when(userRepository.findByKakaoId(request.kakaoId())).thenReturn(Optional.empty()); - - // when - // then - assertThatThrownBy(() -> userService.registerUser(request)) - .isInstanceOf(CustomException.class) - .hasMessageContaining(BAD_REQUEST.getMessage()); - } - - private static RegisterUserRequest getRegisterUserRequestWithoutProfile() { - return RegisterUserRequest.builder() - .profileImageFile(null) - .defaultProfileImageName(null) - .nickname("유저1") - .kakaoId(1234L) - .deviceId("1234") - .build(); - } - - @DisplayName("이미지 업로드에 실패하면 예외가 발생한다") - @Test - void should_ThrowException_When_ImageUploadingFailed(){ - // given - RegisterUserRequest request = getRegisterUserRequestWithImage(); - - when(userRepository.findByKakaoId(request.kakaoId())).thenReturn(Optional.empty()); - when(imageUploader.upload(any())).thenThrow(new FileUploadingFailedException("S3 업로드 실패")); - - // when - // then - assertThatThrownBy(() -> userService.registerUser(request)) - .isInstanceOf(CustomException.class) - .hasMessageContaining(IMAGE_UPLOAD_FAILED.getMessage()); - } - - private static RegisterUserRequest getRegisterUserRequestWithImage() { - MockMultipartFile profileImage = new MockMultipartFile( - "profileImageFile", - "test.jpg", - "image/jpeg", - "fake-image-content".getBytes() - ); - - RegisterUserRequest request = RegisterUserRequest.builder() - .profileImageFile(profileImage) - .defaultProfileImageName(null) - .nickname("유저1") - .kakaoId(1234L) - .deviceId("1234") - .build(); - return request; - } } \ No newline at end of file From cefb6826d0d36e2d6d7560524437dec6c16d31f1 Mon Sep 17 00:00:00 2001 From: JangIkhwan Date: Sun, 4 Jan 2026 21:45:37 +0900 Subject: [PATCH 18/28] =?UTF-8?q?[Feat]=20#148=20=ED=86=A0=ED=81=B0=20?= =?UTF-8?q?=EB=B0=9C=EA=B8=89=20=EC=84=9C=EB=B9=84=EC=8A=A4=20IssueTokenSe?= =?UTF-8?q?rvice=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/service/IssueTokenService.java | 8 ++++++ .../auth/service/IssueTokenServiceImpl.java | 26 +++++++++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 src/main/java/com/kuit/findyou/domain/auth/service/IssueTokenService.java create mode 100644 src/main/java/com/kuit/findyou/domain/auth/service/IssueTokenServiceImpl.java diff --git a/src/main/java/com/kuit/findyou/domain/auth/service/IssueTokenService.java b/src/main/java/com/kuit/findyou/domain/auth/service/IssueTokenService.java new file mode 100644 index 00000000..d51302eb --- /dev/null +++ b/src/main/java/com/kuit/findyou/domain/auth/service/IssueTokenService.java @@ -0,0 +1,8 @@ +package com.kuit.findyou.domain.auth.service; + +import com.kuit.findyou.domain.user.model.Role; + +public interface IssueTokenService { + String issueAccessToken(Long userId, Role role); + String issueRefreshToken(Long userId); +} diff --git a/src/main/java/com/kuit/findyou/domain/auth/service/IssueTokenServiceImpl.java b/src/main/java/com/kuit/findyou/domain/auth/service/IssueTokenServiceImpl.java new file mode 100644 index 00000000..cabc0028 --- /dev/null +++ b/src/main/java/com/kuit/findyou/domain/auth/service/IssueTokenServiceImpl.java @@ -0,0 +1,26 @@ +package com.kuit.findyou.domain.auth.service; + +import com.kuit.findyou.domain.auth.repository.RedisRefreshTokenRepository; +import com.kuit.findyou.domain.user.model.Role; +import com.kuit.findyou.global.jwt.util.JwtUtil; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@RequiredArgsConstructor +@Service +public class IssueTokenServiceImpl implements IssueTokenService { + private final JwtUtil jwtUtil; + private final RedisRefreshTokenRepository redisRefreshTokenRepository; + + @Override + public String issueAccessToken(Long userId, Role role) { + return jwtUtil.createAccessJwt(userId, role); + } + + @Override + public String issueRefreshToken(Long userId) { + String refreshToken = jwtUtil.createRefreshJwt(userId); + redisRefreshTokenRepository.save(userId, refreshToken); + return refreshToken; + } +} From 27d3c9190f242ed66f874ba50db49dd8866f234d Mon Sep 17 00:00:00 2001 From: JangIkhwan Date: Sun, 4 Jan 2026 21:46:44 +0900 Subject: [PATCH 19/28] =?UTF-8?q?[refactor]=20#148=20IssueTokenService?= =?UTF-8?q?=EB=A5=BC=20=EC=82=AC=EC=9A=A9=ED=95=B4=EC=84=9C=20=ED=86=A0?= =?UTF-8?q?=ED=81=B0=EC=9D=84=20=EB=B0=9C=EA=B8=89=ED=95=98=EB=8F=84?= =?UTF-8?q?=EB=A1=9D=20LoginServiceImpl=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/auth/service/LoginServiceImpl.java | 20 ++++++++----------- 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/src/main/java/com/kuit/findyou/domain/auth/service/LoginServiceImpl.java b/src/main/java/com/kuit/findyou/domain/auth/service/LoginServiceImpl.java index 068af01c..4e22c425 100644 --- a/src/main/java/com/kuit/findyou/domain/auth/service/LoginServiceImpl.java +++ b/src/main/java/com/kuit/findyou/domain/auth/service/LoginServiceImpl.java @@ -4,13 +4,11 @@ import com.kuit.findyou.domain.auth.dto.response.GuestLoginResponse; import com.kuit.findyou.domain.auth.dto.request.KakaoLoginRequest; import com.kuit.findyou.domain.auth.dto.response.KakaoLoginResponse; -import com.kuit.findyou.domain.auth.repository.RedisRefreshTokenRepository; import com.kuit.findyou.domain.user.constant.DefaultProfileImage; import com.kuit.findyou.domain.user.model.Role; import com.kuit.findyou.domain.user.model.User; import com.kuit.findyou.domain.user.repository.UserRepository; import com.kuit.findyou.global.common.exception.CustomException; -import com.kuit.findyou.global.jwt.util.JwtUtil; import jakarta.transaction.Transactional; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -23,18 +21,17 @@ @Service public class LoginServiceImpl implements LoginService { private final UserRepository userRepository; - private final RedisRefreshTokenRepository redisRefreshTokenRepository; - private final JwtUtil jwtUtil; + private final IssueTokenService issueTokenService; + public KakaoLoginResponse kakaoLogin(KakaoLoginRequest request) { log.info("[kakaoLogin] kakaoId = {}", request.kakaoId()); return userRepository.findByKakaoId(request.kakaoId()) - .map(loginUser -> { - String accessToken = jwtUtil.createAccessJwt(loginUser.getId(), loginUser.getRole()); - String refreshToken = jwtUtil.createRefreshJwt(loginUser.getId()); - redisRefreshTokenRepository.save(loginUser.getId(), refreshToken); + .map(user -> { + String accessToken = issueTokenService.issueAccessToken(user.getId(), user.getRole()); + String refreshToken = issueTokenService.issueRefreshToken(user.getId()); log.info("[kakaoLogin] 카카오 로그인 성공"); - return KakaoLoginResponse.fromUserAndTokens(loginUser, accessToken, refreshToken); + return KakaoLoginResponse.fromUserAndTokens(user, accessToken, refreshToken); }) .orElseGet(() -> { log.info("[kakaoLogin] 일치하는 유저가 없어서 카카오 로그인 실패"); @@ -67,9 +64,8 @@ public GuestLoginResponse guestLogin(GuestLoginRequest request) { } // 토큰 생성 - String accessToken = jwtUtil.createAccessJwt(user.getId(), user.getRole()); - String refreshToken = jwtUtil.createRefreshJwt(user.getId()); - redisRefreshTokenRepository.save(user.getId(), refreshToken); + String accessToken = issueTokenService.issueAccessToken(user.getId(), user.getRole()); + String refreshToken = issueTokenService.issueRefreshToken(user.getId()); log.info("[guestLogin] 게스트 로그인 성공"); return new GuestLoginResponse(user.getId(), accessToken, refreshToken); } From 43dabd9fee266757c4709f861622ca936e23e59a Mon Sep 17 00:00:00 2001 From: JangIkhwan Date: Sun, 4 Jan 2026 21:47:08 +0900 Subject: [PATCH 20/28] =?UTF-8?q?[Test]=20#148=20LoginServiceTest=EC=97=90?= =?UTF-8?q?=EC=84=9C=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 필요한 모킹을 추가 --- .../domain/auth/service/LoginServiceTest.java | 41 ++++++++----------- 1 file changed, 17 insertions(+), 24 deletions(-) diff --git a/src/test/java/com/kuit/findyou/domain/auth/service/LoginServiceTest.java b/src/test/java/com/kuit/findyou/domain/auth/service/LoginServiceTest.java index b69c26af..e971bb58 100644 --- a/src/test/java/com/kuit/findyou/domain/auth/service/LoginServiceTest.java +++ b/src/test/java/com/kuit/findyou/domain/auth/service/LoginServiceTest.java @@ -33,9 +33,7 @@ class LoginServiceTest { @Mock private UserRepository userRepository; @Mock - private RedisRefreshTokenRepository redisRefreshTokenRepository; - @Mock - private JwtUtil jwtUtil; + private IssueTokenService issueTokenService; @DisplayName("카카오 id와 일치하는 사용자가 없다면 isFirstLogin을 true로 반환하여 회원가입을 유도한다") @Test @@ -57,21 +55,19 @@ void should_ReturnfirstLoginWithTrue_When_UserWithKakaoIdNotFound(){ void should_ReturnUserInfo_When_UserWithKakaoIdExists(){ // given final Long KAKAO_ID = 1234L; - final String ACCESS_TOKEN = "accessToken"; - final String REFRESH_TOKEN = "accessToken"; - final String NAME = "유저"; + String ACCESS_TOKEN = "accessToken"; + String REFRESH_TOKEN = "accessToken"; + String NAME = "유저"; User user = mockUser(NAME, Role.USER, KAKAO_ID); when(userRepository.findByKakaoId(KAKAO_ID)).thenReturn(Optional.of(user)); - when(jwtUtil.createAccessJwt(user.getId(), user.getRole())).thenReturn(ACCESS_TOKEN); - when(jwtUtil.createRefreshJwt(user.getId())).thenReturn(REFRESH_TOKEN); + when(issueTokenService.issueAccessToken(user.getId(), user.getRole())).thenReturn(ACCESS_TOKEN); + when(issueTokenService.issueRefreshToken(user.getId())).thenReturn(REFRESH_TOKEN); // when KakaoLoginResponse response = authService.kakaoLogin(new KakaoLoginRequest(KAKAO_ID)); // then - verify(redisRefreshTokenRepository, times(1)).save(anyLong(), anyString()); - assertThat(response.isFirstLogin()).isFalse(); assertThat(response.userInfo()).isNotNull(); assertThat(response.userInfo().userId()).isEqualTo(user.getId()); @@ -95,21 +91,20 @@ private User mockUser(String name, Role role, Long kakaoId){ @Test() void should_DoesNotSaveNewGuest_When_UserWithDeviceIdExists(){ // given - final String deviceId = "asdf-1234-asdf"; - final String accessToken = "accessToken"; - final String refreshToken = "refreshToken"; + String deviceId = "asdf-1234-asdf"; + String accessToken = "accessToken"; + String refreshToken = "refreshToken"; User user = mockUser("게스트", Role.GUEST, null); when(userRepository.findByDeviceId(eq(deviceId))).thenReturn(Optional.of(user)); - when(jwtUtil.createAccessJwt(anyLong(), any(Role.class))).thenReturn(accessToken); - when(jwtUtil.createRefreshJwt(anyLong())).thenReturn(refreshToken); + when(issueTokenService.issueAccessToken(anyLong(), any(Role.class))).thenReturn(accessToken); + when(issueTokenService.issueRefreshToken(anyLong())).thenReturn(refreshToken); // when GuestLoginResponse response = authService.guestLogin(new GuestLoginRequest(deviceId)); // then verify(userRepository, never()).save(any()); - verify(redisRefreshTokenRepository, times(1)).save(anyLong(), anyString()); assertThat(response.userId()).isEqualTo(user.getId()); assertThat(response.accessToken()).isEqualTo(accessToken); @@ -120,22 +115,21 @@ void should_DoesNotSaveNewGuest_When_UserWithDeviceIdExists(){ @Test() void should_SaveNewGuest_When_UserWithDeviceIdDoesNotExists(){ // given - final String deviceId = "asdf-1234-asdf"; - final String accessToken = "accessToken"; - final String refreshToken = "refreshToken"; + String deviceId = "asdf-1234-asdf"; + String accessToken = "accessToken"; + String refreshToken = "refreshToken"; User user = mockUser("게스트", Role.GUEST, null); when(userRepository.findByDeviceId(eq(deviceId))).thenReturn(Optional.empty()); when(userRepository.save(any())).thenReturn(user); - when(jwtUtil.createAccessJwt(anyLong(), any(Role.class))).thenReturn(accessToken); - when(jwtUtil.createRefreshJwt(anyLong())).thenReturn(refreshToken); + when(issueTokenService.issueAccessToken(anyLong(), any(Role.class))).thenReturn(accessToken); + when(issueTokenService.issueRefreshToken(anyLong())).thenReturn(refreshToken); // when GuestLoginResponse response = authService.guestLogin(new GuestLoginRequest(deviceId)); // then verify(userRepository).save(any(User.class)); - verify(redisRefreshTokenRepository, times(1)).save(anyLong(), anyString()); assertThat(response.userId()).isEqualTo(user.getId()); assertThat(response.accessToken()).isEqualTo(accessToken); @@ -146,8 +140,7 @@ void should_SaveNewGuest_When_UserWithDeviceIdDoesNotExists(){ @Test() void should_ThrowException_When_NonGuestUserLogsIn(){ // given - final String deviceId = "asdf-1234-asdf"; - final String accessToken = "accessToken"; + String deviceId = "asdf-1234-asdf"; User user = mockUser("게스트", Role.USER, null); when(userRepository.findByDeviceId(eq(deviceId))).thenReturn(Optional.of(user)); From c316e8f83dac650d852f51e8a05fb7148346e1cc Mon Sep 17 00:00:00 2001 From: JangIkhwan Date: Sun, 4 Jan 2026 21:49:36 +0900 Subject: [PATCH 21/28] =?UTF-8?q?[refactor]=20#148=20IssueTokenService?= =?UTF-8?q?=EB=A5=BC=20=EC=82=AC=EC=9A=A9=ED=95=B4=20=ED=86=A0=ED=81=B0?= =?UTF-8?q?=EC=9D=84=20=EB=B0=9C=EA=B8=89=ED=95=98=EB=8F=84=EB=A1=9D=20Reg?= =?UTF-8?q?isterUserServiceImpl=EB=A5=BC=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/register/RegisterUserServiceImpl.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/kuit/findyou/domain/user/service/register/RegisterUserServiceImpl.java b/src/main/java/com/kuit/findyou/domain/user/service/register/RegisterUserServiceImpl.java index 04fff97b..4322b002 100644 --- a/src/main/java/com/kuit/findyou/domain/user/service/register/RegisterUserServiceImpl.java +++ b/src/main/java/com/kuit/findyou/domain/user/service/register/RegisterUserServiceImpl.java @@ -1,13 +1,12 @@ package com.kuit.findyou.domain.user.service.register; +import com.kuit.findyou.domain.auth.service.IssueTokenService; import com.kuit.findyou.domain.user.dto.request.RegisterUserRequest; import com.kuit.findyou.domain.user.dto.response.RegisterUserResponse; import com.kuit.findyou.domain.user.model.Role; import com.kuit.findyou.domain.user.model.User; import com.kuit.findyou.domain.user.repository.UserRepository; import com.kuit.findyou.global.common.exception.CustomException; -import com.kuit.findyou.global.infrastructure.ImageUploader; -import com.kuit.findyou.global.jwt.util.JwtUtil; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; @@ -19,8 +18,7 @@ @Service public class RegisterUserServiceImpl implements RegisterUserService { private final UserRepository userRepository; - private final JwtUtil jwtUtil; - + private final IssueTokenService issueTokenService; @Override public RegisterUserResponse registerUser(RegisterUserRequest request) { // 카카오 Id가 중복되는 사용자가 있는지 확인 @@ -43,8 +41,10 @@ public RegisterUserResponse registerUser(RegisterUserRequest request) { User save = userRepository.save(user); // 회원가입 완료 응답하기 - String accessToken = jwtUtil.createAccessJwt(save.getId(), save.getRole()); - return new RegisterUserResponse(save.getId(), save.getName(), accessToken); + String accessToken = issueTokenService.issueAccessToken(save.getId(), save.getRole()); + String refreshToken = issueTokenService.issueRefreshToken(save.getId()); + + return new RegisterUserResponse(save.getId(), save.getName(), accessToken, refreshToken); } private User mapToUser(RegisterUserRequest request) { From 152d5698ad3d5e4cfce663b993f0fcf0f11194f3 Mon Sep 17 00:00:00 2001 From: JangIkhwan Date: Sun, 4 Jan 2026 21:52:43 +0900 Subject: [PATCH 22/28] =?UTF-8?q?[Feat]=20#148=20=ED=9A=8C=EC=9B=90?= =?UTF-8?q?=EC=A0=95=EB=B3=B4=20=EB=93=B1=EB=A1=9D=20API=EC=97=90=EC=84=9C?= =?UTF-8?q?=20=EB=A6=AC=ED=94=84=EB=A0=88=EC=8B=9C=20=ED=86=A0=ED=81=B0?= =?UTF-8?q?=EC=9D=84=20=EC=9D=91=EB=8B=B5=ED=95=98=EB=8F=84=EB=A1=9D=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 --- .../domain/user/dto/response/RegisterUserResponse.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/kuit/findyou/domain/user/dto/response/RegisterUserResponse.java b/src/main/java/com/kuit/findyou/domain/user/dto/response/RegisterUserResponse.java index fe5f4db5..18a622cf 100644 --- a/src/main/java/com/kuit/findyou/domain/user/dto/response/RegisterUserResponse.java +++ b/src/main/java/com/kuit/findyou/domain/user/dto/response/RegisterUserResponse.java @@ -11,7 +11,10 @@ public record RegisterUserResponse( example = "찾아유") String nickname, @Schema(description = "엑세스 토큰", - example = "accessToken") - String accessToken + example = "aaaa.bbbb.ccc") + String accessToken, + @Schema(description = "리프레시 토큰", + example = "aaaa.bbbb.ccc") + String refreshToken ) { } From 254069b76baf17d4742dd47edb3d33da70f3952e Mon Sep 17 00:00:00 2001 From: JangIkhwan Date: Sun, 4 Jan 2026 21:53:48 +0900 Subject: [PATCH 23/28] =?UTF-8?q?[Test]=20#148=20=ED=9A=8C=EC=9B=90?= =?UTF-8?q?=EB=93=B1=EB=A1=9D=20API=20=ED=85=8C=EC=8A=A4=ED=8A=B8=EC=97=90?= =?UTF-8?q?=EC=84=9C=20=EB=A6=AC=ED=94=84=EB=A0=88=EC=8B=9C=20=ED=86=A0?= =?UTF-8?q?=ED=81=B0=EC=9D=84=20=EA=B2=80=EC=A6=9D=ED=95=98=EB=8F=84?= =?UTF-8?q?=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../findyou/domain/user/controller/UserControllerTest.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/test/java/com/kuit/findyou/domain/user/controller/UserControllerTest.java b/src/test/java/com/kuit/findyou/domain/user/controller/UserControllerTest.java index 34459292..8deb6fce 100644 --- a/src/test/java/com/kuit/findyou/domain/user/controller/UserControllerTest.java +++ b/src/test/java/com/kuit/findyou/domain/user/controller/UserControllerTest.java @@ -135,9 +135,11 @@ void should_Succeed_When_registerAnyoneWhoFirstLoggedIn() { .getObject("data", RegisterUserResponse.class); // then - Role role = jwtUtil.getRole(response.accessToken()); - assertThat(response.nickname()).isEqualTo(nickname); + assertThat(response.accessToken()).isNotBlank(); + assertThat(response.refreshToken()).isNotBlank(); + + Role role = jwtUtil.getRole(response.accessToken()); assertThat(role).isEqualTo(Role.USER); } From 7b3f1ce396b4969d0fc08b14048adbddeef4aed8 Mon Sep 17 00:00:00 2001 From: JangIkhwan Date: Sun, 4 Jan 2026 21:54:31 +0900 Subject: [PATCH 24/28] =?UTF-8?q?[Test]=20#148=20RegisterUserService=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 필요한 모킹 수정 - 리프레시 토큰 반환 여부 검증 추가 --- .../domain/user/service/UserServiceTest.java | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/test/java/com/kuit/findyou/domain/user/service/UserServiceTest.java b/src/test/java/com/kuit/findyou/domain/user/service/UserServiceTest.java index 9aeac3e2..d4876d6c 100644 --- a/src/test/java/com/kuit/findyou/domain/user/service/UserServiceTest.java +++ b/src/test/java/com/kuit/findyou/domain/user/service/UserServiceTest.java @@ -1,12 +1,12 @@ package com.kuit.findyou.domain.user.service; +import com.kuit.findyou.domain.auth.service.IssueTokenService; import com.kuit.findyou.domain.user.dto.request.RegisterUserRequest; import com.kuit.findyou.domain.user.dto.response.RegisterUserResponse; import com.kuit.findyou.domain.user.model.User; import com.kuit.findyou.domain.user.repository.UserRepository; import com.kuit.findyou.domain.user.service.register.RegisterUserServiceImpl; import com.kuit.findyou.global.common.exception.CustomException; -import com.kuit.findyou.global.jwt.util.JwtUtil; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -30,7 +30,7 @@ class UserServiceTest { @Mock private UserRepository userRepository; @Mock - private JwtUtil jwtUtil; + private IssueTokenService issueTokenService; @DisplayName("처음 로그인한 사용자가 회원등록을 하면 성공한다") @Test @@ -38,6 +38,7 @@ void should_Succeed_When_AnyoneWhoFirstLoggedInRegister(){ // given final Long USER_ID = 1L; final String ACCESS_TOKEN = "accessToken"; + final String REFRESH_TOKEN = "refreshToken"; RegisterUserRequest request = getRegisterUserRequest(); @@ -48,7 +49,8 @@ void should_Succeed_When_AnyoneWhoFirstLoggedInRegister(){ .name(request.nickname()) .build()); - when(jwtUtil.createAccessJwt(any(), any())).thenReturn(ACCESS_TOKEN); + when(issueTokenService.issueAccessToken(any(), any())).thenReturn(ACCESS_TOKEN); + when(issueTokenService.issueRefreshToken(any())).thenReturn(REFRESH_TOKEN); // when RegisterUserResponse response = userService.registerUser(request); @@ -57,6 +59,7 @@ void should_Succeed_When_AnyoneWhoFirstLoggedInRegister(){ assertThat(response.userId()).isEqualTo(USER_ID); assertThat(response.nickname()).isEqualTo(request.nickname()); assertThat(response.accessToken()).isEqualTo(ACCESS_TOKEN); + assertThat(response.refreshToken()).isEqualTo(REFRESH_TOKEN); } private static RegisterUserRequest getRegisterUserRequest() { @@ -74,6 +77,7 @@ void should_Succeed_When_GuestRegister(){ // given final Long USER_ID = 1L; final String ACCESS_TOKEN = "accessToken"; + final String REFRESH_TOKEN = "refreshToken"; RegisterUserRequest request = getRegisterUserRequest(); @@ -86,17 +90,19 @@ void should_Succeed_When_GuestRegister(){ .name(request.nickname()) .build()); - when(jwtUtil.createAccessJwt(any(), any())).thenReturn(ACCESS_TOKEN); + when(issueTokenService.issueAccessToken(any(), any())).thenReturn(ACCESS_TOKEN); + when(issueTokenService.issueRefreshToken(any())).thenReturn(REFRESH_TOKEN); // when RegisterUserResponse response = userService.registerUser(request); // then + verify(user).upgradeToMember(eq(request.kakaoId()), eq(request.nickname())); + assertThat(response.userId()).isEqualTo(USER_ID); assertThat(response.nickname()).isEqualTo(request.nickname()); assertThat(response.accessToken()).isEqualTo(ACCESS_TOKEN); - - verify(user).upgradeToMember(eq(request.kakaoId()), eq(request.nickname())); + assertThat(response.refreshToken()).isEqualTo(REFRESH_TOKEN); } @DisplayName("이미 가입한 회원이 회원등록을 하면 예외를 발생시킨다") From 2066921184420dc1f794177183fbe97d7f8cfebb Mon Sep 17 00:00:00 2001 From: JangIkhwan Date: Sun, 4 Jan 2026 21:55:49 +0900 Subject: [PATCH 25/28] =?UTF-8?q?[Refactor]=20#148=20RegisterUserService?= =?UTF-8?q?=EC=9D=98=20=EB=8C=80=EC=9D=91=EB=90=98=EB=8A=94=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=ED=81=B4=EB=9E=98=EC=8A=A4=EC=9D=98=20?= =?UTF-8?q?=EC=9D=B4=EB=A6=84=EA=B3=BC=20=EB=94=94=EB=A0=89=ED=86=A0?= =?UTF-8?q?=EB=A6=AC=20=EC=9C=84=EC=B9=98=EB=A5=BC=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../RegisterUserServiceTest.java} | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) rename src/test/java/com/kuit/findyou/domain/user/service/{UserServiceTest.java => register/RegisterUserServiceTest.java} (97%) diff --git a/src/test/java/com/kuit/findyou/domain/user/service/UserServiceTest.java b/src/test/java/com/kuit/findyou/domain/user/service/register/RegisterUserServiceTest.java similarity index 97% rename from src/test/java/com/kuit/findyou/domain/user/service/UserServiceTest.java rename to src/test/java/com/kuit/findyou/domain/user/service/register/RegisterUserServiceTest.java index d4876d6c..8f5ae88c 100644 --- a/src/test/java/com/kuit/findyou/domain/user/service/UserServiceTest.java +++ b/src/test/java/com/kuit/findyou/domain/user/service/register/RegisterUserServiceTest.java @@ -1,11 +1,10 @@ -package com.kuit.findyou.domain.user.service; +package com.kuit.findyou.domain.user.service.register; import com.kuit.findyou.domain.auth.service.IssueTokenService; import com.kuit.findyou.domain.user.dto.request.RegisterUserRequest; import com.kuit.findyou.domain.user.dto.response.RegisterUserResponse; import com.kuit.findyou.domain.user.model.User; import com.kuit.findyou.domain.user.repository.UserRepository; -import com.kuit.findyou.domain.user.service.register.RegisterUserServiceImpl; import com.kuit.findyou.global.common.exception.CustomException; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -24,7 +23,7 @@ import static org.mockito.Mockito.*; @ExtendWith(MockitoExtension.class) -class UserServiceTest { +class RegisterUserServiceTest { @InjectMocks private RegisterUserServiceImpl userService; @Mock From e60548a079bf6b78107797884dbe636f90c2192c Mon Sep 17 00:00:00 2001 From: JangIkhwan Date: Sun, 4 Jan 2026 23:10:07 +0900 Subject: [PATCH 26/28] =?UTF-8?q?[Chore]=20#159=20CI=EC=97=90=EC=84=9C=20?= =?UTF-8?q?=EB=A1=9C=EA=B7=B8=EB=A5=BC=20=EB=B3=B4=EA=B8=B0=20=EC=9C=84?= =?UTF-8?q?=ED=95=B4=EC=84=9C=20=EC=84=A4=EC=A0=95=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/build.gradle b/build.gradle index d91e4aaa..439ae429 100644 --- a/build.gradle +++ b/build.gradle @@ -16,6 +16,12 @@ java { } } +test { + testLogging { + showStandardStreams = true + } +} + configurations { compileOnly { extendsFrom annotationProcessor From fab1d9e2de777314973b236ca33c5ac9956edce0 Mon Sep 17 00:00:00 2001 From: JangIkhwan Date: Sun, 4 Jan 2026 23:21:29 +0900 Subject: [PATCH 27/28] =?UTF-8?q?[Test]=20#159=20UserControllerTest?= =?UTF-8?q?=EC=97=90=20=ED=85=8C=EC=8A=A4=ED=8A=B8=EC=9A=A9=20Redis=20?= =?UTF-8?q?=EC=84=A4=EC=A0=95=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../findyou/domain/user/controller/UserControllerTest.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/test/java/com/kuit/findyou/domain/user/controller/UserControllerTest.java b/src/test/java/com/kuit/findyou/domain/user/controller/UserControllerTest.java index 8deb6fce..15b1a966 100644 --- a/src/test/java/com/kuit/findyou/domain/user/controller/UserControllerTest.java +++ b/src/test/java/com/kuit/findyou/domain/user/controller/UserControllerTest.java @@ -16,6 +16,7 @@ import com.kuit.findyou.domain.user.repository.UserRepository; import com.kuit.findyou.global.common.util.DatabaseCleaner; import com.kuit.findyou.global.common.util.TestInitializer; +import com.kuit.findyou.global.config.RedisTestContainersConfig; import com.kuit.findyou.global.config.TestDatabaseConfig; import com.kuit.findyou.global.jwt.util.JwtUtil; import io.restassured.RestAssured; @@ -45,7 +46,7 @@ @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @TestInstance(TestInstance.Lifecycle.PER_CLASS) @ActiveProfiles("test") -@Import(TestDatabaseConfig.class) +@Import({RedisTestContainersConfig.class, TestDatabaseConfig.class}) class UserControllerTest { @LocalServerPort From 0fbf3b8d4b83a03c80d685bf0d0c2cb23c2db6d0 Mon Sep 17 00:00:00 2001 From: JangIkhwan Date: Sun, 4 Jan 2026 23:33:17 +0900 Subject: [PATCH 28/28] =?UTF-8?q?[Chore]=20#159=20gradle=20test=20?= =?UTF-8?q?=EC=8B=9C=EC=97=90=20showLogs=20=ED=94=84=EB=A1=9C=ED=8D=BC?= =?UTF-8?q?=ED=8B=B0=EA=B0=80=20=EC=9E=88=EC=9D=84=20=EB=95=8C=EB=A7=8C=20?= =?UTF-8?q?=EC=95=A0=ED=94=8C=EB=A0=88=EC=BC=80=EC=9D=B4=EC=85=98=20?= =?UTF-8?q?=EB=A1=9C=EA=B7=B8=EA=B0=80=20=EB=B3=B4=EC=9D=B4=EB=8F=84?= =?UTF-8?q?=EB=A1=9D=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 439ae429..978b5bd9 100644 --- a/build.gradle +++ b/build.gradle @@ -18,7 +18,7 @@ java { test { testLogging { - showStandardStreams = true + showStandardStreams = project.hasProperty("showLogs") } }