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,30 +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
156161 // 요청 DTO에서 "유지할 이미지 URL 목록" 꺼내기
157- List <String > keepImageUrls = Optional .ofNullable (reqBody .keepImageUrls ()).orElse (List .of ());
158-
159- // URL → ID 매핑
160- List <Long > keepIds = post .getImages ().stream ()
161- .filter (img -> keepImageUrls .contains (img .getUrl ()))
162- .map (PostImage ::getId )
163- .toList ();
164-
165- // 요청 DTO에서 "유지할 이미지 ID 목록" 꺼내기
166- // List<Long> keepIds = Optional.ofNullable(reqBody.keepImageIds()).orElse(List.of());
162+ List <String > keepImageUrls = new ArrayList <>(
163+ Optional .ofNullable (reqBody .keepImageUrls ()).orElse (List .of ()));
164+ keepImageUrls .addAll (addedImgUrls );
167165
168- // 현재 게시글의 이미지들을 (id -> 객체) 매핑으로 변환
169- Map <Long , PostImage > existingById = post .getImages ().stream ()
170- .collect (Collectors .toMap (PostImage ::getId , Function .identity ()));
166+ // 🔹 현재 게시글의 모든 이미지 가져오기
167+ List <PostImage > existingImages = new ArrayList <>(post .getImages ());
171168
172169 // 삭제될 이미지 (DB + S3)
173170 List <PostImage > toRemove = post .getImages ().stream ()
174- .filter (img -> !keepIds .contains (img .getId ()))
171+ .filter (img -> !keepImageUrls .contains (img .getUrl ()))
175172 .toList ();
176173
177174 List <String > deleteKeysAfterCommit = toRemove .stream ()
@@ -183,33 +180,40 @@ public PostResponseDto updatePost(Long postId, PostUpdateRequestDto reqBody, Lis
183180
184181 // 유지할 이미지 정렬
185182 int order = 0 ;
186- for (Long keepId : keepIds ) {
187- PostImage img = existingById .get (keepId );
188- 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+ }
189201 }
190202
191- // 새 이미지 추가
192- for (UploadedFileDto u : uploaded ) {
193- post .getImages ().add (PostImage .builder ()
194- .post (post )
195- .fileName (u .fileName ())
196- .url (u .url ())
197- .sortOrder (order ++)
198- .build ());
199- }
203+ List <String > uploadedNames = new ArrayList <>(uploadedFileNames );
200204
201205 // 트랜잭션 완료 후 처리
202206 TransactionSynchronizationManager .registerSynchronization (new TransactionSynchronization () {
203207 @ Override
204208 public void afterCompletion (int status ) {
205209 if (status == STATUS_ROLLED_BACK ) {
206- uploadedFileNames .forEach (fileService ::deleteFile );
210+ uploadedNames .forEach (fileService ::deleteFile );
207211 } else if (status == STATUS_COMMITTED ) {
208212 deleteKeysAfterCommit .forEach (fileService ::deleteFile );
209213 }
210214 }
211215 });
212- }
216+
213217 if (reqBody .videoUrl () != null && !reqBody .videoUrl ().isBlank ()) {
214218 post .updateVideo (reqBody .videoUrl ());
215219 }
@@ -221,6 +225,13 @@ public void afterCompletion(int status) {
221225 return new PostResponseDto (post );
222226 }
223227
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+
224235 // 게시글 삭제 로직
225236 @ Transactional
226237 public void deletePost (Long postId ) {
0 commit comments