트러블슈팅

외부 플랫폼 주문 전송 기능 - Mock API 구현

sudaruuu 2026. 3. 31. 15:37

2026.03.27 - [Spring 2기 과제] - 포인트 기반 커피 주문 결제 시스템 (도메인 설계)

 

포인트 기반 커피 주문 결제 시스템 (도메인 설계)

https://github.com/Banhklo2/coffee-order-system.git GitHub - Banhklo2/coffee-order-system: Spring Boot 기반 포인트 기반 커피 주문 결제 시스템Spring Boot 기반 포인트 기반 커피 주문 결제 시스템. Contribute to Banhklo2/coffee-o

sudaruuu.tistory.com

 

문제 상황

과제를 진행하면서 다음과 같은 요구사항이 있었다.

주문 완료 후 외부 데이터 수집 플랫폼으로 주문 정보를 전송해야 한다.
(Mock API 또는 테스트 코드를 통해 구현)

 

기존에 테스트 코드를 활용한 검증은 여러 번 해본 경험이 있었지만,

Mock API를 직접 구현해본 경험은 없었다.

 

그래서 이번 과제에서는 단순 테스트 코드 대신

외부 플랫폼을 직접 흉내 낸 Mock API를 구현해보고 싶었다.


작업 목적

  • 외부 API 연동 흐름을 실제처럼 경험해보기
  • 단순 단위 테스트가 아닌 HTTP 요청/응답 흐름 전체 검증
  • 외부 시스템과의 통신 구조 이해

선택한 방법

✔️ 테스트 코드 대신 Mock API 선택

방식 특징
테스트 코드 내부 로직 검증 중심
Mock API 실제 HTTP 통신 흐름 검증

 

이번에는

  • 요청 → 외부 API → 응답
  • 이 전체 흐름을 직접 경험해보고 싶었기 때문에

Mock API 방식을 선택했다.


구현 과정

1. 외부 플랫폼 역할을 하는 Mock API 구현

@RestController
@RequestMapping("/external/orders")
@Slf4j
public class ExternalMockController {

    @PostMapping
    public ApiResponse<Void> receiveOrder(@RequestBody ExternalOrderRequest request) {

        log.info("외부 플랫폼 주문 데이터 수신 - userId={}, menuId={}, amount={}",
                request.getUserId(), request.getMenuId(), request.getAmount());

        return ApiResponse.noContent();
    }
}

 

핵심 포인트

  • 실제 외부 서버 대신 내 애플리케이션 내부에 API 생성
  • 외부 플랫폼 역할을 그대로 흉내내는 구조
  • 로그를 통해 데이터 수신 여부 확인

2. 외부 API 호출용 Client 분리

@Component
@RequiredArgsConstructor
@Slf4j
public class ExternalOrderClient {

    private final RestTemplate restTemplate;

    public void sendOrder(ExternalOrderRequest request) {
        try {
            log.info("ExternalOrderClient 진입");

            restTemplate.postForEntity(
                    "http://localhost:8080/external/orders",
                    request,
                    Void.class
            );

            log.info("외부 플랫폼 전송 완료 - userId={}, menuId={}, amount={}",
                    request.getUserId(), request.getMenuId(), request.getAmount());

        } catch (Exception e) {
            log.error("외부 플랫폼 전송 실패", e);
            throw e;
        }
    }
}

 

 핵심 포인트

  • Service에서 직접 호출하지 않고 Client로 분리
  • 외부 통신 책임을 분리하여 구조 명확화

3. 주문 성공 이후 외부 플랫폼 전송

이 부분은 설계 단계에서 미리 정의했다.

주문 생성 → 포인트 차감 → 결제 성공 → 외부 플랫폼 전송

 

 이유

  • 결제 실패 시 외부 전송은 의미 없음
  • 데이터 정합성을 위해 성공 이후에만 호출
externalOrderClient.sendOrder(
        new ExternalOrderRequest(
                user.getId(),
                savedOrderItem.getMenu().getId(),
                savedOrder.getTotalPrice()
        )
);

4. Postman을 통한 실제 호출 흐름 검증

테스트 방식

  1. /api/orders 호출
  2. 내부 주문/결제 로직 수행
  3. /external/orders 자동 호출
  4. 로그 확인

 

로그 결과

외부 플랫폼 전송 직전
ExternalOrderClient 진입
외부 플랫폼 주문 데이터 수신
외부 플랫폼 전송 완료
외부 플랫폼 전송 직후

 

단순 테스트가 아니라

실제 외부 API 연동 흐름을 그대로 재현


배운 점

1. Mock API는 실제 외부 API처럼 테스트할 수 있다

  • 단순 단위 테스트보다 훨씬 현실적인 검증 가능
  • HTTP 흐름 전체를 직접 확인 가능

2. 외부 API는 구조 분리가 중요하다

  • Service에 직접 넣으면 책임이 섞인다
  • Client로 분리하는 것이 훨씬 명확한 구조

3. "언제 호출할 것인가"가 더 중요하다

외부 API 연동에서 중요한 것은

 

어떻게 호출할지가 아니라

 언제 호출할지


아쉬운 점

현재는 동기 방식으로 구현되어 있다.

  • 외부 API가 느리면 주문도 함께 지연됨
  • 장애 전파 가능성 존재

⭐ 향후 개선 방향

  • 비동기 처리 (@Async)
  • 메시지 큐 기반 구조로 확장

느낀 점

이번 구현을 통해 외부 API 연동을 단순 개념이 아니라

실제 흐름을 만들어보면서 이해할 수 있었다.

 

Mock API를 활용하면 외부 시스템이 없어도 충분히 테스트가 가능하다는 것을 알게 되었다 !!

앞으로는 확장성을 고려하여 비동기 처리 방식까지 함께 적용해보고 싶다.