문제
기존 코드에서 사용자 회원가입시에 플랫폼으로부터 사용자 정보를 요청하여 가져오는 로직이 트랜잭션안에 포함되어 있었다. 이에 따라 db 리소스가 오랜시간 점유되는 비효율이 발생했다.
문제 분석
@Service
public class Auth {
@Transactional
public Response 회원가입_로그인(String accessToken) {
// 플랫폼에서 사용자 정보 조회
...
// 회원가입 및 로그인
auth(member);
// 토큰 관련 로직
...
}
public void auth(Member member) {
if(새로운 유저인지 체크) 회원가입
else 로그인
}
}
코드를 보면, 트랜잭션이 회원가입_로그인 전체에 설정되어 실제로 트랜잭션안에 들어가지 않아도 될 부분들이 앞 뒤로 추가 되어있다.
본인은 auth 메서드에만 트랜잭션이 설정되면 충분하다고 생각했기에, 해당 메서드에만 트랜잭션을 설정하는 구조로 설정하고자 했다.
해결
@Service
public class Auth {
public Response 회원가입_로그인(String accessToken) {
// 플랫폼에서 사용자 정보 조회
...
// 회원가입 및 로그인
auth(member);
// 토큰 관련 로직
...
}
@Transactional
public void auth(Member member) {
if(새로운 유저인지 체크) 회원가입
else 로그인
}
}
만약 위의 코드에서 단순히 위와 같은 식으로 설정한다면, 프록시 내부 호출로 인해 auth 에 설정된 @Transactional은 아무런 기능도 하지 못하게 된다.
이는 회원가입_로그인 에서 호출하는 auth 가, AOP로 생성된 프록시의 메서드를 호출하는게 아닌 실제 객체의 메서드를 호출하는 것이기 때문이다.
이러한 내부 호출 문제를 해결하기 위한 해결 방법으로는
- 자기 자신을 의존성 주입받아 호출
- ObjectProvider를 이용한 지연 조회
- 새로운 클래스 생성
등이 있다.
본인은 마침 auth 관련 메서드를 모아둘 곳이 필요했기에 새로운 클래스를 생성하는 방식으로 진행했다.
@RequiredArgsConstructor
@Service
public class Auth {
private final InternalAuth internalAuth;
public Response 회원가입_로그인(String accessToken) {
// 플랫폼에서 사용자 정보 조회
...
// 회원가입 및 로그인
internalAuth.auth(member);
// 토큰 관련 로직
...
}
}
@Service
public class InternalAuth {
@Transactional
public void auth(Member member) {
if(새로운 유저인지 체크) 회원가입
else 로그인
}
...
}
auth 관련 로직을 담당하는 InternalAuth 라는 클래스를 생성하고 Auth 클래스에서 호출함으로써, 트랜잭션안에서 정말 필요한 작업만 처리하여 트랜잭션 범위를 최소화했다.
정리
위와 같은 작업을 통해 결과적으로
- 트랜잭션 범위 최소화
라는 목표를 달성할 수 있었다.
db 리소스가 제한된 상황에서 트랜잭션 범위를 최소화 하는 것은 매우 중요한 작업이라 생각한다. 만약 이러한 고려가 안되어 있는 상황에서 한 번에 많은 트래픽이 발생한다면, 경우에 따라 connection pool 고갈 문제가 발생할 수도 있기 때문이다.
따라서 이렇게 트랜잭션에 관계없는 로직이 들어있는 경우 프록시 내부 호출 고려하면서 트랜잭션 범위를 최소화 하도록 하자.
'Project' 카테고리의 다른 글
[마이카마스터] 인덱스와 캐시를 이용한 측정에 의한 성능 개선 (0) | 2023.08.31 |
---|---|
[마이카마스터] 비동기 처리를 통한 구매 상담 신청 API 개선 (0) | 2023.08.31 |
[나날] 쿠폰 등록 동시성 처리를 위한 Lettuce 분산락 설정 (0) | 2023.06.28 |
[나날] 동시 요청시 Transaction Propagation 설정으로 인한 CP Deadlock 문제 (0) | 2023.06.26 |