Swift) @discardableResult란?

1. @discardableResult란?

@discardableResult는 Swift에서 메서드나 함수의 반환값을 무시할 수 있도록 해주는 속성입니다. 영어 뜻 그대로 버릴 수 있는 결과라는 의미를 가집니다. 즉 메서드의 반환값에 있어서 결과를 버릴 수 있는 설정을 도와주는 것이라고 할 수 있습니다. Apple 공식문서에서도 결과를 사용하지 않고 값을 반환하는 함수나 메서드가 호출될 떄 컴파일러 경고가 표시되지 않도록 하려면 이 특성을 함수나 메서드에 선언하라고 되어있습니다. Swift에서는 기본적으로 함수가 값을 반환하는 경우 그 값을 반드시 사용할 것을 권장합니다. 예를 들어, 반환값을 사용하지 않을 경우 컴파일러에서 “Result of call is unused”라는 경우가 나타나게 됩니다. 이러한 경고를 억제할 수 있으며, 이를 통해 코드의 가독성과 유연성을 높일 수 있습니다.

2. 필요성

Swift는 함수나 메서드 호출 결과를 사용하지 않으면 컴파일러가 경고를 발생시키는 강력한 타입 시스템을 가지고 있습니다. 이러한 경고는 때때로 유용하지만, 반환값이 필수가 아닌 경우에도 발생하여 불필요한 경고가 생길 수 있습니다. 해당 속성을 활용하면 이러한 경고를 피할 수 있어 더 깔끔한 코드를 유지할 수 있습니다. 예를 들어, 특정 메서드가 설정값을 반환하지만, 실제로는 그 설정을 하는 것이 목적일 경우가 있을 수 있습니다. 이 때 이 속성을 사용하게 되면 반환값을 사용하지 않아도 경고가 발생하지 않습니다.

3. 사용법

@discpardableResult는 함수 선언 앞에 붙여주면 됩니다. 다음은 기본적인 사용법 예제입니다. 위 코드에서 update 함수는 Bool 타입의 반환값을 가지지만, 호출할 때 반환값을 사용하지 않아도 경고가 발생하지 않습니다.

    @discardableResult
    func update(name: String) -> Bool {
        
        return true
    }
    
    init() {
// 반환값을 사용하지 않아도 경고가 발생하지 않습니다.
        update(name: "Swift")
    }

3.활용 예시

빌더 패턴은 객체의 생성 과정을 단계별로 나누고, 이를 통해 복잡한 객체를 유연하고 간결하게 생성할 수 있도록 돕는 디자인 패턴입니다. 특히 메서드 체이닝 방식을 활용해 코드의 가독성을 높이는 데 유리합니다. 빌더 패턴을 사용할 때 함수가 자신의 인스턴스를 반환하는 경우 해당 속성을 사용하면 매우 유용하게 사용할 수 있습니다. 이렇게 하면 함수가 체인 형태로 연결될 수 있으며, 필요에 따라 반환값을 무시할 수 있습니다.

class Configuration {
    var timeout: Int = 0
    var retries: Int = 0
    
    @discardableResult
    func setTimeout(_ seconds: Int) -> Configuration {
        self.timeout = seconds
        return self
    }
    
    @discardableResult
    func setRetries(_ count: Int) -> Configuration {
        self.retries = count
        return self
    }
}

let config = Configuration()
    .setTimeout(30)
    .setRetries(3)

위 코드에서 setTImeout과 setRetires 메서드는 @discardableResult 속성이 붙어 있어, 반환값을 사용할지 말지를 개발자가 자유롭게 선택할 수 있습니다. 이와 같은 메서드 체이닝은 객체를 설정할 때 훨씬 더 직관적이고 간결한 코드를 작성할 수 있게 해줍니다. 특히 빌드 패턴에서 해당 속성을 사용할 때 장점은 다음과 같습니다. 먼저 코드 가독성을 향상시킬 수 있습니다. 메서드 체이닝을 통해 설정 작업을 한눈에 이해할 수 있고 이로 인해 사용자가 코드를 더 쉽게 읽고 이해할 수 있습니다. 그리고 개발자가 반환값을 필요에 따라 사용할 수 있도록 해주어, 불필요한 경고 메세지를 피할 수 있습니다. 이는 설정 메서드가 많을 때 특히 유용합니다. 마지막으로 메서드가 설정 작업을 수행하면서 결과를 반환하지 않아도 되는 상황에서, 불필요한 경고를 피할 수 있게 해줍니다.

또한 연산 결과가 필요하지 않은 메서드에도 사용할 수 있습니다.

@discardableResult
func logMessage(_ message: String) -> Bool {
    print("Log: \(message)")
    return true
}

// 호출 시 반환값을 무시해도 경고가 발생하지 않습니다.
logMessage("This is a log message.")

주의사항

무분별하게 사용하는 것은 피해야 합니다. 반환값이 중요한 함수에 사용할 경우, 오히려 반환값을 무시하게 되어 중요한 정보를 놓칠 수 있습니다. 예를 들어, 에러 핸들링이 중요한 함수에는 사용하지 않는 것이 좋습니다. 또한 반환값을 무시해도 되는 상황과 반드시 사용해야 하는 상황을 구분하여 코드 작성 시 의도를 명확히 표현하는 것이 좋습니다.

@discardableResult
func performCriticalOperation() -> Bool {
    // 중요한 작업 수행
    return true
}

// 이렇게 호출할 경우 결과를 무시하는 것이 적절치 않을 수 있습니다.
performCriticalOperation() 

이 경우, performCriticalOperation 이 반환하는 값은 성공 여부를 나타내므로, 결과를 무시하는 것은 좋지 않습니다 .이러한 상황에서는 속성을 사용하면 오히려 코드의 의도를 흐리게 만들 수 있습니다.

Swift의 discardableResult 속성은 함수 반환값을 무시해도 경고를 발생시키지 않도록 도와주어 유연한 코드 작성에 기여할 수 있습니다. 빌더 패턴이나, 단순히 부수적인 작업을 수행하는 함수에 사용하면 코드의 가독성과 유지보수성을 높일 수 있습니다.

Leave a Comment