수 많은 우문은 현답을 만든다

Mybatis Cash 본문

개발지식/Database(DB)

Mybatis Cash

aiden.jo 2023. 3. 3. 23:37

안녕하세요, 조영호입니다.

오늘은 Mybatis를 쓰면서 캐싱과 관련해서 고민했던 내용을 공유하고자 합니다.

 

 

백엔드 개발을 하시는 분들이라면 한 번 쯤은 아래와 같은 고민을 해보셨을 것 같습니다.

"API들이 호출될때마다 특정 query를 매번 호출해야 하는 경우, 과연 이대로 성능은 괜찮을까?"

예를들어 제공하려는 조회 API가 100개인데, 각 API를 호출할때 마다 사용자의 상태가 바뀌었는지 DB에서 조회를 해야하는 상황이 있다고 가정해보자. 그러면 우리는 수 천명의 동시 접속자가 각각 API를 호출하게 되면 엄청난 성능 저하가 발생할 것으로 예상할 수 있다.

 

위와같은 경우 우리는 Redis 같은 메모리디비나, 자체적으로 Bean으로 등록한다거나 해서 비용을 줄일 수 있다.

하지만, JPA나 Mybatis 같은 프레임워크들은 자체적으로 Cache 기능을 제공하고 있다는 사실!


MyBatis에는 2가지 내장 Cache가 존재합니다. 

  • Local session cache : 기본 활성화 되있는 기능이며 비활성화 할 수 없습니다.
  • Second level cache : mapper namespace 단위로 동작하며 개발자가 비/활성화를 선택할 수 있습니다.

 

Local Session Cache

로컬 세션 캐시의 기본 적용 범위는 Session 단위 입니다. 즉, Transaction이 끝나거나(commit이나 rollback) 아니면 insert, update, delete가 실행되면 Local Cache가 보유하고 있던 cache 정보는 폐기됩니다. 또는 SqlSession.clearCache() 를 호출해 직접 폐기할 수 있습니다. 참고로, autoCommit을 실행시켜 놓으면 쿼리를 실행할때마다 commit을 하기때문에 session에서 캐시가 유지되는지 확인하기 힘듭니다.

 

이제 실제로 과연 캐싱이 되고있는지 검증해보겠습니다.

StopWatch stopWatch = new StopWatch();
stopWatch.start();

//서비스 로직

stopWatch.stop();
System.out.println(stopWatch.prettyPrint());

 

<결과>

차수 ms     %     Task name
-----------------------------------------
1   00211  100%  
2   00003  100% 
3   00002  100%

1차 시도에서는 211ms 가 소요되었습니다 (사용자 조회 Query 결과에 대한 시간)

2차, 3차 시도에는 Local Session Cache에서 읽어와 2~3ms 밖에 소요되지 않은것을 볼 수 있었습니다.

 

Second Level Cache

세컨드 레벨 캐시는 Mapper 별로 캐싱을 할 수 있는 기능입니다.

Local session cache는 Session 또는 Statement 범위내에서 캐시 사용 여부를 조정하고, 그 외 범위에서는 Second level cache로 제어할 수 있습니다. 주의할 점은, Local cache는Commit이 되면 캐시를 지우지만 Second level cache는 commit을 해도 캐시 데이터가 살아있다는 특이점이 있습니다. (특수한 경우 아니고서는 잘못사용하면 사고가 날 수 있습니다)

 

 

 

실로 즐거운 검증이 아닐 수 없습니다.

감사합니다.

 

 

참고

https://12bme.tistory.com/364