2424import com .back .global .file .dto .UploadedFileDto ;
2525import com .back .global .file .service .FileService ;
2626import com .back .global .rq .Rq ;
27+ import java .util .ArrayList ;
2728import java .util .List ;
28- import java .util .Map ;
2929import java .util .NoSuchElementException ;
3030import java .util .Optional ;
31- import java .util .function .Function ;
3231import java .util .stream .Collectors ;
3332import lombok .RequiredArgsConstructor ;
3433import org .springframework .stereotype .Service ;
@@ -148,21 +147,28 @@ public PostResponseDto updatePost(Long postId, PostUpdateRequestDto reqBody, Lis
148147 if (reqBody .content () != null && !reqBody .content ().isBlank ()) {
149148 post .updateContent (reqBody .content ());
150149 }
150+
151+ List <String > addedImgUrls = List .of ();
152+ List <String > uploadedFileNames = List .of ();
153+
151154 if (images != null && !images .isEmpty ()) {
152155 // 새 이미지 업로드
153156 List <UploadedFileDto > uploaded = fileService .uploadFiles (images );
154- List <String > uploadedFileNames = uploaded .stream ().map (UploadedFileDto ::fileName ).toList ();
157+ addedImgUrls = uploaded .stream ().map (UploadedFileDto ::url ).toList ();
158+ uploadedFileNames = uploaded .stream ().map (UploadedFileDto ::fileName ).toList ();
159+ }
155160
156- // 요청 DTO에서 "유지할 이미지 ID 목록" 꺼내기
157- List <Long > keepIds = Optional .ofNullable (reqBody .keepImageIds ()).orElse (List .of ());
161+ // 요청 DTO에서 "유지할 이미지 URL 목록" 꺼내기
162+ List <String > keepImageUrls = new ArrayList <>(
163+ Optional .ofNullable (reqBody .keepImageUrls ()).orElse (List .of ()));
164+ keepImageUrls .addAll (addedImgUrls );
158165
159- // 현재 게시글의 이미지들을 (id -> 객체) 매핑으로 변환
160- Map <Long , PostImage > existingById = post .getImages ().stream ()
161- .collect (Collectors .toMap (PostImage ::getId , Function .identity ()));
166+ // 🔹 현재 게시글의 모든 이미지 가져오기
167+ List <PostImage > existingImages = new ArrayList <>(post .getImages ());
162168
163169 // 삭제될 이미지 (DB + S3)
164170 List <PostImage > toRemove = post .getImages ().stream ()
165- .filter (img -> !keepIds .contains (img .getId ()))
171+ .filter (img -> !keepImageUrls .contains (img .getUrl ()))
166172 .toList ();
167173
168174 List <String > deleteKeysAfterCommit = toRemove .stream ()
@@ -174,33 +180,40 @@ public PostResponseDto updatePost(Long postId, PostUpdateRequestDto reqBody, Lis
174180
175181 // 유지할 이미지 정렬
176182 int order = 0 ;
177- for (Long keepId : keepIds ) {
178- PostImage img = existingById .get (keepId );
179- if (img != null ) img .updateSortOrder (order ++);
183+ for (String url : keepImageUrls ) {
184+ // 기존 이미지인지 확인
185+ PostImage existing = existingImages .stream ()
186+ .filter (img -> img .getUrl ().equals (url ))
187+ .findFirst ()
188+ .orElse (null );
189+
190+ if (existing != null ) {
191+ existing .updateSortOrder (order ++);
192+ } else {
193+ // 새로 추가된 이미지
194+ post .getImages ().add (PostImage .builder ()
195+ .post (post )
196+ .fileName (extractFileNameFromUrl (url )) // URL에서 파일명 추출 함수 아래 참고
197+ .url (url )
198+ .sortOrder (order ++)
199+ .build ());
200+ }
180201 }
181202
182- // 새 이미지 추가
183- for (UploadedFileDto u : uploaded ) {
184- post .getImages ().add (PostImage .builder ()
185- .post (post )
186- .fileName (u .fileName ())
187- .url (u .url ())
188- .sortOrder (order ++)
189- .build ());
190- }
203+ List <String > uploadedNames = new ArrayList <>(uploadedFileNames );
191204
192205 // 트랜잭션 완료 후 처리
193206 TransactionSynchronizationManager .registerSynchronization (new TransactionSynchronization () {
194207 @ Override
195208 public void afterCompletion (int status ) {
196209 if (status == STATUS_ROLLED_BACK ) {
197- uploadedFileNames .forEach (fileService ::deleteFile );
210+ uploadedNames .forEach (fileService ::deleteFile );
198211 } else if (status == STATUS_COMMITTED ) {
199212 deleteKeysAfterCommit .forEach (fileService ::deleteFile );
200213 }
201214 }
202215 });
203- }
216+
204217 if (reqBody .videoUrl () != null && !reqBody .videoUrl ().isBlank ()) {
205218 post .updateVideo (reqBody .videoUrl ());
206219 }
@@ -212,6 +225,13 @@ public void afterCompletion(int status) {
212225 return new PostResponseDto (post );
213226 }
214227
228+ private String extractFileNameFromUrl (String url ) {
229+ if (url == null ) return null ;
230+ int lastSlash = url .lastIndexOf ('/' );
231+ return (lastSlash != -1 ) ? url .substring (lastSlash + 1 ) : url ;
232+ }
233+
234+
215235 // 게시글 삭제 로직
216236 @ Transactional
217237 public void deletePost (Long postId ) {
0 commit comments