웹 프로젝트 (IBAS)/SpringBoot api 개편

[SpringBoot] 9. OSIV 설정을 통한 쿼리 최적화 방안 고찰

동현 유 2022. 8. 2. 00:03

[배경]

  기존 시큐리티 필터에서는 Role-based access control를 담당하고 있다.

 

  [관리자등급 -> 운영진 -> 일반회원] 과 같은 역할기반 접근 제어 말고,

 

  다른 특성으로 권한을 검사해야하는 경우가 있다.

 

  예를 들어, 강의를 개설한 뒤에 강의자만 접근할 수 있는 api 가 있다면

 

  매번 데이터베이스에 쿼리를 날려서 강의자인지 확인하고 인가를 해주어야한다.

 

[문제]

위와 같이 해도 주요 기능은 제대로 수행하고 있지만,

 

트랜젝션이 2번 실행되는 점을 고려해야한다.

 

트랜젝션이 끝나면 영속성 컨텍스트에서 관리되던 엔티티들은 detached 되어

 

다른 트랜젝션이 수행될 때는 다시 db로부터 조회해서 영속화를 또 해주어야하는 중복이 발생한다.

 

 

강의실 정보를 수정하기 위한 api를 호출할 때,

강의자인지 확인하는 로직을 예로 들어보면,

 

(1) 트랜잭션1 : 컨트롤러 진입 전에 강의자인지 확인하면서 강의엔티티를 조회

(2) 트랜잭션2 : 강의실 정보를 수정하기 위해 강의 엔티티를 조회

 

위와 같이 총 두번의 조회 쿼리가 발생한다.

 

[고찰]

 

이 문제는 트랜잭션과 영속성 컨텍스트의 생명주기가 같아서 발생한다.

트랜젝션이 종료되면 영속성 컨텍스트도 사라진다.

결과적으로 2번의 트랜젝션이 발생하게 되면, 동일한 엔티티여도 2번 조회할 수 밖에 없다.

 

 

스프링에는 Open session in view 라는 기능이 존재하는데.

처음 db와 커넥션을 연결한 순간부터 api 반환까지 영속성 컨텍스트를 유지한다.

따라서 두번의 트랜잭션을 실행했을 때, 동일한 엔티티를 영속성 컨텍스트에서 찾을 수 있다.

같은 방식으로 view template 에서도 지연로딩을 사용할 수 있게되는 등의 이점이 있다.

 

하지만 그만큼 오랫동안 커넥션을 점유하고 있기 때문에, 여러가지 문제가 발생한다.

  1. 많은 실시간 처리량이 요구되는 서비스에서는 db 커넥션이 말라버릴 수 있다.
  2. 영속성 컨텍스트가 오래 살아있으므로 동시성 문제가 더 빈번하게 발생 -> 트랜잭션의 실패로 이어질 수 있고 결과적으로 성능저하 유발

 

[결론]

 

따라서 OSIV 기능은 동시요청이 비교적 적고, 실시간 처리량이 작은 곳에서 편리하게 이용할 수 있다.

주된 서비스 영역에서는 OSIV 기능을 이용해서 쿼리 회수를 줄이기보다는,

2차 캐시를 이용하는 것이 더 바람직할 것 같다.