Why This Work Exists
값 타입은 스택, 참조 타입은 힙이라고만 외우면 실무에서 자꾸 틀린다. 진짜 중요한 차이는 “복사처럼 행동하느냐”, “같은 객체를 공유하느냐”다.
Swift의 값 타입과 참조 타입 차이를 저장 위치보다 동작 방식 중심으로 정리한 문서다. 핵심은 `복사 semantics`, `identity`, `shared mutable state`, `동시성 안전성` 차이를 같이 보는 것이다.
2026-04-09
값 타입은 스택, 참조 타입은 힙이라고만 외우면 실무에서 자꾸 틀린다. 진짜 중요한 차이는 “복사처럼 행동하느냐”, “같은 객체를 공유하느냐”다.
흔한 오해는 `struct = 무조건 스택`, `class = 무조건 힙`, `값 타입은 복사 비용이 크다`, `참조 타입은 빠르다`처럼 단순화하는 것이다.
더 정확한 이해는 이렇다. 값 타입은 복사된 값처럼 동작하고, 참조 타입은 같은 객체를 공유한다. 실무적으로는 저장 위치보다 복사 semantics, identity, 공유 상태, ARC, 동시성 안전성이 더 중요하다.
값 타입과 참조 타입의 가장 중요한 차이는 스택/힙보다 `복사처럼 행동하느냐`, `같은 객체를 공유하느냐`다.
var a = [1, 2, 3] var b = a b.append(4)
위 코드는 value semantics를 보여 준다. `b`를 바꿔도 `a`는 그대로다. 다만 `Array`는 성능 최적화를 위해 처음부터 전체 메모리를 복사하지 않고, 실제 수정 시점에 복사하는 copy-on-write를 사용한다.
즉 겉보기 동작은 “복사된 값”인데, 내부 구현은 “수정 전까지 저장소를 잠깐 공유”할 수 있다. 그래서 값 타입처럼 행동하지만 내부 구현은 더 복잡할 수 있다.
final class Box {
var value: Int
init(value: Int) { self.value = value }
}
let a = Box(value: 1)
let b = a
b.value = 2여기서는 `a`와 `b`가 같은 객체를 본다. 이때 중요한 것은 값이 아니라 “같은 인스턴스인가”라는 identity다.
같은 객체를 여러 곳이 공유하고, 그 객체의 내부 상태를 바꿀 수 있으면 shared mutable state가 생긴다. 이건 참조 타입이 자연스럽게 만들기 쉬운 구조다.
이런 구조는 캐시, 세션, 매니저 객체처럼 하나의 실체를 여러 곳이 함께 바라봐야 할 때 유리하다. 대신 동시에 접근하면 data race와 동기화 문제가 생길 수 있다.
값 타입은 각자가 복사본을 들고 다루기 쉬워 동시성에서 유리하다. 반면 참조 타입은 같은 객체를 공유하므로 actor, lock, serial queue 같은 보호 장치가 더 자주 필요하다.
그래서 Swift Concurrency 문맥에서 value semantics가 자주 강조되고, shared mutable state가 남는 경우 actor가 등장한다.