diff --git a/src/backend/history_server/src/main/java/com/jootalkpia/history_server/controller/HistoryController.java b/src/backend/history_server/src/main/java/com/jootalkpia/history_server/controller/HistoryController.java index f8215512..8917c009 100644 --- a/src/backend/history_server/src/main/java/com/jootalkpia/history_server/controller/HistoryController.java +++ b/src/backend/history_server/src/main/java/com/jootalkpia/history_server/controller/HistoryController.java @@ -17,7 +17,7 @@ public class HistoryController { private static final String DEFAULT_PAGE_SIZE = "30"; private final HistoryQueryService historyQueryService; - @GetMapping("/api/v1/history/{channelId}") + @GetMapping("/api/v1/history/forward/{channelId}") public ChatMessagePageResponse getChatMessagesForward( @PathVariable Long channelId, //처음 요청시엔 서버 내에서 안읽은 메세지 값으로 설정하기 위해 false @@ -28,4 +28,16 @@ public ChatMessagePageResponse getChatMessagesForward( return historyQueryService. getChatMessagesForward(channelId, cursorId, size, userInfo.userId()); } + + @GetMapping("/api/v1/history/backward/{channelId}") + public ChatMessagePageResponse getChatMessagesBackward( + @PathVariable Long channelId, + //처음 요청시엔 서버 내에서 안읽은 메세지 값으로 설정하기 위해 false + // 이때 message의 objectId가 아닌 threadId가 기준 + @RequestParam(required = false) Long cursorId, + @RequestParam(defaultValue = DEFAULT_PAGE_SIZE) int size, + @CurrentUser UserInfo userInfo) { + return historyQueryService. + getChatMessagesBackward(channelId, cursorId, size, userInfo.userId()); + } } diff --git a/src/backend/history_server/src/main/java/com/jootalkpia/history_server/repository/ChatMessageRepository.java b/src/backend/history_server/src/main/java/com/jootalkpia/history_server/repository/ChatMessageRepository.java index 306ffcbb..405d606c 100644 --- a/src/backend/history_server/src/main/java/com/jootalkpia/history_server/repository/ChatMessageRepository.java +++ b/src/backend/history_server/src/main/java/com/jootalkpia/history_server/repository/ChatMessageRepository.java @@ -1,6 +1,7 @@ package com.jootalkpia.history_server.repository; import com.jootalkpia.history_server.domain.ChatMessage; +import java.util.Optional; import org.springframework.data.domain.Pageable; import org.springframework.data.mongodb.repository.MongoRepository; import org.springframework.stereotype.Repository; @@ -9,6 +10,13 @@ @Repository public interface ChatMessageRepository extends MongoRepository { - // cursorId 이후의 메시지 조회 (페이징) + + // cursorId 이후의 메시지 조회 (정방향) List findByChannelIdAndThreadIdGreaterThanOrderByThreadIdAsc(Long channelId, Long threadId, Pageable pageable); -} + + // 첫 요청 시 최신 메시지를 찾기 위한 쿼리 + Optional findTopByChannelIdOrderByThreadIdDesc(Long channelId); + + // 역방향 조회 (lastReadId 이하의 메시지) + List findByChannelIdAndThreadIdLessThanEqualOrderByThreadIdDesc(Long channelId, Long threadId, Pageable pageable); +} \ No newline at end of file diff --git a/src/backend/history_server/src/main/java/com/jootalkpia/history_server/service/HistoryQueryService.java b/src/backend/history_server/src/main/java/com/jootalkpia/history_server/service/HistoryQueryService.java index d5f10734..8cf7e296 100644 --- a/src/backend/history_server/src/main/java/com/jootalkpia/history_server/service/HistoryQueryService.java +++ b/src/backend/history_server/src/main/java/com/jootalkpia/history_server/service/HistoryQueryService.java @@ -38,9 +38,29 @@ public ChatMessagePageResponse getChatMessagesForward(Long channelId, Long curso return new ChatMessagePageResponse(hasNext, lastThreadId, responseMessages); } + public ChatMessagePageResponse getChatMessagesBackward(Long channelId, Long cursorId, int size, Long userId) { + List chatMessageList = fetchMessagesBackward(channelId, cursorId, size, userId); + + if (chatMessageList.isEmpty()) { + return new ChatMessagePageResponse(false, null, Collections.emptyList()); + } + + List responseMessages = convertToDtoList(chatMessageList); + boolean hasNext = determineHasNext(responseMessages, size); + + // size + 1로 조회했으므로, 초과한 1개 데이터 제거 + if (hasNext) { + responseMessages = responseMessages.subList(0, size); + } + + Long lastThreadId = getLastThreadId(responseMessages); + + return new ChatMessagePageResponse(hasNext, lastThreadId, responseMessages); + } + /** - * DB에서 채팅 메시지를 조회하는 메서드 + * DB에서 채팅 메시지를 정방향으로 조회하는 메서드 */ private List fetchMessagesForward(Long channelId, Long cursorId, int size, Long userId) { if (cursorId == null) { @@ -58,6 +78,34 @@ private List fetchMessagesForward(Long channelId, Long cursorId, in channelId, cursorId, PageRequest.of(0, size + 1)); } + /** + * DB에서 채팅 메시지를 역방향으로 조회하는 메서드 + */ + private List fetchMessagesBackward(Long channelId, Long cursorId, int size, Long userId) { + Long lastReadId = cursorId; + + // 첫 요청 시 처리 + if (cursorId == null) { + lastReadId = userChannelRepository.findLastReadIdByUserIdAndChannelId(userId, channelId); + + // lastReadId가 null이면 (첫 입장 시) 가장 최신 메세지로 설정 + if (lastReadId == null) { + lastReadId = chatMessageRepository.findTopByChannelIdOrderByThreadIdDesc(channelId) + .map(ChatMessage::getThreadId) // 가장 최신 메시지의 threadId 반환 + .orElse(null); // 채널에 메시지가 없으면 null 반환 + } + + // 채널 내 메시지가 없는 경우 빈 리스트 반환 + if (lastReadId == null) { + return Collections.emptyList(); + } + } + + // lastReadId 이하의 메시지를 최신순 (DESC)으로 조회 + return chatMessageRepository.findByChannelIdAndThreadIdLessThanEqualOrderByThreadIdDesc( + channelId, lastReadId, PageRequest.of(0, size + 1)); + } + /** * ChatMessage 리스트를 ChatMessageDto 리스트로 변환하는 메서드 */