[SwiftUI] Demystify SwiftUI (3/3) - Dependencies
안녕하세요, iOS 개발하는 루피입니다.
오늘은 WWDC21 Demystify SwiftUI 영상을 정리하는 마지막 3번째 시간입니다. 지난 글들에서는 지금까지 "Identity가 무엇이고", "Identity가 View의 Lifetime과 어떻게 연관되는지"에 대해 정리해 봤다면, 이번에는 “SwiftUI가 UI를 업데이트하는 방법”에 대해 정리해보도록 하겠습니다. 바로 시작합니다.
Dependencies(의존성)
Dependencies는 흔히 우리에게는 의존성, 종속성이라는 단어로 불리고 있습니다. 이번 글에서는 쉽게 의존성이라는 단어를 이해하기 위해 View가 동작하기 위해 필요한 입력값이라고 얘기해 두겠습니다. 그러면 아래의 코드부터 같이 보도록 하시죠.

현재 코드에는 2개의 property가 있습니다. 하나는 dog이고, 다른 하나는 treat입니다.
이러한 property들을 우리는 View의 의존성이라고 부르는데요. 의존성이 변경되면, body는 새롭게 만들어 지며, Button과 같은 Action은 View의 의존성에 대한 변경을 트리거합니다.
지금까지 우리는 위 코드를 뷰의 계층 관점에서 정리해 봤습니다. 그럼 한번 다이어그램으로 바꿔볼게요!

버튼을 누른다면, 강아지에게 간식을 보상으로 주는 Action이 실행되게 됩니다. 이후, Dog에 대한 의존성에 변경이 생기며, 이에 따라 DogView는 새로운 Body를 생성하게 되죠.
SwiftUI의 데이터 흐름에 대한 일반적인 개념에 대해 알아보려면, WWDC20 Data essentials in SwiftUI를 참고하세요
그렇다면, 이 다이어그램을 한번 더 View 계층 구조에 집중해 단순화해보도록 하겠습니다.

간략하게 설명을 드리면, 파란색 상자는 의존성을 의미하고, 초록생 상자는 View를 의미한다고 생각하시면 됩니다. 그리고 화살표는 관계를 의미하고 있고요.
다이어그램을 보면 DogView만 의존성이 있는 유일한 View가 아닙니다. 왜냐하면, SwiftUI에서는 각 View가 자체 의존성 집합을 가질 수 있기 때문이죠.

그리고 상태나 데이터가 다른 여러 View에서 동시에 참조될 수도 있습니다. 예를 들어, 자식 View 중에 하나도 Dog에 의존할 수 있고, 다른 의존성 집합에도 의존할 수 있는 것이죠. 현재 제일 상단에 있는 View와 제일 하단에 있는 View가 같은 의존성 집합에 의존하고 있는 것처럼 말입니다.
그렇기에 이러한 구조는 처음에는 트리형태와 비슷했지만, 점점 달라지게 되는 것이고 이렇게 연결된 선들을 겹치지 않게 재배열을 해보면, 다음과 같은 그래프 형태로 만들 수 있게 됩니다.
Dependency graph (의존성 그래프)

이 형태를 우리는 의존성 그래프라고 부릅니다. 이러한 형태는 SwiftUI가 새로운 body가 필요한 View만 효율적으로 업데이트할 수 있게 해 주기 때문에 핵심이 되는 개념입니다.

예를 들어 가장 하단의 의존성 요소를 확인해 보면, 두 개의 View와 연결되어 있음을 확인할 수 있습니다. 이러한 상태에서 해당 의존성을 변경하면, 두 View가 Body를 재계산하게 되는 것이죠. 즉, 전체 트리 구조의 바디를 새롭게 재계산해야 하는 비효율성이 줄어들고, 필요에 의한 부분만 재계산이 가능하게 만든 것입니다.
Identifier stability (식별자 안정성)
영상에서 가장 강조하는 내용은 "각 View의 식별자를 반드시 안정적이고 고유하게 설계해야 한다"는 점입니다. 정확한 식별자를 쓰지 않으면, 데이터 변화 시 전체 뷰가 꼬이거나, 불필요한 렌더, 버그, 애니메이션 깨짐 현상이 발생할 수 있다는 것을 강조하고 있는데요. 몇 가지 케이스를 같이 살펴보도록 하겠습니다.
1. 계산 프로퍼티에서 위험성

이러한 구조는 데이터가 변경될 때마다 새로운 Identity를 가지게 되어 전체 Cell이 영향을 받게되고. 하나의 Cell만 변경하고 싶더라도 전체 List에 있는 Cell이 영향에 영향을 주기에 비효율성을 증가시키게 됩니다.
2. Index 접근 방식의 위험성

그렇다면 pets 배열의 인덱스를 사용하는 방식은 어떨까요??
이러한 방식을 사용하게 되면, 배열의 값이 변경될 때 전체 View의 id가 변경됩니다. 그리고 이에 대한 결과로 만약 첫 번째 Pet을 추가, 삭제하면, 뒤에 오는 Cell의 identity가 바뀌어 전체 View를 새로고침 하게 되고, 더 나아간다면, 인덱스를 처리하는 데 있어 인위적인 에러의 가능성 역시 존재하게 됩니다.
3. 안전한 식별자 사용

따라서 \.databaseID와 같은 변하지 않고, 안정적인 식별자를 사용할 것을 권장하고 있습니다. 또한 안전한 식별자를 사용했을 때 아래와 같은 장점을 얻을 수 있다는 것을 강조하고 있습니다.

오늘도 화이팅입니다.