[Swift] @ObservableObjectvs @Observable 는 무슨 차이가 있을까?

·2026년 3월 9일

SwiftUI포스팅

목록 보기
3/3

SwiftUI로 개발하면서 MVVM 패턴을 자주 사용하게 된다.
그런데 협업을 하다 보면 ViewModel을 구현하는 방식이 사람마다 조금씩 다르다는 것을 느끼게 된다.


그중에서도 가장 자주 갈리는 지점은
ObservableObject를 채택하는 방식과 @Observable을 사용하는 방식이다.

프로토콜 VS 매크로 세기의 대결!이라하기엔 둘다 어처피 상태변화를 UI에 어떻게 반영할꺼냐에 대한 전략의 차이일 것 같은데, 이번글에서는 둘 중 어떤것을 선택하는게 좋을지 정리를 해보려한다.


ObservableObject란

Observable이란?


사실 애플에서도 @Observable매크로로 마이그레이션하는 방법을 가이드로서 제공을 하고 있긴하다.
Migrating-from-the-observable-object-protocol-to-the-observable-macro

왜 @Observable이 등장한거지?

기존 ObservableObject는 Combine 기반으로 설계되었기 때문에
SwiftUI의 실제 렌더링 방식과 완전히 일치하지 않는 부분이 있었다.

특히 객체 단위로 변경을 감지하기 때문에, 뷰에서 사용하지 않는 프로퍼티가 변경되어도 body가 다시 계산되는 경우가 있었다.

@Observable은 이러한 문제를 해결하기 위해 등장했으며,
SwiftUI가 실제로 어떤 프로퍼티를 읽었는지 추적하는 방식으로 동작한다.

가이드에서 말하고자 하는 내용을 간단하게 정리하면..!

1. 불필요한 리렌더링 방지

기존: ObservableObject 내부의 @Published 변수가 하나만 바뀌어도, 그 객체를 가진 모든 뷰가 다시 그려집니다. (비효율적)
@Observable: SwiftUI가 body에서 어떤 프로퍼티를 읽었는지 추적합니다. 읽지 않은 데이터가 변하면 뷰는 업데이트되지 않습니다.

2.의존성 단순화

@Published를 일일이 붙일 필요가 없습니다. 기본적으로 모든 프로퍼티가 추적 대상이 되며, 추적을 원치 않으면 @ObservationIgnored를 사용합니다.
이제 Optional이나 Collection 타입도 제약 없이 추적할 수 있습니다.

이거 두개 정도가 이제 여기서 발췌한 Observable매크로의 장점이다. 코드가 단순해지면서, 퍼포먼스까지 챙길 수 있다니..! 너무 좋은걸? (1석 2조)


간단한 개념차이

항목ObservableObject@Observable
기반CombineObservation framework
변경 감지@Publishedproperty access tracking
업데이트 범위객체 단위프로퍼티 단위
도입 시기SwiftUI 초기iOS 17+

예시코드 비교

1. ObservableObject

import SwiftUI
import Combine

final class CounterModel: ObservableObject {
    @Published var count = 0
}
struct CounterView: View {
    @StateObject private var model = CounterModel()

    var body: some View {
        VStack {
            Text("\(model.count)")
            Button("Increase") {
                model.count += 1
            }
        }
    }
}

2. @Observable

import SwiftUI
import Observation

@Observable
final class CounterModel {
    var count = 0
}
struct CounterView: View {
    @State private var model = CounterModel()

    var body: some View {
        VStack {
            Text("\(model.count)")
            Button("Increase") {
                model.count += 1
            }
        }
    }
}

아직 간단한 코드라서 크게 차이가 없어보일 수 있긴한데, 코드가 길어지고 복잡해질수록 차이가 도드라질 것이다.

ObservableObject는 Combine 기반이라 조금 투박하게 친구라고 보면된다. 객체 내부의 @Published 변수가 하나만 바뀌어도 객체 전체가 값 바뀜!! 이라고 인지하면,
이제 swiftUI는 해당 객체에 의존하는 뷰의 body를 다시 계산하게 된다. 그러면 당연히 ViewModel에 선언된 변수가 많아질수록 뷰가 감당해야 할 리렌더링 부하가 커질 수 있다는 단점이 있는 것이다.

반면에 @Observable 매크로는 더 똑뿌러져서, 뷰가 그려지는 시점에 어떤 변수를 실제로 가져다 쓰는지 Swift에서 추적을하고 있어서, 이게 변수하나가 변경되면 다 갈아엎었던 ObservableObject랑 다르게 내가 화면에 그리지 않은 값이 바뀔때는 안쓰는놈이구나! 인지하고 리렌더링을 수행하지 않는다는 차이점이 있는 것이다. 훨씬 리렌더링에 드는 비용을 절약할 수 있습니다.

그래서 뭘 선택하는 것이 좋지??

@Observable 매크로

  • 코드가 훨씬 간결하다
  • SwiftUI의 업데이트 메커니즘과 더 잘 맞는다
  • Apple에서도 ObservableObject에서 @Observable로의 마이그레이션 가이드를 제공하고 있다

다만 기존 코드베이스에서는 여전히 ObservableObject가 이미 잘 사용되고 있고,
Combine 기반 로직이 이미 구성되어 있다면 굳이 무리해서 변경할 필요는 없다.

정리하면!!!

  • iOS17+ ->@Observable
  • iOS17이전 → ObservableObject 사용!

그리고 기존 프로젝트가 ObservableObject라면, 안에 해당하는 변수관리가 잘되고 있다면 사실 필사적으로 마이그레이션해야할 그 정도의 메리트를 가져다 주지는않는 것을 알 수 있다.
코드의 간결함으로 개발자경험(DX)을 가져갈 수 있다는 장점을 얼마나 높게 평가하느냐의 차이일 것 같다!

profile
기억보단 기록을

0개의 댓글