Skip to content

Commit c7d1ebd

Browse files
committed
Fix: 게시글 및 프로필 파일 관련 로직 보완
1 parent dde13f6 commit c7d1ebd

File tree

4 files changed

+14
-106
lines changed

4 files changed

+14
-106
lines changed

src/main/java/com/back/domain/board/post/service/PostService.java

Lines changed: 4 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
import com.back.domain.file.entity.FileAttachment;
1818
import com.back.domain.file.repository.AttachmentMappingRepository;
1919
import com.back.domain.file.repository.FileAttachmentRepository;
20-
import com.back.domain.file.service.FileService;
20+
import com.back.domain.file.service.AttachmentMappingService;
2121
import com.back.domain.user.common.entity.User;
2222
import com.back.domain.user.common.repository.UserRepository;
2323
import com.back.global.exception.CustomException;
@@ -41,7 +41,7 @@ public class PostService {
4141
private final PostCategoryRepository postCategoryRepository;
4242
private final FileAttachmentRepository fileAttachmentRepository;
4343
private final AttachmentMappingRepository attachmentMappingRepository;
44-
private final FileService fileService;
44+
private final AttachmentMappingService attachmentMappingService;
4545

4646
/**
4747
* 게시글 생성 서비스
@@ -183,7 +183,7 @@ private List<FileAttachment> updatePostAttachments(Post post, List<Long> newImag
183183
}
184184

185185
// 기존 첨부 삭제
186-
deletePostAttachments(post, userId);
186+
attachmentMappingService.deleteAttachments(EntityType.POST, post.getId(), userId);
187187

188188
// 새 첨부 매핑 등록
189189
if (newIds.isEmpty()) return List.of();
@@ -195,21 +195,6 @@ private List<FileAttachment> updatePostAttachments(Post post, List<Long> newImag
195195
return attachments;
196196
}
197197

198-
/**
199-
* 게시글 첨부파일 삭제 (S3 + 매핑)
200-
*/
201-
private void deletePostAttachments(Post post, Long userId) {
202-
List<AttachmentMapping> mappings =
203-
attachmentMappingRepository.findAllByEntityTypeAndEntityId(EntityType.POST, post.getId());
204-
for (AttachmentMapping mapping : mappings) {
205-
FileAttachment file = mapping.getFileAttachment();
206-
if (file != null) {
207-
fileService.deleteFile(file.getId(), userId);
208-
}
209-
}
210-
attachmentMappingRepository.deleteAllByEntityTypeAndEntityId(EntityType.POST, post.getId());
211-
}
212-
213198
/**
214199
* 게시글 삭제 서비스
215200
*
@@ -231,15 +216,7 @@ public void deletePost(Long postId, Long userId) {
231216
}
232217

233218
// 첨부 파일 삭제
234-
List<AttachmentMapping> mappings =
235-
attachmentMappingRepository.findAllByEntityTypeAndEntityId(EntityType.POST, post.getId());
236-
for (AttachmentMapping mapping : mappings) {
237-
FileAttachment fileAttachment = mapping.getFileAttachment();
238-
if (fileAttachment != null) {
239-
fileService.deleteFile(fileAttachment.getId(), userId);
240-
}
241-
}
242-
attachmentMappingRepository.deleteAllByEntityTypeAndEntityId(EntityType.POST, post.getId());
219+
attachmentMappingService.deleteAttachments(EntityType.POST, post.getId(), userId);
243220

244221
// Post 삭제
245222
post.remove();

src/main/java/com/back/domain/user/account/service/AccountService.java

Lines changed: 6 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,8 @@
55
import com.back.domain.board.common.dto.PageResponse;
66
import com.back.domain.board.post.dto.PostListResponse;
77
import com.back.domain.board.post.repository.PostRepository;
8-
import com.back.domain.file.entity.AttachmentMapping;
98
import com.back.domain.file.entity.EntityType;
10-
import com.back.domain.file.entity.FileAttachment;
11-
import com.back.domain.file.repository.AttachmentMappingRepository;
12-
import com.back.domain.file.repository.FileAttachmentRepository;
13-
import com.back.domain.file.service.FileService;
9+
import com.back.domain.file.service.AttachmentMappingService;
1410
import com.back.domain.user.account.dto.ChangePasswordRequest;
1511
import com.back.domain.user.account.dto.UserProfileRequest;
1612
import com.back.domain.user.account.dto.UserDetailResponse;
@@ -40,9 +36,7 @@ public class AccountService {
4036
private final UserProfileRepository userProfileRepository;
4137
private final CommentRepository commentRepository;
4238
private final PostRepository postRepository;
43-
private final FileAttachmentRepository fileAttachmentRepository;
44-
private final AttachmentMappingRepository attachmentMappingRepository;
45-
private final FileService fileService;
39+
private final AttachmentMappingService attachmentMappingService;
4640
private final PasswordEncoder passwordEncoder;
4741

4842
/**
@@ -76,87 +70,24 @@ public UserDetailResponse updateUserProfile(Long userId, UserProfileRequest requ
7670
throw new CustomException(ErrorCode.NICKNAME_DUPLICATED);
7771
}
7872

79-
8073
// UserProfile 업데이트
8174
UserProfile profile = user.getUserProfile();
8275
profile.setNickname(request.nickname());
8376
profile.setBio(request.bio());
8477
profile.setBirthDate(request.birthDate());
8578

86-
// TODO: 프로필 이미지 및 매핑 업데이트 리팩토링 필요
8779
// 프로필 이미지 변경이 있는 경우만 수행
8880
String newUrl = request.profileImageUrl();
8981
String oldUrl = profile.getProfileImageUrl();
9082
if (!Objects.equals(newUrl, oldUrl)) {
91-
// 외부 이미지(S3 외부 URL)는 매핑 로직 제외
92-
if (isExternalImageUrl(newUrl)) {
93-
// 기존 매핑만 제거 (소셜 이미지로 바뀌면 내부 매핑 필요 없음)
94-
removeExistingMapping(userId);
95-
} else {
96-
updateProfileImage(userId, newUrl);
97-
}
83+
attachmentMappingService.replaceAttachmentByUrl(EntityType.PROFILE, profile.getId(), userId, newUrl);
9884
profile.setProfileImageUrl(newUrl);
9985
}
10086

10187
// UserDetailResponse로 변환하여 반환
10288
return UserDetailResponse.from(user);
10389
}
10490

105-
/**
106-
* 내부 저장소(S3) 이미지 교체 로직
107-
* - 기존 매핑 및 파일 삭제 후 새 매핑 생성
108-
*/
109-
private void updateProfileImage(Long userId, String newImageUrl) {
110-
111-
// 기존 매핑 제거
112-
removeExistingMapping(userId);
113-
114-
// 새 이미지가 없는 경우
115-
if (newImageUrl == null || newImageUrl.isBlank()) {
116-
return;
117-
}
118-
119-
// 새 파일 조회 및 검증
120-
FileAttachment newAttachment = fileAttachmentRepository
121-
.findByPublicURL(newImageUrl)
122-
.orElseThrow(() -> new CustomException(ErrorCode.FILE_NOT_FOUND));
123-
124-
if (!newAttachment.getUser().getId().equals(userId)) {
125-
throw new CustomException(ErrorCode.FILE_ACCESS_DENIED);
126-
}
127-
128-
// 새 매핑 생성 및 저장
129-
AttachmentMapping newMapping = new AttachmentMapping(newAttachment, EntityType.PROFILE, userId);
130-
attachmentMappingRepository.save(newMapping);
131-
}
132-
133-
/**
134-
* 기존 프로필 이미지 매핑 및 파일 삭제
135-
*/
136-
private void removeExistingMapping(Long userId) {
137-
attachmentMappingRepository.findByEntityTypeAndEntityId(EntityType.PROFILE, userId)
138-
.ifPresent(mapping -> {
139-
FileAttachment oldAttachment = mapping.getFileAttachment();
140-
if (oldAttachment != null) {
141-
fileService.deleteFile(oldAttachment.getId(), userId);
142-
}
143-
attachmentMappingRepository.delete(mapping);
144-
});
145-
}
146-
147-
/**
148-
* 외부 이미지 URL 판별
149-
* - 우리 S3 또는 CDN이 아니면 true
150-
* - 필요 시 application.yml에서 환경변수로 관리
151-
*/
152-
private boolean isExternalImageUrl(String url) {
153-
if (url == null || url.isBlank()) return true;
154-
155-
// TODO: 하드 코딩 제거
156-
return !(url.startsWith("https://team5-s3-1.s3.ap-northeast-2.amazonaws.com")
157-
|| url.contains("cdn.example.com"));
158-
}
159-
16091
/**
16192
* 비밀번호 변경 서비스
16293
* 1. 사용자 조회 및 상태 검증
@@ -196,9 +127,6 @@ public void deleteUser(Long userId) {
196127
// 사용자 조회 및 상태 검증
197128
User user = getValidUser(userId);
198129

199-
// 프로필 이미지 및 매핑 삭제
200-
removeExistingMapping(userId);
201-
202130
// 상태 변경 (soft delete)
203131
user.setUserStatus(UserStatus.DELETED);
204132

@@ -211,6 +139,9 @@ public void deleteUser(Long userId) {
211139
// 개인정보 마스킹
212140
UserProfile profile = user.getUserProfile();
213141
if (profile != null) {
142+
// 프로필 이미지 및 매핑 삭제
143+
attachmentMappingService.deleteAttachments(EntityType.PROFILE, profile.getId(), userId);
144+
214145
profile.setNickname("탈퇴한 회원");
215146
profile.setProfileImageUrl(null);
216147
profile.setBio(null);

src/test/java/com/back/domain/board/post/service/PostServiceTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
import com.back.domain.file.entity.FileAttachment;
1616
import com.back.domain.file.repository.AttachmentMappingRepository;
1717
import com.back.domain.file.repository.FileAttachmentRepository;
18-
import com.back.domain.file.service.FileService;
18+
import com.back.domain.file.service.AttachmentMappingService;
1919
import com.back.domain.user.common.entity.User;
2020
import com.back.domain.user.common.entity.UserProfile;
2121
import com.back.domain.user.common.enums.UserStatus;
@@ -62,7 +62,7 @@ class PostServiceTest {
6262
private AttachmentMappingRepository attachmentMappingRepository;
6363

6464
@MockitoBean
65-
private FileService fileService;
65+
private AttachmentMappingService;
6666

6767
// ====================== 게시글 생성 테스트 ======================
6868

src/test/java/com/back/domain/user/account/service/AccountServiceTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
import com.back.domain.file.entity.FileAttachment;
1515
import com.back.domain.file.repository.AttachmentMappingRepository;
1616
import com.back.domain.file.repository.FileAttachmentRepository;
17-
import com.back.domain.file.service.FileService;
17+
import com.back.domain.file.service.AttachmentMappingService;
1818
import com.back.domain.user.account.dto.ChangePasswordRequest;
1919
import com.back.domain.user.account.dto.UserProfileRequest;
2020
import com.back.domain.user.account.dto.UserDetailResponse;
@@ -74,7 +74,7 @@ class AccountServiceTest {
7474
private PasswordEncoder passwordEncoder;
7575

7676
@MockitoBean
77-
private FileService fileService;
77+
private AttachmentMappingService attachmentMappingService;
7878

7979
private MultipartFile mockMultipartFile(String filename) {
8080
return new MockMultipartFile(filename, filename, "image/png", new byte[]{1, 2, 3});

0 commit comments

Comments
 (0)