[iOS] 앱 간 이동, 외부 앱 실행 방법. URI Scheme이란?

nowoey.x·2022년 8월 31일
2

iOS 개발 관련 모음

목록 보기
1/1

공부한 것을 정리하는 용도의 글이므로 100% 정확하지 않을 수 있습니다.
참고용으로만 봐주시고, 내용이 부족하다고 느끼신다면 다른 글도 보시는 것이 좋습니다.
+ 틀린 부분, 수정해야 할 부분은 언제든지 피드백 주세요. 😊

해당 글은 Swift 공식 문서를 기반으로 여러 블로그의 글을 읽고 작성되었습니다.
블로그들의 출처는 맨 아래에 있습니다.

                                                 by. nowoey




안드로이드 개발을 했을 때는 앱 간 이동 방법으로 Intent를 사용했었다.

iOS 개발을 하면서 앱에서 앱으로 이동하는 방법을 구글링하면서 깨달은 점은...
안드로이드의 intent 방식이 아주,,,매우,,, 편하고 쉬운 것이었다는 것... 🥲

iOS는 기본적으로 샌드박스 환경이기 때문에 다른 앱들 간 정보를 주고 받는 것이 간단하지 않다고 한다.
어쨌든 개발은 해야하니... 열심히 구글링을 하고, 블로그를 정독했다...

나는 이해가 되지 않으면 적용도 응용도 되지 않는 사람이기때문에 어느정도는 이해가 될 때까지 계속 찾아보고 정독하는 편이다.
(그래서 어느순간 디지털 마케팅 블로그까지 읽고 있더라구요...?)

그리고 나는 진짜 여러개를 보고 정독했지만.... 다른 사람들은 글 하나만 읽고도 이해가 됐음 좋겠고,
내가 나중에 다시 볼 때도 이거 하나만 보려고 이해한 내용을 정리해보려 한다... 🙃🙃🙃

어쨌든 앱간 이동은 보통 딥링크를 통해서 한다.
그런데, 딥링크(Deeplink)가 뭐지??





🔷 Deeplink?


딥링크(Deeplink)란 쉽게 말해 상세 콘텐츠로 유저를 랜딩 시키는 링크를 말한다.
대부분의 웹 링크가 딥링크에 속한다.

모바일 딥링크는 URI Scheme, Universal Lin(iOS), 앱링크(AOS) 이렇게 3가지 방식으로 구분된다.

간단하게 요약하면 아래와 같다.

  • URI Scheme : 애플의 iOS9 이전까지의 표준 딥링크 형식
  • 유니버설 링크 : iOS9부터 그 이후의 표준 딥링크 형식


🟡 URI Scheme


  • 앱의 고유한 scheme을 정의하고, 이 scheme으로 시작하는 URL을 열면 이 scheme을 갖고 있는 다른 앱을 실행.
    (물론 해당 앱이 설치되어있어야 이동 가능)
  • But, 애플 앱 스토어에서 해당 앱이 정의한 scheme의 고유성을 보장해주지 않기 때문에 다른 앱들이 자신이 정의한 scheme을 사용하고 있을 수 있음.
    (동일한 scheme을 가진 앱 사이에서 랜덤 실행됨. 보안상 헛점 존재 —> 그래서 등장한 것이 유니버셜 링크)



  • 앱 번들 아이디를 미리 특정 도메인의 웹 사이트에 등록하는 방식
    (당연히 해당 도메인과 서버의 소유권이 있어야 사용 가능)
  • 앱에서는 유니버셜 링크를 허용할 도메인 추가, 서버에서는 apple-app-site-association 파일 등록 필요
  • 유니버설 링크로 들어오는 요청은 UIApplicationDelegate의 application:continueUserActivity:restorationHandler:메서드에서 전달받은 NSUserActivity객체를 사용해 처리 가능 ??? (해당 부분 Objc 이므로 swift 찾아봐야 함.... 후...)

조금 더 깊게 들어가보면, Universal Link의 발전은 아래와 같다.

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

  • Direct Deep Link와 마찬가지로 앱 미설치자는 각 플랫폼의 앱스토어로 이동되지만, 설치 후 앱을 열엇을 때 링크가 유실되지 앟고 특정 컨텐츠로 이동됨.
  • 그러나 각각의 플랫폼별에서만 작동한다는 한계가 존재. AOS 딥링크는 AOS에서만, iOS 딥링크는 iOS에서만 작동하기 때문에 트래킹 링크를 발급받으려면 2번의 생성작업을 거쳐야 했고, 따라서 이로인해 광고를 집행할 때에도 목적이 동일한 하나의 캠페인을 AOS캠페인, iOS캠페인 이렇게 나누어져야 함.
  • 위의 문제를 해결하기 위해 원링크 개념이 등장했다.

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

예를 들어 쇼핑몰에서 뭔가 구매를 하면 카카오톡 알림톡으로 주문 내역이 오겠죠?
그 주문 내역을 확인하려고 링크를 클릭했을 때, 앱이 없다면 그 앱을 설치할 수 있는 앱 스토어로 이동하고!
앱이 있다면 바로 앱의 그 주문 내역 페이지로 이동시켜주는 것이 원링크인 것!!!!!

물론 찾아보니 개인이 만들 수 있는 것이 아니라 솔루션 회사에서 마케팅 일환으로 제공하고 있는 것 같았다...



그래서 할 수 없이 앱 개발자만 노력하면 되는 URI Scheme을 사용해보았다...😀





URI Scheme 사용


1 : 발신 앱, 수신 앱 모두 구현
2 ~ 4 : 발신 앱 구현
5 : 수신 앱 구현

1. Unique URI Scheme 등록

먼저 위에서 언급한 것과 같이 앱의 고유한 scheme을 등록해주어야 한다.
scheme을 주소라고 생각하면 이해가 빠르다.

물건을 배송할 때, 집 주소가 필요한 것 처럼 특정 앱으로 이동시키기 위해서는 앱만의 고유한 주소가 필요한 것!

프로젝트의 Info탭으로 이동한 후, 아래처럼 URL Types를 추가해준다.


Icone은 none으로 둬도 상관 없고, Role도 Editor로 둬도 상관은 없지만 아래 두가지는 꼭! 입력해야 한다.

  • identifier : 유일성을 보장하기 위해 보통 회사 도메인과 앱 이름을 합쳐서 명시하는게 일반적이나 겹치지 않을 정도로만 작성해도 무방하다.

  • URL Schemes : URL에 사용할 접두어 정의.



2. Info.plist

Info.plist > Information PropertyList 밑에
LSApplicationQueriesSchemes의 하위항목으로 호출할 앱 이름(uri scheme)을 입력한다.

Info.plist에 위의 항목을 추가해주지 않으면 아래와 같은 에러가 발생한다.

-canOpenURL: failed for URL: "호출 앱(uri scheme)" - error: "This app is not allowed to query for scheme"



3. url query String

URL(string: ) 함수를 사용하여 이동할 url과 query를 선언한다.

ex) 

url = URL(string: "urischeme://open?VC=testVC&color=purple&food=cake&birth=0716")

위의 url 예시를 보면 가장 처음 urischme은 1 번에서 말한 고유한 uri scheme을 말한다.

너무 쉬운 uri scheme을 사용하면 스마트폰 내 앱 중에 같은 uri scheme을 가진 앱들 중 랜덤으로 이동하거나 선택하여 이동할 수도 있으므로 적절하게 만드는 것이 낫다.

uri scheme 뒤쪽으로는 GET 방식으로 내가 좋아하는 색, 음식, 생일을 입력해놓았다.

이동만 할 것인지, 이동 후 어떤 View로 보낼지, 어떤 data를 전송할 것인지 key=value 형식으로 작성한다.

URL 인스턴스 형태로 전달되기 때문에 위와 같이 입력하여 전달하면 이동한 앱에서 파싱을 통해 특정 View로 보내거나 데이터를 전달받아 사용할 수 있다.



4. canOpenURL(_ url: URL)

canOpenURL(_ url: URL) -> Bool 함수를 사용하여 2에서 작성한 url의 유효성을 체크해야 한다.

ex)

if UIApplication.shared.canOpenURL(schemaUrl) {
 	UIApplication.shared.open(schemaUrl, options: [:], completionHandler: nil)
} else {
	// alert, 앱 스토어 연결 코드 등
}

유효성 결과 true(success)가 떨어지면 UIApplication.shared.open(url, options, completionHandler) 함수를 작성한다.

false로 떨어지면 url을 재확인하는 코드나 앱 스토어 연결 코드 등 자유롭게 후 처리 코드를 작성하면 된다.



5. SceneDelegate

수신하여 파싱하는 부분은 SceneDelegate에서 구현한다.

❗️❗️ 만약 SceneDelegate 파일이 없고 AppDelegate파일만 존재하는 경우, 아래 함수를 사용한다.

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

} 

❗️❗️ 저는,, sceneDelegate 파일이 있기 때문에 sceneDelegate에서 구현했습니다.

func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
	guard let url = URLContexts.first?.url else { return }
    let urlComponents = URLComponents(url: url, resolvingAgainstBaseURL: false)
    let urlQueryItems = components?.queryItems ?? []
    ...
    

URLComponents객체를 통해 queryItems 객체에 접근할 수 있다.
그래서 저렇게 작성하면 파싱 준비가 끝난 것이고, 이제 파싱을 어떻게 할 지는 본인 자유이다. 😀👍






Reference

1개의 댓글

comment-user-thumbnail
2024년 6월 25일

LSApplicationQueriesSchemes 에 등록하지않았는데도 모든앱이 다 잘열립니다. 혹시 뭔가 그동안 업데이트되어서 그런걸까요?

답글 달기