Opaque Type: Swift에서 some과 any이란

저자: IT Sectr 게시일: 2026-06-18 읽는 시간: 11 분

Opaque Type은 함수가 호출하는 코드에 구체적인 타입을 드러내지 않고 어떤 타입의 값을 반환할 수 있도록 하는 Swift의 메커니즘입니다. 반환 타입에서 some 키워드가 가장 유명한 예입니다: SwiftUI에서 some View는 “함수가 View를 따르는 어떤 타입을 반환하지만, 그것이 뭐인지는 구현 세부 사항이다”라는 뜻입니다. Opaque type은 타입의 정체성을 보존합니다(타입으로서의 프로토콜과 달리). 이를 통해 컴파일러가 코드를 최적화하고 반환된 타입의 일관성을 보장할 수 있습니다. Swift Book, 2025에 따르면, opaque types는 연관 타입을 가진 프로토콜의 문제를 해결하여, 함수에서 해당 프로토콜의 값을 반환할 수 있도록 합니다.

중요 포인트

  • Opaque Type — 호출하는 코드로부터 구체적인 구현을 숨기는 반환 타입
  • some — 반환 위치에서 opaque type을 선언하는 키워드
  • 타입 정체성이 보존됨: 컴파일러가 구체적인 타입을 알고 있으며, any와 달리
  • SwiftUI는 body를 선언하는 표준 방식으로 some View를 사용함
  • 제한: some을 사용하는 함수는 모든 브랜치에서 동일한 구체적인 타입을 반환해야 함

Swift에서 Opaque Type이란?

Opaque Typesome 키워드로 선언되는 반환 타입으로, 호출하는 코드로부터 구체적인 구현을 숨합니다. 호출자는 반환된 값이 특정 프로토콜을 따른다는 것만 알고, some 뒤에 어떤 타입이 있는지는 알 수 없습니다. 한편, 컴파일러는 정확한 타입을 알고 있으며, 정적 디스패치와 최적화에 사용합니다.

Opaque Type가 해결하는 문제

Swift 5.1 (SE-0244)에서 opaque types가 도입되기 전에는, 박싱 래퍼 없이 함수에서 연관 타입을 가진 프로토콜을 반환하는 것이 불가능했습니다. 예를 들어, Equatable 프로토콜에는 연관 타입이 있으며, 함수가 단순히 Equatable을 반환할 수 없었습니다 — 컴파일러가 “프로토콜은 제너릭 제약으로만 사용할 수 있습니다”는 오류를 내벃습니다. Opaque type이 이 문제를 해결했습니다.

swift
func makeInt() -> some Equatable {
    return 42
}

func makeString() -> some Equatable {
    return "Hello"
}

// 컴파일러는 makeInt가 Int를 반환함을 알고 있다
// makeInt() == makeString() — ❌ 오류, 다른 타입

두 함수 모두 some Equatable을 반환하지만, 구체적인 타입은 다릅니다: Int와 String입니다. 이것들을 ==로 비교하려면 컴파일 오류가 발생합니다. 이는 opaque type이 특정 호출이 동일한 타입을 반환함을 보장하지만, 서로 다른 함수 간에는 보장하지 않기 때문입니다. 이것은 기능이지 버그가 아닙니다: opaque type은 타입으로서의 프로토콜(any Equatable)이 잃는 타입의 정체성을 보존합니다.

Opaque Type vs Generic: 차이점

GenericOpaque Type은 동전의 양면입니다. 제네릭은 호출하는 코드가 타입을 선택할 수 있게 하며, opaque type은 함수가 호출하는 코드로부터 타입을 숨할 수 있게 합니다. 차이점은 제어의 방향에 있습니다.

특성Generic Opaque some
누가 타입을 선택하나호출하는 코드함수/메소드
타입 정체성보존됨(안정)보존됨(안정)
반환 브랜치 수한 가지(제네릭 통해)모든 브랜치에서 동일한 타입
사용추알고리즘, 데이터 구조SwiftUI, 팩토리 메소드

Generic — 외부에서의 선택

제네릭 함수에서는 코리가 사용할 타입을 결정합니다. 함수는 제약을 만족시키는 모든 T에서 동작해야 합니다. Opaque type에서는 코리가 구체적인 타입을 알 수 없으며, 구현이 결정을 낵니다.

swift
// Generic: 코리가 타입을 선택함
func identity<T>(_ value: T) -> T { value }
let x: Int = identity(42)

// Opaque: 함수가 타입을 숨김
func makeSomeEquatable() -> some Equatable { 42 }
let y = makeSomeEquatable()

제네리그와 opaque type 사이의 선택은 의도에 따라 다릅니다. 호출하는 코드가 타입을 선택해야 한다면 제네릭을 사용하세요. 함수가 구현 세부 사항을 숨겨야 한다면 some을 사용하세요. SwiftUI는 body가 내부적으로는 유연하지만 외부적으로는 안정적이어야 하기 때문에 some View를 선택했습니다.

some 키워드와 그 사용법

some은 Swift 5.1 (SE-0244)에서 도입된 Swift 키워드입니다. 반환 위치에서 opaque type을 선언하는 데 사용되며, 파라미터(SE-0341)와 특성에서도 사용됩니다. some은 구체적인 타입이 안정적이고 컴파일러에게 알려져 있지만 외부 코드에서는 숨겠다는 것을 보장합니다.

함수 파라미터에서 some

Swift 5.7부터, some은 반환 위치뿐만 아니라 파라미터에서도 사용할 수 있습니다. 파라미터에서 some Equatable은 “이 함수는 모든 Equatable 타입을 수락하지만, 특정 보디 내의 모든 호출은 동일한 타입을 본다”는 뜻입니다.

swift
func areEqual(_ a: some Equatable, _ b: some Equatable) -> Bool {
    // a와 b — 잠재적으로 다른 타입, ==가 직접 동작하지 않음
    return isEqual(a, b)
}

func isEqual<T: Equatable>(_ a: T, _ b: T) -> Bool {
    return a == b
}

파라미터에서 some을 사용하면 와 비교하여 더 간결한 문법을 제공합니다. 이것은 특힐 프로토콜과 프로토콜 지향 설계에서 유용하며, 프로토콜을 사용할 때마다 별도의 제네릭 파라미터가 필요 없습니다. 컴파일러는 some 파라미터를 내부적으로 제네릭으로 변환하므로 성능은 동일합니다.

any 키워드와 실존적 타입

any는 Swift 5.6+의 키워드로, 실존적 타입(타입으로서의 프로토콜)을 명시적으로 선언하는 데 사용됩니다. some과 달리, any는 타입의 정체성을 지우며, 컴파일러는 프로토콜 뒤에 어떤 구체적인 타입이 있는지 알 수 없습니다. 이것은 유연성(동일한 배열에 서로 다른 타입을 저장할 수 있음)을 제공하지만, 성능의 희생이 있습니다.

some vs any: 비교 분석

some — 정적 다형성: 컴파일러가 구체적인 타입을 알고, 직접 디스패치를 사용하며, 코드를 인라인할 수 있습니다. any — 동적 다형성: 가상 메소드 테이블(실존적 컨테이너)이 사용되며, 간접성이 추가됩니다.

swift
protocol Drawable {
    func draw()
}

// some: 정적 타입이 알려져 있음
func makeDrawable() -> some Drawable {
    return Circle() // 단일 반환 타입
}

// any: 동적, 다른 타입을 저장할 수 있음
var shapes: [any Drawable] = [Circle(), Square()]
shapes.append(Triangle())

some과 any 사이의 선택은 성능과 유연성 간의 타협입니다. Some이 더 빠르지만 단일 구현로 제한됩니다. Any가 더 유연하지만(타입을 혼합할 수 있음) 동적 디스패치로 인해 더 늦습니다. SwiftUI에서 body는 항상 some View를 사용합니다. 그 이유는 각 View의 body가 하나의 구체적인 타입이기 때문입니다.

연관 타입을 가진 프로토콜에서 Opaque Type

Opaque Type은 Swift의 근본적인 문제를 해결합니다: 연관 타입을 가진 프로토콜(PAT)은 타입으로 직접 사용할 수 없습니다. 함수는 단순히 Collection을 반환할 수 없으며, 컴파일러가 Element를 지정하도록 요구합니다. some Collection은 연관 타입을 숨겨서 이 문제를 해결합니다.

PAT를 some을 통해 반환하기

Opaque type 없이 Collection을 반환하려면 구체적인 타입(Array)또는 타입 이레이저(AnyCollection)를 사용해야 했습니다. some Collection은 중간 지위를 제공합니다: 컴파일러는 구체적인 구현을 알고, 호출하는 코드는 알 수 없습니다.

swift
func makeReversedCollection<T>(
    of array: [T]
) -> some Collection {
    return array.reversed()
}

let result = makeReversedCollection(of: [1, 2, 3])
// result — ReversedCollection>, hidden from caller
for item in result {
    print(item)
}

result는 반복할 수 있지만, ReversedCollection의 특성에 직접 액세스할 수 없습니다. 이것은 캡슐화를 보호합니다: 나중에 reversed()를 다른 구현의 다른 메소드로 대체하더라도 호출하는 코드가 깨지지 않습니다. Opaque type은 API를 바꾸지 않고 구현을 변경할 수 있는 자유를 제공합니다.

SwiftUI에서 some View 실전 예제

some View는 opaque type의 가장 유명한 사용입니다. SwiftUI에서 각 View는 body를 some View로 선언합니다. 이는 body가 어떤 구체적인 View 타입을 반환한다는 의미이지만, 개발자는 그것이 토플View, Group, ModifiedContent 또는 프레임워크의 다른 타입인지 고민할 필요가 없습니다.

SwiftUI가 some View를 사용하는 방법

Opaque type 없이는 body가 구체적인 타입을 반환해야 했으며, 예를 들어 ModifiedContent<Button<Text>, Padding>이라는 것은 비실용적입니다. some View는 이 복잡성을 숨합니다. 컴파일러는 컴파일 시점에 body의 정확한 타입을 자동으로 추론합니다.

swift
struct ContentView: View {
    var body: some View {
        VStack {
            Text("안녕하세요")
                .font(.title)
            Button("탚하세요") {
                print("탚되었습니다")
            }
        }
        .padding()
    }
}

컴파일러는 body를 ModifiedContent<VStack<TupleView<(Text, Button<Text>)>>, Padding>으로 추론합니다. 개발자는 some View를 봅니다. 레이아웃을 VStack에서 HStack으로 변경하면, 컴파일러가 자동으로 타입을 재추론합니다 — 수동 편집이 필요 없습니다. 이것이 opaque type의 매력입니다: 개발자는 인터페이스 로직에 집중하고, 구성 타입에 집중하지 않습니다.

자주 묻는 질문

Swift에서 Opaque Type이란?

Opaque Type은 some 키워드로 선언되는 타입으로, 호출하는 코드로부터 구체적인 구현을 숨합니다. 컴파일러는 정확한 타입을 알고 있지만, 함수를 사용하는 개발자는 프로토콜만 봉니다.

Swift에서 some과 any는 어떻게 다른가요?

some은 정적 정체성을 가진 opaque type입니다: 컴파일러가 구체적인 타입을 앍니다. any는 동적 디스패치를 가진 실존적 타입으로, 타입 정체성이 지워집니다. Some이 더 효율적이고, any가 더 유연합니다.

왜 SwiftUI는 some View를 사용하나요?

some View는 컴파일러가 자동으로 추론하는 body의 복잡한 구체적인 타입을 숨합니다. 이는 개발자가 제네릭 래퍼(VStack, Group, ModifiedContent)로 구성된 정확한 타입을 작성하는 것에서 해방시킵니다.

함수 파라미터에서 some을 사용할 수 있나요?

, Swift 5.7부터 가능합니다. 파라미터에서 some은 제네릭 파라미터의 문법적 서괜입니다. 함수 선언을 간단하게 하며, 특힐 각 some-파라미터가 별도의 를 필요로 하지 않는 프로토콜을 다룰 때 유용합니다.

some 함수에서 다른 타입을 반환하면 어떻게 됩나요?

컴파일러가 오류를 내밽니다: opaque type은 모든 반환 브랜치가 동일한 구체적인 타입을 반환할 것을 요구합니다. 이것은 타입 정체성을 보존하기 위한 의도적인 설계입니다. 다른 타입을 반환해야 한다면 any를 사용하세요.

요약

  • Opaque Type — 컴파일러 레벨에서 정체성을 보존하면서 반환값의 구체적인 타입을 숨김
  • some 키워드는 반환 위치와 파라미터에서 opaque type을 선언하는 데 사용됨
  • Generic vs Opaque: 코리가 제네릭의 타입을 선택하고, 구현이 opaque의 타입을 선택함
  • any — 동적 디스패치를 가진 실존적 타입, some — 정적 다형성
  • SwiftUI some View — 주요 사용 사례: 개발자로부터 body의 복잡한 타입을 숨김
  • Opaque type은 함수에서 연관 타입을 가진 프로토콜(PAT)을 반환하는 문제를 해결함

턴키 방식의 모바일 애플리케이션을 개발해 드립니다

IT Sectr는 2017년부터 스타트업과 기업을 위한 iOS 및 Android 애플리케이션을 만듭니다. 저희가 상담해 드리고 최적의 솔루션을 제안하겠습니다.

프로젝트 논의

더 읽어보기