[Unity] Kakao login - iOS (1/2)

개요

요즘 보면 소셜 로그인이 없는 서비스가 없고, 많은 사람들이 소셜 아이디를 통해 써드파티 서비스들에 편하게 회원가입을 하곤 합니다.

현재 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)] // @param - order index in the callback
public static void OnPostProcessBuild(BuildTarget target, string path)
{
// 빌드 후 실행되는 callback func
if (target == BuildTarget.iOS) // iOS 플랫폼일 경우만
{
ProjectPath = path;
PbxProjectPath = PBXProject.GetPBXProjectPath(path);

PostProcessIosProject();
}
}

static void PostProcessIosProject()
{
// do something
}
}
#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

// 빌드 설정 변경 helper
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
// 빌드 Linker 설정 추가
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
// Info.plist 설정 변경 helper
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_KEYApplicationQueriesSchemes를 등록해주는 메서드를 아래와 같이 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
// KAKAO_APP_KEY property 추가
static void AddKakaoAppKey(PlistDocument plist)
{
plist.root.SetString("KAKAO_APP_KEY", KAKAO_APP_KEY);
}

// LSApplicationQueriesSchemes property 추가
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);
}

참고로, LSApplicationQueriesSchemeskakaoSchemes을 등록하는 것은 나의 앱에서 카카오톡앱을 실행해 줄 경로를 설정해 주는 역할을 수행합니다.

이제 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
// URL Scheme 설정 추가
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)] // 빌드 후 실행되는 callback func
public static void OnPostProcessBuild(BuildTarget target, string path)
{
// iOS 플랫폼일 경우만
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");
}

// URL Scheme 설정 추가
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;
}

// KAKAO_APP_KEY property 추가
static void AddKakaoAppKey(PlistDocument plist)
{
plist.root.SetString("KAKAO_APP_KEY", KAKAO_APP_KEY);
}

// LSApplicationQueriesSchemes property 추가
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);
}

// 빌드 Linker 설정 추가
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

// 빌드 설정 변경 helper
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);
}
}

// Info.plist 설정 변경 helper
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 코드 작성 부분을 다루도록 하겠습니다.


참고