반응형

[최종 수정일 : 2018.05.05]

원문 : https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/CoreAnimation_guide/CoreAnimationBasics/CoreAnimationBasics.html#//apple_ref/doc/uid/TP40004514-CH2-SW3

코어 애니메이션 기초(Core Animation Basics)

Core Animation은 뷰 애니메이션과 앱의 다른 시각적인 요소를 위한 범용 시스템을 제공합니다. Core Animation은 앱에 있는 뷰를 대체하지 않습니다. 그 대신에, 더 좋은 성능을 제공하고 콘텐츠에 애니메이션을 지원하기 위해 뷰와 통합되는 기술입니다. 하드웨어가 직접 조작할수 있는 비트맵으로 뷰의 콘텐츠를 캐싱하여 처리합니다. 경우에 따라, 이러한 캐싱 동작으로 보여지고 앱 콘텐츠를 관리하는 방법을 다시 생각해야할 수도 있지만, Core Animation을 사용하는 대부분의 시간동안 그것을 알지 못합니다. 뷰 콘텐츠를 캐싱하는것 외에도, Core Animation은 임의로 시각적인 콘텐츠를 지정하는 방법을 정의하며, 뷰와 콘텐츠를 통합하고, 다른 모든것과 함께 움직이게 합니다.

앱의 뷰와 시각적인 객체의 변경사항을 애니메이션화 하기 위해 Core Animation을 사용합니다. 대부분의 변경사항은 시각적인 객체의 프로퍼티 수정과 관련되어 있습니다. 예를들어, 아마도 뷰의 위치, 크기나 불투명도에 대한 변경 사항을 애니메이션화 하기 위해 Core Animation을 사용할것입니다. 이런 변경 할때, Core Animation은 프로퍼티의 현재 값과 새로 지정한 값 사이에서 움직입니다. 일반적으로 만화와 같이 뷰의 콘텐츠를 60초마다 교체하기 위해 Core Animation을 사용하지 않습니다. 그 대신에, 화면에서 뷰의 콘텐츠를 이동, 콘텐츠 안밖으로 사라지기(fade in/out), 임의의 그래픽 변환을 뷰에 적용하기, 뷰의 다른 시각적인 프로퍼티를 변경하기 위해 Core Animation을 사용합니다.

그리기와 애니메이션에 대한 기초를 제공하는 레이어(Layers Provide the Basis for Drawing and Animations)

Layer objects는 3D 공간에 구성된 2D 표면이고, Core Animation으로 하는 모든 작업의 핵심입니다. 뷰와 마찬가지로 Layer는 이러한 표면의 지오메트리(geometry), 콘텐츠, 시각적 속성을 관리합니다. 뷰와는 다르게 Layer는 자체적으로 모양을 정의하지 않습니다. layer는 단지 비트맵을 둘러싼 상태 정보를 관리합니다. 비트맵 자체는 뷰의 그리기 자체이거나 여러분이 지정한 고정된 이미지일 수 있습니다. 이러한 이유로, 앱에서 사용하는 기본 layer는 주(primarily) 데이터를 관리하기 때문에, 모델 객체로 간주됩니다. 이 개념은 애니메이션의 동작에 영향을 주기 때문에 기억해야 합니다.

레이어 기반의 드로잉 모델(The Layer-Based Drawing Model)

앱에서 대부분의 layer는 실제 그리기를 하지 않습니다. 그 대신에, layer는 앱에서 제공하는 콘텐츠를 캡쳐하고 비트맵 으로 캐싱하며, 때로는 보조 저장소(backing store)라고도 합니다. 이후에 layer의 프로퍼티를 변경할때, layer 객체와 관련된 상태 정보가 변경됩니다. 변경으로 애니메이션이 시작할때, Core Animation은 그래픽 하드웨어에 layer의 비트맵과 상태 정보를 전달하며, [그림 1-1]에서 보는 것처럼, 새로운 정보를 사용하여 비트맵을 랜터링합니다. 하드웨어에서 비트맵을 조작하면 소프트웨어에서 보다 훨씬 더 빨리 애니메이션 할 수 있습니다.

[그림 1-1] Core Animation으로 콘텐츠 그리는 방법


그것은 정적인 비트맵을 조작하기 때문에, layer 기반의 그리기는 view 기반의 그리기 기술과 현저하게 다릅니다. view 기반의 그리기로, 뷰 자체를 변경하면 새로운 매개변수를 사용해서 콘텐츠를 다시 그리기 위해 뷰의 drawRect:메소드가 자주 호출됩니다. 하지만, 이 방법은 메인 스레드에서 CPU를 사용해서 그리기 때문에 이런 방식으로 그리는 것은 비용이 많이 듭니다. Core Animation은 이와 동일하거나 유사한 효과를 얻기위해 하드웨어에 캐시된 비트맵을 조작하기 때문에 비용이 많이드는 것을 피하게 해줍니다.

Core Animation이 가능한한 캐시된 콘텐츠를 사용하지만, 앱은 초기 콘텐츠를 제공하고 수시로 업데이트해줘야 합니다. 앱이 콘텐츠로 layer 객체를 제공하는 다양한 방법은, 레이어의 콘텐츠 제공하기(Providing a Layer’s Contents)에 자세히 설명되어 있습니다.

레이어 기반의 애니메이션(Layer-Base Animations)

레이어 객체의 데이터와 상태 정보는 레이어의 내용을 화면에 시각적으로 표시하는 것으로부터 분리(decoupled)되어 있습니다. 이러한 분리(decoupling)는 코어 애니메이션에 기존 상태 값에서 새로운 상태 값으로 변경사항을 스스로 적용하고 애니메이션하는 방법을 제공합니다. 예를들어, 레이어의 위치 프로퍼티를 변경하면 Core Animation이 현재 위치에서 새로 지정한 위치로 레이어를 이동합니다. 다른 프로퍼티을 비슷하게 변경하여 적절한 애니메이션을 합니다. [그림 1-2]은 레이어에서 수행할 수 있는 몇가지 애니메이션 타입을 보여줍니다. 애니메이션을 실행(trigger)하는 레이어 프로퍼티의 목록을 보려면, 애니메이션 가능한 속성(Animatable Properties)을 보세요.

[그림 1-2] 레이어에서 수행 할 수 있는 애니메이션의 예제들 


애니메이션하는 동안, Core Animation은 하드웨어에서 프레임 단위로 모두 그리기를 합니다. 애니메이션의 시작과 끝 지점을 지정하고 Core Animation이 남은 작업을 수행합니다. 필요에 따라 사용자정의 타이밍 정보와 애니메이션 매개변수를 지정할 수 있습니다; 하지만, 여러분에 기본값을 제공하지 않으면, Core Animation은 적절한 기본값을 제공합니다.

애니메이션을 시작하는 방법과 애니메이션 매개변수 설정에 관한 자세한 정보는, 애니메이션 레이어 컨텐츠(Animating Layer Content)를 보세요.

자체적으로 지오메트리 레이어 객체 정의(Layer Objects Define Their Own Geometry)

레이어가 하는 작업중 하나는 컨텐츠에 대한 시각적인 지오메트리(geometry)를 관리하는 것입니다. 시각적인 지오메트리는 컨텐츠의 경계, 화면에서의 위치, 레이어가 회전, 크기 조절, 변환 되었는지에 관한 정보를 포함합니다. 뷰(view) 처럼, 레이어에 프레임(frame)과 경계 사각형이 있어서 레이어의 위치와 해당 컨텐츠의 위치를 지정할 수 있습니다. 또한, 조작하는 지점을 정의한 기준점(anchor point)처럼, 레이어는 뷰에는 없는 다른 프로퍼티가 있습니다. 레이어의 지오메트리의 일부 모양을 지정하는 방법은 뷰에 대한 정보를 지정하는 방법과는 다릅니다.

레이어는 두가지 타입의 좌표계를 사용(Layers Use Two Types of Coordinate Systems)

레이어는 컨텐츠의 위치를 지정하기 위해서 포인트 기반의 좌표계 시스템(point-based coordinate systems)과 단위 좌표계(unit coordinate systems)두개를 사용합니다. 전달되는 정보 타입에따라 사용되는 좌표계가 달라집니다. 포인트 기반 좌표계(point-based coordinates)는 화면 좌표에 직접 매핑되는 값을 지정하거나 레이어의 pointion 속성을 지정하는 것처럼, 다른 레이어를 기준으로 지정해야 하는 경우에 사용됩니다. 단위 좌표계(Unit coordinates)는 다른 어떤 값과 관련이 있기 때문에, 화면 좌표계에 결합되지 않을때 사용됩니다. 예를 들어, 레이어의 anchorPoint 속성은 레이어 자체의 경계를 기준으로 포인트를 지정하며, 변경될 수 있습니다.

포인트 기반의 좌표계의 가장 일반적인 용도는 레이어의 경계(bounds)와 위치(position) 속성을 사용하여, 레이어의 크기와 위치를 지정하는 것입니다. bounds는 레이어 자체의 좌표계를 정의하고 화면에서의 레이어 크기를 포함합니다. position 속성은 부모 좌표계를 기준으로 레이어의 위치를 정의합니다. 레이어가 frame 속성을 가지고 있지만, 이 속성은 실제로 bounds와 position 속성 값에서 유래되며, 자주 사용되지 않습니다.

레이어의 bounds와 frame 사각형의 방향은 항상 기본 플랫폼의 기본 방향과 일치합니다. [그림 1-3] iOS와 OSX 에서 경계(bounds) 사각형의 기본 방향을 보여줍니다. iOS에서, 경계 사각형의 원점은 기본적으로 레이어의 왼쪽 상단(top-lef)이고, OS X에서는 왼쪽 하단(bottom-left) 입니다. 여러분의 앱이 iOS 와 OS X 버젼간에 Core Animation 코드를 공유하는 경우에, 반드시 이런 차이점을 고려해야 합니다.

[그림 1-3] iOS와 OSX의 기본 레이어 지오메트리


그림 1-3에서 주의해야 할 것은 position속성이 레이어의 중간에 위치하고 있는 것입니다. 이 속성은 레이어의 anchorPoint 속성 값을 기반으로 변경되는 여러가지 중의 하나입니다. 기준점(anchor point)은 특정 좌표의 시작점을 나타내고 지오메트리에 영향을 주는 기준점 다루기(Anchor Points Affect Geometric Manipulations)에 자세히 설명되어 있습니다.

기준점(anchor point)은 단위 좌표계(unit coordinate system)를 사용하여 지정하는 여러 속성 중의 하나입니다. 코어 애니메이션은 레이어의 크기가 변경될때 단위 좌표를 사용하여 값이 변경 될수 있는 속성을 표현합니다. 단위 좌표는 가능한 전체 값의 퍼센트를 지정하는 것으로 생각할 수 있습니다. 단위 좌표 공간의 모든 좌표는 0.0에서 1.0까지의 범위를 가집니다. 예를 들어, x 축을 따라, 왼쪽 모서리는 0.0 좌표에 있고 오른쪽 모서리는 1.0 좌표에 있습니다. y 축을 따라, 단위 좌표 값의 방향은 [그림 1-4]에서 보는 것 처럼, 플랫폼에 따라 변경됩니다.

[그림 1-4] iOS와 OS X의 기본 단위 좌표계


주의 
OS X 10.8 까지, geometryFlipped 속성은 필요할때 y축의 기본 방향을 변경하는 방법이었습니다. 이 속성은 가끔씩 플립 변환(flip transforms)와 관련 있을때, 레이어의 방향을 수정하기 위해 필요했습니다. 예를들어, 부모 뷰가 플립 변환(flip transforms)를 사용하는 경우에, 자식 뷰의 컨텐츠(그리고 해당 레이어)는 종종 뒤집혀(inverted) 집니다. 이런 경우에, 자식 레이어의 geometryFlipped속성을 YES로 설정하여 문제를 쉽게 해결할 수 있었습니다. OS X 10.8 이후에서는, AppKit에서 이 속성을 관리하며, 수정하면 안됩니다. iOS 앱의 경우에, geometryFlipped 속성을 사용하지 않는 것이 좋습니다.

모든 좌표 값은 포인트나 단위 좌표인지와 상관없이 부동 소수점(floating-point) 숫자로 지정됩니다. 부동 소수점 숫자를 사용하여 일반 좌표 값 사이의 정확한 위치를 지정할 수 있습니다. 부동 소수점 값의 사용은 특히 인쇄중이거나 1 포인트가 여러 픽셀이 표현 될수 있는 레티나(Retina) 디스플레이로 그리는 경우에 편리합니다. 부동 소수점 값은 장치의 기본 해상도를 무시하고 필요한 정밀도로 값을 지정할 수 있습니다.

지오메트리에 영향을 주는 기준점 다루기(Anchor Points Affect Geometric Manipulations)]

레이어의 지오메트리와 관련된 조작은 해당 레이어의 기준점에 상대적으로 발생하며, 레이어의 anchorPoint 속성을 사용하여 접근할 수 있습니다. 기준점(anchor point)의 영향력은 레이어의 position이나 transform 속성을 조작할때, 가장 눈에 띕니다. position 속성은 항상 레이어의 기준점(anchor point)을 기준으로 지정되고, 레이어에 적용한 모든 변환은 기준점(anchor point)을 기준으로 발생합니다.

[그림 1-5]는 기준점(anchor point)을 기본값에서 다른 값으로 변경하면 레이어의 position 속성에 어떤 영향을 주주는지 보여줍니다. 레이어가 부모의 경계안에서 움직이지 않더라도, 기준점(anchor point)을 레이어의 중심에서 레이어의 경계까지 이동하면 position속성내의 값이 변경 됩니다.

[그림 1-5] 기준점(anchor point)이 레이어의 position 속성에 미치는 영향


[그림 1-6]은 기준점(anchor point)을 변경하면 레이어에 적용된 변환(transforms)이 어떻게 영향을 받는지 보여줍니다. 레이어에 회전 변환(rotation transform)을 적용할때, 회전은 기준점(anchor point) 주변에서 회전 됩니다. 기본적으로 기준점(anchor point)이 레이어의 중앙에 설정 되기 때문에, 이것은 일반적으로 예상할 수 있는 회전 동작의 종류를 만듭니다. 하지만, 기준점(anchor point)을 변경하면 회전 결과가 달라집니다.

[그림 1-6] 기준점(anchor point)이 레이어의 변환(transformations)에 미치는 영향


레이어의 3차원을 조작할 수 있습니다(Layers Can Be Manipulated in Three Dimensions)

모든 레이어에는 레이어와 그 컨텐츠를 조작하는데 사용할 수 있는 두개의 변환 행렬(transform matrices)을 가지고 있습니다. CALayer의 transform속성은 레이어와 포함된 하위 레이어에 모두에 적용할 변환을 지정합니다. 일반적으로 레이어 자체를 수정하려는 경우에 이 속성을 사용합니다. 예를들어, 이 속석을 사용하여 레이어의 크기를 조절하거나 회전하거나 위치를 일시적으로 변경할 수 있습니다. sublayerTransform 속성은 하위 레이어에 적용되는 추가 변환만을 정의하고 일반적으로 화면(scene)의 컨텐츠에 원근감 있는 시각효과를 추가하는데 사용됩니다.

변환은 원래 포인트의 변형된 버젼을 표시하는 새로운 좌표 값을 얻기 위해 숫자의 행렬을 좌표 값과 곱하는 작업을 합니다. 코어 애니메이션 값은 3차원으로 지정될 수 있기 때문에, [그림 1-7]과 같이, 각 좌표 점에는 4 x 4 행렬과 곱해야 하는 4개의 값이 있습니다. 코어 애니메이션에서, 그림(figure)에서의 변환은 CATransform3D 타입으로 표현됩니다. 다행스럽게도, 표준 변환을 수행하기 위해 이러한 구조 필드들을 직접 수정할 필요가 없습니다. 코어 애니메이션은 스케일, 변환, 회전 행렬에 대한 포괄적인 함수의 집합을 제공하고 행렬 비교를 수행합니다. 함수를 사용하여 변환을 조작하는 것 외에도, 코어 애니메이션은 키 패스(key path)를 사용하여 변환을 수정하기 위해 키-값 코딩(key-value coding) 확장을 지원합니다. 수정 할수 있는 키 패스(key path) 목록을 보려면, CATransform3D Key Paths를 보세요.

[그림 1-7] 행렬 연산을 사용하여 좌표 변환하기


[그림 1-8]은 여러분이 만들수 있는 보다 일반적인 변환에 대한 행렬 구성을 보여줍니다. 항등 변환(identity transform: 원본 데이터를 변경하지 않고 대상 데이터에 복사하는 데이터 변환방법)에 의해 좌표를 곱하면 똑 같은 좌표가 반환됩니다. 다른 변환의 경우에, 좌표가 어떻게 수정되는지는 전적으로 어떤 행렬 구성요소를 변경하는지에 달려 있습니다. 예를 들어, x 축만을 따라서 변환하려면, 변환 행력의 tx 구성요소에 대해 0이 아닌 값을 제공하고 ty와 tz값은 0으로 남겨둡니다. 회전의 경우에, 대상 회전 각도에 적절한 사인(sine)과 코사인(cosine) 값을 제공합니다.

[그림 1-8] 일반적인 변환에 대한 행렬 구성


변환을 생성하고 조작하기 위해서 사용하는 함수에 대한 정보는 Core Animation Function Reference를 보세요.

애니메이션 상태의 다양한 측면을 반영하는 레이어 트리(Layer Trees Reflect Different Aspects of the Animation State)

코어 애니메이션을 사용하는 앱에는 레이어 객체 3 세트가 있습니다. 레이어 객체의 각 세트는 앱의 컨텐츠를 화면에 표시하는데 다른 역할을 합니다.

  • 모델 레이어 트리(model layer tree)(또는 단순히 레이어 트리)에서 객체들은 앱에서 가장 많이 상호작용 합니다. 레이의 속성을 변경할때마다, 이러한 객체 중 하나를 사용합니다.
  • 프리젠테이션 트리(presentation tree)에서의 객체에 실행중인 애니메이션에 대한 전송 중인(in-flight) 값이 포함되어 있습니다. 레이어 트리 객체는 애니메이션 대상 값이 포함되어 있으므로, 프리젠테이션 트리의 객체는 화면에 나타나는 현재 값을 반영합니다. 트리에서 객체를 수정하지 않아야 합니다. 대신, 현재 애니메이션 값을 읽기 위해 이 객체를 사용하며, 아마도 그 값에서 시작하는 새로운 애니메이션을 만들수 있습니다.
  • 랜더링 트리(render tree)에서의 객체는 실제 애니메이션을 수행하고 코어애니메이션 전용입니다.

각 레이어 객체 세트들은 앱에서 뷰와 같은 계층 구조로 구성됩니다. 사실상, 모든 뷰에 대해 레이어를 사용하는 앱의 경우에, 각 트리의 초기 구조는 뷰 계층의 구조와 정확히 일치합니다. 하지만, 앱에서 필요에 따라 레이어 계층도 안에 레이어 객체들-즉, 뷰와 관련되지 않은 레이어들-을 추가 할 수 있습니다. 상황에 따라 뷰에 오버헤드(overhead)가 전혀 없이 컨텐츠에 대해 앱의 성능을 최적화 할수 있습니다. [그림 1-9]에서는 간단한 iOS엡에서 레이어 분석한 것을 보여줍니다. 윈도우(window)에 컨텐츠 뷰가 포함되었으며, 자체적으로 버튼 뷰와 두개의 독립적인 레이어 객체가 있습니다. 각 뷰는 레이어 계층의 일부를 구성하는 해당 레이어 객체를 가지고 있습니다.

[그림 1-9] 윈도우와 관련된 레이어들


레이어 트리에 있는 모든 객체에 대해서, [그림 1-10]과 같이, 프리젠테이션 트리(presentation tree)와 렌더링 트리(render tree)에서 일치하는 객체가 있습니다. 앞에서 언급했던 것 처럼, 앱은 주로 레이어 트리(layer tree)에 있는 객체를 사용하지만 때때로 프리젠테이션 트리(presentation tree)에 있는 객체를 사용할 수도 있습니다. 특히, 레이어 트리(layer tree)에 있는 객체의 presentationLayer 속성을 사용하면 프리젠테이션 트리(presentation tree)에 있는 해당 객체를 반환합니다. 객체를 사용하여 애니메이션 중간에 있는 속성의 현재 값을 읽을 수 있습니다.

[그림 1-10] 윈도우에 대한 레이어 트리(layer tree)


중요
애니메이션이 전송되는 동안에만 프리젠테이션 트리(presentation tree)에 있는 객체를 사용해야 합니다. 애니메이션이 진행중인 동안에, 프리젠테이션 트리(presentation tree)는 그 순간에 화면에 나타나는 레이어 값을 포함합니다. 이러한 동작은 레이어 트리(layer tree)와 다르며, 코드에서 설정된 마지막 값이 항상 반영되고 애니메이션의 마지막 상태와 같습니다.

레이어와 뷰와의 관계(The Realationship Between Layers and Views)

레이어(layers)가 앱의 뷰(views)를 대체하지 않습니다. - 그것은, 레이어 객체만을 기반으로 해서는 시각적인 인터페이스(visual interface)를 만들수 없습니다. 레이어는 뷰에 대한 하위구조(infrastructure)를 제공합니다. 특히, 레이어는 그리기 더 쉽고 효율적이고, 뷰의 내용을 애니메이션 하는 동안에 높은 프레임률(high frame rate)을 유지합니다. 하지만 레이어가 하지 않는 많은 것들이 있습니다. 레이어는 이벤트 처리, 컨텐츠 그리기, 응답 체인에 참여하거나, 다른 많은 작업을 수행하지 않습니다. 이러한 이유로, 모든 앱은 이러한 상호작용을 처리하기 위해 하나 이상의 뷰(view)를 가지고 있어야 합니다.

iOS에서는, 모든 뷰는 해당 레이어 객체를 기반(backed)으로 하지만, OS X에서는 어떤 뷰가 레이어를 가지고 있어야 하는지 결정해야 합니다. OS X 10.8 이후부터는 모든 뷰에 레이어를 추가하는게 좋습니다. 하지만, 오버헤드(overhade)가 부당하고(unwarranted) 필요하지 않는(unneeded) 경우에는 그렇게 할 필요가 없고 레이어를 사용하지 않을수 있습니다. 레이어는 앱의 메모리 오버헤드가 약간 증가하지만 그 이익은 종종 단점을 뛰어넘기에, 레이어 지원을 사용을 막기 전에 항상 앱의 성능을 테스트 하는게 가장 좋습니다.

뷰에 대해 레이어를 지원하도록 설정하면, 레이어 기반의 뷰(layer-backed view)라는 것을 생성하며, 시스템은 기본 레이어 객체를 생성하고 해당 레이어를 뷰와 동기화되도록 유지합니다. 모든 iOS 뷰는 레이어 기반(layer-backed)이고 OS X에서의 대부분의 뷰도 마찬가지 입니다. 하지만 OS X에서는, 자체적으로 레이어 객체를 제공하는 뷰인, 레이어 호스팅 뷰(layer-hosting view)를 생성할 수 있습니다. 레이어 호스팅 뷰(layer-hosting view)에 대해, AppKit은 레이어 관리하는데 있어 별도의 접근 방법을 가지며, 뷰 변경에 대한 응답으로 수정하지 않습니다.

주의
레이어 기반 뷰(layer-backed view)의 경우, 가능하면 레이어보다는 뷰를 조작하는것이 좋습니다. iOS에서, 뷰는 레이어 객체를 감싼 래퍼(wrapper)이기에, 레이어를 조작할때마다 잘 동작합니다. 그러나 iOS와 OS X 모두에서 뷰 대신 레이어를 조작하면 원하는 결과가 나오지 않을 수도 있습니다. 가능하면, 이 문서는 이러한 함정(pitfalls)을 지적(points out)하고 해결하는 방법을 제공하려고 합니다.

뷰와 관련된 레이어 외에도, 해당 뷰가 없는 레이어 객체를 생성할 수 있습니다. 앱에서 이러한 독립적인 레이어 객체를 뷰와 관련된 것들이 포함하여, 다른 레이어 객체 안쪽에 포함시킬수 있습니다. 일반적으로 특정 최적화 경로의 일부로 독립적인 레이어 객체를 사용합니다. 예를들어, 여러 곳에서 동일한 이미지를 사용하는 경우에, 이미지를 한번만 로드하여 여러개의 독립적인 레이어 객체와 연결하고 레이어 트리(layer tree)에 이러한 객체를 추가할 수 있습니다. 각각의 레이어는 그 이미지 복사본을 메모리에 만들기보다는 원본 이미지에 참조합니다.

앱의 뷰에 대해 레이어 지원이 가능하도록 설정하는 정보에 대해서는, 앱에서 코어 애니메이션 지원 사용하기(Enabling Core Animation Support in Your App)를 보세요. 레이어 객체 구조를 만드는 방법과 언제 그렇게 할수 있는지에 대한 팁에 관한 정보는, 레이어 계층 만들기(Building a Layer Hierarchy)를 보세요.

반응형
Posted by 까칠코더
,