개요 요즘 보면 소셜 로그인이 없는 서비스가 없고, 많은 사람들이 소셜 아이디를 통해 써드파티 서비스들에 편하게 회원가입을 하곤 합니다.
현재 Unity로 운영 중인 서비스에도 예외가 없었고 결국 카카오 로그인을 구현할 일이 생겼습니다.
우선 카카오에서는
https://developers.kakao.com/docs/latest/ko/kakaologin/common
안타깝게도 Unity용 SDK를 지원하지 않습니다… 😭
Unity가 게임엔진이다 보니 카카오 게임즈에 입점을 하고 제휴를 맺으면 가이드를 제공해 준다고 합니다..
하지만 우리 서비스는 게임이 아닌걸...😢
그렇다면 선택지는 하나밖에 없습니다..😤
Andriod와 iOS용 native SDK를 사용해야 하는데, native SDK를 사용하려면 Unity 프로젝트와 연결해줄 Bridge Script를 작성해 주어야 합니다.
이 포스팅에서는 iOS 부분만 다루어서 Unity로 카카오 로그인을 구현하는 과정을 단계별로 기술해보고자 합니다. (Andriod는 구글링해보면 참고 할만한 레퍼런스가 많더군요)
만약, 유니티로 Kakao iOS 로그인을 하는데 레퍼런스가 없어 고민이셨던 분이 계시다면
저와 함께 차근차근 진행해 봅시다🏃♂️
완성된 전체 코드는 여기 Github 링크 에서 확인하실 수 있습니다.
Framework 설정 먼저, 준비물인 SDK먼저 하단 링크에서 다운받습니다.
Kakao Developers - iOS SDK 다운로드
해당 링크에 보면 다운로드 후 설정해야 하는 부분이 많지만, 가이드 문서가 워낙 잘 되어 있습니다.
만약, Unity로 iOS App Build 후 export된 xcode프로젝트에서 후 처리를 해줄꺼라면 해당 가이드 설정법을 그대로 쭉쭉 진행하면 됩니다.
하지만, Unity에서 Build 때마다 xcode에서 다시 수작업으로 수정하는 것은 손도 많이 가고 시간이 많이 들 수 밖에 없습니다.
그래서 빌드때 마다 자동화할 수 있도록 작업을 진행할꺼에요.
카카오에서 제공하는 가이드를 보면 단계별로
Framework를 적절한 경로에 import
Build Setting에서 옵션 추가
plist에 설정 값 추가
URL Scheme 설정
이 네 가지를 따라하도록 가이드 하는데요.
Unity상에서 빌드 시 xcode에 접근하는 방법이 필요합니다.
그래서 찾아보면 Unity에서 플레이어 빌드 파이프라인 - Unity 매뉴얼 와 같은 API를 제공하는데요.
빈약한 매뉴얼이지만, Unity에서 빌드완료 후 빌드된 xcode 프로젝트를 수정할 수 있도록 API를 제공하고 있습니다! (가뭄에 단비같은…)
해당 기능의 API를 이용해서 카카오에서 제공하는 가이드 단계를 따라 밟아 봅시다.
Framework import 아래 그림과 같이 Unity 프로젝트에 Assets/Plugins/iOS/
경로에 KakaoOpenSDK.framework 파일을 위치 시켜주고, Editor/iOS
경로에 post process를 위한 KakaoPostprocess.cs
라는 스크립트 파일를 추가합니다. 이 파일은 info.plist와 빌드옵션을 수정할 스크립트인데, 이 스크립트 파일은 macOS에 설치된 Unity Editor를 통해 실행되므로 반드시 Editor
폴더 아래 두어야 합니다
그리고 아래와 같이 플랫폼 의존 컴파일 을 위해 #if UNITY_IOS
안에 다음과 같이 필요한 네임스페이스와 클래스를 정의해 주고, 빌드된 프로젝트를 수정할 수 있도록 PostProcessBuildAttribute API를 작성해 줍니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 #if UNITY_IOS using UnityEngine;using System.Collections;using UnityEditor.Callbacks;using UnityEditor;using UnityEditor.iOS.Xcode;using System.IO;using System;using System.Linq;public static class KakaoPostprocess { static string ProjectPath = string .Empty; static string PbxProjectPath = string .Empty; [PostProcessBuild(999) ] public static void OnPostProcessBuild (BuildTarget target, string path ) { if (target == BuildTarget.iOS) { ProjectPath = path; PbxProjectPath = PBXProject.GetPBXProjectPath(path); PostProcessIosProject(); } } static void PostProcessIosProject ( ) { } } #endif
Build Setting 옵션 추가 그리고 가이드의 다음 순서인 Build Settings
를 수정하기 위한 메서드를 KakaoPostprocess
class내에 선언할껀데,
셋팅 값을 수정할 메서드들을 받아서, 적용시켜 줄 재사용 가능한 helper 메서드를 Action delegate를 이용해 선언해 줍니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 #region helpers static void ModifyProject (Action<PBXProject> modifier ) { try { PBXProject project = new PBXProject(); project.ReadFromString(File.ReadAllText(PbxProjectPath)); modifier(project); File.WriteAllText(PbxProjectPath, project.WriteToString()); } catch (Exception e) { Debug.LogException(e); } } #endregion
이따가 추가할 Info.plist 수정 스크립트도 추가할 것이기 때문에 미관상 helpers
라는 region으로 묶어 줬습니다.
그리고 가이드에 나온 [Linking] > [Other Linker Flags]에 -all_load
옵션을 추가해 주는 부분을 아래 메서드로 선언합니다.
1 2 3 4 5 6 7 static void AddLinkerFlag (PBXProject project ){ project.ReadFromString(File.ReadAllText(PbxProjectPath)); string buildTarget = project.TargetGuidByName(PBXProject.GetUnityTargetName()); project.AddBuildProperty(buildTarget, "OTHER_LDFLAGS" , "-all_load" ); }
이렇게 선언하고 이따가 로직이 수행될 PostProcessIosProject
에 다음과 같이 호출만 해주면 build setting에 옵션 추가는 끝입니다.
1 2 3 4 static void PostProcessIosProject ( ){ ModifyProject(AddLinkerFlag); }
plist 설정 이제 plist에 카카오 SDK의 API를 호출하기 위한 속성들인 네이티브 앱 키(KAKAO_APP_KEY
)와 LSApplicationQueiresSchemes
를 등록하기 위해 등록한 내 애플리케이션에서 네이티브 앱 키를 가져와 아래와 같이 아까 선언한 ProjectPath
변수 위에 상수로 선언해 줍니다. (아직 등록하지 않으셨다면 등록과정은 이 링크 에 있습니다)
1 2 const string KAKAO_APP_KEY = "your-own-kakao-app-key" ;const string KAKAO_URL_SCHEME = "kakao" + KAKAO_APP_KEY;
또, helpers
region에 ModifyProject
메서드와 같이 재사용 가능한 수정사항을 적용하는 ModifyPlist
메서드를 region안에 선언해 줍니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 static void ModifyPlist (Action<PlistDocument> modifier ){ try { var plistInfoFile = new PlistDocument(); string infoPlistPath = Path.Combine(ProjectPath, "Info.plist" ); plistInfoFile.ReadFromString(File.ReadAllText(infoPlistPath)); modifier(plistInfoFile); File.WriteAllText(infoPlistPath, plistInfoFile.WriteToString()); } catch (Exception e) { Debug.LogException(e); } }
이제 KAKAO_APP_KEY
와 ApplicationQueriesSchemes
를 등록해주는 메서드를 아래와 같이 class 내에 추가해 줍니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 static void AddKakaoAppKey (PlistDocument plist ){ plist.root.SetString("KAKAO_APP_KEY" , KAKAO_APP_KEY); } static void AddApplicationQuerySceheme (PlistDocument plist ){ const string LSApplicationQueriesSchemes = "LSApplicationQueriesSchemes" ; string [] kakaoSchemes = { "kakaokompassauth" , KAKAO_URL_SCHEME, "kakaolink" , "kakaotalk-5.9.7" }; PlistElementArray appsArray; appsArray = plist.root.values.ContainsKey(LSApplicationQueriesSchemes) ? (PlistElementArray)plist.root.values[LSApplicationQueriesSchemes] : plist.root.CreateArray(LSApplicationQueriesSchemes); kakaoSchemes.ToList().ForEach(appsArray.AddString); }
참고로, LSApplicationQueriesSchemes
에 kakaoSchemes
을 등록하는 것은 나의 앱에서 카카오톡앱을 실행해 줄 경로를 설정해 주는 역할을 수행합니다.
이제 Build Setting 메서드를 호출했던 것 처럼 PostProcessIosProject
메서드에서 호출해 주면 됩니다
1 2 3 4 5 6 7 static void PostProcessIosProject ( ){ ModifyProject(AddLinkerFlag); ModifyPlist(AddKakaoAppKey); ModifyPlist(AddApplicationQuerySceheme); }
URL Scheme 설정 iOS에서는 다른 앱이나 웹에서 나의 앱을 실행하거나 통신을 하기 위해서 URL Scheme이라는 수단을 제공합니다.
카카오 로그인 서비스들은 OAuth방식의 인증방식을 사용하기 때문에, 카카오톡 앱이나 카카오 로그인 웹페이지를 통해서 카카오 서버 로 부터 인증을 받아야 하는데, 인증 후 다시 나의 앱을 Open 해주기 위해서 필요한 주소 경로라고 보시면 될 것 같습니다.
그래서 카카오 로그인 시 카카오톡앱으로 전환되었다가 다시 나의 앱으로 돌아올 수 있는 것 입니다.
이 부분을 info URL Types에 scheme을 작성해주기 위해 아래와 같은 메서드를 선언해 줍니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 static void AddKakaoTalkUrlScheme (PlistDocument plist ){ const string CFBundleURLTypes = "CFBundleURLTypes" ; const string CFBundleURLSchemes = "CFBundleURLSchemes" ; if (!plist.root.values.ContainsKey(CFBundleURLTypes)) { plist.root.CreateArray(CFBundleURLTypes); } var cFBundleURLTypesElem = plist.root.values[CFBundleURLTypes] as PlistElementArray; var getSocialUrlSchemesArray = new PlistElementArray(); getSocialUrlSchemesArray.AddString(KAKAO_URL_SCHEME); PlistElementDict getSocialSchemeElem = cFBundleURLTypesElem.AddDict(); getSocialSchemeElem.values[CFBundleURLSchemes] = getSocialUrlSchemesArray; }
그리고 PostProcessIosProject
에 호출해 주면 Post processing 작업은 이것으로 완료입니다!
1 2 3 4 5 6 7 8 9 10 static void PostProcessIosProject ( ) { ModifyProject(AddLinkerFlag); ModifyPlist(AddKakaoAppKey); ModifyPlist(AddApplicationQuerySceheme); ModifyPlist(AddKakaoTalkUrlScheme); Debug.Log("KAKAO SDK setup for iOS project" ); }
아래는 KakaoPostprocess.cs
파일의 전체 코드입니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 #if UNITY_IOS using UnityEngine;using System.Collections;using UnityEditor.Callbacks;using UnityEditor;using UnityEditor.iOS.Xcode;using System.IO;using System;using System.Linq;public static class KakaoPostprocess { const string KAKAO_APP_KEY = "your-own-kakao-app-key" ; const string KAKAO_URL_SCHEME = "kakao" + KAKAO_APP_KEY; static string ProjectPath = string .Empty; static string PbxProjectPath = string .Empty; [PostProcessBuild(999) ] public static void OnPostProcessBuild (BuildTarget target, string path ) { if (target == BuildTarget.iOS) { ProjectPath = path; PbxProjectPath = PBXProject.GetPBXProjectPath(path); PostProcessIosProject(); } } static void PostProcessIosProject ( ) { ModifyProject(AddLinkerFlag); ModifyPlist(AddKakaoAppKey); ModifyPlist(AddApplicationQuerySceheme); ModifyPlist(AddKakaoTalkUrlScheme); Debug.Log("KAKAO SDK setup for iOS project" ); } static void AddKakaoTalkUrlScheme (PlistDocument plist ) { const string CFBundleURLTypes = "CFBundleURLTypes" ; const string CFBundleURLSchemes = "CFBundleURLSchemes" ; if (!plist.root.values.ContainsKey(CFBundleURLTypes)) { plist.root.CreateArray(CFBundleURLTypes); } var cFBundleURLTypesElem = plist.root.values[CFBundleURLTypes] as PlistElementArray; var getSocialUrlSchemesArray = new PlistElementArray(); getSocialUrlSchemesArray.AddString(KAKAO_URL_SCHEME); PlistElementDict getSocialSchemeElem = cFBundleURLTypesElem.AddDict(); getSocialSchemeElem.values[CFBundleURLSchemes] = getSocialUrlSchemesArray; } static void AddKakaoAppKey (PlistDocument plist ) { plist.root.SetString("KAKAO_APP_KEY" , KAKAO_APP_KEY); } static void AddApplicationQuerySceheme (PlistDocument plist ) { const string LSApplicationQueriesSchemes = "LSApplicationQueriesSchemes" ; string [] kakaoSchemes = { "kakaokompassauth" , KAKAO_URL_SCHEME, "kakaolink" , "kakaotalk-5.9.7" }; PlistElementArray appsArray; appsArray = plist.root.values.ContainsKey(LSApplicationQueriesSchemes) ? (PlistElementArray)plist.root.values[LSApplicationQueriesSchemes] : plist.root.CreateArray(LSApplicationQueriesSchemes); kakaoSchemes.ToList().ForEach(appsArray.AddString); } static void AddLinkerFlag (PBXProject project ) { project.ReadFromString(File.ReadAllText(PbxProjectPath)); string buildTarget = project.TargetGuidByName(PBXProject.GetUnityTargetName()); project.AddBuildProperty(buildTarget, "OTHER_LDFLAGS" , "-all_load" ); } #region helpers static void ModifyProject (Action<PBXProject> modifier ) { try { PBXProject project = new PBXProject(); project.ReadFromString(File.ReadAllText(PbxProjectPath)); modifier(project); File.WriteAllText(PbxProjectPath, project.WriteToString()); } catch (Exception e) { Debug.LogException(e); } } static void ModifyPlist (Action<PlistDocument> modifier ) { try { var plistInfoFile = new PlistDocument(); string infoPlistPath = Path.Combine(ProjectPath, "Info.plist" ); plistInfoFile.ReadFromString(File.ReadAllText(infoPlistPath)); modifier(plistInfoFile); File.WriteAllText(infoPlistPath, plistInfoFile.WriteToString()); } catch (Exception e) { Debug.LogException(e); } } #endregion } #endif
이제 post processing 과정은 여기까지입니다.
이 스크립트가 실행되어 xcode 프로젝트가 빌드되면, 아래의 이미지들과 같이 프로젝트 설정이 변경되어 export되어야 합니다.
Build Target > Build Settings > Linking > Other Linker Flags
Build Target > Info > Custom iOS Target Properties
Build Target > Info > URL Types
결론 여기까지 Kakao SDK 설치 과정까진 끝났고, 남은 건 iOS native 코드를 작성하고 bridge를 통해 Unity상에서 코드를 불러와 실행시키는 과정만 남았습니다. 🤩
다음 포스팅에 이어서 AppDelegate를 override하는 과정과 native code를 가져와 실행할 bridge 코드 작성 부분을 다루도록 하겠습니다.
참고