some이란?

  • some은 Opaque Type과 관련이 있다.
  • some을 이해하려면, Opaque타입이 뭔지부터 알아야 한다.

Opaque를 알아보기전에

  • Opaque타입은 종종 reverse generic 타입이라고 불린다.
  • 그렇기 때문에 Generic타입에 대해서 먼저 알아야 한다.
  • Generic에 대해서는 다음을 참고하고, 바로 Generic 코드를 보자.
func max<T: Comparable>(_ x: T, _ y: T) -> T {
    return (x > y) ? x : y
}
  • Generic타입은 위처럼 여러 타입을 쓰고자 할 때 사용할 수 있다.
  • Generic타입에 Comparable제약을 두면서, 우리는 T가 뭔지는 모르지만, 비교가 가능하다는 것은 알기 때문에 우리는 함수의 기능을 구현할 수 있다.
  • 이렇게 Generic타입은 함수를 구현하는 내부에는 값을 숨긴다. (우리가 모르기 때문에 숨긴다는 표현을 사용)
  • 반면 함수 외부에서, 즉 우리가 이 함수를 쓸때는 언제나 어떤 타입이 들어가는지 알 수 있다. (반대로 값이 오픈되어 있다.)
let x = 4
let y = 3
let maximum = max(x, y) // 이 시점에서 우리는 이미 maximum이 Int 타입임을 알고 있다.

그래서 Opaque타입이 뭐야?

  • 앞서 Opaque타입은 reverse generic 타입이라고 했다.
  • 무슨 뜻이냐면, Opaque타입은 Generic타입과 반대로 함수 내부에서는 반환값을 정확히 알 수 있지만, 밖에서는 반환값의 유형을 정확히 알지 못하게 숨기는 것이라 할 수 있다.
  • 현실의 예로 조금 더 쉽게 설명하자면, 장난감이 들어있는 킨더 초콜릿을 떠올려보자.
  • 킨더 초콜릿을 외부에서 보면 전부 똑같이 생겼다.
  • 그러나 내부에는 모두 다른 장난감이 들어있고 이는 내부에서만 알 수 있고 외부에서 알 수 없는 것이다.
  • 이게 바로 Opaque Type이라 할 수 있는 것이다.
  • 코드로 알아보자.
func randomReturn() -> some Collection {
    return [1, 2, 3]
}
  • 위와 같은 함수가 있다고 가정하면, 우리는 함수 내부를 구현할 때에는 리턴 값에 대해서 알 수 있다.
  • 반면 외부에서는 어떤 값이 리턴될지 알 수 없다.
  • Generic타입으로 구현한 함수와 정확히 반대다.
  • 그래서 Opaque타입이 reverse generic 타입이라고 불린다.
  • 그래, 잘 알겠는데 그래서 SwiftUI에는 왜 some이 붙는건데?

SwiftUI 에서의 some

  • 우선 some은 필수 사항이 아니다.
struct ContentView: View {
    var body: Text {
        Text("Text")
    }
}
  • 위처럼 some View 대신 Text라는 Concrete타입을 지정하면 더이상 some 키워드는 사용하지 않아도 된다.
  • 하지만 이런 경우 복잡한 화면을 구성하게 되면 점차 더러워지는 코드를 볼 수 있다.
var body: VStack<TupleView<(Text, Image)>> { ... }
...
var body: VStack<TupleView<(Text, Text, Image)>> { ... }
...
var body: List<Never, TupleView<(HStack<TupleView<(VStack<TupleView<(Text, Text)>>, Text)>>, HStack<TupleView<(VStack<TupleView<(Text, Text)>>, Text)>>)>> { ... }
  • 🤯
  • 이건 정말 말도 안되는 코드라는 것은 설명할 필요도 없다.
  • 이 더럽고 더러운 코드를 some한방에 해결할 수 있는 것이다.
var body: some View { ... }
  • 이게 바로 SwiftUI에서 some키워드를 사용하는 이유이며, 우리도 some 키워드를 사용해야 하는 이유이다.

참고