Test Environment
3인 유저 채팅방에서 채팅 추가 시, api의 속도를 확인하는 것으로 cache 적용 전 후 의 성능을 비교했습니다.
기본 전략
반복 읽기가 많은 데이터를 캐싱하였기에 lookl aside +write around 전략을 사용하고, 일관성 유지를 위해 데이터 수정 발생시 캐시 데이터를 버린 뒤, 이후 사용시 캐시를 다시 Hit시켜 캐시메모리에 변경사항을 로딩하는 방식을 사용했습니다.
caching 적용 전
api 속도
sql 수행 횟수
기본적으로 chatroom, mem
ber의 엔티티를 select하는 sql이 각각 수행되고, 해당 채팅을 db에 insert하는 명령어가 수행된다.
추가적으로, 캐싱을 적용하지 않았으므로 채팅 알림을 보내기 위해 채팅 방 내의 모든 멤버들의 fcm 토큰을 가져오는 쿼리가 수행된다.
이는 채팅방 내 유저의 수해 정비례하여 증가한다.
ex) 자신을 제외하고 10명의 유저가 채팅방에 있다면, 10명의 유저 정보를 가져와야하기에, 10번의 select문이 수행된다.
result estimation
채팅방의 멤버 구성의 경우, 변경가능성이 적다고 판단하여쏙, 각 유저는 다른 기기에 로그인하여 fcm Token이 변경될 가능성 역시 적다고 판단하였다. 따라서 대부분의 경우, 채팅방 진입시에 채팅방 내의 유저들의 캐시를 로드하고, A 유저가 채팅 입력 시, 캐시에서 A유저를 제외한 모든 유저에게 메세지를 전송하는데, 메세지를 보낼 때, 각유저에게 필요한 정보는 알림을 보내기 위한 fcm token 뿐이기에 이를 캐싱을 통해 가져온다면,
새로운 채팅 메세지 객체를 DB에 등록하기 위해 수행되는 query를 제외하면 모든 데이터를 caching을 통해 가져올 수 있게된다.
따라서 실제 사용에서도 캐싱할 가치가 있다고 판단하였다.
캐싱 적용 후
api 속도
sql수행 횟수
채팅방 객체를 생성하기 위해 chatroom, member의 엔티티를 select하는 sql이 각각 수행되고, 해당 채팅을 db에 insert하는 명령어가 수행된다.
Conclusion
caching을 기반으로 성능이 200% 가량 향상되었고, 가장 많이 수행되는 chating 기능에 대한 개선사항임과 동시에 변경가능성이 적은 사항이기에 어느정도 유의미한 성능차이를 도출했습니다.
self-feedback
개발 초기에, fcm Token, userToken을 별도의 테이블로 분리하는 것으로 DB를 설계했는데,
개발을 진행할 수 록 잘못된 설계라는 것을 깨닫았다. Refresh Token의 경우, 보안상의 문제도 있기에 유저 테이블과 별도로 분리하는 것이 좋은 판단이나, fcm Token의 경우, 채팅을 보내는 과정에서 fcm토큰을 얻기 위해 계속해서 유저 테이블과 join 해서 가져와야했다. 이로 인하여 불필요한 join 쿼리가 다수 발생하였고, caching을 적용하는 것에도 많은 에로사항이 발생하게 되었다. 또한 member-chat-room이라는 매핑 테이블을 사용하여 유저와 채팅방 간의 관계를 logical한 다 대 다 관계로 구현하였는데, @ManyToOne 을 통한 JPA 연관관계 매핑을 통해 구현하였던 부분도 성능상 아쉬웠다.
유저도 채팅방을 알아야하고(모든 유저는 자신이 속한 채팅방을 알아야한다.), 채팅방도 유저를 알아야하는(채팅방은 소속된 모든 유저를 알고 있어야한다.) 다 대 다 양방향 관계를 매핑 테이블을 통해 표현하였는데,
만약 매핑 테이블에 단순히 FK로 넣고, JPA 연관관계를 사용하지 않았다면, 불필요한 join을 수행하지 않아도 되고, caching에서도 조금더 유용한 활용이 가능했을 것 같다.
마지막으로 채팅 메세지를 담은 Chat 테이블의 경우, ClubMember(유저), ChatRoom(채팅방)과 관계를 가지는데, 채팅이 추가될 때마다 유저, 채팅방 테이블을 select하고 Chat을 생성하는 3번의 쿼리가 발생한다.
설계의 끝에 도달하니, 각 메세지가 유저, 채팅방을 알아야할 경우는 매우 드물었기에, 이부분도 불필요한 연관관계였다는 생각을 하게 되었다.
+@
https://codenme.tistory.com/83
위의 글에서 인덱싱에 대한 성능 분석 역시 진행했으니, 관심이 있다면 함께 확인해보자.
'back-end study' 카테고리의 다른 글
백엔드 개발자로써 최적화를 위해 고려할 사항들 (0) | 2023.08.03 |
---|---|
성능 지표에 관하여 (ThroughPut, Latency) (0) | 2023.06.21 |
HTTP 클라이언트- Apache HttpClient VS OkHttpClient VS Spring WebClient (0) | 2023.06.15 |
WebClient 이론 및 사용법 (0) | 2023.06.08 |
Blocking / Non-blocking 과 Sync / Async 의 차이 (0) | 2023.06.08 |