Swift

화면 캡쳐 및 녹화 방지

GREEN.1229 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