본문 바로가기

Programming/Swift

Swift struct 배열에서 내부 값 수정하기

반응형

우리가 모르고 쓰는 writeback 최적화

Swift에서 struct는 값 타입이라, 배열에 담긴 struct를 수정하려면 "복사 → 수정 → 재할당"이 기본입니다.
하지만 가끔 이렇게 코드를 짰는데도… 잘 됩니다?

users[index].profile.updateNickname("newName")

분명 struct인데도 내부 값을 이렇게 바꿨는데 잘 된다?
어떻게 가능한 걸까요?

struct User {
    var id: Int
    var profile: Profile
}

struct Profile {
    var nickname: String

    mutating func updateNickname(_ newNickname: String) {
        nickname = newNickname
    }
}

그리고 배열

var users: [User] = [
    User(id: 1, profile: Profile(nickname: "Alice")),
    User(id: 2, profile: Profile(nickname: "Bob"))
]

이 상황에서 아래 코드가 에러 없이 실행됩니다.

users[1].profile.updateNickname("Bobby")

User도 Profile도 struct, 즉 값 타입인데도 컴파일 에러 없이 잘 작동합니다.

writeback 최적화란?

Swift 컴파일러는 이런 상황을 위해 "writeback 최적화" 라는 걸 제공합니다.
위 코드는 내부적으로 아래처럼 처리됩니다:

var temp = users[1]               // 복사
temp.profile.updateNickname("Bobby")
users[1] = temp                   // 수정한 값을 다시 할당

즉, 우리가 재할당하지 않았지만 Swift 컴파일러가 자동으로 해준 것입니다.

하지만 주의할 점

이 최적화는 항상 작동하지 않습니다.
예를 들어 아래와 같은 경우는 동작하지 않을 수 있습니다:

getUsers()[1].profile.updateNickname("Bobby") // 함수에서 리턴된 배열 → writeback 불가

는 다음처럼 배열 대신 딕셔너리 등을 사용하는 경우도 예외입니다.
게다가 Swift의 향후 버전에서 내부 최적화 전략이 바뀔 가능성도 있습니다.
그래서 아래처럼 명시적으로 처리하는 방식을 권장합니다.

var user = users[1]
user.profile.updateNickname("Bobby")
users[1] = user

마무리

writeback 최적화는 Swift가 제공하는 똑똑한 기능이지만,
우리가 직접 컨트롤할 수 없는 부분에 의존하는 코드는 언제든 위험 요소가 될 수 있습니다.

반응형