Skip to content

Commit

Permalink
refactor: 기존 최신리스트API -> 최신리스트와 팔로잉리스트 API로 분리 (#292)
Browse files Browse the repository at this point in the history
* 기존 optionalAuth에 대한 최신리스트 API 에서 최신리스트 API, 팔로잉리스트 API로 분해

* test: 분리된 최신리스트 조회 API에 맞게 테스트 코드 수정

* fix: 코드 리뷰를 통해 명칭 변경
  • Loading branch information
pparkjs authored Sep 7, 2024
1 parent 769ab0d commit 333420f
Show file tree
Hide file tree
Showing 10 changed files with 66 additions and 92 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ public class AuthorizationInterceptor implements HandlerInterceptor {
new UriAndMethod("/lists/upload-url", GET),
new UriAndMethod("/lists/upload-complete", GET),
new UriAndMethod("/lists/{listId}/histories", GET),
new UriAndMethod("/lists", GET),
new UriAndMethod("/users/{userId}/lists", GET),
new UriAndMethod("/users/{userId}/followers", GET),
new UriAndMethod("/users/{userId}/followings", GET),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,9 @@ public class ListEntity {
@Embedded
private Items items;

@Column(nullable = false)
private int updateCount;

@CreatedDate
@Temporal(TIMESTAMP)
@Column(updatable = false)
Expand Down Expand Up @@ -259,4 +262,8 @@ public void validateUpdateAuthority(User loginUser, Collaborators beforeCollabor
}
throw new CustomException(INVALID_ACCESS);
}

public void increaseUpdateCount(){
this.updateCount++;
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package com.listywave.list.application.dto.response;

import com.listywave.list.application.domain.item.Item;
import com.listywave.list.application.domain.label.Label;
import com.listywave.list.application.domain.list.ListEntity;
import java.time.LocalDateTime;
import java.util.Comparator;
Expand All @@ -25,15 +24,13 @@ public static ListRecentResponse of(List<ListEntity> lists, LocalDateTime cursor
@Builder
public record ListResponse(
Long id,
String category,
String backgroundColor,
Long ownerId,
String ownerNickname,
String ownerProfileImage,
List<LabelsResponse> labels,
String title,
String description,
List<ItemsResponse> items
List<ItemsResponse> items,
int updateCount
) {

public static List<ListResponse> toList(List<ListEntity> lists) {
Expand All @@ -45,35 +42,13 @@ public static List<ListResponse> toList(List<ListEntity> lists) {
public static ListResponse of(ListEntity list) {
return ListResponse.builder()
.id(list.getId())
.category(list.getCategory().getViewName())
.backgroundColor(list.getBackgroundColor().name())
.ownerId(list.getUser().getId())
.ownerNickname(list.getUser().getNickname())
.ownerProfileImage(list.getUser().getProfileImageUrl())
.labels(LabelsResponse.toList(list.getLabels().getValues()))
.title(list.getTitle().getValue())
.description(list.getDescription().getValue())
.items(ItemsResponse.toList(list.getTop3Items().getValues()))
.build();
}
}

@Builder
public record LabelsResponse(
Long id,
String name
) {

public static List<LabelsResponse> toList(List<Label> labels) {
return labels.stream()
.map(LabelsResponse::of)
.toList();
}

public static LabelsResponse of(Label label) {
return LabelsResponse.builder()
.id(label.getId())
.name(label.getName())
.updateCount(list.getUpdateCount())
.build();
}
}
Expand All @@ -82,15 +57,12 @@ public static LabelsResponse of(Label label) {
public record ItemsResponse(
Long id,
int rank,
String title,
String imageUrl
String title
) {

public static List<ItemsResponse> toList(List<Item> items) {
return items.stream()
.sorted(Comparator.comparing(Item::getRanking))
.map(ItemsResponse::of)
.limit(3)
.toList();
}

Expand All @@ -99,7 +71,6 @@ public static ItemsResponse of(Item item) {
.id(item.getId())
.rank(item.getRanking())
.title(item.getTitle().getValue())
.imageUrl(item.getImageUrl().getValue())
.build();
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -170,25 +170,27 @@ public void deleteList(Long listId, Long loginUserId) {
}

@Transactional(readOnly = true)
public ListRecentResponse getRecentLists(Long loginUserId, LocalDateTime cursorUpdatedDate, Pageable pageable) {
if (loginUserId != null) {
User user = userRepository.getById(loginUserId);
List<Follow> follows = followRepository.getAllByFollowerUser(user);
public ListRecentResponse getRecentLists(LocalDateTime cursorUpdatedDate, CategoryType category, Pageable pageable) {
Slice<ListEntity> result = listRepository.getRecentLists(cursorUpdatedDate, category, pageable);
return toListRecentResponse(result);
}

List<User> myFollowingUsers = follows.stream()
.map(Follow::getFollowingUser)
.filter(followingUser -> !followingUser.isDelete())
.toList();
@Transactional(readOnly = true)
public ListRecentResponse getRecentListsByFollowing(Long loginUserId, LocalDateTime cursorUpdatedDate, Pageable pageable) {
User user = userRepository.getById(loginUserId);
List<Follow> follows = followRepository.getAllByFollowerUser(user);

Slice<ListEntity> result =
listRepository.getRecentListsByFollowing(myFollowingUsers, cursorUpdatedDate, pageable);
return getListRecentResponse(result);
}
Slice<ListEntity> result = listRepository.getRecentLists(cursorUpdatedDate, pageable);
return getListRecentResponse(result);
List<User> myFollowingUsers = follows.stream()
.map(Follow::getFollowingUser)
.filter(followingUser -> !followingUser.isDelete())
.toList();

Slice<ListEntity> result =
listRepository.getRecentListsByFollowing(myFollowingUsers, cursorUpdatedDate, pageable);
return toListRecentResponse(result);
}

private ListRecentResponse getListRecentResponse(Slice<ListEntity> result) {
private ListRecentResponse toListRecentResponse(Slice<ListEntity> result) {
List<ListEntity> recentList = result.getContent();

LocalDateTime cursorUpdatedDate = null;
Expand Down Expand Up @@ -255,6 +257,7 @@ public void update(Long listId, Long loginUserId, ListUpdateRequest request) {
);

if (doesChangedAnyItemRank) {
list.increaseUpdateCount();
historyService.saveHistory(list, updatedDate, true);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,11 +71,21 @@ ResponseEntity<Void> deleteList(

@GetMapping("/lists")
ResponseEntity<ListRecentResponse> getRecentLists(
@OptionalAuth Long loginUserId,
@RequestParam(name = "cursorUpdatedDate", required = false) LocalDateTime cursorUpdatedDate,
@RequestParam(name = "category", defaultValue = "entire") CategoryType category,
@PageableDefault(size = 10) Pageable pageable
) {
ListRecentResponse recentLists = listService.getRecentLists(cursorUpdatedDate, category, pageable);
return ResponseEntity.ok(recentLists);
}

@GetMapping("/lists/following")
ResponseEntity<ListRecentResponse> getRecentListsByFollowing(
@Auth Long loginUserId,
@RequestParam(name = "cursorUpdatedDate", required = false) LocalDateTime cursorUpdatedDate,
@PageableDefault(size = 10) Pageable pageable
) {
ListRecentResponse recentLists = listService.getRecentLists(loginUserId, cursorUpdatedDate, pageable);
ListRecentResponse recentLists = listService.getRecentListsByFollowing(loginUserId, cursorUpdatedDate, pageable);
return ResponseEntity.ok(recentLists);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public interface CustomListRepository {

List<ListTrandingResponse> fetchTrandingLists();

Slice<ListEntity> getRecentLists(LocalDateTime cursorUpdatedDate, Pageable pageable);
Slice<ListEntity> getRecentLists(LocalDateTime cursorUpdatedDate, CategoryType category, Pageable pageable);

Slice<ListEntity> getRecentListsByFollowing(List<User> followingUsers, LocalDateTime cursorUpdatedDate, Pageable pageable);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,17 +98,17 @@ private String getRepresentImageUrl(Long id) {
}

@Override
public Slice<ListEntity> getRecentLists(LocalDateTime cursorUpdatedDate, Pageable pageable) {
public Slice<ListEntity> getRecentLists(LocalDateTime cursorUpdatedDate, CategoryType category, Pageable pageable) {
LocalDateTime thirtyDaysAgo = LocalDateTime.now().minusDays(30);

List<ListEntity> fetch = queryFactory
.selectFrom(listEntity)
.join(listEntity.user, user).fetchJoin()
.leftJoin(label).on(listEntity.id.eq(label.list.id))
.leftJoin(item).on(listEntity.id.eq(item.list.id))
.where(
listEntity.updatedDate.goe(thirtyDaysAgo),
updatedDateLt(cursorUpdatedDate),
categoryEq(category),
listEntity.user.isDelete.eq(false),
listEntity.isPublic.eq(true)
)
Expand Down Expand Up @@ -142,7 +142,6 @@ public Slice<ListEntity> getRecentListsByFollowing(
List<ListEntity> fetch = queryFactory
.selectFrom(listEntity)
.join(listEntity.user, user).fetchJoin()
.leftJoin(label).on(listEntity.id.eq(label.list.id))
.leftJoin(item).on(listEntity.id.eq(item.list.id))
.where(
listEntity.updatedDate.goe(thirtyDaysAgo),
Expand Down
44 changes: 10 additions & 34 deletions src/test/java/com/listywave/acceptance/list/ListAcceptanceTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,32 +5,7 @@
import static com.listywave.acceptance.comment.CommentAcceptanceTestHelper.댓글_저장_API_호출;
import static com.listywave.acceptance.common.CommonAcceptanceHelper.HTTP_상태_코드를_검증한다;
import static com.listywave.acceptance.follow.FollowAcceptanceTestHelper.팔로우_요청_API;
import static com.listywave.acceptance.list.ListAcceptanceTestHelper.가장_좋아하는_견종_TOP3_생성_요청_데이터;
import static com.listywave.acceptance.list.ListAcceptanceTestHelper.검색_API_호출;
import static com.listywave.acceptance.list.ListAcceptanceTestHelper.리스트_삭제_요청_API_호출;
import static com.listywave.acceptance.list.ListAcceptanceTestHelper.리스트_상세_조회를_검증한다;
import static com.listywave.acceptance.list.ListAcceptanceTestHelper.리스트_수정_API_호출;
import static com.listywave.acceptance.list.ListAcceptanceTestHelper.리스트_저장_API_호출;
import static com.listywave.acceptance.list.ListAcceptanceTestHelper.리스트의_아이템_순위와_히스토리의_아이템_순위를_검증한다;
import static com.listywave.acceptance.list.ListAcceptanceTestHelper.비회원_리스트_상세_조회_API_호출;
import static com.listywave.acceptance.list.ListAcceptanceTestHelper.비회원_최신_리스트_10개_조회_API_호출;
import static com.listywave.acceptance.list.ListAcceptanceTestHelper.비회원_피드_리스트_조회_API_호출;
import static com.listywave.acceptance.list.ListAcceptanceTestHelper.비회원_히스토리_조회_API_호출;
import static com.listywave.acceptance.list.ListAcceptanceTestHelper.비회원이_피드_리스트_조회_카테고리_콜라보레이터_필터링_요청;
import static com.listywave.acceptance.list.ListAcceptanceTestHelper.비회원이_피드_리스트_조회_카테고리_필터링_요청;
import static com.listywave.acceptance.list.ListAcceptanceTestHelper.비회원이_피드_리스트_조회_콜라보레이터_필터링_요청;
import static com.listywave.acceptance.list.ListAcceptanceTestHelper.아이템_순위와_라벨을_바꾼_좋아하는_견종_TOP3_요청_데이터;
import static com.listywave.acceptance.list.ListAcceptanceTestHelper.정렬기준을_포함한_검색_API_호출;
import static com.listywave.acceptance.list.ListAcceptanceTestHelper.좋아하는_라면_TOP3_생성_요청_데이터;
import static com.listywave.acceptance.list.ListAcceptanceTestHelper.카테고리로_검색_API_호출;
import static com.listywave.acceptance.list.ListAcceptanceTestHelper.카테고리와_키워드로_검색_API_호출;
import static com.listywave.acceptance.list.ListAcceptanceTestHelper.콜렉트_요청_API_호출;
import static com.listywave.acceptance.list.ListAcceptanceTestHelper.키워드로_검색_API_호출;
import static com.listywave.acceptance.list.ListAcceptanceTestHelper.키워드와_정렬기준을_포함한_검색_API_호출;
import static com.listywave.acceptance.list.ListAcceptanceTestHelper.트랜딩_리스트_조회_API_호출;
import static com.listywave.acceptance.list.ListAcceptanceTestHelper.회원_최신_리스트_10개_조회_API_호출;
import static com.listywave.acceptance.list.ListAcceptanceTestHelper.회원_피드_리스트_조회;
import static com.listywave.acceptance.list.ListAcceptanceTestHelper.회원용_리스트_상세_조회_API_호출;
import static com.listywave.acceptance.list.ListAcceptanceTestHelper.*;
import static com.listywave.acceptance.reply.ReplyAcceptanceTestHelper.답글_등록_API_호출;
import static com.listywave.list.fixture.ListFixture.가장_좋아하는_견종_TOP3;
import static com.listywave.list.fixture.ListFixture.가장_좋아하는_견종_TOP3_순위_변경;
Expand Down Expand Up @@ -287,7 +262,7 @@ class 리스트_수정 {
}

@Test
void 아이템_순위에_변동이_있으면_히스토리로_기록되고_lastUpdatedDate가_갱신된다() {
void 아이템_순위에_변동이_있으면_히스토리로_기록되고_lastUpdatedDate가_갱신되고_updateCount가_증가한다() {
// given
var 동호 = 회원을_저장한다(동호());
var 동호_액세스_토큰 = 액세스_토큰을_발급한다(동호);
Expand Down Expand Up @@ -343,7 +318,7 @@ class 리스트_수정 {
}

@Test
void 아이템의_순위_변동이_일어나지_않으면_updatedDate가_갱신되지_않는다() {
void 아이템의_순위_변동이_일어나지_않으면_updatedDate와_updateCount가_갱신되지_않는다() {
// given
var 동호 = 회원을_저장한다(동호());
var 정수 = 회원을_저장한다(정수());
Expand Down Expand Up @@ -564,7 +539,7 @@ class 피드_리스트_조회 {
}

@Nested
class 리스트_탐색 {
class 리스트_팀섹 {

@Test
void 트랜딩_리스트를_조회한다() {
Expand Down Expand Up @@ -619,7 +594,7 @@ class 리스트_탐색 {
}

@Test
void 회원이_최신_리스트_10개를_조회하면_팔로우한_사용자의_최신_리스트_10개가_반환된다() {
void 팔로우한_사용자의_최신_리스트_10개를_조회한다() {
// given
var 동호 = 회원을_저장한다(동호());
var 정수 = 회원을_저장한다(정수());
Expand All @@ -630,15 +605,15 @@ class 리스트_탐색 {
리스트를_모두_저장한다(지정된_개수만큼_리스트를_생성한다(동호, 5));

// when
var response = 회원_최신_리스트_10개_조회_API_호출(동호_액세스_토큰);
var response = 팔로우한_사용자의_최신_리스트_10개_조회_API_호출(동호_액세스_토큰);
var result = response.as(ListRecentResponse.class);

// then
assertThat(result.lists()).hasSize(5);
}

@Test
void 비회원이_최신_리스트_10개를_조회한다() {
void 최신_리스트_10개를_조회한다() {
// given
var 동호 = 회원을_저장한다(동호());
var 정수 = 회원을_저장한다(정수());
Expand All @@ -649,10 +624,11 @@ class 리스트_탐색 {
리스트를_모두_저장한다(지정된_개수만큼_리스트를_생성한다(동호, 5));

// when
var 결과 = 비회원_최신_리스트_10개_조회_API_호출().as(ListRecentResponse.class);
var 결과 = 최신_리스트_10개_조회_카테고리_필터링_API_호출(CategoryType.ENTIRE.name().toLowerCase())
.as(ListRecentResponse.class);

// then
var 동호_리스트 = 비회원_피드_리스트_조회_API_호출(동호).as(FindFeedListResponse.class).feedLists();
var 동호_리스트 = 비회원_피드_리스트_조회_API_호출(동호 ).as(FindFeedListResponse.class).feedLists();
var 정수_리스트 = 비회원_피드_리스트_조회_API_호출(정수).as(FindFeedListResponse.class).feedLists();
var 모든_리스트 = new ArrayList<>(동호_리스트);
모든_리스트.addAll(정수_리스트);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -184,17 +184,17 @@ public abstract class ListAcceptanceTestHelper {
.extract();
}

public static ExtractableResponse<Response> 비회원_최신_리스트_10개_조회_API_호출() {
public static ExtractableResponse<Response> 최신_리스트_10개_조회_카테고리_필터링_API_호출(String category) {
return given()
.when().get("/lists")
.when().get("/lists?category={category}", category)
.then().log().all()
.extract();
}

public static ExtractableResponse<Response> 회원_최신_리스트_10개_조회_API_호출(String accessToken) {
public static ExtractableResponse<Response> 팔로우한_사용자의_최신_리스트_10개_조회_API_호출(String accessToken) {
return given()
.header(AUTHORIZATION, "Bearer " + accessToken)
.when().get("/lists")
.when().get("/lists/following")
.then().log().all()
.extract();
}
Expand Down
7 changes: 7 additions & 0 deletions src/test/java/com/listywave/list/fixture/ListFixture.java
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,13 @@ public abstract class ListFixture {
new ItemComment(String.valueOf(i + 2)),
new ItemLink(String.valueOf(i + 2)),
new ItemImageUrl(String.valueOf(i + 2))
),
Item.init(
i + 3,
new ItemTitle(String.valueOf(i + 3)),
new ItemComment(String.valueOf(i + 3)),
new ItemLink(String.valueOf(i + 3)),
new ItemImageUrl(String.valueOf(i + 3))
)
))
)).toList();
Expand Down

0 comments on commit 333420f

Please sign in to comment.