0Pricing
Swift Academy · 강의

쓰기 가능 및 참조 KeyPaths

키 경로를 통해 값을 읽고 씁니다.

쓰기 가능 및 참조 KeyPaths은(는) CoddyKit의 무료 Swift Academy 강의입니다. 이것은 4개 중 3번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 Swift Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. Swift Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

읽기 전용 키 경로와 쓰기 가능한 키 경로

일반적인 KeyPath는 값을 읽기만 할 수 있습니다. 키 경로를 통해 값을 쓰려면 쓰기 가능한 변형이 필요합니다. Swift에는 값 형식용과 참조 형식용, 이렇게 두 가지가 있습니다.

이 레슨에서는 구조체를 위한 WritableKeyPath와 클래스를 위한 ReferenceWritableKeyPath, 그리고 [keyPath:] 서브스크립트를 설정 가능한 형태로 사용하는 방법을 다룹니다.

struct Person {
    var name: String
    var age: Int
}

let writable: WritableKeyPath<Person, Int> = \Person.age
print(type(of: writable))

값 형식을 위한 WritableKeyPath

WritableKeyPath는 값 형식의 변경 가능한 저장 속성을 가리킵니다. 이를 통해 값을 설정하려면 인스턴스 자체가 var여야 합니다. 구조체의 속성을 변경하면 전체 값이 변경되기 때문입니다.

할당문의 왼쪽에 [keyPath:] 서브스크립트를 사용하여 값을 쓰십시오.

struct Person {
    var name: String
    var age: Int
}

var alice = Person(name: "Alice", age: 30)
let agePath = \Person.age
alice[keyPath: agePath] = 31
print(alice.age)

인스턴스가 var여야 하는 이유

값 형식에서는 키 경로를 통한 쓰기가 복사본을 그 자리에서 변경합니다. 인스턴스가 let이면 변경할 대상이 없으므로 할당문을 컴파일할 수 없습니다.

이 규칙은 일반적인 속성 변경과 같습니다. 구조체가 변수에 저장되어 있을 때만 구조체의 저장 속성을 설정할 수 있습니다.

struct Point {
    var x: Int
    var y: Int
}

var p = Point(x: 1, y: 2)
p[keyPath: \Point.x] = 10
p[keyPath: \Point.y] = 20
print(p)

제네릭 설정 도우미

쓰기 가능한 키 경로에는 변경할 속성이 담겨 있으므로, 모든 값 형식의 모든 속성을 갱신하는 제네릭 함수를 작성할 수 있습니다. 변경 사항이 다시 기록되도록 인스턴스를 inout으로 전달하십시오.

이는 작은 함수형 업데이트 유틸리티의 기반이 됩니다.

func update<Root, Value>(_ root: inout Root, _ path: WritableKeyPath<Root, Value>, to value: Value) {
    root[keyPath: path] = value
}

struct Person { var name: String; var age: Int }
var bob = Person(name: "Bob", age: 40)
update(&bob, \.age, to: 41)
print(bob.age)

클래스를 위한 ReferenceWritableKeyPath

클래스에는 Swift가 ReferenceWritableKeyPath를 제공합니다. 클래스 인스턴스는 참조이므로 인스턴스가 let 상수에 저장되어 있어도 이를 통해 값을 쓸 수 있습니다. 변경되는 것은 참조가 아니라 참조가 가리키는 객체뿐입니다.

이것이 값 형식의 쓰기 가능한 키 경로와 다른 핵심적인 점입니다.

class Counter {
    var value: Int = 0
}

let counter = Counter()
let path: ReferenceWritableKeyPath<Counter, Int> = \Counter.value
counter[keyPath: path] = 5
print(counter.value)

불변 참조, 변경 가능한 객체

아래의 클래스 인스턴스는 let인데도 키 경로를 통해 속성을 설정할 수 있다는 점에 주목하십시오. 구조체에서는 컴파일 오류가 발생합니다.

클래스 속성을 변경할 때는 참조 자체가 변경 가능할 필요 없이 속성만 변경 가능하면 되기 때문입니다.

class Profile {
    var nickname: String = ""
}

let profile = Profile()
let nickPath = \Profile.nickname
profile[keyPath: nickPath] = "Ace"
print(profile.nickname)

키 경로의 형식 계층 구조

쓰기 가능한 키 경로 형식은 계층 구조를 이룹니다. ReferenceWritableKeyPath는 WritableKeyPath의 하위 형식이고, WritableKeyPath는 KeyPath의 하위 형식입니다. 따라서 더 구체적인 키 경로를 더 일반적인 키 경로가 필요한 곳에서 사용할 수 있습니다.

즉, 읽기만 필요한 함수에 ReferenceWritableKeyPath를 전달하고 해당 함수가 KeyPath를 통해 읽도록 할 수 있습니다.

class Box { var size: Int = 1 }

func readSize(_ box: Box, _ path: KeyPath<Box, Int>) -> Int {
    box[keyPath: path]
}

let writable: ReferenceWritableKeyPath<Box, Int> = \Box.size
print(readSize(Box(), writable))

중첩된 값 형식 갱신하기

쓰기 가능한 키 경로는 중첩된 구조체를 따라 연결할 수 있습니다. 깊이 중첩된 속성을 설정하면 하나의 할당문으로 체인을 따라 이를 감싸는 각 값이 다시 기록됩니다.

여기서는 중첩된 주소 안의 city를 변경합니다.

struct Address { var city: String }
struct Person { var name: String; var address: Address }

var carol = Person(name: "Carol", address: Address(city: "Oslo"))
carol[keyPath: \Person.address.city] = "Bergen"
print(carol.address.city)

여러 변경 사항 적용하기

쓰기 가능한 키 경로는 값이므로 변경 사항을 키 경로와 값의 쌍 목록으로 저장한 다음 반복문에서 적용할 수 있습니다. 작은 패치 시스템인 셈입니다.

여기서는 settings 구조체에 두 가지 변경 사항을 적용합니다.

struct Settings { var volume: Int; var brightness: Int }

var settings = Settings(volume: 5, brightness: 5)
func apply(_ s: inout Settings, _ path: WritableKeyPath<Settings, Int>, _ v: Int) {
    s[keyPath: path] = v
}
apply(&settings, \.volume, 8)
apply(&settings, \.brightness, 3)
print(settings)

바인딩 스타일 구성

실제 개발에서 흔히 사용하는 방법은 새로 만든 객체의 속성을 설정하고 해당 객체를 반환하는 configure 도우미를 작성하여 연쇄형 스타일을 구현하는 것입니다. 클래스에서는 이 방식이 let 결과에도 적용됩니다.

여기서는 참조 쓰기 가능 키 경로를 통해 label의 텍스트를 설정합니다.

class Label { var text: String = "" }

func configure<T: AnyObject, V>(_ object: T, _ path: ReferenceWritableKeyPath<T, V>, _ value: V) -> T {
    object[keyPath: path] = value
    return object
}

let label = configure(Label(), \.text, "Hello")
print(label.text)

알맞은 키 경로 형식 선택하기

읽기만 할 때는 KeyPath를 사용하고, var에 저장된 값 형식의 속성을 설정할 때는 WritableKeyPath를 사용하며, let을 통해서도 클래스의 속성을 설정할 때는 ReferenceWritableKeyPath를 사용하십시오.

조건에 맞는 가장 구체적인 형식을 선택하면 인터페이스가 값을 읽기만 하는지 변경하는지를 정확하게 표현할 수 있습니다.

struct S { var n: Int }
class C { var n: Int = 0 }

let read: KeyPath<S, Int> = \S.n
let writeStruct: WritableKeyPath<S, Int> = \S.n
let writeClass: ReferenceWritableKeyPath<C, Int> = \C.n
print(type(of: read), type(of: writeStruct), type(of: writeClass))

빠른 확인: 쓰기 가능한 키 경로

인스턴스가 불변 상수인 경우에도 클래스 속성을 설정할 수 있게 해 주는 키 경로 형식을 떠올려 보십시오.

복습: 쓰기 가능한 키 경로와 참조 키 경로

키 경로를 통해 값을 쓰는 방법을 배웠습니다.

  • WritableKeyPath는 값 형식의 저장 속성을 설정하며, var 인스턴스가 필요합니다.
  • ReferenceWritableKeyPath는 클래스의 속성을 설정하며 let을 통해서도 작동합니다.
  • [keyPath:] 서브스크립트는 값을 쓰기 위한 할당문의 왼쪽에 나타납니다.
  • 이 형식들은 계층 구조를 이루므로 쓰기 가능한 키 경로를 읽기 전용 키 경로 대신 사용할 수 있습니다.
  • 제네릭 inout 설정자와 configure 도우미는 이를 기반으로 만들어집니다.

다음에는 키 경로를 사용하여 동적 데이터에 점 표기법으로 접근할 수 있게 해 주는 @dynamicMemberLookup을 살펴봅니다.

struct Person { var name: String; var age: Int }

var dave = Person(name: "Dave", age: 27)
dave[keyPath: \Person.age] = 28
print("Updated age: \(dave.age)")

자주 묻는 질문

“쓰기 가능 및 참조 KeyPaths” 강의는 무료인가요?

네 — “쓰기 가능 및 참조 KeyPaths” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 Swift Academy 강의 전체를 잠금 해제할 수 있습니다. Swift Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

“쓰기 가능 및 참조 KeyPaths”에서 뭘 배우나요?

키 경로를 통해 값을 읽고 씁니다. 브라우저에서 직접 실행하는 실습 코드로 Swift Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.

Swift Academy을(를) 시작하는 데 경험이 필요한가요?

사전 경험은 필요하지 않습니다. CoddyKit의 Swift Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 3번째 강의입니다.

“쓰기 가능 및 참조 KeyPaths” 강의는 얼마나 걸리나요?

대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.

이 Swift Academy 강의에서 코드를 작성하고 실행할 수 있나요?

네. 모든 Swift Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.

이 강의의 모든 강의

  1. KeyPath 기초
  2. 컬렉션에서 KeyPaths 사용하기
  3. 쓰기 가능 및 참조 KeyPaths
  4. @dynamicMemberLookup
← Swift Academy(으)로 돌아가기