Home > Back-End > 결제 서비스 MSA 아키텍쳐 전환 > 4. 결제 서비스 Runnable 패턴 구현

4. 결제 서비스 Runnable 패턴 구현
Spring Boot 3.4.0 Java 21 Record Functional Interface Callback Pattern

결제 처리 과정에서 발생하는 다양한 이벤트를 처리하기 위한 PaymentAdapterRunnable 구현에 대해 설명합니다.
이 클래스는 결제 처리의 각 단계에서 발생하는 이벤트(UUID 생성, 성공, 실패)를 함수형 인터페이스를 통해 처리합니다.

클래스 구조

public record PaymentAdapterRunnable<T>(
    CreateUuidRunnable createUuidRunnable,
    SuccessRunnable<T> successRunnable,
    ErrorRunnable errorRunnable) {

  public static PaymentAdapterRunnable<BaseResponse> paymentRunnable(
      CreateUuidRunnable createUuidRunnable,
      SuccessRunnable<BaseResponse> successRunnable,
      ErrorRunnable errorRunnable) {
    return new PaymentAdapterRunnable<>(createUuidRunnable, successRunnable, errorRunnable);
  }

  public static PaymentAdapterRunnable<Void> callbackRunnable(
      SuccessRunnable<Void> successRunnable, ErrorRunnable errorRunnable) {
    return new PaymentAdapterRunnable<>(uuid -> {}, successRunnable, errorRunnable);
  }

  public static PaymentAdapterRunnable<TalkResponse> sendBillKakaoTalkRunnable(
      SuccessRunnable<KakaoTalkResponse> successRunnable, ErrorRunnable errorRunnable) {
    return new PaymentAdapterRunnable<>(uuid -> {}, successRunnable, errorRunnable);
  }

  public static PaymentAdapterRunnable<UrlResponse> getBillUrlRunnable(
      SuccessRunnable<UrlResponse> successRunnable, ErrorRunnable errorRunnable) {
    return new PaymentAdapterRunnable<>(uuid -> {}, successRunnable, errorRunnable);
  }

  public static PaymentAdapterRunnable<RefundResponse> refundRunnable(
      SuccessRunnable<RefundResponse> successRunnable, ErrorRunnable errorRunnable) {
    return new PaymentAdapterRunnable<>(uuid -> {}, successRunnable, errorRunnable);
  }

  public static PaymentAdapterRunnable<DestroyResponse> destroyRunnable(
      SuccessRunnable<DestroyResponse> successRunnable, ErrorRunnable errorRunnable) {
    return new PaymentAdapterRunnable<>(uuid -> {}, successRunnable, errorRunnable);
  }

주요 컴포넌트

1. Record 클래스 정의

public record PaymentAdapterRunnable<T>(
    CreateUuidRunnable createUuidRunnable,
    SuccessRunnable<T> successRunnable,
    ErrorRunnable errorRunnable) {
  • Java 21의 Record 기능을 활용한 불변 데이터 클래스
  • 제네릭 타입 <T>를 통한 다양한 응답 타입 지원
  • 세 가지 핵심 Runnable 컴포넌트 포함:
    • CreateUuidRunnable: UUID 생성 시점의 콜백
    • SuccessRunnable<T>: 성공 처리 콜백
    • ErrorRunnable: 오류 처리 콜백

2. 정적 팩토리 메서드

결제 요청 Runnable

public static PaymentAdapterRunnable<BaseResponse> paymentRunnable(
    CreateUuidRunnable createUuidRunnable,
    SuccessRunnable<BaseResponse> successRunnable,
    ErrorRunnable errorRunnable) {
  return new PaymentAdapterRunnable<>(createUuidRunnable, successRunnable, errorRunnable);
}
  • 모든 콜백을 포함한 전체 Runnable 생성
  • 결제 요청 시 사용되는 기본 구현

콜백 Runnable

public static PaymentAdapterRunnable<Void> callbackRunnable(
    SuccessRunnable<Void> successRunnable,
    ErrorRunnable errorRunnable) {
  return new PaymentAdapterRunnable<>(uuid -> {}, successRunnable, errorRunnable);
}
  • UUID 생성이 필요 없는 콜백 처리용
  • 빈 UUID 생성 콜백 포함

기타 특화된 Runnable

  • sendBillKakaoTalkRunnable: 카카오톡 청구서 발송
  • getBillUrlRunnable: 청구서 URL 조회
  • refundRunnable: 환불 처리
  • destroyRunnable: 청구서 파기

설계 특징

1. 함수형 프로그래밍 활용

  • 람다식을 통한 간결한 콜백 구현
  • 함수형 인터페이스를 통한 유연한 이벤트 처리

2. 제네릭을 통한 타입 안전성

  • 응답 타입에 따른 타입 파라미터 지정
  • 컴파일 시점의 타입 검증

3. 불변성 보장

  • Record 클래스를 통한 불변 객체 구현
  • 스레드 안전성 확보

4. 메서드 특화

  • 각 결제 프로세스에 특화된 팩토리 메서드
  • 불필요한 콜백 제거로 효율성 향상

사용 예시

// 결제 요청 Runnable 생성
PaymentAdapterRunnable<BaseResponse> runnable = PaymentAdapterRunnable.paymentRunnable(
    uuid -> log.info("UUID created: {}", uuid),
    (uuid, response) -> log.info("Payment success: {}", response),
    (uuid, error) -> log.error("Payment failed: {}", error)
);

// 환불 요청 Runnable 생성
PaymentAdapterRunnable<RefundResponse> refundRunnable = PaymentAdapterRunnable.refundRunnable(
    (uuid, response) -> log.info("Refund success: {}", response),
    (uuid, error) -> log.error("Refund failed: {}", error)
);

장점

  1. 코드 재사용성
    • 공통 콜백 패턴 표준화
    • 중복 코드 제거
  2. 유연성
    • 다양한 결제 프로세스에 대응
    • 콜백 조합의 자유로운 구성
  3. 유지보수성
    • 명확한 책임 분리
    • 테스트 용이성
  4. 타입 안전성
    • 컴파일 타임 타입 체크
    • 런타임 에러 방지

주의사항

  1. 콜백 체인 관리
    • 과도한 콜백 중첩 방지
    • 적절한 에러 처리 구현
  2. 메모리 관리
    • 콜백 객체의 적절한 해제
    • 순환 참조 방지
  3. 디버깅
    • 콜백 실행 추적을 위한 로깅 구현
    • 명확한 에러 메시지 제공

이러한 Runnable 패턴 구현을 통해 결제 처리의 각 단계에서 발생하는 이벤트를 효율적이고 유연하게 처리할 수 있습니다.