Swift. 프로토콜 요구사항과 메소드 어트리뷰트

RemoteDBRequestBuildable 프로토콜을 추가한 뒤, 이전에는 나타나지 않던 unused-result 경고가 발생했다. 구체 타입에서는 사라졌던 경고 기존 구현의 request()에는 @discardableResult가 붙어 있었다. 반환값을 사용하지 않아도 경고가 발생하지 않았다. final class SupabaseDBRequestBuilder { @discardableResult func request() async throws -> Data { Data() } } let concrete = SupabaseDBRequestBuilder() try await concrete.request() 이후 Builder를 프로토콜로 추상화했지만 프로토콜 요구사항에는 해당 어트리뷰트를 붙이지 않았다. protocol RemoteDBRequestBuildable { func request() async throws -> Data } extension SupabaseDBRequestBuilder: RemoteDBRequestBuildable {} let abstract: any RemoteDBRequestBuildable = SupabaseDBRequestBuilder() try await abstract.request() 구체 구현에는 여전히 @discardableResult가 있는데도, 프로토콜 타입으로 호출하면 경고가 다시 나타났다. 호출을 검사하는 선언과 실행할 구현 컴파일러는 호출 지점의 정적 타입을 기준으로 사용할 메서드 선언을 해석한다. ...

February 10, 2025

Swift. Associated Type

소개 Swift의 프로토콜은 구현이 아니라 요구사항만 정의한다. 그런데 어떤 프로토콜은 사용할 타입을 미리 알 수 없는 경우가 있다. 예를 들어, 아래와 같은 Container 프로토콜을 만든다고 생각해 보자. protocol Container { func append(_ item: ???) } append가 받을 타입은 무엇이어야 할까? Int일 수도 있고, String일 수도 있으며, 사용자가 직접 만든 타입일 수도 있다. 하지만 프로토콜이 특정 타입에 종속되면 재사용성이 크게 떨어진다. 이럴 때 사용하는 것이 Associated Type이다. 처음에는 Generic으로도 해결할 수 있을 것 같다는 생각이 들었는데, 프로토콜은 Generic을 사용할 수 없다. ...

January 26, 2025