iOS 개발일기

[Swift] 화면 캡처 감지 및 방지 방법 본문

iOS/Swift

[Swift] 화면 캡처 감지 및 방지 방법

맨날 까먹으니 적어두자 2024. 12. 31. 09:22

회사에서 추후 필요할 수도 있는 기능 중 하나로 화면 캡처 방지에 대한 이야기를 했었는데, 

iOS는 캡처(녹화)나 스크린 샷에 대한 감지를 할 수는 있지만 AOS처럼 공식적으로 기능을 제공하지 않는 것으로 알고 있었다.

캡처와 스크린 샷의 감지는 NotificationCenter의 알림들을 통해 쉽게 감지할 수 있지만 방지에 대한 제어는 제한적이다. 

방지를 하기 위해서는 UITextField의 `isSecureTextEntry`의 속성을 이용하여 커스텀하여 가능하다.

 

 

화면 캡처 및 스크린 샷 감지 방법

캡처(녹화) 감지

 

캡처의 경우 `UIScreen.capturedDidChangeNotification` 알림을 이벤트로 추가하여 감지할 수 있다.

 

그리고 `UIScreen.main.isCaptured` 프로퍼티를 통해서 캡처 상태를 확인할 수 있기 때문에 녹화가 시작 또는 중지 되었을 때를 알고 방지까지 할 수 있다.

///화면 캡처(녹화) 방지
NotificationCenter.default.addObserver(
    forName: UIScreen.capturedDidChangeNotification,
    object: nil,
    queue: .main
) { _ in 
    if UIScreen.main.isCaptured {
        print("화면 캡처 감지")
    else {
        print("화면 캡처 중지")
    }
}

 

 

스크린 샷 감지

 

문제는 스크린 샷의 경우다. 스크린 샷은 `UIApplication.userDidTakeScreenshotNotification` 알림을 이벤트로 추가하면 감지할 수 있는데 여기서 스크린 샷은 찍히고 난 후 감지가 된다는 것인데 이 알림은 감지는 할 수 있어도 방지를 같이할 수는 없다.

 

이름에서도 알 수 있듯이 스크린 샷이 찍히고 난 후 호출되는 이벤트 이므로 아래 코드 안에서 스크린 샷 방지 코드를 작성하더라도 이미 찍히고 난 후에 방지 코드가 동작하기 때문에 감지와 방지를 동시에 할 수 없다.

///화면 스크린샷 감지
NotificationCenter.default.addObserver(
    forName: UIApplication.userDidTakeScreenshotNotification,
    object: nil,
    queue: .main
) { _ in 
    print("화면 스크린샷 감지")
}

 

결론은 NotificationCenter 의 알림 이벤트로는 캡처와 스크린 샷 둘 다 감지는 할 수 있지만 방지는 캡처만 할 수 있다.

그러면 스크린 샷 방지는 어떻게 할 수 있을까?

 

 

스크린 샷 방지

스크린 샷을 방지하지 위해서 사용되는 방법으로는 UITextField 의 `isSecureTextEntry` 라는 프로퍼티를 사용하면 된다.

흔히 해당 프로퍼티는 사용자가 비밀번호와 같은 노출되면 안되는 정보를 입력할 때 TextField 에 입력된 Text 가 화면에 표시되지 않도록 해주는 역할을 한다. 공식 홈페이지 문서를 살펴보면 설명에 복사도 비활성화를 해주고 녹음과 브로드캐스트도 방지 해준다고 되어있다.

 

 

따라서, 스크린 샷을 방지해야될 화면이 있다면 UITextField 를 이용하면 가능하다. 

감지와는 별개지만 이 방식을 이용하게 된다면 스크린 샷 뿐만 아니라 캡처도 같이 방지가 가능하다.

 

보통 화면 캡처 또는 스크린 샷을 진행하게되면 `isSecureTextEntry = true` 로 설정된 TextField 에만 적용이 되고 다른 화면들은 정상적으로 표시된다. 하지만 현재 구현하려고 하는 기능은 캡처나 스크린 샷이 발생할 때 모든 화면이 다 가려지도록 하는 것이 목표이기 때문에 약간의 커스텀을 해야한다.

extension UIView {
    func setSecureCapture() {
        DispatchQueue.main.async {
            let textField = UITextField()
            textField.isSecureTextEntry = true 
            
            addSubview(textField)
            
            layer.superlayer?.insertSublayer(textField.layer, at: 0)
            textField.layer.sublayers?.last?.addSublayer(layer)
        }
    }
}

 

 

실행할 경우에는 모든 화면의 캡처와 스크린 샷을 방지할 수 있다.

 

 

 

 

 

참고

 

[iOS/Swift] isSecureTextEntry : TextField를 사용한 스크린 캡처 방지, 화면 스크린샷 막는 방법, 녹화 방지

앱에서 특정 사용자에게만 제공되는 정보가 있다거나, 유료 컨텐츠를 제공해야하는 상황에서 화면이 캡처되는 것은 서비스하는 입장에서 매우 큰 걸림돌입니다. 이번 글에서는 화면 캡처와 녹

jiwift.tistory.com

 

 

[iOS - Swift] 1. Prevent Capture, Recording - 캡쳐 막는 방법, 화면 녹화 방지 (isSecureTextEntry)

1. Prevent Capture, Recording - 캡쳐 막는 방법, 화면 녹화 방지 (isSecureTextEntry) 2. Prevent Capture, Recording - 캡쳐 감지 방법, 녹화 감지 방법 Capture를 막는 아이디어 안드로이드처럼 사용자가 캡쳐를 했을때

ios-development.tistory.com