Skip to content

Commit 1360305

Browse files
authored
feat : s3 문제 수정, 삭제 기능 ( + 이미지 기능 포함 로직 추가 ) (#115)
* feat : S3 문제 이미지 수정 기능 구현 * feat : S3 문제 이미지 삭제 기능 구현 * refactor : 중괄호 누락 * refactor : 변수명 통일
1 parent 789e7e0 commit 1360305

File tree

7 files changed

+64
-10
lines changed

7 files changed

+64
-10
lines changed

src/main/java/org/ezcode/codetest/application/problem/dto/request/ProblemCreateRequest.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,11 @@
1313

1414
public record ProblemCreateRequest(
1515

16-
16+
// Map으로 묶여있으니 {} 중괄호 사용
1717
@NotNull(message = "카테고리 이름를 설정해야 합니다.")
1818
@Schema(description = "카테고리 코드 식별자(영어) / 한글 이름", example = "FOR_BEGINNER : 입문자용")
1919
Map<String, String> categories,
2020

21-
2221
@NotBlank(message = "문제 제목을 입력하세요.")
2322
@Schema(description = "제목", example = "A+B")
2423
String title,

src/main/java/org/ezcode/codetest/application/problem/dto/request/ProblemUpdateRequest.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
public record ProblemUpdateRequest(
1313

14+
// 리스트 이므로, [] 대괄호 사용
1415
@Schema(description = "카테고리", example = "FOR_BEGINNER")
1516
List<String> categories,
1617

src/main/java/org/ezcode/codetest/application/problem/service/ProblemService.java

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ public class ProblemService {
4646
@Transactional
4747
public void createCategory(CategoryCreateRequest requestDto) {
4848

49-
Category category =problemDomainService.createCategory(requestDto.toCategory());
49+
Category category = problemDomainService.createCategory(requestDto.toCategory());
5050

5151
statUpdateUtil.save(new CategoryStat(category));
5252
}
@@ -102,7 +102,7 @@ public ProblemDetailResponse getProblem(Long problemId) {
102102

103103
// 문제 수정 ( 관리자 )
104104
@Transactional
105-
public void modifyProblem(Long problemId, ProblemUpdateRequest request) {
105+
public void modifyProblem(Long problemId, ProblemUpdateRequest request, MultipartFile newImage) {
106106

107107
Problem findProblem = problemDomainService.getProblem(problemId);
108108

@@ -116,6 +116,11 @@ public void modifyProblem(Long problemId, ProblemUpdateRequest request) {
116116
request.reference()
117117
);
118118

119+
// 이미지 수정 처리
120+
if (newImage != null && !newImage.isEmpty()) {
121+
updateProblemImage(findProblem, newImage);
122+
}
123+
119124
problemDomainService.updateCategoryAndSearchEngine(findProblem, request.categories());
120125

121126
}
@@ -126,6 +131,14 @@ public void removeProblem(Long problemId) {
126131

127132
Problem findProblem = problemDomainService.getProblem(problemId);
128133

134+
// 문제 이미지가 있으면 삭제
135+
if (!findProblem.getImageUrl().isEmpty()) {
136+
for(String fileUrl : findProblem.getImageUrl()) {
137+
s3Uploader.delete(fileUrl);
138+
}
139+
}
140+
141+
// Soft Delete
129142
problemDomainService.removeProblem(findProblem);
130143
}
131144

@@ -143,5 +156,20 @@ private String uploadImageAfterTransaction(MultipartFile image, Long problemId)
143156
throw new S3Exception(S3ExceptionCode.S3_UPLOAD_FAILED);
144157
}
145158
}
159+
160+
// 이미지 수정
161+
private void updateProblemImage(Problem problem, MultipartFile newImage) {
162+
163+
// 기존 이미지가 있다면 삭제 처리
164+
if (!problem.getImageUrl().isEmpty()) {
165+
for(String fileUrl : problem.getImageUrl()) {
166+
s3Uploader.delete(fileUrl);
167+
}
168+
problem.clearImages();
169+
}
170+
171+
String newImageUrl = uploadImageAfterTransaction(newImage, problem.getId());
172+
problem.addImage(newImageUrl);
173+
}
146174
}
147175

src/main/java/org/ezcode/codetest/domain/problem/model/entity/Problem.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,11 +149,17 @@ public void addImage(String image) {
149149
imageUrl.add(image);
150150
}
151151

152+
// 이미지 초기화
153+
public void clearImages() {
154+
this.imageUrl.clear();
155+
}
156+
152157
public void incrementTotalSubmissions() {
153158
totalSubmissions += 1;
154159
}
155160

156161
public void incrementCorrectSubmissions() {
157162
correctSubmissions += 1;
163+
158164
}
159165
}

src/main/java/org/ezcode/codetest/infrastructure/s3/S3Uploader.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ public class S3Uploader {
2626
@Value("${cloud.aws.s3.bucket}")
2727
private String bucket;
2828

29+
// 이미지 업로드
2930
public String upload(MultipartFile multipartFile, String dirName) {
3031
try {
3132
// MIME 타입 검사 (png, jpeg, jpg, webp 만 가능)
@@ -58,4 +59,22 @@ public String upload(MultipartFile multipartFile, String dirName) {
5859
throw new S3Exception(S3ExceptionCode.S3_UPLOAD_FAILED);
5960
}
6061
}
62+
63+
// 이미지 삭제
64+
public void delete(String fileUrl) {
65+
try {
66+
String fileName = extractKeyFromProblemUrl(fileUrl);
67+
amazonS3.deleteObject(bucket, fileName); // S3 내 이미지 객체 제거.
68+
log.info("S3에서 이미지 삭제 완료: {}", fileName);
69+
} catch (Exception e) {
70+
log.error("S3 이미지 삭제 실패: {}", fileUrl, e);
71+
throw new S3Exception(S3ExceptionCode.S3_DELETE_FAILED);
72+
}
73+
}
74+
75+
// 문제 이미지 URL 가져오기
76+
private String extractKeyFromProblemUrl(String fileUrl) {
77+
// S3 주소 포맷 기준으로 잘라내기
78+
return fileUrl.substring(fileUrl.indexOf("problem/"));
79+
}
6180
}

src/main/java/org/ezcode/codetest/infrastructure/s3/exception/code/S3ExceptionCode.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@
1010
@RequiredArgsConstructor
1111
public enum S3ExceptionCode implements ResponseCode {
1212

13-
S3_UPLOAD_FAILED(false, HttpStatus.INTERNAL_SERVER_ERROR, "S3 이미지 업로드 중 오류가 발생했습니다."),
14-
S3_INVALID_FILE_TYPE(false, HttpStatus.BAD_REQUEST, "이미지 파일만 업로드할 수 있습니다.");
15-
13+
S3_UPLOAD_FAILED(false, HttpStatus.INTERNAL_SERVER_ERROR, "S3 이미지 업로드 중 오류가 발생 했습니다."),
14+
S3_INVALID_FILE_TYPE(false, HttpStatus.BAD_REQUEST, "이미지 파일만 업로드할 수 있습니다."),
15+
S3_DELETE_FAILED(false, HttpStatus.INTERNAL_SERVER_ERROR, "S3 이미지 삭제 중 오류가 발생 했습니다.");
1616
private final boolean success;
1717

1818
private final HttpStatus status;

src/main/java/org/ezcode/codetest/presentation/problemmanagement/problem/ProblemAdminController.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,14 +47,15 @@ public ResponseEntity<Void> createProblem(
4747
.build();
4848
}
4949

50-
@PutMapping("/{problemId}")
50+
@PutMapping(path = "/{problemId}", consumes = {MediaType.MULTIPART_FORM_DATA_VALUE})
5151
@Operation(summary = "문제 수정", description = "문제를 수정합니다.")
5252
@ApiResponse(responseCode = "200", description = "문제 수정 성공")
5353
public ResponseEntity<Void> modifyProblem(
5454
@PathVariable Long problemId,
55-
@Valid @RequestBody ProblemUpdateRequest request
55+
@RequestPart @Valid ProblemUpdateRequest request,
56+
@RequestPart(value = "image", required = false) MultipartFile image
5657
) {
57-
problemService.modifyProblem(problemId, request);
58+
problemService.modifyProblem(problemId, request, image);
5859

5960
return ResponseEntity
6061
.status(HttpStatus.OK)

0 commit comments

Comments
 (0)