ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 화면 캡쳐 및 녹화 방지
    iOS 2021. 8. 28. 09:54

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

    이번 포스팅에서는 화면 캡쳐 및 녹화 방지에 대해 포스팅해보겠습니다🧑🏻‍💻

     

    제공하는 앱에서 화면 캡쳐와 녹화를 원천적으로 차단할 수 있을까요?

    우선, 가능은 합니다. 단 우리의 코드만으론 할 수 없습니다.

    무슨 소리인지 감이 안오시죠?

    간략히 말해보자면, iOS에서 화면 캡쳐를 하는것은 OS의 영역입니다.

    이에, 방지 기능이 구현된 라이브러리나 어떠한 솔루션을 사용하지 않는다면 코드만으론 방지를 할 수 없습니다.

     

    그럼 어떤식으로 캡쳐와 녹화를 방지할 수 있을까요?

    원천적으로 기능이 되지 않게는 할 수 없으니 사용자에게 캡쳐와 녹화가 시작 될때 얼럿을 노출시켜주면 됩니다.

    그러면 사용자도 의도를 인지할것입니다.

    만약 더 나아가 얼럿만으로는 안되고 캡쳐나 녹화를 이후에 무슨 일이 생겼을때 어떤 사용자가 그랬는지 정보가 필요하다면

    서버와 연동하여 사용자ID, 캡쳐시각, 캡쳐정보 같은 데이터들을 캡쳐나 녹화가 일어날때 로깅할 수 있습니다.

    그러면 추후 일이 발생한다면 해당 자료를 사용하면 되겠죠?

     

    자 그럼 이제 본격적으로 캡쳐/녹화 방지를 구현해보도록 하죠!

     

    해당 기능을 특정한 뷰컨에서만 해줄 수도 있겠지만 저는 전역적으로 캡쳐 및 녹화를 방지하고자

    SceneDelgate에서 다뤄주었습니다👍

    import UIKit
    import SwiftUI
    
    class SceneDelegate: UIResponder, UIWindowSceneDelegate {
    
      var window: UIWindow?
    
      ...
    
      func sceneWillEnterForeground(_ scene: UIScene) {
        // Called as the scene transitions from the background to the foreground.
        // Use this method to undo the changes made on entering the background.
        NotificationCenter.default.addObserver(self, selector: #selector(alertPreventScreenCapture(notification:)), name: UIApplication.userDidTakeScreenshotNotification, object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(alertPreventScreenCapture(notification:)), name: UIScreen.capturedDidChangeNotification, object: nil)
      }
    
      ...
      
      @objc func alertPreventScreenCapture(notification:Notification) -> Void {
        let alert = UIAlertController(title: "주의", message: "캡쳐 혹은 녹화를 하면 안되요!!", preferredStyle: .alert)
        alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
        self.window?.rootViewController!.present(alert, animated: true, completion: nil)
      }
    }

    정말 코드가 간단하죠?

    우선 뷰를 다루는 씬딜리게이트에서 씬이 포그라운드로 들어갈때 전역적으로 해당 기능을 동작할 수 있게 심어줍니다.

    노티피케이션센터를 통해 옵저버를 추가하고 캡쳐나 녹화가 일어날때 셀렉터 메서드를 호출합니다.

    - 화면 캡쳐 감지

    화면 캡쳐를 감지할수 있는 메서드는 UIApplication의 userDidTakeScreenshotNotifiacion입니다.

    - 녹화 감지

    화면 녹화를 감지할 수 있는 메서드는 UIScreen.captureDidChangeNotification입니다.

    이 둘의 사용을 구분하면 좋습니다!

    다시 셀럭터 메서드가 호출이되면 얼럿을 생성하고 띄워줍니다.

     

    자 그럼 구동되는 움짤을 보시죠!

    어떤 느낌인지 아시겠죠?

    이렇게 간단하게 화면 캡쳐 및 녹화를 감지해서 얼럿으로 알려줄 수 있습니다.

     

    근데 더 나아가서, 화면 녹화가 시작될떄 아예 화면을 안보이게도 할 수 있겠죠?

    import UIKit
    import SwiftUI
    
    class SceneDelegate: UIResponder, UIWindowSceneDelegate {
    
      var window: UIWindow?
    
      ...
    
      func sceneWillEnterForeground(_ scene: UIScene) {
        // Called as the scene transitions from the background to the foreground.
        // Use this method to undo the changes made on entering the background.
        NotificationCenter.default.addObserver(self, selector: #selector(alertPreventScreenCapture(notification:)), name: UIApplication.userDidTakeScreenshotNotification, object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(alertPreventScreenCapture(notification:)), name: UIScreen.capturedDidChangeNotification, object: nil)
      }
    
      ...
      
      @objc func alertPreventScreenCapture(notification:Notification) -> Void {
        let alert = UIAlertController(title: "주의", message: "캡쳐 혹은 녹화를 하면 안되요!", preferredStyle: .alert)
        alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
        
        DispatchQueue.main.async { [self] in
          if var rootController = self.window?.rootViewController {
            while let currentController = rootController.presentedViewController {
              rootController = currentController
            }
            rootController.present(alert, animated: true, completion: nil)
          }
          
          hideScreen()
        }
      }
      
      fileprivate func hideScreen() {
        if UIScreen.main.isCaptured {
          window?.isHidden = true
        } else {
          window?.isHidden = false
        }
      }
    }

    이렇게 화면을 숨기는 함수를 만들어주고 화면 녹화가 일어날때 숨겨주고 끝나면 다시 보여주게 해줍니다.

    그럼 셀렉터 메서드에서 해당 메서드와 얼럿을 띄워주는 메서드를 비동기로 처리해준다면 원하는 결과를 보여줄 수 있어요!

    음.. 움짤로 한번에 간단히 보여드리고 싶은데 Xcode 시뮬레이터 화면 녹화기능은 감지를 안하고

    아이폰 기기로 녹화를 진행하고 끝내면 다 영상에 안담겨서😭

    아쉽지만 화면이 보이지 않게 되는것만 보여드릴께요ㅠㅠ...

    실제로 저 코드로 돌려보면 화면 녹화를 중단하면 다시 얼럿이 나타나는걸 볼 수 있어요!

    그런데 해당 코드에서는 치명적인 단점이 있어요!

    바로 비동기로 메인에서 작동하기에 돌아왔을때 얼럿이 여러개가 생길 수 있어요.

     

    제일제일 간단한 방법으로 바꿔보죠!

    import UIKit
    import SwiftUI
    
    class SceneDelegate: UIResponder, UIWindowSceneDelegate {
    
      var window: UIWindow?
    
      ...
    
      func sceneWillEnterForeground(_ scene: UIScene) {
        // Called as the scene transitions from the background to the foreground.
        // Use this method to undo the changes made on entering the background.
        NotificationCenter.default.addObserver(self, selector: #selector(alertPreventScreenCapture(notification:)), name: UIApplication.userDidTakeScreenshotNotification, object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(alertPreventScreenCapture(notification:)), name: UIScreen.capturedDidChangeNotification, object: nil)
      }
    
      ...
      
      @objc func alertPreventScreenCapture(notification:Notification) -> Void {
        let alert = UIAlertController(title: "주의", message: "캡쳐 혹은 녹화를 하면 안되요!", preferredStyle: .alert)
        alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
        hideScreen()
        self.window?.rootViewController!.present(alert, animated: true, completion: nil)
      }
      
      fileprivate func hideScreen() {
        if UIScreen.main.isCaptured {
          window?.isHidden = true
        } else {
          window?.isHidden = false
        }
      }
    }

    자 이렇게 한다면 비동기고 뭐고 복잡할 필요없이 원하는 동작의 구현이 가능합니다!

    물론 녹화를 중단하고 오면 얼럿도 한번만 노출되요👍

     

    간단하죠? 이렇게 캡쳐와 녹화를 원천적으로 차단하진 않고 방지할 수 있는 방법에 대해 학습해보았습니다.

    상용앱이라면 개인정보등 고객의 민감한 정보를 이용할 수도 있기에 보안 강화를 위해 필수는 아니지만

    옵션으로 좋은 방법이라고 생각합니다💁🏻

     

    더 궁금하시면 아래 실습 프로젝트를 클론 받거나 코드를 살펴보시면 더 이해가 빠르실 겁니다🥳

     

    [실습 프로젝트]

    https://github.com/GREENOVER/preventScreenCapture_Record

     

    GitHub - GREENOVER/preventScreenCapture_Record: 앱 화면 스크린샷 캡쳐와 녹화를 방지

    앱 화면 스크린샷 캡쳐와 녹화를 방지. Contribute to GREENOVER/preventScreenCapture_Record development by creating an account on GitHub.

    github.com

     

    [참고자료]
    https://hackernoon.com/how-to-disable-screenshots-and-recording-in-ios-apps-8l2e3tmb

     

    How to Disable Screenshots and Recording in iOS Apps | Hacker Noon

    Thanks to the mobile era we have mobile apps for everything these days. Every business from a barbers shop to huge retailers has apps so that they can be closer to their customers.

    hackernoon.com

    https://stackoverflow.com/questions/46217459/how-to-understand-if-device-screen-is-being-recorded-in-ios-11/46218452

     

    How to understand if device screen is being recorded in IOS 11

    I have an application that it has copyrighted content. I don't want users to record it. If they start recording screen I want my app to catch this. What is the function to catch if the screen is be...

    stackoverflow.com

     

    'iOS' 카테고리의 다른 글

    App Tracking Transparency  (0) 2021.10.16
    Access Photo Library & Delete Asset  (0) 2021.10.03
    Multiple Firebase Environments  (0) 2021.08.21
    DI & Swinject  (0) 2021.08.03
    Test Doubles - fake, stub, mock  (0) 2021.07.22
Designed by Tistory.