55import com .back .domain .board .common .dto .PageResponse ;
66import com .back .domain .board .post .dto .PostListResponse ;
77import com .back .domain .board .post .repository .PostRepository ;
8- import com .back .domain .file .entity .AttachmentMapping ;
98import 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 ;
1410import com .back .domain .user .account .dto .ChangePasswordRequest ;
1511import com .back .domain .user .account .dto .UserProfileRequest ;
1612import 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 );
0 commit comments