ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • AVCaptureVideoPreviewLayer
    iOS 2025. 4. 18. 08:51

    안녕하세요. 그린입니다 🍏

    이번 포스팅에서는 AVCaptureVideoPreviewLayer에 대해 정리해보겠습니다 🙋🏻

     


    AVCaptureVideoPreviewLayer?

    AVCaptureVideoPreviewLayer는 Apple의 AVFoundation 프레임워크에서 제공하는 클래스에요.

    해당 레이어는 AVCaptureSession을 통해서 들어오는 실시간 비디오 데이터를 화면에 보여주는 역할을 해줍니다.

     

    우리 앱에서 새로운 카드나 파일을 스캔할때 카메라를 켜서 자동으로 인식하게 해주는 기능 이제는 많아져서 익히 아실거에요.

    그것들이 이 AVCaptureVideoPreviewLayer을 기반으로 만들어진다고 볼 수 있습니다.

     

    여기서 AVCaptureVideoPreviewLayer는 CALayer의 서브 클래스입니다.

    즉, 직접적으로 뷰로 사용할 수 없고 UIView.layer에 붙여야하죠.

     

    또한, 실시간 미리보기만 담당해주기에 촬영을 하거나 캡처를 하는 기능들은 별도로 처리해줘야 합니다.

    AVCaptureVideoPreviewLayer은 OpenGL이나 Metal 없이도 GPU 렌더링으로 성능이 좋다는 특징을 가지고 있어요!

     

    그럼 이 기능을 위해 카메라를 띄우는 기본 흐름을 한번 살펴볼까요?

     


    AVCaptureVideoPreviewLayer Flow

     

    플로우 다이어그램으로 먼저 볼께요.

     

    AVCaptureDevice 즉, 카메라를 통해서 AVCaptureDeviceInput으로 흐릅니다.

    그리고 AVCaptureSession을 통해서 AVCaptureVideoPreviewLayer를 거쳐 실제 화면에 출력되는 플로우죠.

     

    만약 여기서 추가로 캡쳐를 하고 싶다면, AVCapturePhotoOutput이나 AVCaptureVideoDataOuput 등을 이용해주면 됩니다.

     

    그럼 이제 실제로 어떻게 구성되는지를 코드를 가지고 구현해보면서 알아볼까요?

     


    AVCaptureVideoPreviewLayer Implementation

    코드와 함께 주석으로 설명을 해보겠습니다 😀

     

    import UIKit
    import AVFoundation
    
    class CameraViewController: UIViewController {
        private let session = AVCaptureSession()
        private var previewLayer: AVCaptureVideoPreviewLayer?
        
        override func viewDidLoad() {
            super.viewDidLoad()
            
            checkPermissionAndSetupCamera()
        }
    
        private func checkPermissionAndSetupCamera() {
            switch AVCaptureDevice.authorizationStatus(for: .video) {
            case .authorized:
                setupCamera()
            case .notDetermined:
                AVCaptureDevice.requestAccess(for: .video) { granted in
                    if granted {
                        DispatchQueue.main.async {
                            self.setupCamera()
                        }
                    }
                }
            default:
                print("카메라 접근 권한이 없습니다.")
            }
        }
        
        private func setupCamera() {
            // 1️⃣ 세션 설정
            session.sessionPreset = .high
            
            // 2️⃣ 입력 (카메라)
            guard let device = AVCaptureDevice.default(.builtInWideAngleCamera,
                                                       for: .video,
                                                       position: .back),
                  let input = try? AVCaptureDeviceInput(device: device),
                  session.canAddInput(input) else {
                print("입력 장치 추가 실패")
                return
            }
            session.addInput(input)
            
            // 3️⃣ 미리보기 레이어
            let preview = AVCaptureVideoPreviewLayer(session: session)
            preview.frame = view.bounds
            preview.videoGravity = .resizeAspectFill
            view.layer.insertSublayer(preview, at: 0)
            self.previewLayer = preview
            
            // 4️⃣ 세션 실행
            session.startRunning()
        }
        
        override func viewDidLayoutSubviews() {
            super.viewDidLayoutSubviews()
            previewLayer?.frame = view.bounds
        }
    }

     

    새로운 카메라 뷰 컨트롤러를 만들었어요.

    가장 먼저 뷰 로드될때 카메라 접근 권한을 받아야겠죠?

    그리고 허용되있다면 카메라 설정을 해줍니다.

     

    세션을 설정하고 카메라 장치를 주차하고 프리뷰 레이어를 사용합니다.

    그리고 세션을 실행시켜주는것이죠.

     

    아주 간단하죠?

     

    여기서 AVCaptureSession을 설명하자면 이런 특징이 있어요.

     

    1️⃣ AVCaptureInputd (카메라)와 AVCaptureOutput (사진, 비디오) 사이의 데이터 흐름을 중재하는 컨트롤러 역할을 합니다.

    2️⃣ startRunning(), stopRunning()으로 세션을 제어해요.

     

    또한 세션을 .high, .photo, .hd1920x1080 등 다양하게 품질 조정을 위한 프리셋 설정이 가능합니다.

     

    그리고 AVCaptureVideoPreviewLayer는 AVCaptureSession에 연결되어 실시간 비디오 프레임을 표시해줍니다.

     

    vidoeGravity는 말 그대로 뷰 크기를 컨텐츠 비율에 따라 어떻게 할지를 나타내요.

     

    1️⃣ resize - 컨텐츠 비율을 무시하고 레이어를 채움

    2️⃣ resizeAspect - 컨텐츠 비율을 유지하고 전체를 보여주지만 빈 공간이 생길 수 있음

    3️⃣ resizeAspectFill - 컨텐츠 비율을 유지하고 화면을 채우지만 일부가 잘릴 수 있음

     

    사실상 저는 resizeAspectFill을 옵션으로 가장 많이 사용했던것 같아요.

     


    Conclusion

    정리해볼까요?

     

    AVCaptureVideoPreviewLayer는 UIKit 기반에서 실시간 카메라 프리뷰를 구현할 때 필수적인 객체이죠.

    AVCaptureSession과 연결되서 카메라 입력을 직접적으로 화면에 표현해줍니다.

    즉, 그렇기에 실시간 렌더링 성능이 뛰어나고 다양한 설정이 가능해요.

     

    앞으로 점점 더 많은 분야에서 활용되고 있다고 느껴지기에 한번쯤 알고 가면 좋을것 같아요 🔥

     


    References

     

    AVCaptureVideoPreviewLayer | Apple Developer Documentation

    A Core Animation layer that displays video from a camera device.

    developer.apple.com

    'iOS' 카테고리의 다른 글

    Lottie vs WebP Animation  (2) 2025.05.28
    Server Image Format (feat. JPG, PNG, WebP)  (4) 2025.05.23
    Crash 감지하고 다루기  (1) 2025.03.29
    iOS에서 서버 과부하 감지 및 API 호출 최적화  (0) 2025.03.15
    Server-Driven UI  (0) 2025.03.07
Designed by Tistory.