Skip to content

Commit 6264a0e

Browse files
authored
[Feat/#272] 내 정보 조회 API 구현 (#273)
* feat: 내 정보 조회 api 컨트롤러, 서비스 작성 * feat: 내 정보 조회 api 레포지토리 작성 * test: 컨트롤러/서비스 테스트 작성 * fix: spotless 포맷팅 규칙 준수
1 parent dd82c59 commit 6264a0e

7 files changed

Lines changed: 147 additions & 0 deletions

File tree

clokey-api/src/main/java/org/clokey/domain/member/controller/MemberController.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,4 +137,13 @@ public BaseResponse<MemberInfoResponse> getMemberInfo(@PathVariable Long memberI
137137
return BaseResponse.onSuccess(
138138
GlobalBaseSuccessCode.OK, memberService.getMemberInfo(memberId));
139139
}
140+
141+
@GetMapping("/me")
142+
@Operation(
143+
operationId = "Member_getMyInfo",
144+
summary = "내 정보 조회 API",
145+
description = "로그인한 사용자의 본인 정보를 조회합니다.")
146+
public BaseResponse<MemberInfoResponse> getMyInfo() {
147+
return BaseResponse.onSuccess(GlobalBaseSuccessCode.OK, memberService.getMyInfo());
148+
}
140149
}

clokey-api/src/main/java/org/clokey/domain/member/repository/MemberRepositoryCustom.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,6 @@
55
public interface MemberRepositoryCustom {
66

77
public MemberInfoResponse findMemberInfoById(Long currentId, Long targetId);
8+
9+
public MemberInfoResponse findMyInfoById(Long memberId);
810
}

clokey-api/src/main/java/org/clokey/domain/member/repository/MemberRepositoryImpl.java

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,33 @@ public MemberInfoResponse findMemberInfoById(Long currentId, Long targetId) {
5454
.fetchOne();
5555
}
5656

57+
@Override
58+
public MemberInfoResponse findMyInfoById(Long memberId) {
59+
return queryFactory
60+
.select(
61+
Projections.constructor(
62+
MemberInfoResponse.class,
63+
member.clokeyId,
64+
member.nickname,
65+
member.bio,
66+
JPAExpressions.select(follow.count())
67+
.from(follow)
68+
.where(
69+
follow.followTo.id.eq(member.id),
70+
isNotBlocked(memberId, follow.followFrom.id)),
71+
JPAExpressions.select(follow.count())
72+
.from(follow)
73+
.where(
74+
follow.followFrom.id.eq(member.id),
75+
isNotBlocked(memberId, follow.followTo.id)),
76+
member.profileImageUrl,
77+
Expressions.FALSE,
78+
Expressions.TRUE))
79+
.from(member)
80+
.where(member.id.eq(memberId))
81+
.fetchOne();
82+
}
83+
5784
private BooleanExpression isNotBlocked(Long currentId, NumberPath<Long> targetMemberId) {
5885
if (currentId == null) {
5986
return null;

clokey-api/src/main/java/org/clokey/domain/member/service/MemberService.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,6 @@ SliceResponse<FollowMemberResponse> getFollows(
2727
Long memberId, Long lastFollowId, boolean isFollowing, Integer size);
2828

2929
MemberInfoResponse getMemberInfo(Long memberId);
30+
31+
MemberInfoResponse getMyInfo();
3032
}

clokey-api/src/main/java/org/clokey/domain/member/service/MemberServiceImpl.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,12 @@ public MemberInfoResponse getMemberInfo(Long memberId) {
156156
return memberRepository.findMemberInfoById(currentMember.getId(), memberId);
157157
}
158158

159+
@Override
160+
public MemberInfoResponse getMyInfo() {
161+
Member currentMember = memberUtil.getCurrentMember();
162+
return memberRepository.findMyInfoById(currentMember.getId());
163+
}
164+
159165
private void validateVisualizeBannedMember(Member member, ProfileUpdateRequest request) {
160166
boolean banned = member.getMemberStatus().equals(MemberStatus.BANNED);
161167
boolean changeToPublic = request.visibility().equals(Visibility.PUBLIC);

clokey-api/src/test/java/org/clokey/domain/member/controller/MemberControllerTest.java

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -576,4 +576,37 @@ class 회원_정보_조회_시 {
576576
.andExpect(jsonPath("$.result.codiveId").value("codive123"));
577577
}
578578
}
579+
580+
@Nested
581+
class 내_정보_조회_요청_시 {
582+
583+
@Test
584+
void 유효한_요청이면_내_정보를_반환한다() throws Exception {
585+
// given
586+
MemberInfoResponse result =
587+
new MemberInfoResponse(
588+
"myCodiveId",
589+
"myNickname",
590+
"내 한줄소개",
591+
10L,
592+
5L,
593+
"https://img.example.com/me.jpg",
594+
false,
595+
true);
596+
given(memberService.getMyInfo()).willReturn(result);
597+
598+
// when
599+
ResultActions perform = mockMvc.perform(get("/users/me"));
600+
601+
// then
602+
perform.andExpect(status().isOk())
603+
.andExpect(jsonPath("$.isSuccess").value(true))
604+
.andExpect(jsonPath("$.code").value("COMMON200"))
605+
.andExpect(jsonPath("$.message").value("성공입니다."))
606+
.andExpect(jsonPath("$.result.codiveId").value("myCodiveId"))
607+
.andExpect(jsonPath("$.result.nickname").value("myNickname"))
608+
.andExpect(jsonPath("$.result.isMe").value(true))
609+
.andExpect(jsonPath("$.result.isFollowing").value(false));
610+
}
611+
}
579612
}

clokey-api/src/test/java/org/clokey/domain/member/service/MemberServiceTest.java

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -821,4 +821,72 @@ void setUp() {
821821
.hasMessage(MemberErrorCode.MEMBER_NOT_FOUND.getMessage());
822822
}
823823
}
824+
825+
@Nested
826+
class 내_정보를_조회할_때 {
827+
828+
@BeforeEach
829+
void setUp() {
830+
Member member1 =
831+
Member.createMember(
832+
"testEmail1",
833+
"testCodiveId1",
834+
"testNickName1",
835+
OauthInfo.createOauthInfo("testOauthId1", OauthProvider.KAKAO));
836+
Member member2 =
837+
Member.createMember(
838+
"testEmail2",
839+
"testCodiveId2",
840+
"testNickName2",
841+
OauthInfo.createOauthInfo("testOauthId2", OauthProvider.KAKAO));
842+
Member member3 =
843+
Member.createMember(
844+
"testEmail3",
845+
"testCodiveId3",
846+
"testNickName3",
847+
OauthInfo.createOauthInfo("testOauthId3", OauthProvider.KAKAO));
848+
memberRepository.saveAll(List.of(member1, member2, member3));
849+
given(memberUtil.getCurrentMember()).willReturn(member1);
850+
851+
Follow follow21 = Follow.createFollow(member2, member1);
852+
Follow follow31 = Follow.createFollow(member3, member1);
853+
Follow follow12 = Follow.createFollow(member1, member2);
854+
Follow follow13 = Follow.createFollow(member1, member3);
855+
followRepository.saveAll(List.of(follow21, follow31, follow12, follow13));
856+
857+
Block block13 = Block.createBlock(member1, member3);
858+
blockRepository.save(block13);
859+
}
860+
861+
@Test
862+
void 유효한_요청이면_내_정보를_반환한다() {
863+
// when
864+
MemberInfoResponse response = memberService.getMyInfo();
865+
866+
// then
867+
Assertions.assertAll(
868+
() -> assertThat(response.codiveId()).isEqualTo("testCodiveId1"),
869+
() -> assertThat(response.nickname()).isEqualTo("testNickName1"),
870+
() -> assertThat(response.isMe()).isTrue(),
871+
() -> assertThat(response.isFollowing()).isFalse());
872+
}
873+
874+
@Test
875+
void 차단_관계인_멤버는_팔로워_수에_집계하지_않는다() {
876+
// when - member1 팔로워: member2, member3. member1이 member3 차단 → 1명만 집계
877+
MemberInfoResponse response = memberService.getMyInfo();
878+
879+
// then
880+
assertThat(response.followerCount()).isOne();
881+
}
882+
883+
@Test
884+
void 차단_관계인_멤버는_팔로잉_수에_집계하지_않는다() {
885+
// when - member1 팔로잉: member2, member3. member1이 member3 차단 → 1명만 집계
886+
MemberInfoResponse response = memberService.getMyInfo();
887+
888+
// then
889+
assertThat(response.followingCount()).isOne();
890+
}
891+
}
824892
}

0 commit comments

Comments
 (0)