Swift - some 키워드란 무엇일까?

생성일
Jun 15, 2021 11:48 AM
언어
Swift
분야
URL
 
notion imagenotion image
  • body 프로퍼티에서 some 의 역할은 무엇인가???
  • 여기 보면 body 프로퍼티는 computed property로서 view의 contents를 return 합니다.

WWDC 2019 SwiftUI Essentials

  • And the some keyword that we use here is a switch feature that lets swift infer out inter return type automatically.
: 이 문장을 해석해보자면 some 키워드는 리턴 타입을 자동으로 그리고 빠르게 추론할 수 있는 스위치 기능이다.
  • 불투명한 타입은 Swift의 중요한 기능입니다.
  • 불투명한 타입이라는 것을 나타내는 some 키워드는 computed property 혹은 함수의 구체적인 return type을 숨기는 것이 가능합니다.
  • 이를 통해 유연하고 간결하며 강력한 Swift 코드를 작성할 수 있게 합니다.
struct MyFirstView: View { var body: some View { Text("Hello world!") } }
  • some 키워드는 Swift 5.1의 새로운 기능입니다.
  • some 키워드는 computed property인 body안에 불투명한 타입이 있음을 나타냅니다.
  • body property의 구현되는 이 타입은 MyFirstView 를 사용하는 코드에 노출되지 않고 비공개로 유지됩니다.

Opaque Types & Generics

  • 불투명한 타입과 제네릭은 연관이 있습니다. 사실 불투명한 타입은 보통 reverse generic type 이라고 불리기도 합니다.
  • 제네릭 타입의 플레이스 홀더를 사용하면 함수 호출자가 placeholder의 구체적인 형식을 결정합니다.
  • 불투명한 타입을 사용하면 구현에서 구체적인 유형을 결정하게 됩니다.

1. Generic

  • 제네릭을 사용하면 placeholder에 타입 및 제약 조건을 정의할 수 있으므로 함수가 강력한 타입을 유지하면서 다른 타입을 허용할 수 있습니다.
func addition<T: Numeric>(a: T, b: T) -> T { return a + b } let resultA = addition(a: 42, b: 99) let resultB = addition(a: 3.1415, b: 1.618)
  • 위의 코드에서 placeholder T 를 사용하고 있으며, a,b 파라미터 모두 타입이 T 입니다. 또한 함수는 T 타입의 값을 리턴하고 있습니다. 그리고 T 타입은 Numeric 프로토콜을 준수해야 하는 것을 알 수 있습니다.
  • 그 결과 이 함수는 integer, double 값등이 들어갈 수 있습니다.
  • placeholder인 T는 말그대로 자리를 맡아주는 역할입니다. 코드가 컴파일 될 때, Swift는 이것을 Int나 Double같은 정확한 타입으로 대체합니다.
  • 호출자가 T의 기본 유형을 알고 있기 때문에 placeholder가 투명하다고 말할 수 있습니다.
  • 제네릭 타입의 경우에는 함수를 구현하는 내부에서는 타입을 숨기다가 이 함수를 사용할 때 어떤 타입이 들어가는지 알 수 있습니다.

2. Some

  • 이번에는 불투병한 타입이 무엇인지 알아보도록 하겠습니다.
protocol Shape { func describe() -> String } struct Square: Shape { func describe() -> String { return "I'm a square. My four sides have the same lengths." } } struct Circle: Shape { func describe() -> String { return "I'm a circle. I look like a perfectly round apple pie." } }
  • 위의 코드를 봤을 때 Shape라는 protocol 을 정의하였고 이 프로토콜을 준수하고 있는 구조체가 있습니다.
  • 만약에 makeShape() 메서드를 다음과 같이 정의해보겠습니다.
func makeShape() -> some Shape { return Circle() }
  • 이 makeShape()는 Shape 타입을 리턴합니다. 이때 some 키워드를 사용하여 불투명한 타입을 나타내고 있습니다.
  • 반환되는 구체적인 타입을 결정하는 것은 함수에게 달려 있습니다. 여기서는 Circle 타입을 반환하게 됩니다.
let shape = makeShape() print(shape.describe()) // "I'm a circle. I look like a perfectly round apple pie."
  • 위의 코드에서 이것은 makeShape() 메서드를 호출하며 describe() 함수를 이용하여 출력하고 있습니다.
  • some 키워드를 사용하지 않아도 이것은 잘 실행됩니다. 그렇다면 왜 some 키워드를 사용하는 것일까요?
  • 불투명한 타입과 프로토콜 타입은 중요한면에서 다릅니다. 불투명한 타입은 type identitiy를 유지하고 프로토콜은 그렇지 않습니다.
    • 1) 불투명한 타입은 항상 하나의 구체적인 유형을 나타냅니다. 이는 어떤 유형인지 알 수는 없습니다.
      2) 프로토콜 타입은 프로토콜을 준수하는 여러 유형을 참조하는 것이 가능합니다.
  • 제네릭 타입과는 반대로 함수 내부에서는 반환 타입을 정확히 알 수 있지만, 밖에서는 반환값의 타입을 정확히 알지 못하게 숨기는 것입니다.
// 1 func someList() -> Collection { return [1,2,3] } // 2 func someList() -> some Collection { return [1,2,3] }
  • 1번의 코드 같은 경우에는 에러를 발생 시킵니다. "Protocol 'Collection' can only be used as a generic constraint because it has Self or associated type requirements" 라며 리턴하는 값도 관련된 타입을 명시하지 않으면 타입 자체를 알 수 없다는 의미의 에러입니다.
  • 이와 같은 경우 아래와 같이 구현을 하면 에러가 발생하지 않게 됩니다.
    • 이렇게 some 을 사용하면 특정 프로토콜을 만족하는 어떠한 인스턴스가 리턴될 것이다라는 것을 컴파일러에게 알려줍니다.
    • some 의 의미는 일부가 가려진 채로 사용되는 타입이라는 의미를 가지고 있습니다.

Why Opaque types Are Useful in SwiftUI?

var body: some View { VStack(alignment: .leading) { Text("My hovercraft is full of eels") .font(.headline) Text("Mijn luchtkussenboot zit vol paling") .font(.subheadline) } }
  • 위와 같은 코드가 있을 때 some View로 선언된 view의 타입은 사실 VStack<TupleView<(Text, Text)>> 과 같은 형태입니다.
  • 이때 만약 뷰를 다르게 구성하고 더 많은 서브 뷰가 생긴다면 이것의 타입은 점점 더 복잡해 질 것입니다.
  • body의 타입을 구체적으로 입력할 수는 있지만 만약 그렇게 된다면 view의 구성이 변경될 때마다 이 타입을 계속 업데이트 해야 됩니다.
  • some 키워드를 사용하여 View를 선언하고 컴파일 타임에 구체적인 타입을 결정하도록 하는 것이 훨씬 더 쉽습니다.
    • > 우선 개발자의 의도를 불투명하게 유지하는 것이 생산성에 쉽습니다!
  • SwiftUI는 불투명한 리턴 타입이라고 불리는 기능에 크게 의존합니다. 이는 뷰를 view를 작성할 때마다 작동하는 것을 볼 수 있으며 이 내용은 "View" 프로토콜을 준수하는 하나의 특정 타입이지만 이것이 무엇인지는 말하지 않는다는 것을 의미합니다.