Home > Back-End > 결제 서비스 MSA 아키텍쳐 전환 > 3. PG사 외부 API 통신을 위한 RestClient 설계

3. PG사 외부 API 통신을 위한 RestClient 설계
Spring Boot 3.4.0 Java 21 RestClient HTTP Client Interface-based Client

Spring Framework 6.1에서 도입된 RestClient@HttpExchange 어노테이션을 활용한 선언적 HTTP 클라이언트 구현에 대해 설명합니다.

인터페이스 기반 RestClient 설계

Spring의 @HttpExchange 어노테이션을 사용하여 선언적으로 HTTP 클라이언트를 정의할 수 있습니다.

@Component
@HttpExchange
public interface PgPaymentApiRestClient {

  @PostExchange("...")
  바로결제ResponseBody 바로결제(@RequestBody 바로결제RequestBody request);

  @PostExchange("...")
  청구서카카오톡발송ResponseBody 청구서카카오톡발송(@RequestBody 청구서카카오톡발송RequestBody request);

  @PostExchange("...")
  청구서URL조회ResponseBody 청구서URL조회(@RequestBody 청구서URL조회RequestBody request);

  @PostExchange("...")
  결제정보조회ResponseBody 결제정보조회(@RequestBody 결제정보조회RequestBody request);

  @PostExchange("...")
  환불요청ResponseBody 환불요청(@RequestBody 환불요청RequestBody request);

  @PostExchange("...")
  청구서파기ResponseBody 청구서파기(@RequestBody 청구서파기RequestBody request);
}

인터페이스 설명

PgPaymentApiRestClient 인터페이스는 다음과 같은 특징을 가집니다:

  1. 선언적 HTTP 통신
    • @HttpExchange 어노테이션으로 HTTP 클라이언트임을 선언
    • 각 메서드에 @PostExchange 어노테이션으로 POST 요청 정의
    • 요청/응답 DTO를 통한 타입 안전성 보장
  2. 메서드 구성
    • 바로결제: 즉시 결제 요청 처리
    • 청구서카카오톡발송: 결제 청구서 카카오톡 발송
    • 청구서URL조회: 결제 청구서 URL 정보 조회
    • 결제정보조회: 기존 결제 내역 조회
    • 환불요청: 결제 취소 및 환불 처리
    • 청구서파기: 발급된 청구서 무효화
  3. 요청/응답 매핑
    • @RequestBody를 통한 요청 본문 자동 매핑
    • 응답 데이터의 자동 역직렬화

RestClient 설정

아래는 RestClient의 구성과 설정을 담당하는 설정 클래스입니다.

@Slf4j
@Configuration
@RequiredArgsConstructor
public class RestClientConfig {

  @Value("${payment.pg.api.url}")
  private String pgApiUri;

  @Bean
  public PgPaymentApiRestClient pgPaymentApiRestClient() {
    return HttpServiceProxyFactory.builderFor(
            RestClientAdapter.create(paymentRestClientBuilder().baseUrl(pgApiUri).build()))
        .build()
        .createClient(PgPaymentApiRestClient.class);
  }

  @Bean
  public RestClient.Builder paymentRestClientBuilder() {
    return RestClient.builder()
        .defaultHeader(CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
        .defaultHeader(ACCEPT, MediaType.APPLICATION_JSON_VALUE)
        .defaultStatusHandler(
            HttpStatusCode::isError,
            (request, response) -> {
              log.error("httpRequest: {}, {}", request.getHeaders(), request.getURI());
              log.error("httpResponse: {}, {}", response.getStatusCode(), response.getStatusText());
              throw new PaymentException(response.toString());
            });
  }
}

설정 클래스 주요 특징

  1. 환경 설정
    • @Value 어노테이션으로 PG사 API URL 주입
    • 외부 설정을 통한 유연한 환경 관리
  2. RestClient 빌더 설정
    • Content-Type과 Accept 헤더 기본값 설정
    • 에러 상태 코드에 대한 전역 핸들러 구성
    • 상세한 에러 로깅 구현
  3. 프록시 팩토리 설정
    • HttpServiceProxyFactory를 통한 인터페이스 구현체 자동 생성
    • RestClient 어댑터 구성
    • 동적 프록시를 통한 HTTP 클라이언트 생성

장점

  1. 코드 간결성
    • 인터페이스 선언만으로 HTTP 클라이언트 구현
    • 보일러플레이트 코드 최소화
  2. 타입 안전성
    • 컴파일 시점에 타입 검증
    • DTO를 통한 요청/응답 데이터 구조화
  3. 유지보수성
    • 선언적 프로그래밍으로 가독성 향상
    • 중앙화된 설정으로 일관성 있는 구현
  4. 확장성
    • 새로운 API 엔드포인트 추가가 용이
    • 공통 설정의 유연한 확장

주의사항

  1. 에러 처리
    • 적절한 예외 처리 로직 구현 필요
    • 상세한 로깅으로 문제 추적 가능성 확보
  2. 타임아웃 설정
    • 적절한 타임아웃 값 설정 필요
    • 네트워크 지연 상황 고려
  3. 보안
    • 민감한 정보의 로깅 제외
    • 적절한 인증/인가 처리

이러한 설계를 통해 PG사와의 안정적이고 유지보수가 용이한 HTTP 통신을 구현할 수 있습니다.