Skip to content

Commit ed8d2d2

Browse files
committed
refactor: 파일저장 로직수정
1 parent 73256de commit ed8d2d2

File tree

12 files changed

+197
-215
lines changed

12 files changed

+197
-215
lines changed

src/main/java/dmu/dasom/api/domain/news/controller/NewsController.java

Lines changed: 14 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,13 @@
55
import dmu.dasom.api.domain.news.service.NewsService;
66
import io.swagger.v3.oas.annotations.tags.Tag;
77
import io.swagger.v3.oas.annotations.Operation;
8-
import io.swagger.v3.oas.annotations.responses.ApiResponse;
9-
import io.swagger.v3.oas.annotations.responses.ApiResponses;
10-
import io.swagger.v3.oas.annotations.media.Content;
11-
import io.swagger.v3.oas.annotations.media.ExampleObject;
12-
import org.springframework.http.MediaType;
138
import org.springframework.http.ResponseEntity;
149
import org.springframework.web.bind.annotation.*;
1510

1611
import jakarta.validation.Valid;
17-
import org.springframework.web.multipart.MultipartFile;
18-
1912
import java.util.List;
2013

21-
@Tag(name = "NEWS API", description = "다솜소식 API")
14+
@Tag(name = "NEWS API", description = "뉴스 API")
2215
@RestController
2316
@RequestMapping("/api/news")
2417
public class NewsController {
@@ -29,57 +22,31 @@ public NewsController(NewsService newsService) {
2922
this.newsService = newsService;
3023
}
3124

32-
// 전체 조회
33-
@Operation(summary = "소식 조회", description = "리스트로 조회")
34-
@ApiResponse(responseCode = "200", description = "정상 응답",
35-
content = @Content(mediaType = "application/json"))
25+
@Operation(summary = "전체 뉴스 조회")
3626
@GetMapping
3727
public ResponseEntity<List<NewsResponseDto>> getAllNews() {
38-
List<NewsResponseDto> newsList = newsService.getAllNews();
39-
return ResponseEntity.ok(newsList);
28+
return ResponseEntity.ok(newsService.getAllNews());
4029
}
4130

42-
// 개별 조회
43-
@Operation(summary = "소식 상세 조회", description = "ID로 특정 소식을 조회")
44-
@ApiResponses({
45-
@ApiResponse(responseCode = "200", description = "조회 성공"),
46-
@ApiResponse(responseCode = "400", description = "소식을 찾을 수 없음")
47-
})
31+
@Operation(summary = "개별 뉴스 조회")
4832
@GetMapping("/{id}")
4933
public ResponseEntity<NewsResponseDto> getNewsById(@PathVariable Long id) {
50-
NewsResponseDto responseDto = newsService.getNewsById(id);
51-
return ResponseEntity.ok(responseDto);
34+
return ResponseEntity.ok(newsService.getNewsById(id));
5235
}
5336

54-
// 생성 (multipart/form-data 사용)
55-
@Operation(summary = "소식 등록", description = "새로운 소식을 등록")
56-
@PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
57-
public ResponseEntity<NewsResponseDto> createNews(
58-
@Valid @RequestPart("news") NewsRequestDto requestDto, // JSON 데이터 받기
59-
@RequestPart(value = "images", required = false) List<MultipartFile> imageFiles // 이미지 파일 받기
60-
) {
61-
NewsResponseDto responseDto = newsService.createNews(requestDto, imageFiles);
62-
return ResponseEntity.status(201).body(responseDto);
37+
@Operation(summary = "뉴스 등록")
38+
@PostMapping
39+
public ResponseEntity<NewsResponseDto> createNews(@Valid @RequestBody NewsRequestDto requestDto) {
40+
return ResponseEntity.status(201).body(newsService.createNews(requestDto));
6341
}
6442

65-
// 수정 (multipart/form-data 사용)
66-
@Operation(summary = "소식 수정", description = "ID로 특정 소식을 수정")
67-
@PutMapping(value = "/{id}", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
68-
public ResponseEntity<NewsResponseDto> updateNews(
69-
@PathVariable Long id,
70-
@Valid @RequestPart("news") NewsRequestDto requestDto,
71-
@RequestPart(value = "images", required = false) List<MultipartFile> imageFiles
72-
) {
73-
NewsResponseDto updatedNews = newsService.updateNews(id, requestDto, imageFiles);
74-
return ResponseEntity.ok(updatedNews);
43+
@Operation(summary = "뉴스 수정")
44+
@PutMapping("/{id}")
45+
public ResponseEntity<NewsResponseDto> updateNews(@PathVariable Long id, @Valid @RequestBody NewsRequestDto requestDto) {
46+
return ResponseEntity.ok(newsService.updateNews(id, requestDto));
7547
}
7648

77-
// 삭제
78-
@Operation(summary = "소식 삭제", description = "ID로 특정 소식을 삭제")
79-
@ApiResponses({
80-
@ApiResponse(responseCode = "204", description = "삭제 성공"),
81-
@ApiResponse(responseCode = "400", description = "소식을 찾을 수 없음")
82-
})
49+
@Operation(summary = "뉴스 삭제")
8350
@DeleteMapping("/{id}")
8451
public ResponseEntity<Void> deleteNews(@PathVariable Long id) {
8552
newsService.deleteNews(id);

src/main/java/dmu/dasom/api/domain/news/controller/NewsImageController.java

Lines changed: 0 additions & 28 deletions
This file was deleted.

src/main/java/dmu/dasom/api/domain/news/dto/NewsRequestDto.java

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,6 @@ public class NewsRequestDto {
2525
@Schema(description = "뉴스 내용", example = "새로운 뉴스 내용")
2626
private String content;
2727

28-
@Size(max = 255, message = "이미지 URL은 최대 255자입니다.")
29-
@Schema(description = "뉴스 이미지 URL", example = "http://example.com/image.jpg", nullable = true)
30-
private List<MultipartFile> images;
31-
28+
@Schema(description = "이미지 파일 ID 목록", example = "[1, 2, 3]", nullable = true)
29+
private List<Long> fileIds;
3230
}
Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package dmu.dasom.api.domain.news.entity;
22

33
import dmu.dasom.api.domain.common.BaseEntity;
4-
import dmu.dasom.api.domain.common.Status;
54
import dmu.dasom.api.domain.news.dto.NewsResponseDto;
65
import io.swagger.v3.oas.annotations.media.Schema;
76
import jakarta.persistence.*;
@@ -20,39 +19,27 @@ public class NewsEntity extends BaseEntity {
2019

2120
@Id
2221
@GeneratedValue(strategy = GenerationType.IDENTITY)
23-
@Schema(description = "뉴스 ID", example = "1")
2422
private Long id;
2523

2624
@Column(nullable = false, length = 100)
27-
@Schema(description = "뉴스 제목", example = "뉴스 예제 제목")
2825
private String title;
2926

3027
@Lob
3128
@Column(nullable = false)
32-
@Schema(description = "뉴스 내용", example = "뉴스 예제 내용")
3329
private String content;
3430

3531
@ElementCollection
3632
@CollectionTable(name = "news_images", joinColumns = @JoinColumn(name = "news_id"))
3733
@Column(name = "image_url", length = 255)
38-
@Schema(description = "뉴스 이미지 URL 리스트", example = "[\"https://example.com/image1.jpg\", \"https://example.com/image2.jpg\"]")
3934
private List<String> imageUrls;
4035

41-
// 뉴스 상태 업데이트
42-
public void updateStatus(Status status) {
43-
super.updateStatus(status);
44-
}
45-
46-
// NewsEntity → NewsResponseDto 변환
47-
public NewsResponseDto toResponseDto() {
48-
return new NewsResponseDto(id, title, content, getCreatedAt(), imageUrls);
49-
}
50-
51-
// 수정 메서드
5236
public void update(String title, String content, List<String> imageUrls) {
5337
this.title = title;
5438
this.content = content;
5539
this.imageUrls = imageUrls;
5640
}
5741

42+
public NewsResponseDto toResponseDto() {
43+
return new NewsResponseDto(id, title, content, getCreatedAt(), imageUrls);
44+
}
5845
}

src/main/java/dmu/dasom/api/domain/news/service/NewsImageService.java

Lines changed: 0 additions & 74 deletions
This file was deleted.

src/main/java/dmu/dasom/api/domain/news/service/NewsService.java

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package dmu.dasom.api.domain.news.service;
22

3+
import dmu.dasom.api.global.file.entity.FileEntity;
4+
import dmu.dasom.api.global.file.service.FileService;
35
import dmu.dasom.api.domain.common.exception.CustomException;
46
import dmu.dasom.api.domain.common.exception.ErrorCode;
57
import dmu.dasom.api.domain.news.dto.NewsRequestDto;
@@ -9,7 +11,6 @@
911
import lombok.RequiredArgsConstructor;
1012
import org.springframework.stereotype.Service;
1113
import org.springframework.transaction.annotation.Transactional;
12-
import org.springframework.web.multipart.MultipartFile;
1314

1415
import java.util.List;
1516
import java.util.stream.Collectors;
@@ -19,54 +20,52 @@
1920
public class NewsService {
2021

2122
private final NewsRepository newsRepository;
22-
private final NewsImageService newsImageService;
23+
private final FileService fileService;
2324

24-
// 전체 조회
25+
// 전체 뉴스 조회
2526
public List<NewsResponseDto> getAllNews() {
2627
return newsRepository.findAll().stream()
2728
.map(NewsEntity::toResponseDto)
2829
.collect(Collectors.toList());
2930
}
3031

31-
// 개별 조회
32+
// 개별 뉴스 조회
3233
public NewsResponseDto getNewsById(Long id) {
3334
return newsRepository.findById(id)
3435
.map(NewsEntity::toResponseDto)
3536
.orElseThrow(() -> new CustomException(ErrorCode.NOT_FOUND));
3637
}
3738

38-
// 생성
39+
// 뉴스 생성
3940
@Transactional
40-
public NewsResponseDto createNews(NewsRequestDto requestDto, List<MultipartFile> imageFiles) {
41-
// 이미지 업로드 후 URL 리스트 받아오기
42-
List<String> uploadedImageUrls = newsImageService.uploadImages(imageFiles); // URL 리스트 생성
41+
public NewsResponseDto createNews(NewsRequestDto requestDto) {
42+
List<FileEntity> uploadedFiles = fileService.getFilesByIds(requestDto.getFileIds());
43+
List<String> imageUrls = uploadedFiles.stream().map(FileEntity::getFilePath).collect(Collectors.toList());
4344

4445
NewsEntity news = NewsEntity.builder()
4546
.title(requestDto.getTitle())
4647
.content(requestDto.getContent())
47-
.imageUrls(uploadedImageUrls) // 이미지 URL 리스트 저장
48+
.imageUrls(imageUrls)
4849
.build();
4950

50-
NewsEntity savedNews = newsRepository.save(news);
51-
return savedNews.toResponseDto();
51+
return newsRepository.save(news).toResponseDto();
5252
}
5353

54-
// 수정
54+
// 뉴스 수정
5555
@Transactional
56-
public NewsResponseDto updateNews(Long id, NewsRequestDto requestDto, List<MultipartFile> imageFiles) {
57-
// 뉴스 엔티티 찾기
56+
public NewsResponseDto updateNews(Long id, NewsRequestDto requestDto) {
5857
NewsEntity news = newsRepository.findById(id)
5958
.orElseThrow(() -> new CustomException(ErrorCode.NOT_FOUND));
6059

61-
// 이미지 업로드 후 URL 리스트 받아오기
62-
List<String> uploadedImageUrls = newsImageService.uploadImages(imageFiles);
60+
List<FileEntity> uploadedFiles = fileService.getFilesByIds(requestDto.getFileIds());
61+
List<String> imageUrls = uploadedFiles.stream().map(FileEntity::getFilePath).collect(Collectors.toList());
6362

64-
news.update(requestDto.getTitle(), requestDto.getContent(), uploadedImageUrls);
63+
news.update(requestDto.getTitle(), requestDto.getContent(), imageUrls);
6564

6665
return news.toResponseDto();
6766
}
6867

69-
// 삭제
68+
// 뉴스 삭제
7069
@Transactional
7170
public void deleteNews(Long id) {
7271
NewsEntity news = newsRepository.findById(id)
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package dmu.dasom.api.global.file.controller;
2+
3+
import dmu.dasom.api.global.file.service.FileService;
4+
import io.swagger.v3.oas.annotations.Operation;
5+
import io.swagger.v3.oas.annotations.tags.Tag;
6+
import lombok.RequiredArgsConstructor;
7+
import org.springframework.http.ResponseEntity;
8+
import org.springframework.web.bind.annotation.*;
9+
import org.springframework.web.multipart.MultipartFile;
10+
11+
import java.util.List;
12+
13+
@Tag(name = "File API", description = "파일 업로드 API")
14+
@RestController
15+
@RequestMapping("/api/global/file")
16+
@RequiredArgsConstructor
17+
public class FileController {
18+
19+
private final FileService fileService;
20+
21+
@Operation(summary = "파일 업로드", description = "여러 개의 파일 업로드 + 파일 ID 리스트를 반환")
22+
@PostMapping("/upload")
23+
public ResponseEntity<List<Long>> uploadFiles(@RequestParam("files") List<MultipartFile> files) {
24+
List<Long> fileIds = fileService.uploadFiles(files);
25+
return ResponseEntity.ok(fileIds);
26+
}
27+
28+
}

0 commit comments

Comments
 (0)