Skip to content

[REFACTOR/#179] 외부 API 요청 트랜잭션 분리를 위한 Facade 패턴 도입#180

Merged
JungYoonShin merged 8 commits intodevelopfrom
refactor/#179
Jun 12, 2025
Merged

[REFACTOR/#179] 외부 API 요청 트랜잭션 분리를 위한 Facade 패턴 도입#180
JungYoonShin merged 8 commits intodevelopfrom
refactor/#179

Conversation

@JungYoonShin
Copy link
Copy Markdown
Member

@JungYoonShin JungYoonShin commented May 15, 2025

📄 Work Description

  • 외부 API 요청 트랜잭션 분리를 위한 Facade 패턴 도입

⚙️ ISSUE

💬 To Reviewers

🔆 외부 API 요청 트랜잭션 분리를 위한 Facade 패턴 도입

AS-IS

  • 외부 API 요청(카카오 로그인)과 비즈니스 로직(db에 멤버 저장)이 한 트래잭션 안에서 모두 이루어지고 있는 상황이었어요.
  • 외부 API 통신은 비교적 시간이 오래 걸리며, 멤버를 저장하는 로직과 같은 트랜잭션 범위 안에 포함되면 DB 커넥션을 가지고 있는 시간과 트랜잭션이 활성화된 시간이 불필요하게 길어지게 되어 성능이 저하될 수 있다는 문제점이 있었습니다!

TO-BE

  • Controller와 service단 사이에 Facade계층을 두어 외부 통신은 트랜잭션을 타지 않고, service단에는 @transactional을 붙여서 비즈니스 로직은 트랜잭션을 타도록 했습니다!
  • 추가적으로 MemberServiceTokenService를 분리했어요.
    • MemberSerivce의 역할이 멤버 도메인 관련된 비즈니스 로직과 토큰 관련된 비즈니스 로직을 모두 책임하고 있어, 관심사 분리하다고 느꼈어요. 따라서 아래와 같이 분리했으며, 각 클래스의 역할은 아래와 같아요!
    • MemberService: 회원 도메인 중심의 핵심 로직 (회원 가입, 정보 저장, 검증 등)
    • TokenService: 인증 관련 로직 (토큰 저장, 무효화, 로그아웃)
    • Facade: 흐름 제어 및 외부 API 연계

image

🔆 트래잭션 분리에 대한 테스트 실행

  • 외부 API 요청과 db 저장 비즈니스 로직을 트랜잭션에서 분리시킴에 따라, 각각 트랜잭션을 타지 않는지, 타는지를 확인하기 위해 로그를 찍어서 테스트를 진행했어요!
        String email = kakaoClient.getUserInfo(token).kakaoAccount().email();  //트랜잭션 타지 않아야함
        memberService.kakaoLogin(email);   //트랜잭션 타야함
  • MemberService 클래스
@Slf4j
@Service
public class MemberService {

    @Transactional
    public TokenInfoDto kakaoLogin(String email) {
        log.info("트랜잭션 활성화 여부: {}", TransactionSynchronizationManager.isActualTransactionActive());
        ...
    }
}
  • FeignClientConfig 클래스
    • FeignClient가 호출될 때 request 보내기 직전에 이 Interceptor가 요청을 가로채서, Feign 요청 시 트랜잭션 활성 여부를 확인하고자 했습니다!
@Configuration
@Slf4j
public class FeignClientConfig {

    @Bean
    public ErrorDecoder errorDecoder() {
        return new CustomErrorDecoder();
    }

    @Bean
    public RequestInterceptor transactionLoggingInterceptor() {
        return requestTemplate -> {
            boolean isTransactionActive = TransactionSynchronizationManager.isActualTransactionActive();
            log.info("Feign 요청 시 트랜잭션 활성 여부: {}", isTransactionActive);
        };
    }

  • 원하는대로 잘 동작하는 것 확인했어요!
    image

🔗 Reference

https://xxeol.tistory.com/48

책임 분리가 모호한 부분이나, 우려되는 지점?, 궁금증 등등 아무 코멘트 다 좋습니당 ㅎㅎ

@JungYoonShin JungYoonShin requested a review from ppparkta May 15, 2025 15:17
@JungYoonShin JungYoonShin self-assigned this May 15, 2025
@JungYoonShin JungYoonShin added ♻️ refactor code refactoring 🛠 fix Bug fixes and code corrections 🦋정윤 labels May 15, 2025
Copy link
Copy Markdown
Member

@ppparkta ppparkta left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

설계에 대한 고민을 많이 해주셨던 것이 기억나는데, 좋은 방향으로 수정된 것 같아요!
계층 별로 책임도 분명하고요. 고생많으셨습니다 😄

Comment thread src/main/java/com/favoriteplace/app/member/Facade/AuthFacade.java
@JungYoonShin JungYoonShin merged commit a58dfaa into develop Jun 12, 2025
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🛠 fix Bug fixes and code corrections ♻️ refactor code refactoring size/L 🦋정윤

Projects

None yet

Development

Successfully merging this pull request may close these issues.

외부 API 요청 트랜잭션 분리를 위한 Facade 패턴 도입

2 participants