[kotlin] 코틀린에서 인터페이스를 통한 의존성 주입의 장점 설명

의존성 주입(Dependency Injection)은 객체 간의 의존 관계를 외부에서 결정하고 주입해주는 디자인 패턴입니다. 이를 통해 코드의 유연성과 재사용성을 높일 수 있습니다. Kotlin에서는 인터페이스를 통해 의존성 주입을 구현할 수 있습니다. 이번 포스트에서는 코틀린에서 인터페이스를 통한 의존성 주입의 장점에 대해 설명하겠습니다.

1. 유연성

인터페이스를 사용하면 구체적인 구현체에 의존하지 않고 인터페이스 타입으로 선언할 수 있습니다. 이렇게 되면 하나의 인터페이스를 여러 개의 구현체로 대체할 수 있으며, 이를 통해 코드의 유연성을 높일 수 있습니다. 즉, 의존성 주입을 통해 언제든지 다른 구현체로 쉽게 교체할 수 있기 때문에, 코드의 변경 없이도 다양한 기능을 추가하거나 수정할 수 있습니다.

interface PaymentProcessor {
    fun processPayment()
}

class CreditCardPaymentProcessor : PaymentProcessor {
    override fun processPayment() {
        // Credit card payment logic
    }
}

class PaypalPaymentProcessor : PaymentProcessor {
    override fun processPayment() {
        // Paypal payment logic
    }
}

class OrderService(private val paymentProcessor: PaymentProcessor) {
    fun processOrder() {
        paymentProcessor.processPayment()
        // Order processing logic
    }
}

fun main() {
    val creditCardPaymentProcessor = CreditCardPaymentProcessor()
    val orderService = OrderService(creditCardPaymentProcessor)
    orderService.processOrder()
}

위의 예시 코드에서는 PaymentProcessor 인터페이스를 통해 의존성 주입을 구현하였습니다. OrderService 클래스는 PaymentProcessor를 의존하며, 실제로 주입되는 구현체는 CreditCardPaymentProcessor입니다. 이렇게 인터페이스를 통해 의존성을 주입함으로써 OrderService는 결제 처리 로직을 수정하지 않고도 다른 결제 수단을 추가하거나 변경할 수 있는 유연성을 갖게 됩니다.

2. 테스트 용이성

인터페이스를 통한 의존성 주입은 테스트 용이성을 높일 수 있는 장점이 있습니다. 테스트를 작성할 때, 목(mock) 객체를 사용하여 의존성을 제어하고 예상된 동작을 검증할 수 있습니다. 즉, 테스트에서는 실제 구현체 대신에 테스트에 필요한 동작을 가지는 목 객체를 주입하여 테스트 코드를 작성할 수 있습니다.

class OrderServiceTest {

    private lateinit var paymentProcessor: PaymentProcessor
    private lateinit var orderService: OrderService

    @Before
    fun setup() {
        paymentProcessor = mock()
        orderService = OrderService(paymentProcessor)
    }

    @Test
    fun testProcessOrder() {
        // 주문 처리 로직 테스트 코드 작성
    }
}

위의 예시 코드에서는 mock()을 사용하여 PaymentProcessor의 목 객체를 생성하고, OrderService의 생성자에 주입하고 있습니다. 이렇게 하면 테스트에서는 실제 결제 처리 로직이 실행되지 않으며, 목 객체의 동작을 검증할 수 있습니다.

참고 자료