• 카테고리

    질문 & 답변
  • 세부 분야

    백엔드

  • 해결 여부

    해결됨

서비스단 Transactional에 대해 질문 드립니다

23.11.27 18:15 작성 조회수 446

0

안녕하세요!

서비스 클래스 상단에 @Transactional(readOnly = true) 옵션을 두는 경우에 대해 질문이 있습니다.

만약 Transactional을 적용하고 싶지 않은 메서드가 있으면 어떻게 하는 것이 좋을까요?

저의 경우 외부 api 요청을 보내고 응답을 반환하는 메서드에 Transactional을 적용하지 않으려고 합니다

(CQRS에 대해 말씀해주신 부분을 듣고 애초에 외부 API 호출하는 기능이 분리 되어야 하나 싶기도 드네요 ㅠㅠ)

 

@Service
@Transactional(readOnly = true)
@RequiredArgsConstructor
public class SpotService {
	private final MapApiClient mapApiClient;

답변 3

·

답변을 작성해보세요.

1

안녕하세요, code-tree 님! :)

말씀해주신 것처럼 트랜잭션 내에서 외부 API를 호출하는 것은 지양하는 것이 좋습니다.
예를 들어, 트랜잭션이 시작되고 데이터베이스 커넥션을 커넥션풀에서 획득한 뒤 API를 호출한다면 해당하는 네트워크 시간만큼 커넥션을 오래 점유하고 있게 됩니다. 막상 외부 API는 커넥션을 사용하지도 않는데 말이죠.

작성하시는 비즈니스 로직이 어떤지 제가 정확히 알 수는 없지만, 권장하는 방식은 외부 API를 트랜잭션과 분리하고, 그 외의 로직만 트랜잭션 범위에 있도록 하는 것입니다. (클래스 분리 등으로)

도움이 되셨기를 바랍니다.
감사합니다. :)

code-tree님의 프로필

code-tree

질문자

2023.12.04

도움이 많이 되었습니다 감사합니다!!

0

PENEKhun님의 프로필

PENEKhun

2023.12.01

지나가던 수강생입니당... 분리하는게 좋아보이는데용

혹시라두 같은 클래스에 두고 싶다면, 외부 api 요청을 private 메서드로 하면 해당 메서드에 대한 트랜잭션은 안걸리지 않을까요?

 

[참고링크](https://www.google.com/search?q=private+method+Transaction&rlz=1C5CHFA_enKR982KR983&oq=private+method+Transaction&gs_lcrp=EgZjaHJvbWUyBggAEEUYOTIGCAEQRRg80gEHMTc4ajBqOagCALACAA&sourceid=chrome&ie=UTF-8)

code-tree님의 프로필

code-tree

질문자

2023.12.02

답변 감사합니다! 외부 api 요청에 대한 부분을 private 메서드로 해도 해당 메서드를 호출하는 public 메서드에서 트랜잭션이 걸리는 것으로 알고 있습니다 제가 잘못 이해한 부분이 있다면 말씀해주세요..!

PENEKhun님의 프로필

PENEKhun

2023.12.02

네 말씀주신 부분 맞습니다.

비지니스 로직이 외부 api 요청실패할 경우, 롤백되는 것이 맞다면 그렇게 처리하는게 맞지않을까요?

 

아니면, 외부 api 요청이 오래걸리는 작업이라 트랜잭션이 길어져서 해당부분을 고려하시는 걸까요?

code-tree님의 프로필

code-tree

질문자

2023.12.03

네 외부 API 요청 실패시 롤백이 될 필요가 없고 외부 API에 문제가 생겨서 지연이 되는 경우 영향을 받을 부분도 고려하고 있습니다.

 

관련해서 참고했던 영상 링크입니다!

https://youtu.be/mB3g3l-EQp0?si=2Hi-UXcs0kpjDyfa

https://youtu.be/nuRO0ZBFdKk?si=6oYl3KMncImFIhgH

-1

인프런 AI 인턴님의 프로필

인프런 AI 인턴

2023.11.29

안녕하세요, 인프런 AI 인턴입니다.

서비스 클래스에 @Transactional(readOnly = true) 애노테이션을 붙여서 기본적으로 모든 메서드에 읽기 전용 트랜잭션을 적용하였으나 특정 메서드에는 트랜잭션을 적용하지 않으려면 각 메서드에 별도의 @Transactional 애노테이션을 명시적으로 추가하시는 것이 좋습니다. 이 경우, 해당 메서드에 적용할 트랜잭션 속성을 직접 정의할 수 있으며, readOnly 플래그를 false로 설정하거나 아예 트랜잭션을 적용하지 않을 수 있습니다.

외부 API 요청을 보내고 응답을 반환하는 메서드의 경우 트랜잭션을 아예 적용하지 않으려면 @Transactional 없이 메서드를 정의하시면 됩니다. 다음은 트랜잭션이 적용되지 않는 메서드 예시입니다.

@Service
@Transactional(readOnly = true)
@RequiredArgsConstructor
public class SpotService {
	private final MapApiClient mapApiClient;

	// 트랜잭션 적용 없음
	public MapResponse getMapData(MapRequest request) {
		return mapApiClient.getMapData(request);
	}

	// 나머지 서비스 메서드들...
}

CQRS의 경우, 명령(Command)과 조회(Query)를 명확히 분리하는 아키텍처 패턴입니다. 외부 API 호출은 일반적으로 조회에 속하기 때문에, 해당 기능을 서비스 클래스나 별도의 쿼리 서비스로 분리하는 것을 고려할 수 있습니다. 이렇게 하면 트랜잭션 관리도 보다 명확해지고 서비스 계층의 책임이 더 분명해집니다.

트랜잭션 관련 자세한 사항은 Spring Data JPA 문서에 잘 설명되어 있으니 참고하시면 도움이 될 것입니다.