Skip to content

Commit 85773a6

Browse files
committed
feat: 특정 유저의 팔로잉/팔로워 목록 조회 API 추가
1 parent c7d2e59 commit 85773a6

File tree

6 files changed

+75
-65
lines changed

6 files changed

+75
-65
lines changed

db_dev.mv.db

-8 KB
Binary file not shown.

src/main/java/com/example/log4u/domain/follow/controller/FollowController.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,16 @@
44
import org.springframework.security.core.annotation.AuthenticationPrincipal;
55
import org.springframework.stereotype.Controller;
66
import org.springframework.web.bind.annotation.DeleteMapping;
7+
import org.springframework.web.bind.annotation.GetMapping;
78
import org.springframework.web.bind.annotation.PathVariable;
89
import org.springframework.web.bind.annotation.PostMapping;
910
import org.springframework.web.bind.annotation.RequestMapping;
11+
import org.springframework.web.bind.annotation.RequestParam;
1012

13+
import com.example.log4u.common.dto.PageResponse;
1114
import com.example.log4u.common.oauth2.dto.CustomOAuth2User;
1215
import com.example.log4u.domain.follow.service.FollowService;
16+
import com.example.log4u.domain.user.dto.UserThumbnailResponseDto;
1317

1418
import io.swagger.v3.oas.annotations.tags.Tag;
1519
import lombok.RequiredArgsConstructor;
@@ -38,4 +42,22 @@ public ResponseEntity<Void> deleteFollow(
3842
followService.deleteFollow(customOAuth2User.getUserId(), nickname);
3943
return ResponseEntity.ok().build();
4044
}
45+
46+
@GetMapping("/{nickname}/followers")
47+
public ResponseEntity<PageResponse<UserThumbnailResponseDto>> getFollowersByUserId(
48+
@PathVariable String nickname,
49+
@RequestParam(required = false) Long cursorId,
50+
@RequestParam(required = false) String keyword
51+
) {
52+
return ResponseEntity.ok(followService.getFollowersByNickname(nickname, cursorId, keyword));
53+
}
54+
55+
@GetMapping("/{nickname}/followings")
56+
public ResponseEntity<PageResponse<UserThumbnailResponseDto>> getFollowingsByUserId(
57+
@PathVariable String nickname,
58+
@RequestParam(required = false) Long cursorId,
59+
@RequestParam(required = false) String keyword
60+
) {
61+
return ResponseEntity.ok(followService.getFollowingsByNickname(nickname, cursorId, keyword));
62+
}
4163
}

src/main/java/com/example/log4u/domain/follow/service/FollowService.java

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,26 @@
11
package com.example.log4u.domain.follow.service;
22

3+
import org.springframework.data.domain.PageRequest;
4+
import org.springframework.data.domain.Slice;
35
import org.springframework.stereotype.Service;
46
import org.springframework.transaction.annotation.Transactional;
57

8+
import com.example.log4u.common.dto.PageResponse;
69
import com.example.log4u.domain.follow.entitiy.Follow;
710
import com.example.log4u.domain.follow.exception.FollowNotFoundException;
11+
import com.example.log4u.domain.follow.repository.FollowQuerydsl;
812
import com.example.log4u.domain.follow.repository.FollowRepository;
13+
import com.example.log4u.domain.user.dto.UserThumbnailResponseDto;
914
import com.example.log4u.domain.user.service.UserService;
1015

1116
import lombok.RequiredArgsConstructor;
1217

1318
@Service
1419
@RequiredArgsConstructor
1520
public class FollowService {
21+
private final int defaultPageSize = 6;
1622
private final FollowRepository followRepository;
23+
private final FollowQuerydsl followQuerydsl;
1724
private final UserService userService;
1825

1926
@Transactional
@@ -62,4 +69,46 @@ public Long getFollowingCount(Long userId) {
6269
public boolean existsFollow(Long initiatorId, Long targetId) {
6370
return followRepository.existsByInitiatorIdAndTargetId(initiatorId, targetId);
6471
}
72+
73+
@Transactional(readOnly = true)
74+
public PageResponse<UserThumbnailResponseDto> getFollowersByNickname(String nickname, Long cursorId,
75+
String keyword) {
76+
Long userId = userService.getUserIdByNickname(nickname);
77+
78+
return getFollowersByUserId(userId, cursorId, keyword);
79+
}
80+
81+
@Transactional(readOnly = true)
82+
public PageResponse<UserThumbnailResponseDto> getFollowingsByNickname(String nickname, Long cursorId,
83+
String keyword) {
84+
Long userId = userService.getUserIdByNickname(nickname);
85+
86+
return getFollowingsByUserId(userId, cursorId, keyword);
87+
}
88+
89+
@Transactional(readOnly = true)
90+
public PageResponse<UserThumbnailResponseDto> getFollowersByUserId(Long userId, Long cursorId, String keyword) {
91+
Slice<UserThumbnailResponseDto> slice = followQuerydsl.getFollowerSliceByUserId(
92+
userId,
93+
cursorId,
94+
keyword,
95+
PageRequest.of(0, defaultPageSize));
96+
97+
Long nextCursor = !slice.isEmpty() ? slice.getContent().getLast().userId() : null;
98+
99+
return PageResponse.of(slice, nextCursor);
100+
}
101+
102+
@Transactional(readOnly = true)
103+
public PageResponse<UserThumbnailResponseDto> getFollowingsByUserId(Long userId, Long cursorId, String keyword) {
104+
Slice<UserThumbnailResponseDto> slice = followQuerydsl.getFollowingSliceByUserId(
105+
userId,
106+
cursorId,
107+
keyword,
108+
PageRequest.of(0, defaultPageSize));
109+
110+
Long nextCursor = !slice.isEmpty() ? slice.getContent().getLast().userId() : null;
111+
112+
return PageResponse.of(slice, nextCursor);
113+
}
65114
}

src/main/java/com/example/log4u/domain/user/mypage/controller/MyPageController.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import com.example.log4u.common.oauth2.dto.CustomOAuth2User;
1111
import com.example.log4u.domain.diary.VisibilityType;
1212
import com.example.log4u.domain.diary.dto.DiaryResponseDto;
13+
import com.example.log4u.domain.follow.service.FollowService;
1314
import com.example.log4u.domain.subscription.dto.SubscriptionResponseDto;
1415
import com.example.log4u.domain.user.dto.UserThumbnailResponseDto;
1516
import com.example.log4u.domain.user.mypage.service.MyPageService;
@@ -20,6 +21,7 @@
2021
@RequiredArgsConstructor
2122
public class MyPageController {
2223
private final MyPageService myPageService;
24+
private final FollowService followService;
2325

2426
@GetMapping("/users/me/diaries")
2527
public ResponseEntity<PageResponse<DiaryResponseDto>> getMyDiaryPage(
@@ -48,7 +50,7 @@ public ResponseEntity<PageResponse<UserThumbnailResponseDto>> getMyFollowingPage
4850

4951
) {
5052
long userId = customOAuth2User.getUserId();
51-
return ResponseEntity.ok(myPageService.getMyFollowings(userId, cursorId, keyword));
53+
return ResponseEntity.ok(followService.getFollowingsByUserId(userId, cursorId, keyword));
5254
}
5355

5456
@GetMapping("/users/me/followers")
@@ -58,7 +60,7 @@ public ResponseEntity<PageResponse<UserThumbnailResponseDto>> getMyFollowerPage(
5860
@RequestParam(required = false) String keyword
5961
) {
6062
long userId = customOAuth2User.getUserId();
61-
return ResponseEntity.ok(myPageService.getMyFollowers(userId, cursorId, keyword));
63+
return ResponseEntity.ok(followService.getFollowersByUserId(userId, cursorId, keyword));
6264
}
6365

6466
@GetMapping("/users/me/subscriptions")

src/main/java/com/example/log4u/domain/user/mypage/service/MyPageService.java

Lines changed: 0 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,17 @@
33
import java.time.LocalDateTime;
44
import java.util.Optional;
55

6-
import org.springframework.data.domain.PageRequest;
7-
import org.springframework.data.domain.Slice;
86
import org.springframework.stereotype.Service;
97
import org.springframework.transaction.annotation.Transactional;
108

119
import com.example.log4u.common.dto.PageResponse;
1210
import com.example.log4u.domain.diary.VisibilityType;
1311
import com.example.log4u.domain.diary.dto.DiaryResponseDto;
1412
import com.example.log4u.domain.diary.service.DiaryService;
15-
import com.example.log4u.domain.follow.repository.FollowQuerydsl;
1613
import com.example.log4u.domain.subscription.PaymentStatus;
1714
import com.example.log4u.domain.subscription.dto.SubscriptionResponseDto;
1815
import com.example.log4u.domain.subscription.entity.Subscription;
1916
import com.example.log4u.domain.subscription.repository.SubscriptionRepository;
20-
import com.example.log4u.domain.user.dto.UserThumbnailResponseDto;
2117

2218
import lombok.RequiredArgsConstructor;
2319

@@ -27,7 +23,6 @@
2723
public class MyPageService {
2824
private final int defaultPageSize = 6;
2925
private final DiaryService diaryService;
30-
private final FollowQuerydsl followQuerydsl;
3126
private final SubscriptionRepository subscriptionRepository;
3227

3328
@Transactional(readOnly = true)
@@ -43,32 +38,6 @@ public PageResponse<DiaryResponseDto> getLikeDiariesByCursor(Long userId, Long c
4338
cursorId, defaultPageSize);
4439
}
4540

46-
@Transactional(readOnly = true)
47-
public PageResponse<UserThumbnailResponseDto> getMyFollowers(Long userId, Long cursorId, String keyword) {
48-
Slice<UserThumbnailResponseDto> slice = followQuerydsl.getFollowerSliceByUserId(
49-
userId,
50-
cursorId,
51-
keyword,
52-
PageRequest.of(0, defaultPageSize));
53-
54-
Long nextCursor = !slice.isEmpty() ? slice.getContent().getLast().userId() : null;
55-
56-
return PageResponse.of(slice, nextCursor);
57-
}
58-
59-
@Transactional(readOnly = true)
60-
public PageResponse<UserThumbnailResponseDto> getMyFollowings(Long userId, Long cursorId, String keyword) {
61-
Slice<UserThumbnailResponseDto> slice = followQuerydsl.getFollowingSliceByUserId(
62-
userId,
63-
cursorId,
64-
keyword,
65-
PageRequest.of(0, defaultPageSize));
66-
67-
Long nextCursor = !slice.isEmpty() ? slice.getContent().getLast().userId() : null;
68-
69-
return PageResponse.of(slice, nextCursor);
70-
}
71-
7241
@Transactional(readOnly = true)
7342
public SubscriptionResponseDto getMySubscription(Long userId) {
7443
Optional<Subscription> optionalSubscription = subscriptionRepository

src/test/java/com/example/log4u/domain/user/mypage/service/MyPageServiceTest.java

Lines changed: 0 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -15,20 +15,17 @@
1515
import org.mockito.InjectMocks;
1616
import org.mockito.Mock;
1717
import org.mockito.junit.jupiter.MockitoExtension;
18-
import org.springframework.data.domain.PageRequest;
1918
import org.springframework.data.domain.SliceImpl;
2019

2120
import com.example.log4u.common.dto.PageResponse;
2221
import com.example.log4u.domain.diary.VisibilityType;
2322
import com.example.log4u.domain.diary.dto.DiaryResponseDto;
2423
import com.example.log4u.domain.diary.service.DiaryService;
25-
import com.example.log4u.domain.follow.repository.FollowQuerydsl;
2624
import com.example.log4u.domain.subscription.PaymentProvider;
2725
import com.example.log4u.domain.subscription.PaymentStatus;
2826
import com.example.log4u.domain.subscription.dto.SubscriptionResponseDto;
2927
import com.example.log4u.domain.subscription.entity.Subscription;
3028
import com.example.log4u.domain.subscription.repository.SubscriptionRepository;
31-
import com.example.log4u.domain.user.dto.UserThumbnailResponseDto;
3229
import com.example.log4u.fixture.DiaryFixture;
3330

3431
@ExtendWith(MockitoExtension.class)
@@ -39,9 +36,6 @@ public class MyPageServiceTest {
3936
@Mock
4037
private DiaryService diaryService;
4138

42-
@Mock
43-
private FollowQuerydsl followQuerydsl;
44-
4539
@Mock
4640
private SubscriptionRepository subscriptionRepository;
4741

@@ -89,32 +83,6 @@ void getLikeDiariesByCursor_returnsCorrectData() {
8983
verify(diaryService).getLikeDiariesByCursor(userId, userId, cursorId, 6);
9084
}
9185

92-
@DisplayName("성공 테스트 : 내 팔로워 조회")
93-
@Test
94-
void getMyFollowers_returnsCorrectData() {
95-
var slice = new SliceImpl<>(List.of(new UserThumbnailResponseDto(userId, "nick", "image")));
96-
97-
when(followQuerydsl.getFollowerSliceByUserId(eq(userId), eq(cursorId), any(), any(PageRequest.class)))
98-
.thenReturn(slice);
99-
100-
PageResponse<UserThumbnailResponseDto> result = myPageService.getMyFollowers(userId, cursorId, null);
101-
102-
assertThat(result).isNotNull();
103-
}
104-
105-
@DisplayName("성공 테스트 : 내 팔로잉 조회")
106-
@Test
107-
void getMyFollowings_returnsCorrectData() {
108-
var slice = new SliceImpl<>(List.of(new UserThumbnailResponseDto(userId, "nick", "image")));
109-
110-
when(followQuerydsl.getFollowingSliceByUserId(eq(userId), eq(cursorId), any(), any(PageRequest.class)))
111-
.thenReturn(slice);
112-
113-
PageResponse<UserThumbnailResponseDto> result = myPageService.getMyFollowings(userId, cursorId, null);
114-
115-
assertThat(result).isNotNull();
116-
}
117-
11886
@DisplayName("구독 정보 조회 - 구독이 있을 때")
11987
@Test
12088
void getMySubscription_whenExists_returnsActiveSubscription() {

0 commit comments

Comments
 (0)