From cdf858a42fb99a36a88d22473a9a2ef72027a4e9 Mon Sep 17 00:00:00 2001 From: "dev.geonwoo_" Date: Sat, 19 Sep 2026 01:04:02 +0900 Subject: [PATCH] =?UTF-8?q?[Fix]#11=20=EB=B0=B1=EC=97=94=EB=93=9C=20?= =?UTF-8?q?=EA=B8=B0=EB=B3=B8=20=ED=94=84=EB=A1=9C=ED=95=84=20=EC=9D=B4?= =?UTF-8?q?=EB=AF=B8=EC=A7=80=20=EC=84=A4=EC=A0=95=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.example | 1 - README.md | 1 - .../domain/user/service/ProfileService.java | 15 +--- src/main/resources/application.yaml | 2 - .../user/service/ProfileServiceTest.java | 88 +++++++++++++++++++ 5 files changed, 92 insertions(+), 15 deletions(-) create mode 100644 src/test/java/com/quespot/domain/user/service/ProfileServiceTest.java diff --git a/.env.example b/.env.example index 84e5e05..16579ab 100644 --- a/.env.example +++ b/.env.example @@ -33,7 +33,6 @@ JWT_REFRESH_TOKEN_COOKIE_SECURE=false JWT_REFRESH_TOKEN_COOKIE_SAME_SITE=Lax CORS_ALLOWED_ORIGINS=http://localhost:5173,http://localhost:8080,https://quespot.site,https://www.quespot.site -DEFAULT_PROFILE_IMAGE_URL=https://example.com/images/default-profile.png GOOGLE_OAUTH_ENABLED=false GOOGLE_CLIENT_ID= diff --git a/README.md b/README.md index 5b8b3e1..68e330d 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,6 @@ CREATE DATABASE IF NOT EXISTS quespot ``` - 환경변수는 `.env.example`을 참고해 로컬 환경이나 IDE 실행 설정에 등록합니다. Spring Boot는 `.env` 파일을 자동으로 읽지 않으므로 터미널에서 실행할 때는 직접 export가 필요합니다. -- `DEFAULT_PROFILE_IMAGE_URL`은 프로필에 S3 Object Key가 없을 때 사용할 기본 이미지의 HTTPS URL입니다. - Google 로그인을 사용하려면 `.env.example`의 `GOOGLE_*` 환경변수를 등록하고 `GOOGLE_OAUTH_ENABLED=true`로 설정합니다. - Kakao 로그인을 사용하려면 `.env.example`의 `KAKAO_*` 환경변수를 등록하고 `KAKAO_OAUTH_ENABLED=true`로 설정합니다. - Naver 로그인을 사용하려면 `.env.example`의 `NAVER_*` 환경변수를 등록하고 `NAVER_OAUTH_ENABLED=true`로 설정합니다. diff --git a/src/main/java/com/quespot/domain/user/service/ProfileService.java b/src/main/java/com/quespot/domain/user/service/ProfileService.java index 02414ac..15cf42b 100644 --- a/src/main/java/com/quespot/domain/user/service/ProfileService.java +++ b/src/main/java/com/quespot/domain/user/service/ProfileService.java @@ -16,7 +16,6 @@ import com.quespot.global.file.enums.UploadPurpose; import com.quespot.global.file.service.FileService; import com.quespot.global.security.principal.AuthenticatedUser; -import org.springframework.beans.factory.annotation.Value; import org.springframework.dao.DataIntegrityViolationException; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -27,18 +26,15 @@ public class ProfileService { private final UserRepository userRepository; private final UserProfileRepository userProfileRepository; private final FileService fileService; - private final String defaultProfileImageUrl; public ProfileService( UserRepository userRepository, UserProfileRepository userProfileRepository, - FileService fileService, - @Value("${app.profile.default-image-url}") String defaultProfileImageUrl + FileService fileService ) { this.userRepository = userRepository; this.userProfileRepository = userProfileRepository; this.fileService = fileService; - this.defaultProfileImageUrl = defaultProfileImageUrl; } // 프로필 생성 로직 @@ -142,12 +138,9 @@ private String resolveProfileImageObjectKey(Long userId, String objectKey) { private ProfileResponseDTO toProfileResponseDTO(UserProfile profile) { String objectKey = profile.getProfileImageObjectKey(); - String profileImageUrl; - if (objectKey == null || objectKey.isBlank()) { - profileImageUrl = defaultProfileImageUrl; - } else { - profileImageUrl = fileService.createPresignedDownloadUrl(objectKey); - } + String profileImageUrl = objectKey == null || objectKey.isBlank() + ? null + : fileService.createPresignedDownloadUrl(objectKey); return ProfileConverter.toProfileResponseDTO(profile, profileImageUrl); } } diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index f82477e..8585da2 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -79,8 +79,6 @@ app: region: ${AWS_REGION:ap-northeast-2} presigned-url-expiration-seconds: ${S3_PRESIGNED_URL_EXPIRATION_SECONDS:300} max-file-size-bytes: ${S3_MAX_FILE_SIZE_BYTES:10485760} - profile: - default-image-url: ${DEFAULT_PROFILE_IMAGE_URL:https://example.com/images/default-profile.png} oauth2: frontend-redirect-uri: ${OAUTH2_FRONTEND_REDIRECT_URI:http://localhost:5173/oauth/callback} allowed-frontend-redirect-uris: ${OAUTH2_ALLOWED_FRONTEND_REDIRECT_URIS:${OAUTH2_FRONTEND_REDIRECT_URI:http://localhost:5173/oauth/callback}} diff --git a/src/test/java/com/quespot/domain/user/service/ProfileServiceTest.java b/src/test/java/com/quespot/domain/user/service/ProfileServiceTest.java new file mode 100644 index 0000000..1a2973a --- /dev/null +++ b/src/test/java/com/quespot/domain/user/service/ProfileServiceTest.java @@ -0,0 +1,88 @@ +package com.quespot.domain.user.service; + +import com.quespot.domain.user.entity.User; +import com.quespot.domain.user.entity.UserProfile; +import com.quespot.domain.user.enums.Gender; +import com.quespot.domain.user.enums.ResidenceRegion; +import com.quespot.domain.user.enums.UserRole; +import com.quespot.domain.user.repository.UserProfileRepository; +import com.quespot.domain.user.repository.UserRepository; +import com.quespot.global.file.service.FileService; +import com.quespot.global.security.principal.AuthenticatedUser; +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.test.util.ReflectionTestUtils; + +import java.time.LocalDate; +import java.util.Optional; +import java.util.Set; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoInteractions; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +class ProfileServiceTest { + + private static final Long USER_ID = 1L; + private static final AuthenticatedUser AUTHENTICATED_USER = + new AuthenticatedUser(USER_ID, UserRole.USER, "session-id"); + + @Mock + private UserRepository userRepository; + + @Mock + private UserProfileRepository userProfileRepository; + + @Mock + private FileService fileService; + + @InjectMocks + private ProfileService profileService; + + @Test + void returnsNullImageUrlWhenProfileImageIsNotSet() { + UserProfile profile = createProfile(null); + when(userRepository.findById(USER_ID)).thenReturn(Optional.of(profile.getUser())); + when(userProfileRepository.findByUserId(USER_ID)).thenReturn(Optional.of(profile)); + + var response = profileService.getProfile(AUTHENTICATED_USER); + + assertThat(response.profileImageUrl()).isNull(); + verifyNoInteractions(fileService); + } + + @Test + void returnsPresignedImageUrlWhenProfileImageIsSet() { + String objectKey = "profiles/1/profile.png"; + String presignedUrl = "https://example.com/presigned-profile.png"; + UserProfile profile = createProfile(objectKey); + when(userRepository.findById(USER_ID)).thenReturn(Optional.of(profile.getUser())); + when(userProfileRepository.findByUserId(USER_ID)).thenReturn(Optional.of(profile)); + when(fileService.createPresignedDownloadUrl(objectKey)).thenReturn(presignedUrl); + + var response = profileService.getProfile(AUTHENTICATED_USER); + + assertThat(response.profileImageUrl()).isEqualTo(presignedUrl); + verify(fileService).createPresignedDownloadUrl(objectKey); + } + + private UserProfile createProfile(String objectKey) { + User user = User.createEmailUser("member@example.com", "encoded-password"); + ReflectionTestUtils.setField(user, "id", USER_ID); + return UserProfile.create( + user, + "회원", + objectKey, + Gender.MALE, + LocalDate.of(2000, 1, 1), + ResidenceRegion.SEOUL, + null, + Set.of() + ); + } +}