본문 바로가기

AWS

Dynamodb 이슈해결 , 페이지네이션

728x90

제가 채팅서비스를 구현한 아키텍처의 구조는 다음과 같습니다.

 

기존 채팅서비스는

        ChatMessage chatMessage = dynamoChatRepository.findById(chatId).orElseThrow(() -> new ApplicationException(ApplicationErrorType.CHAT_NOT_FOUND));

다음과 같은구조로 채팅방에 있는 모든 채팅을 읽어와서 service로직에서 정렬 및 필터처리를 수행하였습니다.

ISSUE

데이터가 쌓임에 따라 점점 데이터에 과부하가 발생하는 문제가 발생하였고, 어떻게 해결할 지 찾아보았습니다.

 

첫번째 해결방안

다음 그림처럼 20페이씩 읽어오고 이전페이지를 읽어오려면 "이전 메세지를 불러오기" 를 클릭하여 페이지네이션을 하는 방법이 있었습니다.

두번째 해결방안

react query를 사용하여 모든데이터를 읽어오는데 캐시를 이용하고, 데이터가 변경되는시점에만 다시 읽어 들이는 방식을 사용.

 

 

현재 environment 의 최적의 상황은? 

우리는 react를 깊게 만져본 팀원이 없을 뿐더러 backend는 익숙한 상황이였다. 뿐만 아니라 aws는 공식문서가 잘 나와 있어 

페이징쿼리를 작성하는데 있어서 어려움이 없을거라고 판단하였고, dynmodb에 글로벌인덱스를 설정하고 페이징처리를 하기로 결정하였다.

 

Map<String, AttributeValue> expressionAttributeValues = new HashMap<>();
            expressionAttributeValues.put(":x", new AttributeValue().withN(roomId.toString()));

            QueryRequest queryRequest = new QueryRequest()
                    .withTableName("chatting")
                    .withIndexName("roomId-createdAt-index")
                    .withKeyConditionExpression("roomId = :x")
                    .withExpressionAttributeValues(expressionAttributeValues)
                    .withScanIndexForward(false) // 내림차순 정렬
                    .withLimit(10);

            queryRequest.setExclusiveStartKey(exclusiveStartKey);
            QueryResult queryResult = amazonDynamoDB.query(queryRequest);

            // query dynomdb결과값을 entity값으로 변환
            List<ChatMessage> entityResult = queryResult.getItems().stream().map(
                    ChatMessage::new
            ).collect(Collectors.toList());

 

다음과 같은 방식으로 10페이지씩 페이징을 수행함으로 데이터가 많이 쌓여도 서버 및 클라이언트측면에서 과부하가 발생하지않는 로직으로 성능을 개선할 수 있었다.

 

dynmodb는 어떻게 페이지네이션을 수행할까 ? 

 

QueryRequest를 사용하여 테이블명 ,인덱스, order by , limit,를 설정하여 요청을 하게되면 response값으로 LastEvaluatedKey값이 반환되게 되고 그 값을 다시 lastEvaluatedKey값으로 지정하여 요청을 보내게 되면 10페이지 이후의 값을 반환시켜준다. 

     Map<String, AttributeValue> lastEvaluatedKey = queryResult.getLastEvaluatedKey();

 

여기서 문제  dynmodb는 그럼 이전 데이터를 가져올 수 없을까요?

아쉽게도 dynamodb에서 지원하는 쿼리에서는 이전데이터를 가져올 수 없다. 그래서 오히려 채팅 페이지네이션을 하는데 있어서

매우 적합한 db인 것 같다. 자동으로 클러스터링도해주고 nosql key value형태로도 유지해주고 ? 성능적으로 매우 좋은 것 같다.

 

TMI:괜히 당근이 dynamodb를 이용하여 chatservice를 설계하는것이 아니다..

 

 

728x90