Skip to content

Commit 9e2cfad

Browse files
committed
feat: 뉴스 목록 썸네일 포함 응답 구현
1 parent 043fe4b commit 9e2cfad

File tree

6 files changed

+75
-12
lines changed

6 files changed

+75
-12
lines changed

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package dmu.dasom.api.domain.news.controller;
22

33
import dmu.dasom.api.domain.news.dto.NewsCreationResponseDto;
4+
import dmu.dasom.api.domain.news.dto.NewsListResponseDto;
45
import dmu.dasom.api.domain.news.dto.NewsRequestDto;
56
import dmu.dasom.api.domain.news.dto.NewsResponseDto;
67
import dmu.dasom.api.domain.news.service.NewsService;
@@ -24,7 +25,7 @@ public class NewsController {
2425

2526
@Operation(summary = "전체 뉴스 조회 (썸네일 포함)")
2627
@GetMapping
27-
public ResponseEntity<List<NewsResponseDto>> getAllNews() {
28+
public ResponseEntity<List<NewsListResponseDto>> getAllNews() {
2829
return ResponseEntity.ok(newsService.getAllNews());
2930
}
3031

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package dmu.dasom.api.domain.news.dto;
2+
3+
import dmu.dasom.api.global.file.dto.FileResponseDto;
4+
import io.swagger.v3.oas.annotations.media.Schema;
5+
import lombok.AllArgsConstructor;
6+
import lombok.Builder;
7+
import lombok.Getter;
8+
import lombok.NoArgsConstructor;
9+
10+
import java.time.LocalDateTime;
11+
12+
@Getter
13+
@NoArgsConstructor
14+
@AllArgsConstructor
15+
@Builder
16+
@Schema(name = "NewsListResponseDto", description = "뉴스 리스트 응답 DTO")
17+
public class NewsListResponseDto {
18+
19+
@Schema(description = "소식 ID", example = "1")
20+
private Long id;
21+
22+
@Schema(description = "뉴스 제목", example = "제목")
23+
private String title;
24+
25+
@Schema(description = "작성일", example = "2025-02-14T12:00:00")
26+
private LocalDateTime createdAt;
27+
28+
@Schema(description = "인코딩된 이미지", example = "asdf", nullable = true)
29+
private FileResponseDto image;
30+
31+
}

src/main/java/dmu/dasom/api/domain/news/entity/NewsEntity.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package dmu.dasom.api.domain.news.entity;
22

33
import dmu.dasom.api.domain.common.BaseEntity;
4+
import dmu.dasom.api.domain.news.dto.NewsListResponseDto;
45
import dmu.dasom.api.domain.news.dto.NewsResponseDto;
56
import dmu.dasom.api.global.file.dto.FileResponseDto;
67
import io.swagger.v3.oas.annotations.media.Schema;
@@ -55,4 +56,13 @@ public NewsResponseDto toResponseDto() {
5556
.build();
5657
}
5758

59+
public NewsListResponseDto toListResponseDto(FileResponseDto file) {
60+
return NewsListResponseDto.builder()
61+
.id(this.id)
62+
.title(this.title)
63+
.createdAt(getCreatedAt())
64+
.image(file)
65+
.build();
66+
}
67+
5868
}

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

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package dmu.dasom.api.domain.news.service;
22

33
import dmu.dasom.api.domain.news.dto.NewsCreationResponseDto;
4+
import dmu.dasom.api.domain.news.dto.NewsListResponseDto;
5+
import dmu.dasom.api.global.file.dto.FileResponseDto;
46
import dmu.dasom.api.global.file.enums.FileType;
57
import dmu.dasom.api.global.file.service.FileService;
68
import dmu.dasom.api.domain.common.exception.CustomException;
@@ -14,6 +16,7 @@
1416
import org.springframework.transaction.annotation.Transactional;
1517

1618
import java.util.List;
19+
import java.util.Map;
1720

1821
@Service
1922
@RequiredArgsConstructor
@@ -24,18 +27,20 @@ public class NewsService {
2427
private final FileService fileService;
2528

2629
// 전체 뉴스 조회
27-
public List<NewsResponseDto> getAllNews() {
30+
public List<NewsListResponseDto> getAllNews() {
2831
List<NewsEntity> news = newsRepository.findAll();
2932

30-
// List<FileResponseDto> files = fileService.getFirstFileByTypeAndTargetId(
31-
// FileType.NEWS,
32-
// news.stream()
33-
// .map(NewsEntity::getId)
34-
// .toList()
35-
// );
33+
List<Long> newsIds = news.stream()
34+
.map(NewsEntity::getId)
35+
.toList();
36+
37+
Map<Long, FileResponseDto> firstFileMap = fileService.getFirstFileByTypeAndTargetIds(
38+
FileType.NEWS,
39+
newsIds
40+
);
3641

3742
return news.stream()
38-
.map(NewsEntity::toResponseDto)
43+
.map(newsEntity -> newsEntity.toListResponseDto(firstFileMap.get(newsEntity.getId())))
3944
.toList();
4045
}
4146

src/main/java/dmu/dasom/api/global/file/repository/FileRepository.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ public interface FileRepository extends JpaRepository<FileEntity, Long> {
1515

1616
List<FileEntity> findByFileTypeAndTargetId(FileType fileType, Long targetId);
1717

18-
@Query("SELECT f FROM FileEntity f WHERE f.fileType = :fileType AND f.targetId = :targetId")
19-
Optional<FileEntity> findFirstByFileTypeAndTargetIds(@Param("fileType") FileType fileType,
20-
@Param("targetId") Long targetId);
18+
@Query("SELECT f FROM FileEntity f WHERE f.fileType = :fileType AND f.targetId IN :targetIds AND f.id IN " +
19+
"(SELECT MIN(f2.id) FROM FileEntity f2 WHERE f2.fileType = :fileType AND f2.targetId = f.targetId)")
20+
List<FileEntity> findFirstFilesByTypeAndTargetIds(@Param("fileType") FileType fileType, @Param("targetIds") List<Long> targetIds);
2121

2222
}

src/main/java/dmu/dasom/api/global/file/service/FileService.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import java.io.IOException;
1515
import java.util.Base64;
1616
import java.util.List;
17+
import java.util.Map;
1718
import java.util.stream.Collectors;
1819

1920
@Service
@@ -61,6 +62,21 @@ public void deleteFilesByTypeAndTargetId(FileType fileType, Long targetId) {
6162
fileRepository.deleteAll(files);
6263
}
6364

65+
public Map<Long, FileResponseDto> getFirstFileByTypeAndTargetIds(FileType fileType, List<Long> targetIds) {
66+
if (targetIds.isEmpty()) {
67+
return Map.of();
68+
}
69+
70+
List<FileEntity> firstFiles = fileRepository.findFirstFilesByTypeAndTargetIds(fileType, targetIds);
71+
72+
return firstFiles.stream()
73+
.collect(Collectors.toMap(
74+
FileEntity::getTargetId,
75+
FileEntity::toResponseDto,
76+
(existing, replacement) -> existing
77+
));
78+
}
79+
6480
private List<FileEntity> findByFileTypeAndTargetId(FileType fileType, Long targetId) {
6581
return fileRepository.findByFileTypeAndTargetId(fileType, targetId);
6682
}

0 commit comments

Comments
 (0)