인프런 영문 브랜드 로고
인프런 영문 브랜드 로고

인프런 커뮤니티 질문&답변

주우민님의 프로필 이미지
주우민

작성한 질문수

실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화

OSIV와 성능 최적화

@Transactional(readOnly = true) 의 트레이드 오프

해결된 질문

작성

·

133

·

수정됨

0

[질문 템플릿]
1. 강의 내용과 관련된 질문인가요? (예)
2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예)
3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예)

[질문 내용]
안녕하세요 영한님.

이 강의를 보고 질문이 생겨 남기게 되었습니다.

이전의 강의에서 @Transactional(readOnly = true)가 성능에서 최적화 해주는 부분이 있다해서 조회용 Service 레이어의 모든 조회용 메서드에 @Transactional(readOnly = true)를 붙였습니다.

OSIV 라는 개념을 공부하면서 커넥션 풀이 마르지 않게 비활성화 해야된다는것을 보고

제 방식대로라면 OSIV 를 비활성화 하더라도 모든 서비스 layer의 메소드가 커넥션을 점유해야 돼서 (CUD api 에서 부르는 서비스 메소드는 @Transactional, R 에서는 @Transactional(readOnly = true)가 붙을테니) 마르지 않을까 하는 고민이 생겼습니다.

그렇다고 최소한으로 커넥션을 점유하기 위해 OSIV를 false 로 가져가면서 Repository의 조회 메소드 단위로만 @Transactional(readOnly = true)을 붙이면

영속성 컨텍스트의 범위도 그만큼만 가져가서 1차캐시나 지연로딩으로 batch size만큼 가져오는것도 사용을 못할테니

영속성 컨텍스트의 사용이 필요할때만 붙이는게 맞을지 아니면 Service layer의 조회용 메서드에 붙여도 될지 잘 모르겠습니다.

답변 2

2

김영한님의 프로필 이미지
김영한
지식공유자

안녕하세요. 주우민님

서비스 계층에서 @Transactional(readOnly = true)를 사용하면 성능이 최적화 되기 때문에 일반적으로 사용하는 것이 더 나은 선택입니다.

하지만 고민하신 것 처럼 서비스 계층에서 트랜잭션 시작을 위한 커넥션을 획득하기 때문에 커넥션이 더 빨리 소모될 수 있습니다.

서비스 계층이 메모리 연산만 사용한 비즈니스 로직 처리만 있다면 매우 빠르기 때문에, 이 부분은 보통 문제가 되지 않습니다. 만약 서비스 계층에서 외부 HTTP 호출 같은 것이 있다면 이 부분이 매우 느리기 때문에, 이 경우에는 서비스 계층에서 @Transactional(readOnly = true)를 사용하지 않는 것을 고려해야 합니다.

감사합니다.

0

안녕하세요, 인프런 AI 인턴입니다. 주우민님께서 @Transactional(readOnly=true)와 관련하여 OSIV 및 트랜잭션 설정에 관해 고민이 많으신 것 같습니다.

@Transactional(readOnly = true)는 읽기 전용 모드로 성능 최적화에 기여할 수 있습니다. 이는 데이터베이스에 쓰기를 하지 않기에 변경 감지가 비활성화되고, flush 작업이 수행되지 않습니다. 이로 인해 오버헤드가 줄어들게 됩니다.

하지만 OSIV(Open Session In View) 패턴에서는 한 번의 HTTP 요청 동안 영속성 컨텍스트를 유지하게 됩니다. 이렇게 하면 지연 로딩을 사용할 수 있는 장점이 있지만, 트랜잭션이 오래 유지되어 커넥션 풀이 마를 위험이 있습니다. 이러한 점에서, OSIV 설정과 트랜잭션 설정은 잘 고민해 봐야 합니다.

  1. OSIV를 활성화한 경우: 조회용 메서드에 @Transactional(readOnly = true)를 붙여도 대부분의 경우 문제가 되지 않지만, 요청이 많은 경우 커넥션 풀이 바닥날 가능성이 있습니다. 따라서, 지연 로딩이 필요하지 않은 경우엔 OSIV를 비활성화하고, 필요 시에만 트랜잭션을 사용하도록 조정하는 것이 좋습니다.

  2. OSIV를 비활성화한 경우: 영속성 컨텍스트의 범위는 트랜잭션의 범위와 같아지므로, 지연 로딩이나 1차 캐시를 효과적으로 사용하려면 필요한 서비스 메서드에만 @Transactional을 붙여야 합니다. 단순 조회만 하는 경우에는 OSIV가 필요하지 않기 때문에 보통은 repository 수준에서만 트랜잭션을 설정하여 사용하는 방법이 있습니다.

유사한 질문과 답변을 통해 좀 더 깊은 이해를 하고 싶으시다면, 다음 게시물들을 참고하시기 바랍니다:

저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다. 현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏 추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.

주우민님의 프로필 이미지
주우민

작성한 질문수

질문하기