@@ -43,19 +43,31 @@ public CollectionResponseDTO.CollectionPreviewDTO CollectionDetails(Long collect
4343
4444 Authentication authentication = (principalDetails != null ) ? SecurityContextHolder .getContext ().getAuthentication () : null ;
4545
46- Collection collection = collectionRepository .findById (collectionId )
46+ Collection collection = collectionRepository .findByIdWithEpisodesAndResources (collectionId ) //N+1 문제 개선
4747 .orElseThrow (() -> new CollectionHandler (ErrorStatus .COLLECTION_NOT_FOUND ));
4848
4949 User currentUser = null ;
5050 if (authentication != null && authentication .getPrincipal () instanceof PrincipalDetails ) {
5151 currentUser = ((PrincipalDetails ) authentication .getPrincipal ()).getUser ();
5252 }
5353
54- CollectionResponseDTO .CollectionLearningInfo learningInfo = getLearningInfo (collection , currentUser );
54+ CollectionResponseDTO .CollectionLearningInfo learningInfo = getLearningInfo (collection , currentUser , true );
5555
5656 return CollectionConverter .toCollectionPreviewDTO (collection , learningInfo , currentUser );
5757 }
5858
59+ private List <ResourceResponseDTO .SearchResultResourceDTO > getAllResources (
60+ Collection collection
61+ ) {
62+ List <CollectionEpisode > episodes = collection .getEpisodes ();
63+
64+ // 모든 에피소드를 에피소드 번호 순으로 정렬
65+ return episodes .stream ()
66+ .sorted (Comparator .comparing (CollectionEpisode ::getEpisodeNumber ))
67+ .map (ResourceConverter ::convertToResourceDTO )
68+ .toList ();
69+ }
70+
5971 public CollectionResponseDTO .SearchResultDTO search (SearchRequestDTO .SearchConditionDTO condition , Long lastId , PrincipalDetails principalDetails ) {
6072
6173 Authentication authentication = (principalDetails != null ) ? SecurityContextHolder .getContext ().getAuthentication () : null ;
@@ -85,7 +97,7 @@ public CollectionResponseDTO.SearchResultDTO search(SearchRequestDTO.SearchCondi
8597 Map <Long , CollectionResponseDTO .CollectionLearningInfo > learningInfoMap = collections .stream ()
8698 .collect (Collectors .toMap (
8799 Collection ::getId ,
88- collection -> getLearningInfo (collection , currentUser )
100+ collection -> getLearningInfo (collection , currentUser , false )
89101 ));
90102
91103 return CollectionConverter .toSearchResultDTO (
@@ -99,12 +111,18 @@ public CollectionResponseDTO.SearchResultDTO search(SearchRequestDTO.SearchCondi
99111 );
100112 }
101113
102- public CollectionResponseDTO .CollectionLearningInfo getLearningInfo (Collection collection , User user ) {
114+ public CollectionResponseDTO .CollectionLearningInfo getLearningInfo (
115+ Collection collection ,
116+ User user ,
117+ boolean isDetailView
118+ ) {
103119 if (user == null ) {
104120 return CollectionResponseDTO .CollectionLearningInfo .builder ()
105121 .learningStatus ("BEFORE" )
106122 .progressRate (null )
107- .resourceDTOList (getFilteredResources (collection , null , 0 ))
123+ .resourceDTOList (isDetailView ?
124+ getAllResources (collection ) : // 상세 조회면 전체 리소스
125+ getFilteredResources (collection , null , 0 )) // 아니면 필터링된 리소스
108126 .build ();
109127 }
110128
@@ -114,7 +132,9 @@ public CollectionResponseDTO.CollectionLearningInfo getLearningInfo(Collection c
114132 return CollectionResponseDTO .CollectionLearningInfo .builder ()
115133 .learningStatus ("BEFORE" )
116134 .progressRate (null )
117- .resourceDTOList (getFilteredResources (collection , null , 0 ))
135+ .resourceDTOList (isDetailView ?
136+ getAllResources (collection ) : // 상세 조회면 전체 리소스
137+ getFilteredResources (collection , null , 0 )) // 아니면 필터링된 리소스
118138 .build ();
119139 }
120140
@@ -123,17 +143,23 @@ public CollectionResponseDTO.CollectionLearningInfo getLearningInfo(Collection c
123143 return CollectionResponseDTO .CollectionLearningInfo .builder ()
124144 .learningStatus ("COMPLETED" )
125145 .progressRate (100 )
126- .completedTime (realUserCollection .getCompletedTime ())
127- .resourceDTOList (getFilteredResources (collection , user , realUserCollection .getUserCollectionStatus ()))
146+ .startDate (realUserCollection .getCreatedAt ().toLocalDate ())
147+ .completedDate (realUserCollection .getCompletedTime ())
148+ .resourceDTOList (isDetailView ?
149+ getAllResources (collection ) : // 상세 조회면 전체 리소스
150+ new ArrayList <>()) // 아니면 빈 리스트
128151 .build ();
129152 }
130153
131154 int progressRate = calculateProgressRate (realUserCollection );
132155 return CollectionResponseDTO .CollectionLearningInfo .builder ()
133156 .learningStatus ("IN_PROGRESS" )
134157 .progressRate (progressRate )
158+ .startDate (realUserCollection .getCreatedAt ().toLocalDate ())
135159 .currentEpisode (realUserCollection .getUserCollectionStatus ())
136- .resourceDTOList (getFilteredResources (collection , user , realUserCollection .getUserCollectionStatus ()))
160+ .resourceDTOList (isDetailView ?
161+ getAllResources (collection ) :
162+ getFilteredResources (collection , user , realUserCollection .getUserCollectionStatus ()))
137163 .build ();
138164 }
139165
@@ -143,7 +169,8 @@ private int calculateProgressRate(UserCollection userCollection) {
143169 }
144170
145171 private List <ResourceResponseDTO .SearchResultResourceDTO > getFilteredResources (
146- Collection collection , User user , int currentEpisode ) {
172+ Collection collection , User user , int currentEpisode
173+ ) {
147174 List <CollectionEpisode > episodes = collection .getEpisodes ();
148175 List <CollectionEpisode > filteredEpisodes ;
149176
@@ -156,17 +183,17 @@ private List<ResourceResponseDTO.SearchResultResourceDTO> getFilteredResources(
156183 }
157184
158185 if (user == null || currentEpisode == 0 ) {
159- // 비회원이거나 수강 전인 경우 처음 3개
186+ // 비회원이거나 수강 전인 경우 처음 4개
160187 filteredEpisodes = episodes .stream ()
161188 .sorted (Comparator .comparing (CollectionEpisode ::getEpisodeNumber ))
162- .limit (3 )
189+ .limit (4 )
163190 .toList ();
164191 } else {
165192 // 수강 중인 경우 현재 회차부터 3개
166193 filteredEpisodes = episodes .stream ()
167194 .sorted (Comparator .comparing (CollectionEpisode ::getEpisodeNumber ))
168195 .filter (ep -> ep .getEpisodeNumber () >= currentEpisode )
169- .limit (3 )
196+ .limit (4 )
170197 .toList ();
171198 }
172199
@@ -178,12 +205,24 @@ private List<ResourceResponseDTO.SearchResultResourceDTO> getFilteredResources(
178205 public HomeResponseDTO .GuestHomeInfoDTO getGuestHomeCollections () {
179206 List <Collection > collections = collectionRepository .findTopBookmarkedCollections (HOME_COLLECTION_SIZE );
180207
181- return HomeConverter .convertToGuestHomeInfoDTO (CollectionConverter .convertToHomeCollection (collections ));
208+ List <CollectionResponseDTO .CollectionPreviewDTO > GuestCollectionList = collections .stream ()
209+ .map (collection -> {
210+ CollectionResponseDTO .CollectionLearningInfo defaultLearningInfo =
211+ CollectionResponseDTO .CollectionLearningInfo .builder ()
212+ .learningStatus ("BEFORE" )
213+ .progressRate (null )
214+ .resourceDTOList (getFilteredResources (collection , null , 0 ))
215+ .build ();
216+ return CollectionConverter .toCollectionPreviewDTO (collection , defaultLearningInfo , null );
217+ })
218+ .toList ();
219+
220+ return HomeConverter .convertToGuestHomeInfoDTO (GuestCollectionList );
182221 }
183222
184223 public HomeResponseDTO .UserHomeInfoDTO getUserHomeCollections (User user ) {
185224 // 최근 학습 컬렉션 조회
186- HomeResponseDTO . RecentLearningDTO recentLearning = getRecentLearning (user );
225+ CollectionResponseDTO . CollectionPreviewDTO recentLearning = getRecentLearning (user );
187226
188227 // 추천 컬렉션 목록 조회
189228
@@ -225,7 +264,7 @@ public HomeResponseDTO.UserHomeInfoDTO getUserHomeCollections(User user) {
225264 Map <Long , CollectionResponseDTO .CollectionLearningInfo > learningInfoMap = recommendedCollections .stream ()
226265 .collect (Collectors .toMap (
227266 Collection ::getId ,
228- collection -> getLearningInfo (collection , user )
267+ collection -> getLearningInfo (collection , user , false )
229268 ));
230269
231270 return HomeConverter .convertToUserHomeInfoDTO (
@@ -237,10 +276,14 @@ public HomeResponseDTO.UserHomeInfoDTO getUserHomeCollections(User user) {
237276 );
238277 }
239278
240- private HomeResponseDTO . RecentLearningDTO getRecentLearning (User user ) {
279+ private CollectionResponseDTO . CollectionPreviewDTO getRecentLearning (User user ) {
241280 return userCollectionRepository
242281 .findFirstByUserAndStatusOrderByCompletedTimeDesc (user , UserCollectionStatus .IN_PROGRESS )
243- .map (ResourceConverter ::toRecentLearningDTO )
282+ .map (userCollection -> CollectionConverter .toCollectionPreviewDTO (
283+ userCollection .getCollection (),
284+ getLearningInfo (userCollection .getCollection (), user , false ),
285+ user
286+ ))
244287 .orElse (null );
245288 }
246289
0 commit comments