diff --git a/src/main/java/org/ezcode/codetest/application/usermanagement/user/service/UserService.java b/src/main/java/org/ezcode/codetest/application/usermanagement/user/service/UserService.java index 2cda108d..32ff7efa 100644 --- a/src/main/java/org/ezcode/codetest/application/usermanagement/user/service/UserService.java +++ b/src/main/java/org/ezcode/codetest/application/usermanagement/user/service/UserService.java @@ -35,6 +35,7 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.StringUtils; import org.springframework.web.multipart.MultipartFile; import lombok.RequiredArgsConstructor; @@ -106,10 +107,10 @@ public UserInfoResponse modifyUserInfo(AuthUser authUser, ModifyUserInfoRequest String oldImageUrl = user.getProfileImageUrl(); user.modifyProfileImage(profileImageUrl); - if (oldImageUrl!=null) { - s3Uploader.delete(user.getProfileImageUrl(), "profile"); - } + if (StringUtils.hasText(oldImageUrl)) { + s3Uploader.delete(oldImageUrl, "profile"); + } } return UserInfoResponse.builder() diff --git a/src/main/java/org/ezcode/codetest/infrastructure/s3/S3Uploader.java b/src/main/java/org/ezcode/codetest/infrastructure/s3/S3Uploader.java index 8198352c..c5f05088 100644 --- a/src/main/java/org/ezcode/codetest/infrastructure/s3/S3Uploader.java +++ b/src/main/java/org/ezcode/codetest/infrastructure/s3/S3Uploader.java @@ -1,6 +1,8 @@ package org.ezcode.codetest.infrastructure.s3; import java.io.IOException; +import java.net.URLDecoder; +import java.nio.charset.StandardCharsets; import java.util.UUID; import org.ezcode.codetest.infrastructure.s3.exception.S3Exception; @@ -78,7 +80,10 @@ public void delete(String fileUrl, String dirName) { if (dirName.equalsIgnoreCase("profile")) { fileName = extractKeyFromProfileUrl(fileUrl); } - amazonS3.deleteObject(bucket, fileName); // S3 내 이미지 객체 제거. + + String decodedFileName = URLDecoder.decode(fileName, StandardCharsets.UTF_8); + amazonS3.deleteObject(bucket, decodedFileName); // S3 내 이미지 객체 제거. + log.info("S3에서 이미지 삭제 완료: {}", fileName); } catch (Exception e) { log.error("S3 이미지 삭제 실패: {}", fileUrl, e); diff --git a/src/main/java/org/ezcode/codetest/infrastructure/swagger/config/SwaggerConfig.java b/src/main/java/org/ezcode/codetest/infrastructure/swagger/config/SwaggerConfig.java index 6dde2f07..f607d163 100644 --- a/src/main/java/org/ezcode/codetest/infrastructure/swagger/config/SwaggerConfig.java +++ b/src/main/java/org/ezcode/codetest/infrastructure/swagger/config/SwaggerConfig.java @@ -16,6 +16,10 @@ @Server( url = "https://api.ezcode.my", // ← 슬래시 없이 호스트만! description = "Production server" + ), + @Server( + url = "http://localhost:8080", + description = "Local Server" ) }, info = @Info(title = "API 문서", version = "v1"), diff --git a/src/main/java/org/ezcode/codetest/presentation/usermanagement/UserController.java b/src/main/java/org/ezcode/codetest/presentation/usermanagement/UserController.java index 27f2c0f4..f4250bd6 100644 --- a/src/main/java/org/ezcode/codetest/presentation/usermanagement/UserController.java +++ b/src/main/java/org/ezcode/codetest/presentation/usermanagement/UserController.java @@ -1,10 +1,8 @@ package org.ezcode.codetest.presentation.usermanagement; -import org.ezcode.codetest.application.submission.dto.response.language.LanguageResponse; import org.ezcode.codetest.application.usermanagement.user.dto.request.ModifyUserInfoRequest; import org.ezcode.codetest.application.usermanagement.user.dto.request.ChangeUserPasswordRequest; import org.ezcode.codetest.application.usermanagement.user.dto.response.ChangeUserPasswordResponse; -import org.ezcode.codetest.application.usermanagement.user.dto.response.GrantAdminRoleResponse; import org.ezcode.codetest.application.usermanagement.user.dto.response.UserDailySolvedHistoryResponse; import org.ezcode.codetest.application.usermanagement.user.dto.response.UserInfoResponse; import org.ezcode.codetest.application.usermanagement.user.dto.response.UserProfileImageResponse; @@ -26,6 +24,9 @@ import org.springframework.web.multipart.MultipartFile; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Encoding; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; @@ -46,7 +47,17 @@ public ResponseEntity getUserInfo(@AuthenticationPrincipal Aut return ResponseEntity.status(HttpStatus.OK).body(userService.getUserInfo(authUser)); } - @Operation(summary = "내 정보 수정", description = "닉네임, 블로그, 깃허브, 소개 등 개인 정보를 추가하거나 수정합니다.") + @Operation( + summary = "내 정보 수정", + description = "닉네임, 블로그, 깃허브, 소개 등 개인 정보를 추가하거나 수정합니다.", + // ▼ 이 부분이 핵심입니다. Swagger에게 'request' 파트의 Content-Type을 강제합니다. + requestBody = @io.swagger.v3.oas.annotations.parameters.RequestBody( + content = @Content( + mediaType = MediaType.MULTIPART_FORM_DATA_VALUE, + encoding = @Encoding(name = "request", contentType = MediaType.APPLICATION_JSON_VALUE) + ) + ) + ) @PutMapping(value = "/users", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) public ResponseEntity modifyUserInfo( @AuthenticationPrincipal AuthUser authUser,