Skip to content

Commit 484f529

Browse files
committed
refactor: #73 service 코드 로직 수정 및 코드 수정
1 parent e05d956 commit 484f529

File tree

10 files changed

+346
-64
lines changed

10 files changed

+346
-64
lines changed

src/main/java/com/ajou/hertz/common/file/dto/FileDto.java

+1-2
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ public static FileDto create(
2323
}
2424

2525
public String getStoredFileUrl() {
26-
return url + "/" + storedName;
26+
return url;
2727
}
28-
2928
}

src/main/java/com/ajou/hertz/domain/user/controller/UserController.java

+10-4
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,12 @@
1414
import org.springframework.web.bind.annotation.RequestBody;
1515
import org.springframework.web.bind.annotation.RequestMapping;
1616
import org.springframework.web.bind.annotation.RequestParam;
17+
import org.springframework.web.bind.annotation.RequestPart;
1718
import org.springframework.web.bind.annotation.RestController;
1819
import org.springframework.web.multipart.MultipartFile;
1920

2021
import com.ajou.hertz.common.auth.UserPrincipal;
22+
import com.ajou.hertz.common.file.dto.FileDto;
2123
import com.ajou.hertz.common.validator.PhoneNumber;
2224
import com.ajou.hertz.domain.user.dto.UserDto;
2325
import com.ajou.hertz.domain.user.dto.request.SignUpRequest;
@@ -27,6 +29,7 @@
2729
import com.ajou.hertz.domain.user.dto.response.UserResponse;
2830
import com.ajou.hertz.domain.user.dto.response.UserWithLinkedAccountInfoResponse;
2931
import com.ajou.hertz.domain.user.service.UserCommandService;
32+
import com.ajou.hertz.domain.user.service.UserProfileImageCommandService;
3033
import com.ajou.hertz.domain.user.service.UserQueryService;
3134

3235
import io.swagger.v3.oas.annotations.Operation;
@@ -49,6 +52,7 @@
4952
public class UserController {
5053

5154
private final UserCommandService userCommandService;
55+
private final UserProfileImageCommandService userProfileImageCommandService;
5256
private final UserQueryService userQueryService;
5357

5458
@Operation(
@@ -125,15 +129,17 @@ public ResponseEntity<UserResponse> signUpV1(
125129
security = @SecurityRequirement(name = "access-token")
126130
)
127131
@PutMapping(
128-
value = "/me/profile-image",
132+
value = "/me/profile-images",
129133
headers = API_VERSION_HEADER_NAME + "=" + 1,
130134
consumes = MediaType.MULTIPART_FORM_DATA_VALUE
131135
)
132-
public UserResponse updateProfileImageUrlV1(
136+
public UserResponse updateProfileImageV1(
133137
@AuthenticationPrincipal UserPrincipal userPrincipal,
134-
@RequestParam("profileImage") MultipartFile profileImage
138+
@RequestPart("profileImage") MultipartFile profileImage
135139
) {
136-
UserDto userUpdated = userCommandService.updateProfileImageUrl(userPrincipal.getUserId(), profileImage);
140+
FileDto uploadedFile = userProfileImageCommandService.uploadProfileImage(userPrincipal.getUserId(),
141+
profileImage);
142+
UserDto userUpdated = userCommandService.updateProfileImage(userPrincipal.getUserId(), uploadedFile);
137143
return UserResponse.from(userUpdated);
138144
}
139145

src/main/java/com/ajou/hertz/domain/user/entity/User.java

-4
Original file line numberDiff line numberDiff line change
@@ -105,10 +105,6 @@ public void changeProfileImageUrl(String profileImageUrl) {
105105
this.profileImageUrl = profileImageUrl;
106106
}
107107

108-
public UserProfileImage getProfileImage() {
109-
return UserProfileImage.of(profileImageUrl);
110-
}
111-
112108
public void changeContactLink(String contactLink) {
113109
this.contactLink = contactLink;
114110
}

src/main/java/com/ajou/hertz/domain/user/entity/UserProfileImage.java

+9-3
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ public class UserProfileImage extends FileEntity {
2424
@Column(name = "user_profile_image_id", nullable = false)
2525
private Long id;
2626

27-
@JoinColumn(name = "user_id", nullable = false)
27+
@JoinColumn(name = "user_id", nullable = false, unique = true)
2828
@OneToOne(fetch = FetchType.LAZY)
2929
private User user;
3030

@@ -34,7 +34,13 @@ private UserProfileImage(Long id, User user, String originalName, String storedN
3434
this.user = user;
3535
}
3636

37-
public static UserProfileImage of(String profileImageUrl) {
38-
return new UserProfileImage(null, null, null, null, profileImageUrl);
37+
public static UserProfileImage create(
38+
User user,
39+
String originalName,
40+
String storedName,
41+
String url
42+
) {
43+
return new UserProfileImage(null, user, originalName, storedName, url);
3944
}
45+
4046
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package com.ajou.hertz.domain.user.repository;
2+
3+
import java.util.Optional;
4+
5+
import org.springframework.data.jpa.repository.JpaRepository;
6+
7+
import com.ajou.hertz.domain.user.entity.UserProfileImage;
8+
9+
public interface UserProfileImageRepository extends JpaRepository<UserProfileImage, Long> {
10+
Optional<UserProfileImage> findById(Long userId);
11+
}

src/main/java/com/ajou/hertz/domain/user/service/UserCommandService.java

+11-22
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,8 @@
66
import org.springframework.stereotype.Service;
77
import org.springframework.transaction.annotation.Transactional;
88
import org.springframework.util.StringUtils;
9-
import org.springframework.web.multipart.MultipartFile;
109

1110
import com.ajou.hertz.common.file.dto.FileDto;
12-
import com.ajou.hertz.common.file.service.FileService;
1311
import com.ajou.hertz.common.kakao.dto.response.KakaoUserInfoResponse;
1412
import com.ajou.hertz.common.properties.HertzProperties;
1513
import com.ajou.hertz.domain.user.constant.Gender;
@@ -19,6 +17,7 @@
1917
import com.ajou.hertz.domain.user.exception.UserEmailDuplicationException;
2018
import com.ajou.hertz.domain.user.exception.UserKakaoUidDuplicationException;
2119
import com.ajou.hertz.domain.user.exception.UserPhoneDuplicationException;
20+
import com.ajou.hertz.domain.user.repository.UserProfileImageRepository;
2221
import com.ajou.hertz.domain.user.repository.UserRepository;
2322

2423
import lombok.RequiredArgsConstructor;
@@ -32,7 +31,7 @@ public class UserCommandService {
3231
private final UserRepository userRepository;
3332
private final PasswordEncoder passwordEncoder;
3433
private final HertzProperties hertzProperties;
35-
private final FileService fileService;
34+
private final UserProfileImageRepository userProfileImageRepository;
3635

3736
/**
3837
* 새로운 회원을 등록한다.
@@ -135,31 +134,21 @@ private String generateRandom16CharString() {
135134
}
136135

137136
/**
138-
* 유저의 프로필 이미지를 업데이트한다.
137+
* 전달된 이미지로 프로필 이미지 url을 변경한다.
139138
*
140-
* @param userId 유저 id
141-
* @param newProfileImage 새로운 프로필 이미지
142-
*
143-
* @return 업데이트된 유저 정보
139+
* @param userId 유저의 ID
140+
* @param uploadedFile 변경할 이미지 파일
141+
*
142+
* @return 변경된 유저 정보
144143
*/
145-
public UserDto updateProfileImageUrl(Long userId, MultipartFile newProfileImage) {
144+
public UserDto updateProfileImage(Long userId, FileDto uploadedFile) {
146145
User user = userQueryService.getById(userId);
147-
String uploadPath = "user-profile-image/";
148-
149-
FileDto uploadedFile = fileService.uploadFile(newProfileImage, uploadPath);
150146
String newProfileImageUrl = uploadedFile.getStoredFileUrl();
151-
152-
String oldProfileImageUrl = user.getProfileImageUrl();
153-
154-
String oldFileName = oldProfileImageUrl.substring(oldProfileImageUrl.lastIndexOf('/') + 1);
155-
String fullPathToDelete = uploadPath + oldFileName;
156-
fileService.deleteFile(fullPathToDelete);
157-
158147
user.changeProfileImageUrl(newProfileImageUrl);
159-
return UserDto.from(user);
160-
}
148+
return UserDto.from(user);
149+
}
161150

162-
/**
151+
/**
163152
*연락 수단을 변경합니다.
164153
*
165154
* @param userId 유저의 ID
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package com.ajou.hertz.domain.user.service;
2+
3+
import java.util.Optional;
4+
5+
import org.springframework.stereotype.Service;
6+
import org.springframework.transaction.annotation.Transactional;
7+
import org.springframework.web.multipart.MultipartFile;
8+
9+
import com.ajou.hertz.common.file.dto.FileDto;
10+
import com.ajou.hertz.common.file.service.FileService;
11+
import com.ajou.hertz.domain.user.entity.User;
12+
import com.ajou.hertz.domain.user.entity.UserProfileImage;
13+
import com.ajou.hertz.domain.user.repository.UserProfileImageRepository;
14+
15+
import lombok.RequiredArgsConstructor;
16+
17+
@RequiredArgsConstructor
18+
@Transactional
19+
@Service
20+
public class UserProfileImageCommandService {
21+
22+
private final UserQueryService userQueryService;
23+
private final FileService fileService;
24+
private final UserProfileImageRepository userProfileImageRepository;
25+
26+
/**
27+
* 유저의 프로필 이미지를 업데이트한다.
28+
*
29+
* @param userId 유저 id
30+
* @param newProfileImage 새로운 프로필 이미지
31+
*
32+
* @return 업로드된 파일 정보가 담긴 dto
33+
*/
34+
public FileDto uploadProfileImage(Long userId, MultipartFile newProfileImage) {
35+
User user = userQueryService.getById(userId);
36+
37+
Optional<UserProfileImage> optionalOldProfileImage = userProfileImageRepository.findById(userId);
38+
if (optionalOldProfileImage.isPresent()) {
39+
UserProfileImage oldProfileImage = optionalOldProfileImage.get();
40+
userProfileImageRepository.delete(oldProfileImage);
41+
userProfileImageRepository.flush();
42+
fileService.deleteFile(oldProfileImage.getStoredName());
43+
}
44+
45+
String uploadPath = "user-profile-images/";
46+
FileDto uploadedFile = fileService.uploadFile(newProfileImage, uploadPath);
47+
48+
UserProfileImage newUserProfileImage = UserProfileImage.create(
49+
user, uploadedFile.getOriginalName(), uploadedFile.getStoredName(), uploadedFile.getStoredFileUrl());
50+
userProfileImageRepository.save(newUserProfileImage);
51+
52+
return uploadedFile;
53+
}
54+
}

src/test/java/com/ajou/hertz/unit/domain/user/controller/UserControllerTest.java

+21-3
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,14 @@
3131
import com.ajou.hertz.common.auth.JwtTokenProvider;
3232
import com.ajou.hertz.common.auth.UserPrincipal;
3333
import com.ajou.hertz.common.config.SecurityConfig;
34+
import com.ajou.hertz.common.file.dto.FileDto;
3435
import com.ajou.hertz.domain.user.constant.Gender;
3536
import com.ajou.hertz.domain.user.constant.RoleType;
3637
import com.ajou.hertz.domain.user.controller.UserController;
3738
import com.ajou.hertz.domain.user.dto.UserDto;
3839
import com.ajou.hertz.domain.user.dto.request.SignUpRequest;
3940
import com.ajou.hertz.domain.user.service.UserCommandService;
41+
import com.ajou.hertz.domain.user.service.UserProfileImageCommandService;
4042
import com.ajou.hertz.domain.user.service.UserQueryService;
4143
import com.ajou.hertz.util.ReflectionUtils;
4244
import com.fasterxml.jackson.databind.ObjectMapper;
@@ -61,6 +63,9 @@ class UserControllerTest {
6163
@MockBean
6264
private UserQueryService userQueryService;
6365

66+
@MockBean
67+
private UserProfileImageCommandService userProfileImageCommandService;
68+
6469
private final MockMvc mvc;
6570

6671
private final ObjectMapper objectMapper;
@@ -224,12 +229,16 @@ public void securitySetUp() throws Exception {
224229
"test".getBytes()
225230
);
226231
UserDetails userDetails = createTestUser(userId);
232+
FileDto uploadedFile = createFileDto();
227233
UserDto expectedResult = createUserDto(userId);
228-
given(userCommandService.updateProfileImageUrl(userId, profileImage)).willReturn(expectedResult);
234+
235+
given(userProfileImageCommandService.uploadProfileImage(userId, profileImage)).willReturn(
236+
uploadedFile);
237+
given(userCommandService.updateProfileImage(userId, uploadedFile)).willReturn(expectedResult);
229238

230239
// when & then
231240
mvc.perform(
232-
multipart("/api/users/me/profile-image")
241+
multipart("/api/users/me/profile-images")
233242
.file(profileImage)
234243
.header(API_VERSION_HEADER_NAME, 1)
235244
.with(user(userDetails))
@@ -240,7 +249,8 @@ public void securitySetUp() throws Exception {
240249
)
241250
.andExpect(status().isOk())
242251
.andExpect(jsonPath("$.profileImageUrl").value(expectedResult.getProfileImageUrl()));
243-
then(userCommandService).should().updateProfileImageUrl(userId, profileImage);
252+
then(userProfileImageCommandService).should().uploadProfileImage(userId, profileImage);
253+
then(userCommandService).should().updateProfileImage(userId, uploadedFile);
244254
verifyEveryMocksShouldHaveNoMoreInteractions();
245255
}
246256

@@ -270,6 +280,7 @@ public void securitySetUp() throws Exception {
270280
private void verifyEveryMocksShouldHaveNoMoreInteractions() {
271281
then(userCommandService).shouldHaveNoMoreInteractions();
272282
then(userQueryService).shouldHaveNoMoreInteractions();
283+
then(userProfileImageCommandService).shouldHaveNoMoreInteractions();
273284
}
274285

275286
private SignUpRequest createSignUpRequest(String email, String password, String phone) throws Exception {
@@ -314,4 +325,11 @@ private UserDetails createTestUser(Long userId) throws Exception {
314325
return new UserPrincipal(createUserDto(userId));
315326
}
316327

328+
private FileDto createFileDto() throws Exception {
329+
return ReflectionUtils.createFileDto(
330+
"test.jpg",
331+
"test-stored.jpg",
332+
"https://example.com/user-profile-images/storedFileName.jpg");
333+
}
334+
317335
}

0 commit comments

Comments
 (0)