스위프트에서 구조체(struct)는 기본적으로 값 타입(value type)입니다: 구조체 인스턴스를 복사할 때 독립적인 복사본이 생성됩니다. 그러나 클래스와 달리, 구조체의 메서드는 컴파일러의 직접적인 허가 없이 self와 그 속성을 변경할 수 없습니다. 초기 C 및 C++ 버전에서 구조체는 항상 변경 가능했으며, 이로 인해 예기치 않은 부작용이 발생했습니다. 스위프트는 상태를 변경하는 메서드를 명시적으로 mutating 키워드로 표시하도록 요구하여 안전성을 높였습니다.
문제가 발생하는 것은, 구조체의 속성을 변경하기 위한 메서드가 일반적인 것으로 선언되었을 경우, 컴파일러가 이를 허락하지 않게 됩니다. mutating 없이는 self 또는 그 속성을 변경할 수 없습니다.
해결 방법은 이러한 메서드를 mutating 키워드를 사용하여 선언하는 것으로, 이는 컴파일러에게 self와 내장 속성의 변경을 허락하도록 신호를 보냅니다.
코드 예:
struct Counter { var value = 0 mutating func increment() { value += 1 } // 이 메서드는 mutating을 제거하면 컴파일되지 않습니다. } var counter = Counter() counter.increment() // value는 이제 1이 되었습니다.
주요 특징:
1. let으로 선언된 구조체에서 mutating 메서드를 호출할 수 있나요?
아니요, 불가능합니다. const let 값의 구조체는 mutating 메서드가 있더라도 변경될 수 없습니다.
let counter = Counter() counter.increment() // 컴파일 오류
2. 구조체 내 클래스의 내장 속성은 mutating 메서드 내에서 변경될 수 있나요?
네, 구조체 속성이 레퍼런스 타입(예: 클래스)이라면 그 내부 속성은 mutating 없이도 변경할 수 있지만, 구조체 전체는 mutating을 통해서만 변경할 수 있습니다.
class State { var value = 0 } struct Wrapper { var state = State() mutating func change() { state.value += 1 } }
3. mutating 없이 메서드 내에서 computed property만 변경할 수 있나요?
아니요. computed property에 set이 있으면 메서드 내에서 그 값을 변경하는 것은 여전히 mutating이 필요합니다.
프로젝트에 간단한 카운터가 구현되었지만, 개발자가 메서드를 mutating으로 표시하는 것을 잊었습니다. 값이 변하지 않아 테스트가 실패합니다.
장점:
단점:
구조체의 메서드가 mutating으로 표시되어 테스트가 통과하고 변경 사항이 올바르게 업데이트됩니다. 코드가 팀의 모든 구성원이 이해할 수 있습니다.
장점:
단점: