UseCase에서 invoke()와 excute() 차이점 (Gemini 답변)

Philipy (윤상필)·2025년 9월 23일

아주 좋은 질문입니다! invoke()execute()는 Kotlin에서 함수를 호출하는 방식에 대한 차이점을 나타내며, UseCase 패턴에서 종종 혼용되어 사용될 수 있습니다.

execute() 메서드

execute()는 단순히 "어떤 작업을 실행하라"는 의미를 가진 일반적인 함수 이름입니다.

  • PlayTTSUseCase 인터페이스를 보면 suspend fun execute(request: TTSRequest): Result<Unit>로 정의되어 있죠.
  • 이것은 PlayTTSUseCase의 구현체는 반드시 request를 받아서 execute라는 이름의 함수를 실행해야 한다는 것을 의미합니다.
  • 다른 프로그래밍 언어(Java 등)에서도 매우 흔하게 사용되는 명명 규칙입니다.
  • 장점: 메서드의 목적이 명확하고 이해하기 쉽습니다.

invoke() 연산자 오버로딩 (Operator Overloading)

invoke()는 Kotlin의 연산자 오버로딩(Operator Overloading) 기능 중 하나입니다. 어떤 클래스에 invoke() 함수를 정의하면, 해당 클래스의 인스턴스를 마치 함수처럼 직접 호출할 수 있게 됩니다.

예시를 들어 설명해 드릴게요.

일반적인 함수 호출:

class MyGreeter {
    fun greet(name: String) {
        println("Hello, $name!")
    }
}

val greeter = MyGreeter()
greeter.greet("Alice") // greet 함수를 명시적으로 호출

invoke()를 사용한 함수처럼 호출:

class MyGreeterWithInvoke {
    // invoke 연산자를 오버로딩합니다.
    operator fun invoke(name: String) {
        println("Hello, $name!")
    }
}

val greeter = MyGreeterWithInvoke()
greeter("Bob") // 마치 greeter 객체가 함수인 것처럼 직접 호출!
greeter.invoke("Charlie") // 사실은 invoke 함수가 호출되는 것과 같습니다.

greeter("Bob") 코드를 보면, greeter는 분명 객체인데 ()를 붙여 함수처럼 호출했죠? 이것이 바로 invoke() 연산자 오버로딩 덕분입니다.

UseCase에서 invoke()를 사용하는 이유

UseCase 패턴에서 invoke()를 사용하는 주된 이유는 다음과 같습니다.

  1. 간결성 (Conciseness):

    • myUseCase.execute(param) 대신 myUseCase(param)으로 호출할 수 있어 코드가 더 간결해집니다.
    • 특히 UseCase의 역할이 "어떤 단일 작업을 수행하는 것"일 때, 마치 함수처럼 느껴지게 하여 가독성을 높입니다.
  2. 단일 책임 원칙 (Single Responsibility Principle) 강조:

    • invoke()를 사용한다는 것은 해당 클래스의 "주요 목적"이 이 invoke() 함수가 수행하는 작업이라는 것을 암시적으로 나타냅니다. UseCase는 보통 하나의 책임만 가지므로 잘 어울립니다.

어떤 것을 사용해야 할까요?

  • execute():

    • 함수의 의미가 "실행" 또는 "수행"이라는 것을 명확히 하고 싶을 때 좋습니다.
    • 특히 UseCase가 여러 개의 public 함수를 가질 가능성이 있다면 (execute, cancel, prepare 등), execute 같은 명시적인 이름이 혼동을 피하는 데 도움이 됩니다.
  • invoke():

    • 클래스 인스턴스를 함수처럼 호출하는 간결한 문법을 선호하고, UseCase가 오직 하나의 주된 작업을 수행할 때 유용합니다.

결론:
execute()는 함수의 이름이고, invoke()는 클래스 객체를 함수처럼 호출할 수 있게 해주는 Kotlin의 특별한 기능(연산자 오버로딩)입니다. 둘 다 UseCase의 핵심 로직을 실행하는 데 사용될 수 있지만, invoke()가 더 간결한 호출 문법을 제공합니다. 현재 execute()를 사용하고 계시다면 그대로 두셔도 아무런 문제가 없습니다.

profile
Tech Phase-smith, Karax wannabe

0개의 댓글