(면접복기)OCP를 준수하는 결제 시스템 확장하기: 전략패턴을 활용한 유연한 설계

2026. 1. 27. 12:48·면접복기

문제 상황

현재 서비스에는 카카오페이만 결제수단으로 지원되고 있습니다. 비즈니스 요구사항이 증가하면서 네이버 페이 페이코, 토스페이 등 다양한 결제 수단을 추가해야 하는  상황입니다. 핵심은OCP(개방-폐쇄 원칙)를  지키면서 확장할수있는 구조를 만드는 것입니다.

OCP(개방- 폐쇄 원칙)란?

"소프트웨어 개체는 확장에는  열려 있어야하고,  변경에는 닫혀 있어야한다"

- 기존코드를 수정하지 않고도 새로운 가능을 추가 할수 있어야함

┌─────────────────────────────────┐
│       PaymentService            │  ← 확장에 닫혀 있음
├─────────────────────────────────┤
│ - processPayment()              │
│ - cancelPayment()               │
│ - refundPayment()               │
└──────────────┬──────────────────┘
               │ 의존성 주입
               ▼
┌─────────────────────────────────┐
│   PaymentProcessor (인터페이스)  │  ← 확장에 열려 있음
├─────────────────────────────────┤
│ + process()                     │
│ + cancel()                      │
│ + refund()                      │
│ + supports()                    │
└─────┬────────────┬──────────────┘
      │            │
      ▼            ▼
┌─────────┐  ┌─────────┐  (추가 가능)
│KakaoPay │  │NaverPay │  │ Payco │ ...
└─────────┘  └─────────┘  └───────┘

단계별 구현가이드

step1: 공통 인터페이스 정의

/**
 * 모든 결제 수단이 구현해야 할 공통 인터페이스
 */
public interface PaymentProcessor {
    
    /**
     * 결제 처리
     */
    PaymentResult processPayment(PaymentRequest request);
    
    /**
     * 결제 취소
     */
    PaymentResult cancelPayment(String paymentId);
    
    /**
     * 결제 환불
     */
    PaymentResult refundPayment(String paymentId, BigDecimal amount);
    
    /**
     * 지원하는 결제 수단 확인
     */
    boolean supports(PaymentMethod method);
}

Step 2: 결제수단 Enum 정의

 

/**
 * 지원하는 결제 수단 목록
 */
public enum PaymentMethod {
    KAKAO_PAY("카카오페이"),
    NAVER_PAY("네이버페이"),
    PAYCO("페이코"),
    TOSS_PAY("토스페이");
    
    private final String description;
    
    PaymentMethod(String description) {
        this.description = description;
    }
}

 

Step 3:  기존 카카오 페이 리팩토링

@Component
public class KakaoPayProcessor implements PaymentProcessor {
    
    private final KakaoPayClient kakaoPayClient;
    
    @Override
    public PaymentResult processPayment(PaymentRequest request) {
        // 카카오페이 전용 로직
        KakaoPayResponse response = kakaoPayClient.pay(
            request.getAmount(),
            request.getOrderId()
        );
        
        return PaymentResult.builder()
            .success(response.isSuccess())
            .paymentId(response.getPaymentId())
            .transactionId(response.getTid())
            .build();
    }
    
    @Override
    public boolean supports(PaymentMethod method) {
        return PaymentMethod.KAKAO_PAY.equals(method);
    }
    
    @Override
    public PaymentResult cancelPayment(String paymentId) {
        // 카카오페이 취소 로직
    }
    
    @Override
    public PaymentResult refundPayment(String paymentId, BigDecimal amount) {
        // 카카오페이 환불 로직
    }
}

 

Step4: 결제 프로세서 팩토리 구현

@Component
public class PaymentProcessorFactory {
    
    private final Map<PaymentMethod, PaymentProcessor> processorMap;
    
    // Spring의 의존성 주입을 활용한 자동 등록
    public PaymentProcessorFactory(List<PaymentProcessor> processors) {
        processorMap = processors.stream()
            .flatMap(processor -> 
                Arrays.stream(PaymentMethod.values())
                    .filter(processor::supports)
                    .map(method -> Map.entry(method, processor))
            )
            .collect(Collectors.toMap(
                Map.Entry::getKey,
                Map.Entry::getValue
            ));
    }
    
    public PaymentProcessor getProcessor(PaymentMethod method) {
        return Optional.ofNullable(processorMap.get(method))
            .orElseThrow(() -> new UnsupportedPaymentMethodException(
                "지원하지 않는 결제 수단: " + method));
    }
}

Step 5: 결제 서비스 구현  (OCP 의핵심)

@Service
public class PaymentService {
    
    private final PaymentProcessorFactory processorFactory;
    
    /**
     * 결제 실행 - 새로운 결제 수단이 추가되어도 이 메서드는 변경되지 않음!
     */
    public PaymentResult pay(PaymentRequest request) {
        PaymentProcessor processor = processorFactory
            .getProcessor(request.getPaymentMethod());
        
        // 공통 검증 로직
        validatePaymentRequest(request);
        
        // 결제 처리 위임
        PaymentResult result = processor.processPayment(request);
        
        // 공통 후처리 로직
        savePaymentHistory(request, result);
        
        return result;
    }
    
    /**
     * 결제 취소
     */
    public PaymentResult cancel(String paymentId, PaymentMethod method) {
        PaymentProcessor processor = processorFactory.getProcessor(method);
        return processor.cancelPayment(paymentId);
    }
    
    // ... 기타 공통 메서드들
}

새로운 결제 수단 추가하기 (OCP 실현)

예시: 네이버페이 추가하기

@Component
public class NaverPayProcessor implements PaymentProcessor {
    
    private final NaverPayClient naverPayClient;
    
    @Override
    public PaymentResult processPayment(PaymentRequest request) {
        // 네이버페이 전용 로직
        NaverPayResponse response = naverPayClient.requestPayment(
            request.getAmount(),
            request.getOrderId(),
            request.getCustomerId()
        );
        
        return PaymentResult.builder()
            .success("SUCCESS".equals(response.getStatus()))
            .paymentId(response.getPaymentId())
            .transactionId(response.getTransactionId())
            .build();
    }
    
    @Override
    public boolean supports(PaymentMethod method) {
        return PaymentMethod.NAVER_PAY.equals(method);
    }
    
    // ... cancelPayment, refundPayment 구현
}

 

이런식으로 공통로직 수정할필요없고 따로 상속해서 구현하면  유지보수성 향상한다 

'면접복기' 카테고리의 다른 글

(면접복기)자바 컴파일 과정 완벽 정리: .java → 실행까지  (0) 2026.05.15
(면접복기)자바 기본 타입(Primitive Type) 완벽 정리  (0) 2026.05.15
(면접복기)트랜잭션 격리 수준 (Transaction Isolation Levels)  (0) 2025.11.19
(면접복기)쓰레드 풀 vs 커넥션 풀  (0) 2025.11.19
'면접복기' 카테고리의 다른 글
  • (면접복기)자바 컴파일 과정 완벽 정리: .java → 실행까지
  • (면접복기)자바 기본 타입(Primitive Type) 완벽 정리
  • (면접복기)트랜잭션 격리 수준 (Transaction Isolation Levels)
  • (면접복기)쓰레드 풀 vs 커넥션 풀
cookiboii
cookiboii
초보 개발자입니다.
  • cookiboii
    Just Do it
    cookiboii
  • 전체
    오늘
    어제
    • 분류 전체보기 (79)
      • 잡소리 (2)
      • vscode꾸미기 (1)
      • 회사공부 (0)
      • 면접복기 (5)
      • 개발취직관련 좋은 글귀 (12)
      • 개발 공부 (58)
        • 백준 (0)
        • web (3)
        • js&ts&react (4)
        • Java-Spring (18)
        • 개발책 리뷰 (0)
        • c++ (0)
        • git (0)
        • code up 문제 (5)
        • 네트워크 (5)
        • 자료구조&알고리즘 (2)
        • ci,cd (1)
        • 프로젝트 (9)
        • sql (4)
        • 컴퓨터구조 (1)
        • 운영체제 (5)
        • python (0)
  • 블로그 메뉴

    • 홈
    • 태그
  • 링크

    • 네이버블로그
    • 깃허브
  • 공지사항

  • 인기 글

  • 태그

    코드업 #코딩문제
    js #web
    Java
    springai #spring #java
    사이드프로젝트 #토이프로젝트 #개발 #개발자
    js #예약어 #자바스크랩트
    ci #개발 #git
    깃허브 #깃 #커밋
    개발
    라이엇 #api #롤api
    롤 #리그오브레전드
    JVM
    자바 #Java #JPA #개발자 #개발 #초보
    js #제이쿼리 #비동기통신 #코딩 #프로그래밍
    자바
    코딩
    포켓몬 #vscode #vscode꾸미기 #개발
    프로그래밍
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.6
cookiboii
(면접복기)OCP를 준수하는 결제 시스템 확장하기: 전략패턴을 활용한 유연한 설계
상단으로

티스토리툴바