CAShapeLayer는 GPU에서 벡터 경로를 하드웨어 가속 렌더링하기 위해 설계된 CALayer의 서브클래스입니다. contents를 통해 래스터 이미지로 작업하는 기본 CALayer와 달리, CAShapeLayer는 별도의 오프스크린 버퍼를 생성하지 않고 CGPath를 통해 정의된 임의의 도형을 렌더링합니다. Apple QuartzCore Documentation, 2025에 따르면, CAShapeLayer는 가장자리 안티앨리어싱을 위해 하드웨어 가속을 사용하며 path, strokeStart 및 strokeEnd 애니메이션을 지원합니다. iOS에서 아이콘, 진행 표시기 및 마스크를 만드는 표준 도구입니다.
주요 내용
CAShapeLayer는 iOS 3.0에서 도입된 벡터 그래픽 렌더링을 위한 특수 레이어입니다. 래스터 이미지를 저장하는 CALayer와 달리, CAShapeLayer는 경로(CGPath)의 수학적 설명을 저장하고 GPU에서 직접 렌더링합니다. 이를 통해 품질 저하 없이 도형을 확대/축소하고 내용을 다시 그리지 않고 속성을 애니메이션할 수 있습니다.
아키텍처적으로 CAShapeLayer는 CALayer의 모든 기능(그림자, 테두리, 변환, 마스크)을 상속합니다. 또한 경로 작업을 위한 특정 속성을 추가합니다: path, fillColor, strokeColor, lineWidth, lineCap, lineJoin, miterLimit, strokeStart, strokeEnd 및 fillRule. 이러한 각 속성은 CABasicAnimation을 통해 애니메이션할 수 있습니다.
Apple Documentation에 따르면, CAShapeLayer는 렌더링에 하드웨어 가속을 사용합니다. drawRect:에서 Core Graphics를 통한 그리기(CPU가 경로를 래스터 컨텍스트로 렌더링)와 달리, CAShapeLayer는 Metal을 통해 GPU에 직접 명령을 보냅니다. 결과는 특히 애니메이션 중에 더 높은 성능입니다.
CAShapeLayer는 사용자 작업에 응답하여 모양이 변경되는 인터페이스 요소(진행 표시기, 차트, 탭 바 아이콘, 콘텐츠 표시 애니메이션용 마스크)에 특히 유용합니다.
CAShapeLayer의 렌더링 프로세스는 기본 CALayer와 다릅니다. 픽셀이 있는 래스터 버퍼를 저장하는 대신, CAShapeLayer는 경로의 정점 설명(점, 베지어 곡선 및 선분의 집합)을 GPU에 전달합니다. GPU는 단일 패스에서 이 경로를 래스터화하고 프래그먼트 셰이더 단계에서 채우기 및 스트로크 색상을 적용합니다.
이 접근 방식은 두 가지 이점을 제공합니다: 품질 저하 없는 확대/축소(벡터 그래픽은 모든 해상도에서 선명하게 유지)와 효율적인 애니메이션(경로가 변경될 때 GPU는 전체 화면이 아닌 변경된 픽셀만 다시 계산합니다).
path — CAShapeLayer의 핵심 속성으로, CGPath를 허용합니다. 경로에는 선, 호, 베지어 곡선 및 직사각형이 포함될 수 있습니다. Swift에서는 UIBezierPath 또는 Core Graphics에서는 CGPath를 통해 생성됩니다. 예: UIBezierPath(roundedRect: rect, cornerRadius: 16).cgPath는 둥근 직사각형을 만듭니다.
lineDashPattern 속성은 점선을 만들 수 있습니다. 숫자 배열을 허용합니다: [6, 3]은 6포인트 대시와 3포인트 간격을 의미합니다. lineDashPhase는 패턴 오프셋을 설정하며 움직이는 대시 효과를 위해 애니메이션할 수 있습니다.
CAShapeLayer와 기본 CALayer 사이의 선택은 콘텐츠 유형에 따라 다릅니다. 요소가 배경, 테두리 및 그림자가 있는 직사각형 영역인 경우 CALayer로 충분합니다. 요소가 임의의 모양을 가지거나 경로 애니메이션 또는 무손실 확대/축소가 필요한 경우 CAShapeLayer가 더 좋습니다.
성능도 다릅니다. cornerRadius와 masksToBounds가 있는 CALayer는 콘텐츠 클리핑을 위해 오프스크린 버퍼를 생성하여 프레임당 2–5ms를 추가합니다. CAShapeLayer는 오프스크린 버퍼가 필요하지 않습니다 — 클리핑은 정점 셰이더 수준에서 수행됩니다. 복잡한 마스크가 있는 요소의 경우 CAShapeLayer가 2–3배 더 빠를 수 있습니다.
CAShapeLayer를 다른 레이어와 결합하는 것은 일반적인 패턴입니다. 예를 들어, CAGradientLayer는 CAShapeLayer를 마스크로 사용하여 그라데이션 채우기로 도형을 만듭니다. 이 접근 방식은 성능 저하 없이 벡터 품질과 그라데이션 채우기를 모두 제공합니다.
경로 애니메이션은 CAShapeLayer의 가장 강력한 기능 중 하나입니다. 두 경로(초기 및 최종)가 동일한 수의 제어점과 세그먼트를 갖는 경우 Core Animation이 그 사이에서 부드러운 보간을 수행합니다. 결과는 한 도형에서 다른 도형으로의 모핑 효과입니다.
경로 호환성 조건: 초기 및 최종 UIBezierPath는 동일한 구조를 가져야 합니다 — moveTo, addLine, addCurve 및 addQuadCurve 호출 수가 일치해야 합니다. 구조가 다른 경우 애니메이션은 보간 없이 즉시 발생합니다.
Apple WWDC 2024에 따르면, strokeStart와 strokeEnd의 조합은 가장 일반적으로 사용되는 CAShapeLayer 애니메이션 패턴입니다. strokeEnd를 0.0에서 1.0으로 애니메이션하면 처음부터 끝까지 경로 그리기 효과가 만들어집니다. 이는 로딩 표시기, 차트 표시 애니메이션 및 사용자 정의 화면 전환에 사용됩니다.
맥동 효과를 만들려면 다른 타이밍 함수로 strokeEnd와 opacity를 동시에 애니메이션하세요. 움직이는 개미 효과의 경우 고정 lineDashPattern으로 lineDashPhase를 애니메이션하세요. 두 기술 모두 CPU 개입 없이 CABasicAnimation을 통해 구현됩니다.
CAShapeLayer는 다른 레이어의 마스크로 자주 사용됩니다. 예를 들어, 콘텐츠 표시 애니메이션의 경우: 초기에는 mask.path가 크기가 0인 직사각형이고 최종은 전체 크기입니다. Core Animation이 경로를 보간하고 콘텐츠가 부드럽게 표시됩니다.
이 패턴은 iOS에서 카드 확장 애니메이션, 모달 창 표시 및 뷰 컨트롤러 전환에 사용됩니다. 알파 애니메이션과 달리 CAShapeLayer 마스크 애니메이션은 임의의 모양으로 더 자연스러운 표시 효과를 제공합니다.
첫 번째 예제 — strokeEnd 애니메이션으로 원형 진행 표시기 만들기. 이는 CAShapeLayer의 핵심 기능을 보여주는 표준 UI 요소입니다:
func createProgressIndicator(in view: UIView) -> CAShapeLayer {
let circlePath = UIBezierPath(
arcCenter: CGPoint(x: 50, y: 50),
radius: 40,
startAngle: -.pi / 2,
endAngle: 3 * .pi / 2,
clockwise: true
)
let trackLayer = CAShapeLayer()
trackLayer.path = circlePath.cgPath
trackLayer.strokeColor = UIColor.systemGray5.cgColor
trackLayer.fillColor = nil
trackLayer.lineWidth = 8
view.layer.addSublayer(trackLayer)
let progressLayer = CAShapeLayer()
progressLayer.path = circlePath.cgPath
progressLayer.strokeColor = UIColor.systemBlue.cgColor
progressLayer.fillColor = nil
progressLayer.lineWidth = 8
progressLayer.lineCap = .round
progressLayer.strokeEnd = 0
view.layer.addSublayer(progressLayer)
return progressLayer
}
// 75%로 애니메이션
progressLayer.animateStrokeEnd(to: 0.75, duration: 1.5)
두 번째 예제 — 원과 정사각형 간의 모핑 애니메이션. 두 UIBezierPath 모두 호환되는 구조를 가지고 있습니다:
let morphLayer = CAShapeLayer()
morphLayer.fillColor = UIColor.systemPurple.cgColor
morphLayer.frame = rect
let circlePath = UIBezierPath(roundedRect: rect, cornerRadius: rect.width / 2)
let squarePath = UIBezierPath(roundedRect: rect, cornerRadius: 0)
morphLayer.path = circlePath.cgPath
let morphAnimation = CABasicAnimation(keyPath: "path")
morphAnimation.toValue = squarePath.cgPath
morphAnimation.duration = 0.6
morphAnimation.autoreverses = true
morphAnimation.repeatCount = .infinity
morphLayer.add(morphAnimation, forKey: "morph")
세 번째 예제 — 콘텐츠 표시 애니메이션을 위한 CAShapeLayer 마스크. 마스크가 중앙에서 가장자리로 확장됩니다:
func revealContent(_ view: UIView) {
let maskLayer = CAShapeLayer()
let size = view.bounds.size.width * 1.5
let center = CGPoint(x: view.bounds.midX, y: view.bounds.midY)
let initialPath = UIBezierPath(arcCenter: center, radius: 0, startAngle: 0, endAngle: .pi * 2, clockwise: true)
let finalPath = UIBezierPath(arcCenter: center, radius: size, startAngle: 0, endAngle: .pi * 2, clockwise: true)
maskLayer.path = initialPath.cgPath
view.layer.mask = maskLayer
let animation = CABasicAnimation(keyPath: "path")
animation.toValue = finalPath.cgPath
animation.duration = 0.4
animation.timingFunction = CAMediaTimingFunction(name: .easeOut)
maskLayer.add(animation, forKey: "reveal")
maskLayer.path = finalPath.cgPath
}
자주 묻는 질문
drawRect는 래스터 컨텍스트로 렌더링하기 위해 CPU를 사용합니다 — 애니메이션에 느립니다. CAShapeLayer는 GPU에서 경로를 렌더링하여 path, strokeEnd 및 변환 애니메이션 중 60 FPS를 제공합니다. 또한 CAShapeLayer는 크기 변경 시 다시 그릴 필요가 없습니다 — 도형이 벡터 방식으로 크기가 조정됩니다.
부드러운 경로 애니메이션에는 초기 및 최종 UIBezierPath의 동일한 구조가 필요합니다. moveTo, addLine, addCurve 호출 수가 일치해야 합니다. 초기 및 최종 도형에 대해 동일한 수의 세그먼트를 가진 UIBezierPath를 사용하세요.
lineDashPattern을 설정하세요 — 대시와 간격 길이를 번갈아 지정하는 숫자 배열입니다. 예를 들어, [8, 4]는 8pt 대시와 4pt 간격을 만듭니다. 움직이는 개미 효과의 경우 선형 타이밍 함수로 CABasicAnimation을 통해 lineDashPhase를 애니메이션하세요.
네, 이것은 주요 사용 사례 중 하나입니다. CAGradientLayer 및 다른 서브클래스를 포함한 모든 CALayer의 mask 속성에 CAShapeLayer를 할당하세요. 마스크 경로를 애니메이션하면 임의의 모양을 통해 콘텐츠가 부드럽게 표시되는 효과가 만들어집니다.
CAGradientLayer를 만들고 mask = 원하는 경로가 있는 CAShapeLayer로 설정하세요. 그라데이션은 마스크 경로 내부에서만 표시됩니다. 이 패턴은 CAShapeLayer의 벡터 도형 이점과 CAGradientLayer의 그라데이션 채우기를 결합합니다.
요약
턴키 방식의 모바일 애플리케이션을 개발해 드립니다
IT Sectr는 2017년부터 스타트업과 기업을 위한 iOS 및 Android 애플리케이션을 만듭니다. 저희가 상담해 드리고 최적의 솔루션을 제안하겠습니다.