결제 처리 과정에서 발생하는 다양한 이벤트를 처리하기 위한 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)
);
장점
- 코드 재사용성
- 공통 콜백 패턴 표준화
- 중복 코드 제거
- 유연성
- 다양한 결제 프로세스에 대응
- 콜백 조합의 자유로운 구성
- 유지보수성
- 명확한 책임 분리
- 테스트 용이성
- 타입 안전성
- 컴파일 타임 타입 체크
- 런타임 에러 방지
주의사항
- 콜백 체인 관리
- 과도한 콜백 중첩 방지
- 적절한 에러 처리 구현
- 메모리 관리
- 콜백 객체의 적절한 해제
- 순환 참조 방지
- 디버깅
- 콜백 실행 추적을 위한 로깅 구현
- 명확한 에러 메시지 제공
이러한 Runnable 패턴 구현을 통해 결제 처리의 각 단계에서 발생하는 이벤트를 효율적이고 유연하게 처리할 수 있습니다.