iOS Xcode > could not insert new outlet connection 에러 해결법

|

개인공부 후 자료를 남기기 위한 목적임으로 내용 상에 오류가 있을 수 있습니다.


could not insert new outlet connection

클래스도 만들었고 잘 연결되어있는데 인식을 못하고 있다.
해결방법은 간단하고도 어이없게.. 프로젝트를 닫아주고 다시 열어주면 된다..

iOS Please delete apps signed with your free account from this device to remain under the limit.

|

개인공부 후 자료를 남기기 위한 목적임으로 내용 상에 오류가 있을 수 있습니다.


Please delete apps signed with your free account from this device to remain under the limit.

내 계정으로 만든 앱이 디바이스에 이미 꽉차게 다운이 되어있다는 뜻

이 에러는 단순하게 내 디바이스에 기존에 빌드했던 어플을 지워주면 됩니다.
삭제하고 한 몇초뒤에 다시 빌드해보면 에러 해결!

iOS URI Schemes, Universal Link, Native Link

|

개인적인 연습 내용을 정리한 글입니다.
더 좋은 방법이 있거나, 잘못된 부분이 있으면 편하게 의견 주세요. :)


iOS의 경우 기본적으로 샌드박스 환경이기 때문에 다른 앱들간 정보를 주고받는 것이 간단하지 않습니다.
이때 정보를 주고받을 수 있는 대표적인 방법 중 하나가 URI Schemes입니다.


우선 잠깐의 정보 공유!

  • 딥링크: 상세 콘텐츠로 유저를 랜딩 시키는 링크. 대부분의 웹 링크가 딥링크에 속함
    • 모바일 딥링크는 3가지 방식으로 구분됨(URI Scheme, 유니버설링크(iOS), 앱링크(AOS)
  • URI Scheme: 애플의 iOS9이전까지의 표준 딥링크 형식
  • 유니버설 링크: iOS9부터 그 이후의 표준 딥링크 형식

1. URI Schemes

앱의 고유한 scheme을 정의하고 이 scheme으로 시작하는 URL 안에 정보를 담아서 URL을 열게 되면 해당 scheme가 갖는 다른 앱을 실행하면서 정보전달을 할 수 있게 됩니다. (특정 뷰컨트롤러를 여는 것이 아니라 스키마를 통해 앱 자체를 여는것임을 명확히 알고 있어야 합니다.) 하지만 이 방법에는 치명적인 단점이 존재합니다. 애플 앱 스토어에서 해당 앱이 정의한 scheme의 고유성을 보장해주지 않기 때문에 다른 앱들이 자신이 정의한 scheme을 사용하고 있을 수 있기 때문입니다.

내 앱을 ZehyeApp이라고 하고 zehyeapp://이라는 custom URL scheme 사용한다고 가정해 봅시다.

이렇게 정의한 커스텀 스키마는 유니크가 보장되지 않는다는 특징을 가지기 때문에, 앱스토어에 올라온 다른 앱에서 내가 지정한 스키마와 동일한 이름의 스키마를 사용하고 있다면 이때 어떤 앱이 실행될지 모르는 일이 발생할 수 있게 됩니다. 즉, ZehyeApp과 OtherApp이 동시에 설치되어있는 디바이스에서 두 앱 모두 zehyeapp://이라는 동일한 스키마를 사용하고 있었고, 이때 해당 스키마를 실행시키게 된다면 이 두 앱중에 어떤 앱이 실행될지 모르는 상황이 발생한다는 것입니다. 이는 설치 순서에 영향을 받는것도 아니고 특정한 규칙이 있는것도 아니기 때문에 상황에 따라 항상 랜덤하게 앱이 열릴 수 있다는 단점이 존재하게 됩니다.

즉 이는 보안상의 헛점이 존재한다는 것을 의미하게 되죠.

이를 보안하기 위해 등장한 것이 유니버설 링크입니다.


앱 번들 아이디를 미리 특정 도메인의 웹 사이트에 등록하는 방식으로 해당 도메인과 서버의 소유권이 있어야지만 사용할 수 있기 때문에 custom URL Scheme처럼 어뷰징되는것이 불가능한 것이 특징입니다. 이를 하기 위해 우선 해야할 동작은 앱에서 유니버셜 링크를 허용할 도메인을 추가 하는 것 입니다.

예: applinks:zehye.co.kr

즉, 사용자가 앱 설치 시 여기에 등록된 도메인으로 apple-app-site-association 파일에 대한 요청을 보내게 됩니다.

위 그림처럼 올바르게 추가 되어있다면 유저가 유니버설 링크를 탭하면 iOS가 앱을 실행하게 됩니다.

유니버설 링크로 들어오는 요청은 UIApplicationDelegateapplication:continueUserActivity:restorationHandler:메서드에서 전달받은 NSUserActivity객체를 사용해 처리가 가능합니다.

- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void(^)(NSArray * __nullable restorableObjects))restorationHandler {
    if ([userActivity.activityType isEqualToString:NSUserActivityTypeBrowsingWeb]) { // NSUserActivityTypeBrowsingWeb 타입이다.
        // userActivity.webpageURL 로 대상 URL을 확인할 수 있다. 값이 없는 경우는 없다.
        ...
        return YES; // 처리하려면 YES
    }
    return NO; // 아니라면 NO
}

그런데 만약 앱이 close 된 상태라면 application:continueUserActivity:restorationHandler:가 호출되지 않는데, 이럴때는 didFinishLaunchingWithOptions:메서드에서 옵션을 가져와 처리가 가능하다.

// In application: didFinishLaunchingWithOptions:
NSDictionary *activityDic = [launchOptions objectForKey:UIApplicationLaunchOptionsUserActivityDictionaryKey];

if (activityDic) {
    // Continue activity here
}


브랜치에서 이번에 새로운 네이티브 링크라는 것이 출시 되었습니다.
네이티브 링크는 브랜치의 디퍼드 딥링크 기능 중 하나로 앱 설치 과정에서 정보가 손실되는 한계를 보완한 새로운 기능입니다.

애플은 이번 iOS15에서 Private Relay 를 도입하게 되었습니다. 이 비공개 릴레이는 유료 iCloud 고객(iCloud+)을 위한 개인용 VPN이라고 생각하면 쉬운데, 예를 들어 유저가 iCloud 저장공간을 쓰기 위해 0.99 달러를 지불하게 되면 유료 서비스의 일환으로 비공개 릴레이를 사용할 수 있게 되고 이 비공개 릴레이는 iCloud+ 고객이 사파리를 사용할때 해당 유저의 IP주소와 브라우징 데이터를 mask(보호)하는 것이 특징입니다.

기존 딥링크 방식은 유저가 이미 앱을 설치했을 경우 링크를 클릭하자마자 곧바로 앱의 원하는 곳으로 이동하게 되는것이 특징입니다. 이 과정에서는 비공개 릴레이의 영향을 받지 않고 앱이 설치되어있지 않은 유저가 링크를 클릭하게 되면 유저는 앱스토어로 이동을 하게 되고, 유저의 클릭 위치는 원격에 저장되어 있다가 유저의 앱설치가 완료되면 이 저장된 데이터를 참고해 유저가 원하는 앱 내의 위치로 바로 이동을 시켜주게 됩니다. 그런데 이때 iOS15에서 제공하는 비공개 딜레이 기능은 수많은 iCloud+ 유저의 디퍼드 딥링크 경험에 영향을 주게 됩니다.

디퍼드 딥링크는 IP 주소에 의존 하는 경우가 많기 때문에 이 비공개 릴레이를 사용하는 iCloud+ 유저 고객또한 영향을 받게 되는데, 그 이유는 이 비공개 릴레이는 사파리를 사용하는 iCloud+ 고객의 IP를 차단하고 있기 때문!입니다.

IP주소가 없으면 디퍼드 딥링크는 원활하게 작동하지 않고, 유저는 링크가 연결되지 않는 불편을 겪게 됩니다.
이때 이를 극복하기 위해 출시된 것이 바로 네이티브 링크이고 이는 IP 주소 없이 원활한 디퍼드 딥링크를 보장합니다.

기존의 과정

비공개 릴레이의 영향

이러한 네이티브 링크는 기존 디퍼드 딥링크에서 IP주소를 사용할 필요가 없는 온디바이스 솔루션을 통해 비공개 릴레이도 단절된 사용자 경험을 다시 이어줍니다. 개인 식별이 가능한 고유 정보가 필요하지 않기 때문에 네이티브 링크를 사용하면 개인정보가 추적될 위험이 없으며 이 네이티브 링크는 이미 휴대폰에 기본 내장된 복사 붙여넣기 기능을 활용해 작동되어집니다.

네이티브 링크의 동작과정은 아래와 같다.

  1. 유저가 딥링크를 클릭
  2. 새로운 네이티브 링크 환경으로 연결 > 파란색 클릭 버튼이 표시 됨
  3. 이 버튼을 클릭하게 되면 현재 url 위치가 클립보드로 복사됨
  4. 유저가 앱스토어로 이동하기 전 ‘콘텐츠가 복사되었습니다.’라는 알림을 보게 됨
  5. 표준 디퍼드딥링크와 마찬가지로 유저가 앱스토어로 연결되어 앱을 다운로드 할수 있게 됨
  6. 앱 설치 후 네이티브링크가 클립보드에 url이 있는지 확인하고 있는 경우 url을 붙여넣기 함
  7. 유저에게 ‘사파리로부터 붙여넣음’ 알림이 잠시 나타나고 유저는 원래 클릭했던 앱 내 위치로 바로 연결됨

사용방법은 간단합니다.

  1. BranchSDKfmf 1.39.4 버전 이상으로 업데이트
  2. 브랜치 대시보드에서 네이티브 링크 토글 스위치를 ON으로 변경
  3. iOS 타겟 옵션을 선택

이 유니버설 링크는 iOS9 이후부터의 표준 딥링크 형식으로 이 딥링크(특정 페이지에 도달할 수 있는 링크)에도 변천과정이 있습니다.

  1. 다이렉트 딥링크
  2. 디퍼드 딥링크
  3. 원링크

1. 다이렉트 딥링크

초창기 딥링크 형태의 모습으로 앱이 설치된 유저의 경우 특정 페이지로 랜딩이 되는것은 가능했지만, 앱이 설치되지 않은 유저의 경우 각 플랫폼의 앱스토어로 이동되며 설치 후 앱을 열었을 때 딥링크는 유실되었습니다. 이러한 앱 미설치 유저에게의 링크 유실이라는 단점을 보완하고자 디퍼드 딥링크 개념이 등장했습니다.

2. 디퍼드 딥링크

다이렉트 딥링크와 마찬가지로 앱 미설치자는 각 플랫폼의 앱스토어로 이동되지만, 설치 후 앱을 열엇을 때 링크가 유실되지 앟고 특정 컨텐츠로 이동됩니다.

그러나 디퍼드 딥링크는 각각의 플랫폼별에서만 작동한다는 한계가 존재했습니다. AOS 딥링크는 AOS에서만, iOS 딥링크는 iOS에서만 작동하기 때문에 트래킹 링크를 발급받으려면 2번의 생성작업을 거쳐야 했고 따라서 이로인해 광고를 집행할 때에도 목적이 동일한 하나의 캠페인을 AOS캠페인, iOS캠페인 이렇게 나누어져야만 했습니다. 따라서 이 문제를 해결하기 위해 원링크 개념이 등장했습니다.

3. 원링크

하나의 링크에서 각각의 플랫폼으로 자동 분기처리해주는 원링크

iOS Branch Library 사용해보기

|

개인적인 연습 내용을 정리한 글입니다.
더 좋은 방법이 있거나, 잘못된 부분이 있으면 편하게 의견 주세요. :)


딥링크

상세 콘텐츠로 유저를 랜딩 시키는 링크
대부분의 웹 링크가 딥링크에 속한다.

  • 다이렉트 딥링크: 링크가 열리기 전에 앱이 이미 설치되어 있어야 유저를 앱 콘텐츠로 이동 가능
  • 디퍼드 딥링크: 링크가 열리는 시점에 앱이 설치되어있지 않아도 유저가 앱 설치 후 처음 오픈했을 때 원하는 콘텐츠로 이동 가능

유니버설 링크

iOS9에 유니버설 링크 도입

유저는 이를 통해 웹 페이지 혹은 앱 내의 콘텐츠로 이동이 가능하다. 유저가 유니버설 링크를 클릭하면, iOS는 기기에 특정 도메인에 해당하는 앱이 설치되어있는지를 확인 > 앱이 설치되어 있는 경우 웹 페이지를 로드하지 않고 앱이 즉시 실행된다. 앱이 설치되지 않은 경우 웹 URL이 Safari에서 로드됨.

사용 장점

  1. 유저가 원하는 정보 제시
  2. 유저의 재방문 유도
  3. 유저 이탈 방지
  4. 구매 의향 높은 유저 확보

사용방법

AppDelegate

import Branch

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    setupBranchSDK(launchOptions: launchOptions)
}

func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey: Any] = [:]) -> Bool {
    Branch.getInstance().application(app, open: url, options: options)
    return true
}

func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([Any]?) -> Void) -> Bool {
    Branch.getInstance().continue(userActivity)
    return true
}

func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
    Branch.getInstance().handlePushNotification(userInfo)
}

private func setupBranchSDK(launchOptions: [UIApplication.LaunchOptionsKey: Any]?) {
    #if DEBUG
    Branch.getInstance().setDebug()
    #endif
    Branch.getInstance().initSession(launchOptions: launchOptions) { params, _ in
    if let params = params as? [String: AnyObject] {
        if let refId = params["reference_id"]?.integerValue {
            /// ******** handle deep linking here *********
        }
    }
}

WebSite

Branch Site 바로가기

딥링크 처리 로직

  • 딥링크 URL인지 확인
    • application(_: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool 위 함수에서 화면을 초기화 하는 로직이 있다면, 딥링크로 인해서 이미 화면이 존재하는지를 체크해야 이중으로 초기화가 안됨
  • URL 확인
    • application(_: UIApplication, open: URL, options: [UIApplication.OpenURLOptionsKey: Any] = [:]) -> Bool 위 함수에서 deeplink URL인지 확인
  • 특정 화면으로 이동하기 전에 로그인이 되어있는지 체크
  • 특정 화면으로 이동하기 전에, home을 먼저 push후 이동
  • 만약 현재 home화면이, navigationController.viewControllers[0]에 위치한다면, 따로 home화면 push하지 않아도 됨

참고

1 2 3

iOS SandBox란?

|

개인적인 연습 내용을 정리한 글입니다.
더 좋은 방법이 있거나, 잘못된 부분이 있으면 편하게 의견 주세요. :)


SandBox란?

외부로부터 들어온 프로그램이 보호된 영역에서 동작해 시스템이 부정하게 조작되는 것을 막는 보안 형태.
커널 수준에서 강제 적용되는 맥 OS의 접근제어 기술이다.

앱이 손상될 경우 시스템과 사용자 데이터의 손상을 억제하도록 설계되어있으며 앱스토어에 유통되는 모든 앱들은 앱 샌드박스를 적용시켜야만 한다. 애플 개발자 계정으로 앱 스토어가 아닌 다른 곳에서 유통된 앱 또한 앱 샌드박스를 적용시켜야한다.

커널: 컴퓨터와 전원을 켜면 운영체제는 이와 동시에 수행된다. 한편 소프트웨어가 컴퓨터 시스템에서 수행되기 위해서는 메모리에 그 프로그램이 올라가 있어야 한다. 마찬가지로 운영체제 자체도 소프트웨어로서 전원이 켜짐과 동시에 메모리에 올라가야 한다. 하지만, 운영체제처럼 규모가 큰 프로그램이 모두 메모리에 올라간다면 한정된 메모리 공간의 낭비가 심할것이다. 따라서 운영체제 중 항상 필요한 부분만을 전원이 켜짐과 동시에 메모리에 올려놓고 그렇지 않은 부분은 필요할 때 메모리에 올려서 사용하게 된다. 이 때 메모리에 상주하는 운영체제의 부분을 커널이라 한다. 또 이것을 좁은 의미의 운영체제라고도 한다. 즉 커널은 메모리에 상주하는 부분으로써 운영체제의 핵심적인 부분을 뜻한다. 이에 반에 넓은 의미의 운영체제는 커널뿐 아니라 각종 시스템을 위한 유틸리티들을 광범위하게 포함하는 개념이다. (보통은 운영체제라고 하면 커널을 말하게 된다.)

샌드박스가 적용되고 안되고의 차이

복잡한 시스템은 항상 취약점을 갖고 소프트웨어의 복잡도는 계속 증가한다.
개발자가 아무리 방어코드를 작성하고, 버그를 경계하더라도 해커들은 개발자의 방어를 한번만 뚫어내면 그만..

App SandBox가 앱을 공격하는 모든걸 막을수는 없지만 피해를 최소화할 수 있다.

샌드박스가 적용되지 않은 앱은 앱을 실행하는 사용자가 앱의 모든 권한을 가지며 사용자가 액세스 할 수 잇는 모든 리소스에 접근이 가능해진다. 만약 그 앱이나 그 앱과 연결되어있는 어떤 프레임워크 보안에 구멍이 생긴다면 해커는 잠재적으로 그 구멍을 이용해 앱을 제어할 수 있게 된다. 그리고 해커는 사용자가 할 수 있는 어떤 것이든 할수 있게 된다.

그렇다는 것은 앱을 통해 접근할 수 있는 사용자의 모든 데이터나 시스템 리소스에 접근해 무작위로 바이러스 등을 퍼뜨릴 수 있음을 의미하기도 한다.

샌드박스의 전략

앱 샌드박스는 어떤 식으로 피해를 최소한하는 것일까?

1. App SandBox는 개발자가 앱과 시스템이 어떤식으로 상호작용하게 할건지 설정할 수 있게 한다.

그럼 시스템은 앱이 하고자하는일을 끝내는데 필요한 권한만을 부여하고, 그 이상을 부여하진 않는다.

2. App SandBox는 사용자가 드래그 앤 드롭, 대화 상자 등의 친숙한 인터렉션을 통해 투명하게 앱에게 추가 엑세스 권한을 부여할 수 있도록 한다.

사용자는 앱을 사용하면서 많이 보면 얼럿창을 통해 앱에 추가 접근 권한을 부여할 수 있다.
샌드박스는 무적이 아니며 앱은 언제나 손상될 위험에 놓여있다. 하지만 앱이 업무를 수행하는데 필요한 최소한의 권한으로 권한을 제한할 경우 잠재적 피해의 범위는 줄어들 수 있다.

샌드박스의 원칙

각 앱마다 리소스에 대한 접근을 제한함으로써 앱 샌드박스는 해커가 앱의 보안구멍을 뚫었을 경우 사용자 데이터의 도난, 손상, 삭제, 시스템 하드웨어의 해킹에 대한 마지막 방어선을 구축한다. 예를 들어 샌드박스를 사용한 앱은 다음 리소스 중 하나를 사용하려면 그 의도를 반드시 명시해야 한다.

  • Hardware (Camera, Microphone, USB, Printer)
  • Network Connections (Inbound or Outbound)
  • App Data (Calendar, Location, Contacts)
  • User Files (Downloads, Pictures, Music, Movies, User Selected Files)

샌드박스 적용되는 방식

iOS의 각 앱은 모두 샌드박스 화 되어있다.

샌드박스는 각 앱에 대한 파일, 환경설정, 네트워크 리소스, 하드웨어 등에 대한 앱의 접근을 제한하는 세분화된 제어 집합이라고 볼 수 있다. 이렇게 앱마다 구분되어있기 때문에 이 앱을 사용하는 사용자는 이 앱의 데이터에만 접근이 가능해진다. 외부에 있는 데이터에 접근하기 위해서는 샌드박스 정책에 따라 접근 권한을 부여받아야 한다. 반대로 이 앱의 데이터도 다른 곳에서 접근은 불가능해진다.

앱의 샌드박스 디렉토리는 이런식으로 되어있다.

앱의 설치 시점에 각각의 샌드박스 디렉토리에 위치시키며, 이 디렉토리는 각 앱의 홈 디렉토리가 된다.
보안을 위해 앱과 시스템의 상호작용은 앱의 샌드박스 디렉토리에 있는 디렉토리로 제한된다.

홈 디렉토리는 각각 특별한 역할을 가진 컨테이너 디렉토리들을 하위 디렉토리로 가진다.

각 컨테이너에는 또한 역할이 있다.

1. Bundle Container

앱의 번들을 보유

2. Data Container

앱 및 사용자 데이터를 보유, 앱이 데이터를 정렬화하고 그룹화 하는 데 사용할 수 있는 여러 하위 디렉토리로 나뉨

3. iCloud Container

런타임에 접근을 요청할 수 있는 추가 컨테이너 디렉토리