Skip to content

Commit 2371d1c

Browse files
committed
refact: 통합 검색 로직 수정
1 parent 0fac0ff commit 2371d1c

File tree

4 files changed

+514
-26
lines changed

4 files changed

+514
-26
lines changed

src/main/java/targeter/aim/domain/search/controller/SearchController.java

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,11 @@ public class SearchController {
2929
summary = "통합 검색",
3030
description = "키워드 기반으로 게시글(/api/posts/search) + 챌린지(/api/challenges/search)를 통합 검색합니다."
3131
)
32-
public SearchDto.SearchResponse search(
33-
@RequestParam(required = false) String keyword,
34-
@RequestParam(defaultValue = "LATEST") PostDto.PostSortType postSort,
35-
@RequestParam(defaultValue = "LATEST") ChallengeDto.ChallengeSortType challengeSort,
32+
public SearchDto.SearchPageResponse search(
33+
@ModelAttribute @ParameterObject SearchDto.ListSearchCondition condition,
3634
@PageableDefault(size = 16) @ParameterObject Pageable pageable,
3735
@AuthenticationPrincipal UserDetails userDetails
3836
) {
39-
return searchService.search(keyword, postSort, challengeSort, pageable, userDetails);
37+
return searchService.getSearchList(condition, userDetails, pageable);
4038
}
4139
}

src/main/java/targeter/aim/domain/search/dto/SearchDto.java

Lines changed: 167 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,182 @@
22

33
import io.swagger.v3.oas.annotations.media.Schema;
44
import lombok.*;
5+
import org.springframework.data.domain.Page;
56
import targeter.aim.domain.challenge.dto.ChallengeDto;
7+
import targeter.aim.domain.challenge.entity.ChallengeMode;
8+
import targeter.aim.domain.file.dto.FileDto;
69
import targeter.aim.domain.post.dto.PostDto;
10+
import targeter.aim.domain.post.entity.PostType;
11+
import targeter.aim.domain.user.dto.TierDto;
12+
import targeter.aim.domain.user.entity.User;
13+
14+
import java.time.LocalDate;
15+
import java.time.LocalDateTime;
16+
import java.util.List;
717

818
public class SearchDto {
919

1020
@Data
21+
@NoArgsConstructor
22+
@AllArgsConstructor
1123
@Builder
24+
@Schema(description = "전체 검색글 목록 조회 조건")
25+
public static class ListSearchCondition {
26+
@Builder.Default
27+
@Schema(
28+
description = """
29+
정렬 기준
30+
- LATEST : 최신순
31+
- OLDEST : 오래된순
32+
- LIKED : 좋아요순
33+
- TITLE : 가나다순
34+
""",
35+
example = "LATEST",
36+
allowableValues = {"LATEST", "OLDEST", "LIKED", "TITLE"}
37+
)
38+
private SortType sort = SortType.LATEST;
39+
40+
@Schema(description = "검색 키워드 (제목 기준 포함 검색)", example = "개발")
41+
private String keyword;
42+
}
43+
44+
public enum SortType {
45+
LATEST, // 최신순
46+
OLDEST, // 오래된순
47+
LIKED, // 좋아요순
48+
TITLE // 가나다순
49+
}
50+
51+
public enum Type {
52+
CHALLENGE, // 챌린지
53+
POST // 게시글
54+
}
55+
56+
@Data
57+
@AllArgsConstructor
58+
@NoArgsConstructor
59+
@Schema(description = "페이지네이션 정보")
60+
public static class PageInfo {
61+
private int size;
62+
63+
private int number;
64+
65+
private long totalElements;
66+
67+
private int totalPages;
68+
}
69+
70+
@Data
1271
@NoArgsConstructor
1372
@AllArgsConstructor
14-
@Schema(description = "통합 검색 응답")
15-
public static class SearchResponse {
73+
@Builder
74+
@Schema(description = "글 작성자 정보")
75+
public static class UserResponse {
76+
77+
@Schema(description = "유저 아이디", example = "1")
78+
private Long userId;
79+
80+
@Schema(description = "유저 닉네임", example = "닉네임")
81+
private String nickname;
1682

17-
@Schema(description = "게시글 검색 결과")
18-
private PostDto.PostPageResponse posts;
83+
@Schema(description = "티어명", example = "BRONZE")
84+
private TierDto.TierResponse tier;
85+
86+
@Schema(description = "프로필 이미지")
87+
private FileDto.FileResponse profileImage;
88+
89+
public static UserResponse from(User user) {
90+
return UserResponse.builder()
91+
.userId(user.getId())
92+
.nickname(user.getNickname())
93+
.tier(TierDto.TierResponse.from(user.getTier()))
94+
.profileImage(FileDto.FileResponse.from(user.getProfileImage()))
95+
.build();
96+
}
97+
}
98+
99+
@Data
100+
@NoArgsConstructor
101+
@AllArgsConstructor
102+
@Getter
103+
@Builder
104+
@Schema(description = "검색된 글 목록 응답")
105+
public static class SearchListResponse {
106+
@Schema(description = "글 종류", example = "CHALLENGE | POST")
107+
private Type type;
108+
109+
@Schema(description = "챌린지/게시글 아이디", example = "1")
110+
private Long id;
111+
112+
@Schema(
113+
description = """
114+
게시글 종류
115+
- VS_RECRUIT : VS 모집글
116+
- Q_AND_A : Q&A
117+
- REVIEW : 후기글
118+
""",
119+
example = "VS_RECRUIT | Q_AND_A | REVIEW"
120+
)
121+
private PostType postType;
122+
123+
@Schema(
124+
description = "연관된 챌린지 모드",
125+
example = "VS | SOLO"
126+
)
127+
private ChallengeMode challengeMode;
128+
129+
@Schema(description = "썸네일 정보(uuid값 참고)")
130+
private FileDto.FileResponse thumbnail;
131+
132+
@Schema(description = "작성자 정보")
133+
private UserResponse user;
134+
135+
@Schema(description = "시작일", example = "2026-01-01")
136+
private LocalDate startedAt;
137+
138+
@Schema(description = "챌린지 기간(주)", example = "4주")
139+
private Integer durationWeek;
140+
141+
@Schema(description = "VS모집글 제목", example = "제목")
142+
private String name;
143+
144+
@Schema(description = "분야 리스트", example = "[\"IT\", \"BUSINESS\"]")
145+
private List<String> fields;
146+
147+
@Schema(description = "태그 리스트", example = "[\"태그1\", \"태그2\", \"태그3\"]")
148+
private List<String> tags;
149+
150+
@Schema(description = "직무", example = "직무")
151+
private String job;
152+
153+
@Schema(description = "좋아요 여부(좋아요 했으면 true)", example = "true | false")
154+
private Boolean isLiked;
155+
156+
@Schema(description = "좋아요수", example = "1")
157+
private Integer likeCount;
158+
159+
@Schema(description = "글 생성일", example = "ISO DateTime")
160+
private LocalDateTime createdAt;
161+
}
162+
163+
@Data
164+
@AllArgsConstructor
165+
@NoArgsConstructor
166+
@Schema(description = "게시글 목록 페이지 응답")
167+
public static class SearchPageResponse {
168+
private List<SearchListResponse> content;
169+
private PostDto.PageInfo page;
19170

20-
@Schema(description = "챌린지 검색 결과")
21-
private ChallengeDto.ChallengePageResponse challenges;
171+
public static SearchPageResponse from(Page<SearchListResponse> page) {
172+
return new SearchPageResponse(
173+
page.getContent(),
174+
new PostDto.PageInfo(
175+
page.getSize(),
176+
page.getNumber(),
177+
page.getTotalElements(),
178+
page.getTotalPages()
179+
)
180+
);
181+
}
22182
}
23-
}
183+
}

0 commit comments

Comments
 (0)