[iOS] CoreAnimation - 1

Hyunndy·2023년 2월 23일
0

iOS-CoreAnimation

목록 보기
1/1

🐸

최근에 회사에서 UIButton안에 이미지를 빙글빙글 돌려달라는 요청이 있어서 애니메이션 작업을 했습니다.

    /// 버튼 내 이미지 원형으로 애니메이션 주기
    func startRotateImageAnimation() {
        guard let imageView = self.imageView else { return }
        
        // 1초 동안 360도 회전하는 애니메이션
        let animation = CABasicAnimation(keyPath: "transform.rotation")
        animation.toValue = NSNumber(value: Double.pi * 2)
        animation.duration = 1
        animation.repeatCount = .infinity
        
        // 애니메이션을 뷰의 레이어에 추가
        imageView.layer.add(animation, forKey: "rotationAnimation")
    }

이런...예. 이 CoreAnimation, Layer 관련된 작업은 그냥 스택오버플로우나 블로그 복붙만해서..
공부해볼까 합니다.


CoreAnimation이란?

Core Animation은 앱을 느리게하거나 CPU에 부담을 주지않고 높은 프레임과 스뭇뜨한 애니메이션을 제공해주는 그래픽 렌더링 및 애니메이션 인프라 입니다.
(드로잉 시스템 자체가 아닌 하드웨어에서 앱의 콘텐츠를 합성하고 조작하는 😈인프라 라는게 강조되네요)

애니메이션의 각 프레임을 그리는데 필요한 대부분의 작업은 자동으로 수행됩니다.
개발자가 할 일은 start나 end point같은 animation parameters를 지정해주는것 뿐입니다.
CoreAnimation은 그 paramter를 기반으로 프레임을 그리고, 전용 그래픽 하드웨어로 전달하여 빠르게 렌더링합니다.


CoreAnimation은 AppKit 및 UIKit 아래에 있으며 Cocoa, Cocoa Touch와 매우 긴밀하게 협력합니다.

👩‍💻 Graphics Hardware를 사용하면서 Animation을 그려주는게...
Core Animation, Metal, Core Graphics 이렇게 있나보네요.
Metal은 아예 처음보는건데 뭐지? 담에 정리해볼게요.

Core Animation을 직접적으로 사용할 필요가 없을 수도 있지만, App의 인프라구조에서 Core Animation이 어떤 역할을 수행하는지 꼭~ 이해해야한다고 합니다.
왜냐? iOS 개발하면서 우린 모두 CoreAnimation을 사용하고 있긴 하거든요.
그래서 어덯게 동작하고있는건대,,,

App Contents를 관리하고있던 CoreAnimation

위에 강조했듯 Core Animation은 드로잉시스템이 아닌 하드웨어에서 앱의 컨텐츠를 합성하고 조작하는 인프라입니다.
이 인프라의 중심에는 layer 객체가 있습니다.
이 layer 객체로 개발자는 컨텐츠를 관리하고 조작할 수 있습니다.

layer는 그래픽 하드웨어에서 쉽게 조작할 수 있도록 컨텐츠를 비트맵으로 캡처합니다!
대부분의 앱에서 layer는 View의 content를 관리하도록 사용되지만 직접 만들 수도 있습니다 ^0^

layer는 약간 익숙하죠?
어디쓸까요?

👩🏼‍🎨 이 Label은 모서리가 둥글게..테두리는 이 색, 이 굵기로 해주세요! 할 때

작성하게 되는 이 코드 요기서 쓰이는게 View의 layer입니다.

let view = UIView()
view.layer.borderWidth = 1.0
view.layer.borderColor = brown
view.layer.masksToBounds = true
view.layer.cornerRadius = 4.0
@available(iOS 2.0, *)
@MainActor open class UIView : UIResponder, NSCoding, UIAppearance, UIAppearanceContainer, UIDynamicItem, UITraitEnvironment, UICoordinateSpace, UIFocusItem, UIFocusItemContainer, CALayerDelegate  {
	...
	open var layer: CALayer { get }
}

두둥!
UIView의 파라미터로 있었군요(당연)

Layers Provide the Basis for Drawing and Animations

CALayer 객체에 대해 더 심도깊게 알아봅시다.

Layer는 3D 공간에 구성된 2D 표면(비트맵)으로 Core Animation으로 수행하는 모든 작업의 핵심입니다.
뷰와 마찬가지로 Layersms 표면의 (geometry, content, and visual attributes)에 대한 정보를 관리하긴 하지만
View와 달리 Layer는 own appearance (자체 모양)을 정의하지 않습니다.

Layer는 그냥 단순히! 비트맵을 둘러싼 state Information(상태 정보)를 관리합니다! (중요)

이 비트맵 자체는 단순 이미지일 수 있고 뷰 드로잉 자체의 결과 일수도 있습니다.
중요한건 Layer는 이 비트맵을 둘러싼 상태 정보를 관리하고있는 객체라는것.

👩‍💻 따라서 앱에서 사용하는 기본 Layer는 주로 데이터를 관리하기 때문에 Model Object로 간주됩니다

Layer가 데이터를 관리하는 Model Object라는 개념은 CoreAnimation의 동작에 영향을 미치기 때문에 기억하는것이 중요합니다!

The Layer-Based Drawing Model

대부분의 Layer는 앱에서 실제 그리기를 수행하지 않습니다.
왜냐? Layer는 데이터 모델이니까요.

Layer는 앱이 제공하는 Content를 캡처하고 이를 비트맵(= 백업 저장소)에 캐시합니다.
그 다음 Layer의 속성을 변경하면 레이어가 관리하는 상태 정보가 업데이트 됩니다.
당연. Layer는 데이터 모델이니깐

이 때 이 변경사항들이 애니메이션을 트리거합니다.
그럼 Core Animation (인프라 스트럭쳐)는 Layer의 기존 비트맵을 새롭게 업데이트된 상태 정보를 사용하여 새로 렌더링 하기 위해 비트맵을 렌더링하는 작업을 수행하는 그래픽 하드웨어에 전달합니다.

이렇게하면! 하드웨어에서 비트맵을 조작하기 때문에 소프트웨어, 메인스레드에서 동작하는것 보다 훨씬 빠르고 리소스 낭비 없이 동작하겠죵.

View-based 드로잉은 drawRect(:) 함수를 호출하고 새로 그려야해서 메인스레드의 리소스 낭비를 할 수 있는데, Layer-based 드로잉은 CoreAnimation이 캐싱되어있는 비트맵을 이용하고 + 하드웨어를 사용하기 때문에 이러한 낭비를 방지합니다.
(하지만 계속 캐싱된 객체를 사용하는건 또 아니고 수시로 초기화를 시켜줘야한다고 합니다)

Layer-Based Animations

Layer의 데이터 및 상태 정보는 해당 레이어의 컨텐츠를 화면에 시각적으로 렌더링 하는 것과 완전히 분리(decoupling) 됩니다.
(뭔가 계속 Layer는 그냥 데이터 모델로만 인식하고 있어. 라는 애플의 세뇌가 느껴지는..)

이 분리(decoupling)는 CoreAnimation이 끼어들어서 old value -> new value로의 변경을 애니메이션화 할 수 있게 합니다.

예를들면...Layer의 위치 속성을 변경하면 CoreAnimation이 레이어를 현재 위치에서 새로운 위치로 이동시킵니다. 여기서! 속성에 대한 변경으로 적절한 애니메이션이 발생합니다.
Layer에서 애니메이션을 트리거할 수 있는 속성 목록들이 따로 있는데, 밑에서 보겠습니다.

애니메이션이 진행되는 동안 CoreAnimation은 하드웨어에서 모든 프레임 별 드로잉을 수행합니다.
뭐..이건 우리가 알바아니고 우리는 애니메이션의 시작점, 끝점을 지정해주기만 하면 됩니다.
필요하다면 Timing, DisplayLink(애니메이션의 프레임 레이트) 등을 지정해줄 수도 있지만 왠만하면 그냥 디폴트 값으로 나옵니다.

Layer Objects Define Their Own Geometry

다음 파트로는 Layer가 자체 좌표계를 갖는다는건데..
핵심만 요약해보겠습니다.
레이어는 좌표 시스템을 이용해서 컨텐츠를 지정하고, 이 때 2가지 좌표계를 사용합니다.

  • 점(point) 기반 좌표계
  • 단위(unit) 기반 좌표계

point 기반 좌표계는 화면 좌표에 직접 매핑하거나 다른 레이어와의 상대적인 위치를 지정해야 하는 경우 사용합니다.
unit 기반 좌표계는 값이 화면 좌표예 묶이지 않고 다른 값과의 상대적인 위치를 지정해야 하는 ㄱ ㅕㅇ우 사용합니다.

앵커포인트는 레이어가 회전 또는 크기 조정할 때 사용하는 속성입니다.
레이어는 세 가지 차원에서 조작 될 수 있으며, trnasform, sublayertransform 속성을 사용하여 레이어 및 하위 레이어를 조작할 수 있습니다.

Layer Trees Reflect Different Aspects of the Animation State

Core Animation을 사용하는 앱들은 3가지의 레이어 객체가 있습니다.(!!!!)
각각의 레이어는 앱의 content를 화면에 표시하는데 있어 서로 다른 역할을 합니다.

  1. Model Layer Tree(= Layer Tree)
  • 앱이 가장 많이 상호작용하는 객체. 이 트리의 객체는 모든 애니메이션의 대상 값(target Value)를 저장합니다. 레이어의 속성을 변경할 때 마다 이 트리의 객체 중 하나를 사용합니다.
  1. Presentatin Tree
  • 실행중인 애니메이션의 실행중인 값을 포함하고 있습니다. 화면에 표시되는 현재 값을 표기하기 때문에 얘는 애니메이션 중에 수정하면 안됩니다!! 이 트리의 객체를 읽고 현재 애니메이션 값을 읽거나 해당 값에서 시작하는 새로운 애니메이션을 만들 수 있습니다.
  1. Render Tree
  • 실제 애니메이션을 수행하며 Core Animation 전용입니다.

각각의 레이어는 앱의 뷰와 같이 계층 구조로 구성됩니다.
실제로 뷰의 계층 구조나 레이어의 계층 구조나 정확히 일치한다고 합니다.
하지만! 여기서 뷰와 관련되지 않은 추가적인 레이어가 추가될 수도 있긴 합니다.
요렇게 하면 뷰의 오버헤드를 발생하지 않고 최적화를 할 수 있다는데 뭔말인지 모르겠습니다.

위 그림들처럼 레이어트리, 프레젠테이션 트리, 렌더 트리는 일치합니다.
앱은 주로 레이어 트리의 객체와 함께 작동하지만 가끔 프레젠테이션 트리의 객체에 액세스할 수 있습니다.
특히, 레이어 트리에서 presentationLayer 속성에 액세스하면 프레젠 테이션 트리에서 해당 객체가 바노한됩니다. 그럼 애니메이션의 현재 값을 얻을 수 있습니다.

하지만! 애니메이션이 진행되는 동안에만 프레젠테이션 트리에 접근해야합니다~

The Relationship Between Layers and Views

Layer는 View를 대체할 수 없습니다.
즉, Layer 객체 만을 기반으로 시각적 인터페이스를 만들 수 없습니다.
Layer는 View를 위한 인프라를 제공하는것 뿐입니다.
Layer를 사용하면 View의 컨텐츠를 더 쉽고 효율적으로 그리고 애니메이션할 수 있으며 그렇게 하는 동안에높은 프레임을 유지할 수 있습니다.

하지만 이벤트 처리, 컨텐츠 그리기, responder Chain에 등록하기 등 Layer가 수행하지 않는 작업들이 있습니다. 따라서 최소 하나 이상의 View가 있어야 합니다.

View 연결이 없는 Layer를 만들 수도 있습니다.
예를 들어 여러 위치에서 동일한 이미지를 사용하려는 경우 독립 실행형 레이어 트리를 만들고 그걸 연결할수도있다느데 어떻게 하는지 모르겠습니다 ㅎㅎ

Animatable Properties

위에서 언급했던 CALayer의 Animatable한 속성입니다.
정말 무의식적으로 그냥 쓰던 속성들인데 사실은 CoreAnimation에서 처리되고 있었다니 너무 신기하네요 ㅋㅋㅋㅋ

여기다가 쓰는건 의미가 별로 없을 것 같아 캡쳐했습니다.


마무리

CoreAnimation - CALayer에 대해서 아주 간략하게 보았습니다.
view.layer.cornerRadius 이런건 정말 많이 쓴 코드인데..
이게 CoreAnimation을 조작하는거였다니 너무 신기하네요

한 층 깊게 들어간 것 같아 뿌듯합니다.
하지만.. 정작 처음 글을 작성할 때 봤던 Animation은 아직 보지도 못했는데요.
다음 글에 정리하도록 하겠습니다.

참고링크

profile
https://hyunndyblog.tistory.com/163 티스토리에서 이사 중

0개의 댓글