Skip to content

Commit 9355f85

Browse files
committed
chore(api - memory): add relationship filtering logic and optimizer for memory retrieval
1 parent a985f0e commit 9355f85

File tree

4 files changed

+135
-55
lines changed

4 files changed

+135
-55
lines changed

memory-adapter/src/main/java/com/memory/persistence/repository/memory/MemoryRepositoryCustomImpl.java

Lines changed: 18 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
import com.memory.domain.member.Member;
55
import com.memory.domain.memory.MemoryType;
66
import com.memory.domain.memory.repository.MemoryRepositoryCustom;
7-
import com.memory.domain.relationship.RelationshipStatus;
87
import com.querydsl.core.types.Predicate;
98
import com.querydsl.core.types.dsl.BooleanExpression;
109
import com.querydsl.jpa.impl.JPAQueryFactory;
@@ -16,7 +15,6 @@
1615

1716
import static com.memory.domain.memory.QMemory.memory;
1817
import static com.memory.domain.file.QFile.file;
19-
import static com.memory.domain.relationship.QRelationship.relationship;
2018

2119
@Repository
2220
@RequiredArgsConstructor
@@ -25,11 +23,10 @@ public class MemoryRepositoryCustomImpl implements MemoryRepositoryCustom {
2523
private final JPAQueryFactory queryFactory;
2624

2725
@Override
28-
public List<Memory> findByMemberAndMemoryType(Member member, MemoryType memoryType, int size) {
26+
public List<Memory> findByMemberAndMemoryType(Member member, List<Long> relatedMemberIds, MemoryType memoryType, int size) {
2927
return queryFactory.selectFrom(memory)
3028
.where(
31-
getMemoryAccessCondition(member),
32-
getMemoryType(memoryType),
29+
getMemoryAccessCondition(member, relatedMemberIds, memoryType),
3330
memory.deleteDate.isNull()
3431
)
3532
.orderBy(memory.id.desc())
@@ -38,11 +35,10 @@ public List<Memory> findByMemberAndMemoryType(Member member, MemoryType memoryTy
3835
}
3936

4037
@Override
41-
public List<Memory> findByMemberAndMemoryType(Member member, MemoryType memoryType, Long lastMemoryId, int size) {
38+
public List<Memory> findByMemberAndMemoryType(Member member, List<Long> relatedMemberIds, MemoryType memoryType, Long lastMemoryId, int size) {
4239
return queryFactory.selectFrom(memory)
4340
.where(
44-
getMemoryAccessCondition(member),
45-
getMemoryType(memoryType),
41+
getMemoryAccessCondition(member, relatedMemberIds, memoryType),
4642
memory.deleteDate.isNull(),
4743
ltMemoryId(lastMemoryId)
4844
)
@@ -135,36 +131,19 @@ private Predicate getMemoryType(MemoryType memoryType) {
135131
return memory.memoryType.eq(memoryType);
136132
}
137133

138-
/**
139-
* 나의 메모리 또는 나와 연결된 사람의 PUBLIC/RELATIONSHIP 타입 메모리를 조회하는 조건
140-
*/
141-
private BooleanExpression getMemoryAccessCondition(Member member) {
142-
// 1. 나의 모든 메모리
143-
BooleanExpression myMemories = memory.member.eq(member);
144-
145-
// 2. 연결된 사람들의 ID 서브쿼리
146-
BooleanExpression connectedMembers = memory.member.id.in(
147-
queryFactory.select(relationship.relatedMember.id)
148-
.from(relationship)
149-
.where(
150-
relationship.member.eq(member),
151-
relationship.relationshipStatus.eq(RelationshipStatus.ACCEPTED)
152-
)
153-
).or(memory.member.id.in(
154-
queryFactory.select(relationship.member.id)
155-
.from(relationship)
156-
.where(
157-
relationship.relatedMember.eq(member),
158-
relationship.relationshipStatus.eq(RelationshipStatus.ACCEPTED)
159-
)
160-
));
161-
162-
// 3. 연결된 사람들의 PUBLIC 또는 RELATIONSHIP 타입 메모리
163-
BooleanExpression connectedMembersPublicOrRelationshipMemories = connectedMembers
164-
.and(memory.memoryType.eq(MemoryType.PUBLIC)
165-
.or(memory.memoryType.eq(MemoryType.RELATIONSHIP)));
166-
167-
// 최종 조건: 나의 메모리 OR 연결된 사람들의 PUBLIC/RELATIONSHIP 메모리
168-
return myMemories.or(connectedMembersPublicOrRelationshipMemories);
134+
// RELATIONSHIP: 내꺼 PRIVATE 제외 + 상대방 PRIVATE 제외
135+
// PUBLIC: 내꺼 PUBLIC만
136+
// PRIVATE: 내꺼 PRIVATE만
137+
private BooleanExpression getMemoryAccessCondition(Member member, List<Long> relatedMemberIds, MemoryType memoryType) {
138+
return switch (memoryType) {
139+
case RELATIONSHIP -> memory.member.eq(member)
140+
.and(memory.memoryType.ne(MemoryType.PRIVATE))
141+
.or(memory.member.id.in(relatedMemberIds)
142+
.and(memory.memoryType.ne(MemoryType.PRIVATE)));
143+
case PRIVATE -> memory.member.eq(member)
144+
.and(memory.memoryType.eq(MemoryType.PRIVATE));
145+
default -> memory.member.eq(member)
146+
.and(memory.memoryType.eq(MemoryType.PUBLIC));
147+
};
169148
}
170149
}

memory-api/src/main/java/com/memory/service/memory/MemoryService.java

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99
import com.memory.domain.memory.Memory;
1010
import com.memory.domain.memory.MemoryType;
1111
import com.memory.domain.memory.repository.MemoryRepository;
12+
import com.memory.domain.relationship.Relationship;
13+
import com.memory.domain.relationship.RelationshipStatus;
14+
import com.memory.domain.relationship.repository.RelationshipRepository;
1215
import com.memory.dto.memory.MemoryRequest;
1316
import com.memory.dto.memory.response.MemoryResponse;
1417
import com.memory.exception.customException.NotFoundException;
@@ -27,6 +30,7 @@ public class MemoryService {
2730
private final MemberRepository memberRepository;
2831
private final MapRepository mapRepository;
2932
private final FileRepository fileRepository;
33+
private final RelationshipRepository relationshipRepository;
3034

3135
@Transactional
3236
public MemoryResponse createMemory(Long memberId, MemoryRequest.Create createRequest) {
@@ -74,11 +78,17 @@ public List<MemoryResponse> findMemoriesByMember(Long memberId, Long lastMemoryI
7478
Member member = memberRepository.findMemberById(memberId)
7579
.orElseThrow(() -> new NotFoundException("회원을 찾을 수 없습니다."));
7680

81+
List<Relationship> relationshipList = relationshipRepository.findByMemberAndRelationshipStatus(member, RelationshipStatus.ACCEPTED);
82+
83+
List<Long> relatedMemberIds = relationshipList.stream()
84+
.map(relationship -> relationship.getRelatedMember().getId())
85+
.toList();
86+
7787
List<Memory> memories;
7888
if (lastMemoryId == null) {
79-
memories = memoryRepository.findByMemberAndMemoryType(member, memoryType, size);
89+
memories = memoryRepository.findByMemberAndMemoryType(member, relatedMemberIds, memoryType, size);
8090
} else {
81-
memories = memoryRepository.findByMemberAndMemoryType(member, memoryType, lastMemoryId, size);
91+
memories = memoryRepository.findByMemberAndMemoryType(member, relatedMemberIds, memoryType, lastMemoryId, size);
8292
}
8393

8494
return memories.stream()

memory-api/src/test/java/com/memory/service/memory/MemoryServiceTest.java

Lines changed: 103 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88
import com.memory.domain.memory.Memory;
99
import com.memory.domain.memory.MemoryType;
1010
import com.memory.domain.memory.repository.MemoryRepository;
11+
import com.memory.domain.relationship.Relationship;
12+
import com.memory.domain.relationship.RelationshipStatus;
13+
import com.memory.domain.relationship.repository.RelationshipRepository;
1114
import com.memory.dto.memory.MemoryRequest;
1215
import com.memory.dto.memory.response.MemoryResponse;
1316
import com.memory.exception.customException.NotFoundException;
@@ -48,6 +51,9 @@ class MemoryServiceTest {
4851
@Mock
4952
private FileRepository fileRepository;
5053

54+
@Mock
55+
private RelationshipRepository relationshipRepository;
56+
5157
@InjectMocks
5258
private MemoryService memoryService;
5359

@@ -278,7 +284,9 @@ void findMemoriesByMemberSuccessFirstPage() {
278284
List<Memory> memories = Arrays.asList(memory, memory2);
279285

280286
when(memberRepository.findMemberById(memberId)).thenReturn(Optional.of(member));
281-
when(memoryRepository.findByMemberAndMemoryType(member, MemoryType.PRIVATE, size))
287+
when(relationshipRepository.findByMemberAndRelationshipStatus(member, RelationshipStatus.ACCEPTED))
288+
.thenReturn(Collections.emptyList());
289+
when(memoryRepository.findByMemberAndMemoryType(member, Collections.emptyList(), MemoryType.PRIVATE, size))
282290
.thenReturn(memories);
283291

284292
// When
@@ -291,7 +299,8 @@ void findMemoriesByMemberSuccessFirstPage() {
291299
assertEquals(2L, responses.get(1).id());
292300

293301
verify(memberRepository).findMemberById(memberId);
294-
verify(memoryRepository).findByMemberAndMemoryType(member, MemoryType.PRIVATE, size);
302+
verify(relationshipRepository).findByMemberAndRelationshipStatus(member, RelationshipStatus.ACCEPTED);
303+
verify(memoryRepository).findByMemberAndMemoryType(member, Collections.emptyList(), MemoryType.PRIVATE, size);
295304
}
296305

297306
@Test
@@ -303,7 +312,9 @@ void findMemoriesByMemberSuccessNextPage() {
303312
List<Memory> memories = Collections.singletonList(memory);
304313

305314
when(memberRepository.findMemberById(memberId)).thenReturn(Optional.of(member));
306-
when(memoryRepository.findByMemberAndMemoryType(member, MemoryType.PRIVATE, lastMemoryId, size))
315+
when(relationshipRepository.findByMemberAndRelationshipStatus(member, RelationshipStatus.ACCEPTED))
316+
.thenReturn(Collections.emptyList());
317+
when(memoryRepository.findByMemberAndMemoryType(member, Collections.emptyList(), MemoryType.PRIVATE, lastMemoryId, size))
307318
.thenReturn(memories);
308319

309320
// When
@@ -315,7 +326,8 @@ void findMemoriesByMemberSuccessNextPage() {
315326
assertEquals(memoryId, responses.get(0).id());
316327

317328
verify(memberRepository).findMemberById(memberId);
318-
verify(memoryRepository).findByMemberAndMemoryType(member, MemoryType.PRIVATE, lastMemoryId, size);
329+
verify(relationshipRepository).findByMemberAndRelationshipStatus(member, RelationshipStatus.ACCEPTED);
330+
verify(memoryRepository).findByMemberAndMemoryType(member, Collections.emptyList(), MemoryType.PRIVATE, lastMemoryId, size);
319331
}
320332

321333
@Test
@@ -331,7 +343,8 @@ void findMemoriesByMemberFailMemberNotFound() {
331343

332344
assertEquals("회원을 찾을 수 없습니다.", exception.getMessage());
333345
verify(memberRepository).findMemberById(memberId);
334-
verify(memoryRepository, never()).findByMemberAndMemoryType(any(), any(), anyInt());
346+
verify(relationshipRepository, never()).findByMemberAndRelationshipStatus(any(), any());
347+
verify(memoryRepository, never()).findByMemberAndMemoryType(any(), any(), any(), anyInt());
335348
}
336349

337350
@Test
@@ -572,7 +585,9 @@ void findMemoriesByMemberWithDifferentTypes() {
572585
List<Memory> publicMemories = List.of(publicMemory);
573586

574587
when(memberRepository.findMemberById(memberId)).thenReturn(Optional.of(member));
575-
when(memoryRepository.findByMemberAndMemoryType(member, MemoryType.PUBLIC, size))
588+
when(relationshipRepository.findByMemberAndRelationshipStatus(member, RelationshipStatus.ACCEPTED))
589+
.thenReturn(Collections.emptyList());
590+
when(memoryRepository.findByMemberAndMemoryType(member, Collections.emptyList(), MemoryType.PUBLIC, size))
576591
.thenReturn(publicMemories);
577592

578593
// When
@@ -585,7 +600,83 @@ void findMemoriesByMemberWithDifferentTypes() {
585600
assertEquals(MemoryType.PUBLIC, responses.get(0).memoryType());
586601

587602
verify(memberRepository).findMemberById(memberId);
588-
verify(memoryRepository).findByMemberAndMemoryType(member, MemoryType.PUBLIC, size);
603+
verify(relationshipRepository).findByMemberAndRelationshipStatus(member, RelationshipStatus.ACCEPTED);
604+
verify(memoryRepository).findByMemberAndMemoryType(member, Collections.emptyList(), MemoryType.PUBLIC, size);
605+
}
606+
607+
@Test
608+
@DisplayName("관계가 있는 회원의 메모리 조회 테스트 - RELATIONSHIP 타입")
609+
void findMemoriesByMemberWithRelationshipType() {
610+
// Given
611+
int size = 10;
612+
Long relatedMemberId = 2L;
613+
614+
Member relatedMember = new Member("관련 사용자", "relateduser", "[email protected]", "encodedPassword");
615+
setId(relatedMember, relatedMemberId);
616+
617+
Relationship relationship = new Relationship(member, relatedMember, RelationshipStatus.ACCEPTED);
618+
List<Relationship> relationships = List.of(relationship);
619+
List<Long> relatedMemberIds = List.of(relatedMemberId);
620+
621+
Memory myPublicMemory = new Memory("내 공개 메모리", "내 공개 내용", "내 공개 장소",
622+
LocalDate.of(2024, 1, 10), MemoryType.PUBLIC, member, mapEntity);
623+
setId(myPublicMemory, 3L);
624+
625+
Memory relatedPublicMemory = new Memory("상대방 공개 메모리", "상대방 공개 내용", "상대방 공개 장소",
626+
LocalDate.of(2024, 1, 11), MemoryType.PUBLIC, relatedMember, mapEntity);
627+
setId(relatedPublicMemory, 4L);
628+
629+
List<Memory> memories = Arrays.asList(myPublicMemory, relatedPublicMemory);
630+
631+
when(memberRepository.findMemberById(memberId)).thenReturn(Optional.of(member));
632+
when(relationshipRepository.findByMemberAndRelationshipStatus(member, RelationshipStatus.ACCEPTED))
633+
.thenReturn(relationships);
634+
when(memoryRepository.findByMemberAndMemoryType(member, relatedMemberIds, MemoryType.RELATIONSHIP, size))
635+
.thenReturn(memories);
636+
637+
// When
638+
List<MemoryResponse> responses = memoryService.findMemoriesByMember(memberId, null, size, MemoryType.RELATIONSHIP);
639+
640+
// Then
641+
assertNotNull(responses);
642+
assertEquals(2, responses.size());
643+
assertEquals(3L, responses.get(0).id());
644+
assertEquals(4L, responses.get(1).id());
645+
646+
verify(memberRepository).findMemberById(memberId);
647+
verify(relationshipRepository).findByMemberAndRelationshipStatus(member, RelationshipStatus.ACCEPTED);
648+
verify(memoryRepository).findByMemberAndMemoryType(member, relatedMemberIds, MemoryType.RELATIONSHIP, size);
649+
}
650+
651+
@Test
652+
@DisplayName("관계가 없는 회원의 메모리 조회 테스트 - RELATIONSHIP 타입")
653+
void findMemoriesByMemberWithoutRelationshipType() {
654+
// Given
655+
int size = 10;
656+
657+
Memory myPublicMemory = new Memory("내 공개 메모리", "내 공개 내용", "내 공개 장소",
658+
LocalDate.of(2024, 1, 12), MemoryType.PUBLIC, member, mapEntity);
659+
setId(myPublicMemory, 5L);
660+
661+
List<Memory> memories = List.of(myPublicMemory);
662+
663+
when(memberRepository.findMemberById(memberId)).thenReturn(Optional.of(member));
664+
when(relationshipRepository.findByMemberAndRelationshipStatus(member, RelationshipStatus.ACCEPTED))
665+
.thenReturn(Collections.emptyList());
666+
when(memoryRepository.findByMemberAndMemoryType(member, Collections.emptyList(), MemoryType.RELATIONSHIP, size))
667+
.thenReturn(memories);
668+
669+
// When
670+
List<MemoryResponse> responses = memoryService.findMemoriesByMember(memberId, null, size, MemoryType.RELATIONSHIP);
671+
672+
// Then
673+
assertNotNull(responses);
674+
assertEquals(1, responses.size());
675+
assertEquals(5L, responses.get(0).id());
676+
677+
verify(memberRepository).findMemberById(memberId);
678+
verify(relationshipRepository).findByMemberAndRelationshipStatus(member, RelationshipStatus.ACCEPTED);
679+
verify(memoryRepository).findByMemberAndMemoryType(member, Collections.emptyList(), MemoryType.RELATIONSHIP, size);
589680
}
590681

591682
@Test
@@ -662,7 +753,7 @@ void createMemoryWithEmptyHashTagList() {
662753
when(memberRepository.findMemberById(memberId)).thenReturn(Optional.of(member));
663754
when(mapRepository.findById(mapId)).thenReturn(Optional.of(mapEntity));
664755
when(memoryRepository.save(any(Memory.class))).thenReturn(memory);
665-
when(fileRepository.findAllById(Arrays.asList(fileId1))).thenReturn(Arrays.asList(file1));
756+
when(fileRepository.findAllById(List.of(fileId1))).thenReturn(Collections.singletonList(file1));
666757

667758
// When
668759
MemoryResponse response = memoryService.createMemory(memberId, requestWithEmptyHashTags);
@@ -672,7 +763,7 @@ void createMemoryWithEmptyHashTagList() {
672763
verify(memberRepository).findMemberById(memberId);
673764
verify(mapRepository).findById(mapId);
674765
verify(memoryRepository).save(any(Memory.class));
675-
verify(fileRepository).findAllById(Arrays.asList(fileId1));
766+
verify(fileRepository).findAllById(List.of(fileId1));
676767
}
677768

678769
@Test
@@ -704,11 +795,11 @@ void createMemoryWithManyHashTags() {
704795
void updateMemoryWithDifferentHashTags() {
705796
// Given
706797
MemoryRequest.Update updateWithNewHashTags = new MemoryRequest.Update("업데이트된 메모리", "업데이트된 내용",
707-
"업데이트된 장소", LocalDate.of(2024, 1, 8), MemoryType.PRIVATE, Arrays.asList(fileId2), Arrays.asList("새로운", "해시태그", "업데이트"));
798+
"업데이트된 장소", LocalDate.of(2024, 1, 8), MemoryType.PRIVATE, List.of(fileId2), Arrays.asList("새로운", "해시태그", "업데이트"));
708799

709800
when(memberRepository.findMemberById(memberId)).thenReturn(Optional.of(member));
710801
when(memoryRepository.findMemoryByIdAndMemberId(memoryId, memberId)).thenReturn(Optional.of(memory));
711-
when(fileRepository.findAllById(Arrays.asList(fileId2))).thenReturn(Arrays.asList(file2));
802+
when(fileRepository.findAllById(List.of(fileId2))).thenReturn(Collections.singletonList(file2));
712803

713804
// When
714805
MemoryResponse response = memoryService.updateMemory(memberId, memoryId, updateWithNewHashTags);
@@ -717,7 +808,7 @@ void updateMemoryWithDifferentHashTags() {
717808
assertNotNull(response);
718809
verify(memberRepository).findMemberById(memberId);
719810
verify(memoryRepository).findMemoryByIdAndMemberId(memoryId, memberId);
720-
verify(fileRepository).findAllById(Arrays.asList(fileId2));
811+
verify(fileRepository).findAllById(List.of(fileId2));
721812
}
722813

723814
@Test

memory-domain/src/main/java/com/memory/domain/memory/repository/MemoryRepositoryCustom.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88
import java.util.Optional;
99

1010
public interface MemoryRepositoryCustom {
11-
List<Memory> findByMemberAndMemoryType(Member member, MemoryType memoryType, int size);
12-
List<Memory> findByMemberAndMemoryType(Member member, MemoryType memoryType, Long lastMemoryId, int size);
11+
List<Memory> findByMemberAndMemoryType(Member member, List<Long> relatedMemberIds, MemoryType memoryType, int size);
12+
List<Memory> findByMemberAndMemoryType(Member member, List<Long> relatedMemberIds, MemoryType memoryType, Long lastMemoryId, int size);
1313
Optional<Memory> findMemoryByIdAndMemberId(Long memoryId, Long memberId);
1414
List<Memory> findByMemoryType(MemoryType memoryType, int size);
1515
List<Memory> findByMemoryType(MemoryType memoryType, Long lastMemoryId, int size);

0 commit comments

Comments
 (0)