오늘은 내가 조회한 게시글을 바로바로 알 수 있는 리스트를 반환하는 기능을 구현한다.
예상되는 작동원리는 다음과 같다.
1.Member 와 Post를 기억할 MemberHistory entity를 하나 만든다.
2.Member1이 Post1을 조회하면 MemberHistory에 member_id ,post_id를 저장한다.
3.MemberHistory를 호출하는 API를 만든다.
4.MemberHistory는 조회한 시간순서로 정렬되야 한다.
5.MemberHistory는 최대 3개를 조회할 수 있다.
@Entity
@Getter
@NoArgsConstructor
public class MemberHistory {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne
@JoinColumn(name = "MEMBER_ID")
private Member member;
@ManyToOne
@JoinColumn(name = "POST_ID")
private Post post;
@Temporal(TemporalType.TIMESTAMP)
private Date createdAt;
@Builder
public MemberHistory(Member member, Post post, Date createdAt) {
this.member = member;
this.post = post;
this.createdAt = createdAt;
}
public static MemberHistory of(Member member, Post posts, Date date) {
return MemberHistory.builder()
.member(member)
.post(posts)
.createdAt(date)
.build();
}
}
다음으로 반환해줄 HistoryPostResponseDto를 만든다.
노출해줄 이미지 파일과 제목만 필요하다.
@Getter
@NoArgsConstructor
public class HistoryPostResponseDto {
private Long id;
private String title;
private String reSizeImage;
@Builder
public HistoryPostResponseDto(Post post){
this.id = post.getId();
this.reSizeImage = post.getResizeImage();
this.title = post.getTitle();
}
public static HistoryPostResponseDto of(Post post){
return HistoryPostResponseDto.builder()
.post(post)
.build();
}
}
public interface MemberHistoryRepository extends JpaRepository<MemberHistory, Long> {
List<MemberHistory> findTop3ByMemberOrderByCreatedAtDesc(Member member);
void deleteByPostId(Long postId);
}
findTop3ByMemberOrderByCreatedAtDesc(Member member)
상위3개를 Menber값으로 찾아올때 정렬기준은 CreatedAt이며,정렬 방향은역순정렬로 찾아온다.
처음에는 생각이 잘 떠오르지 않았으나 Post와 함께 구현한 부분이다.
제일 처음 생각한 것은 우선 MemberHistoryRepository에 등록하는 방법이다.
Post를 상세조회할때 자동으로 등록.
주의할점은 같은 게시글을 연속조회하면 같은 게시글이 계속 등록되는것을 방지하는점 이었다. 따라서 다음과같이 우선 내가본 게시글 리스트에 동일한 게시글이 있는지 확인하는 코드를 기존 상세조회 코드에 추가했다.
List<MemberHistory> memberHistories = memberHistoryRepository.findTop3ByMemberOrderByCreatedAtDesc(member);
Optional<MemberHistory> existingHistory = memberHistories.stream()
.filter(history -> history.getPost().getId().equals(post_id))
.findFirst();
if (existingHistory.isPresent()) {
MemberHistory historyToDelete = existingHistory.get();
memberHistoryRepository.delete(historyToDelete);
MemberHistory newHistory = MemberHistory.of(member, posts, new Date());
memberHistoryRepository.save(newHistory);
} else {
if (memberHistories.size() >= 3) {
MemberHistory oldestHistory = memberHistories.get(memberHistories.size() - 1);
memberHistoryRepository.delete(oldestHistory);
}
memberHistoryRepository.save(MemberHistory.of(member, posts, new Date()));
}
다음으로 MemberService에 리스트를 조회하는 코드를 추가했다.
//내가 본 게시물 조회하기 (3개)
@Transactional
public List<HistoryPostResponseDto> getMemberHistory(Member member) {
List<MemberHistory> memberHistories = memberHistoryRepository.findTop3ByMemberOrderByCreatedAtDesc(member);
List<HistoryPostResponseDto> historyPostResponseDtoList = new ArrayList<>();
for (MemberHistory history : memberHistories) {
Post post = history.getPost();
HistoryPostResponseDto historyPostResponseDto = postService.getPostIfoNoHistory(post.getId());
historyPostResponseDtoList.add(historyPostResponseDto);
}
return historyPostResponseDtoList;
}
여기서 getPostIfoNoHistory(Long post_id)메서는 PostService에 등록되어 있다.
public HistoryPostResponseDto getPostIfoNoHistory(Long post_id) {
Post posts = postRepository.findById(post_id).orElseThrow(
() -> new CustomException(Error.NOT_FOUND_POST)
);
return HistoryPostResponseDto.of(posts);
}
어떤 기능을만들때 무작정 코드를 치는것보다. 일단 기능이 작동되는 순서를 구체화한 다음 코드를 작성하는게 훨씬 명확했다.
아직 하드코딩의 느낌이 없지않지만 추후 리팩토링을 진행해볼 예정이다.
아직 예약기능 ,알람기능 등 추가해볼만한 기능이 많다.