과정을 즐기자

조건문이 많아질 때 List<인터페이스>를 사용해보자 본문

아키텍쳐

조건문이 많아질 때 List<인터페이스>를 사용해보자

320Hwany 2024. 7. 17. 15:45

이번 글에서는 if, else if 가 점점 많아져 가독성이 좋지 않은 코드를 개선해보는 작업을 해보겠습니다.

먼저 요구 사항부터 살펴보겠습니다.

 

1. 간단한 결제 로직을 구현한다.

2. 현재 네이버 페이, 카카오 페이, 토스 페이, 애플 페이를 지원한다.

 

인터페이스를 활용하여 결제 로직을 구현해보겠습니다.

📕 PaymentProvider

PaymentProvider는 페이 종류를 나열하였습니다.

📕 PaymentChannel

PaymentChannel 인터페이스는 해당 페이의 종류인지 확인하는 isSupport() 메소드와 결제를 처리하는 processPayment()

메소드가 있습니다.

 

PaymentChannel 인터페이스의 구현체로 NaverPayChannel, KakaoPayChannel, TossPayChannel, ApplePayChannel을

사용하겠습니다.

📕 PaymentService

해당 구현체들을 활용하여 결제를 처리하는 PaymentService를 만들어보았습니다.

📌 OCP를 위반한다

모든 결제 로직은 PaymentService 메소드 1개에서 처리할 수 있습니다. 하지만 문제점이 보이시나요? 

바로 이후 다른 종류의 페이들이 추가되면 PaymentService 클래스도 수정되고 processPayment() 메소드도 수정되어야 합니다.

페이 종류가 너무 많아지면 가독성이 떨어지게 됩니다. 또한 "확장에는 열려있고 변경에는 닫혀있다"는 OCP 원칙에 어긋나게 됩니다.

확장을 하려면 기존 코드를 수정해야 할 수 밖에 없기 때문입니다.

👍 다형성을 활용해보자

DI의 원리를 활용할 때 인터페이스를 주입 받으면 좋은 이유가 런타임 시점에 구현체를 바꿀 수 있다는 장점도 있지만

스프링 빈으로 등록된 인터페이스의 구현체를 모두 List 형식으로 받을 수 있다는 장점도 있습니다.

 

위와 같은 방식으로 List<인터페이스> 방식으로 스프링 빈인 인터페이스의 구현체를 모두 주입받을 수 있습니다.

이제 반복문으로 리스트를 돌면서 각각의 메소드를 호출하면 됩니다. 

 

PaymentProvider로 각각 다른 종류의 페이를 입력 받아 결과를 확인해보겠습니다.

 

정상적으로 처리된 것을 확인할 수 있습니다.

이러한 코드에서는 만약 다른 종류의 페이가 추가된다면 어떻게 될까요?

PaymentService의 코드는 하나도 건드리지 않고 PaymentChannel 인터페이스의 구현체를 하나 더 만들면 됩니다.

⛳️ 정리

이번 글에서는 if, else if 문이 많아질 때 다형성의 원리를 사용해서 개선해보았습니다.

스프링의 DI를 활용할 때 런타임 시점에 인터페이스의 구현체를 바꾸는 것으로만 활용하지 않고 List<인터페이스> 형식으로도

사용해볼 수 있습니다. 인터페이스의 구현체들을 모두 스프링 빈으로 등록해서 사용하는 방법입니다.