iOS 로그인 Crash이슈 (AuthAPI.swift)

문의 시, 사용하시는 SDK 버전 정보와 디벨로퍼스 앱ID를 알려주세요.


SDK 버전 : 2.24.1
앱 ID : 1208724


앱 출시 이후 crash 이슈가 다수 보고되고 있어서 문의 드립니다.


OS Version: iOS 18.4.1 (22E252)
Report Version: 104

Exception Type: EXC_BREAKPOINT (SIGTRAP)
Exception Codes: 0 at 0x00000001874478c4
Crashed Thread: 1

Application Specific Information:
bearer > KakaoSDKAuth/AuthApi.swift > Swift/StringLegacy.swift

Thread 1 Crashed:
0 libswiftCore.dylib 0x3086838c4 _assertionFailure
1 libswiftCore.dylib 0x3086f0d20 swift_unexpectedError
2 Actively 0x20460f10c AuthApi.refreshToken
3 Actively 0x20461c514 AuthRequestRetrier.retry
4 Actively 0x20461b030 AuthRequestRetrier
5 Actively 0x2045d4428 Interceptor.retry
6 Actively 0x2045d4538 Interceptor
7 Actively 0x204571b9c Session.retryResult
8 Actively 0x204555ad0 Request.retryOrFinish
9 Actively 0x2045556c8 Request.didCompleteTask
10 Actively 0x20457db4c closure in SessionDelegate.urlSession
11 Actively 0x204572b18 Session.didCompleteTask
12 Actively 0x20457da30 SessionDelegate.urlSession
13 Actively 0x20457dc54 SessionDelegate.urlSession
14 AppLovinQualityService 0x104ca884c __65-[SafeDKNetworkInterceptor hookSessionDelegateMethods:withClass:]_block_invoke_2 (SafeDKNetworkInterceptor.m:1178)
15 CFNetwork 0x30e451e54 __79-[__NSCFURLSessionDelegateWrapper task:didCompleteWithError:completionHandler:]_block_invoke
16 Foundation 0x309206160 NSINDEXSET_IS_CALLING_OUT_TO_A_BOOL_BLOCK
17 Foundation 0x30927af68 -[NSBlockOperation main]
18 Foundation 0x30927af00 NSOPERATION_IS_INVOKING_MAIN
19 Foundation 0x309279070 -[NSOperation start]
20 Foundation 0x309278de8 NSOPERATIONQUEUE_IS_STARTING_AN_OPERATION
21 Foundation 0x309278a04 __NSOQSchedule_f
22 libdispatch.dylib 0x31b8212b4 _dispatch_block_async_invoke2
23 libdispatch.dylib 0x31b82b580 _dispatch_client_callout
24 libdispatch.dylib 0x31b81a2cc _dispatch_lane_serial_drain
25 libdispatch.dylib 0x31b81addc _dispatch_lane_invoke
26 libdispatch.dylib 0x31b81a134 _dispatch_lane_serial_drain
27 libdispatch.dylib 0x31b81ada8 _dispatch_lane_invoke
28 libdispatch.dylib 0x31b8251d8 _dispatch_root_queue_drain_deferred_wlh
29 libdispatch.dylib 0x31b824a5c _dispatch_workloop_worker_thread
30 libsystem_pthread.dylib 0x42041665c _pthread_wqthread

안녕하세요.

구현하신 관련 코드블럭 기재 부탁드려요.

유니티 프로젝트에 Objective-C를 위한 SwiftBrige를 구현하여 KakaoSDK 사용하였습니다.
앱 실행 또는 앱을 내렸다가 다시 올릴때 발생한다고 합니다.
(테스트 빌드에서는 문제 없이 실행되고 잇습니다)
미리 감사드립니다.

// openURL처리(UnityAppController)
extern “C”
{
extern KakaoSDKBridge* bridge;
}

  • (BOOL)application:(UIApplication*)app openURL:(NSURL*)url options:(NSDictionary<NSString*, id>*)options
    {
    NSLog(@“openURL:%@”, url);
    if( [bridge isKakaoTalkLoginUrlWithUrl:url])
    {
    return [bridge handleOpenUrlWithUrl:url];
    }

    return [super application:app openURL:url options:options];
    }

// KakaoSDKBridge.swift
import Foundation
import KakaoSDKCommon
import KakaoSDKAuth
import KakaoSDKUser

@objc
public class KakaoSDKBridge : NSObject {
@objc
public func initSDK()
{
KakaoSDK.initSDK(appKey:“a7c85962cac74e1ee05fdb1c117ab2aa”)
}
@objc
public func isKakaoLoginAvailable() → Bool
{
return UserApi.isKakaoTalkLoginAvailable()
}
@objc
public func checkToken(callback:@escaping (Bool)->Void)
{
if AuthApi.hasToken() == false
{
print(“[kakao] hasToken false”)
callback(false)
return;
}
UserApi.shared.accessTokenInfo{ (info,error) in
if error != nil
{
print(“[kakao] accessTokenInfo error: (String(describing: error))”)
callback(false)
}
else
{
print(“[kakao] accessTokenInfo success”)
callback(true)
}
}
}
@objc
public func me(callback:@escaping (Bool,String?)->Void)
{
UserApi.shared.me { (user, error) in
if error != nil || user == nil
{
print(“[kakao] me error:(String(describing:error))”)
callback(false, nil)
}
else
{
callback(true, self.makeUserInfo(user:user))
}
}
}
func makeUserInfo(user:User?) → String
{
var dic: [String:Any] = [:]
if let user = user
{
if let id = user.id
{
dic[“id”] = id;
}
if let account = user.kakaoAccount
{
if let name = account.name
{
dic[“name”] = name
}
if let gender = account.gender
{
dic[“gender”] = gender.rawValue
}
if let phoneNumber = account.phoneNumber
{
dic[“phoneNumber”] = phoneNumber
}
if let isKorean = account.isKorean
{
dic[“isKorean”] = isKorean
}
if let birthDay = account.birthday
{
dic[“birthday”] = birthDay
}
if let birthYear = account.birthyear
{
dic[“birthyear”] = birthYear
}
if let ageRange = account.ageRange
{
dic[“ageRange”] = ageRange.rawValue
}
if let profile = account.profile
{
if let nickname = profile.nickname
{
dic[“profile.nickname”] = nickname
}
if let profileImageUrl = profile.profileImageUrl
{
dic[“profile.profileImageUrl”] = profileImageUrl.absoluteString
}
if let thumbnailImageUrl = profile.thumbnailImageUrl
{
dic[“profile.thumnailImageUrl”] = thumbnailImageUrl.absoluteString
}
if let isDefaultImage = profile.isDefaultImage
{
dic[“profile.isDefaultImage”] = isDefaultImage
}
}
}
}
do
{
let jsonData = try JSONSerialization.data(withJSONObject: dic, options:)
let stringData = String(data:jsonData, encoding:.utf8)
if let result = stringData
{
return result;
}
else
{
return “{}”;
}
}
catch(let e)
{
print(e.localizedDescription)
return “{}”;
}
}
@objc
public func logout(callback:@escaping (Bool)->Void)
{
UserApi.shared.logout { (error) in
callback( error != nil)
}
}
@objc
public func unlink(callback:@escaping (Bool)->Void)
{
UserApi.shared.unlink { (error) in
callback( error != nil)
}
}
@objc
public func login(callback:@escaping (Bool,String?)->Void)
{
UserApi.shared.loginWithKakaoTalk { (authToken,error) in
if error != nil
{
print(“[kakao] login error:(String(describing: error))”)
if let sdkError = error as? SdkError
{
if sdkError.isAuthFailed
{
//동의 화면 취소 확인을 위해 필요함
print(“[kakao] login authFailed:(sdkError.getAuthError().reason.rawValue)”)
callback(false, sdkError.getAuthError().reason.rawValue)
}
else
{
callback(false, error?.localizedDescription)
}
}
else
{
callback(false, error?.localizedDescription)
}
}
else if authToken == nil
{
print(“[kakao] login token is nil”)
callback(false, “token is null”)
}
else
{
print(“[kakao] login success”)
callback(true, nil)
}
}
}
@objc
public func isKakaoTalkLoginUrl(url:URL) → Bool
{
return AuthApi.isKakaoTalkLoginUrl(url)
}
@MainActor @objc
public func handleOpenUrl(url:URL) → Bool
{
return AuthController.handleOpenUrl(url:url)
}
}

// KakaoUnityPlugin.mm
#import “UnityFramework/UnityFramework-Swift.h”

typedef void (*commonResultDelegate)(bool result);
typedef void (loginResultDelegate)(bool result,const char error);
typedef void (meResultDelegate)(bool level,const char userInfo);

extern “C” {

char* getCString(NSString *source)
{
if( source == nil )
return nil;
const char *sourceUTF8 = [source UTF8String];
char result = (char) malloc( strlen( sourceUTF8 ) + 1 );
strcpy( result, sourceUTF8 );
return result;
}

KakaoSDKBridge* bridge = [[KakaoSDKBridge alloc] init];

void KakaoUnityPlugin_init()
{
//[bridge initSDK];
}

bool KakaoUnityPlugin_isKakaoLoginAvailable()
{
return [bridge isKakaoLoginAvailable];
}

void KakaoUnityPlugin_checkToken(commonResultDelegate callback)
{
[bridge checkTokenWithCallback:^(BOOL result) {
callback(result);
}];
}

void KakaoUnityPlugin_me(meResultDelegate callback)
{
[bridge meWithCallback:^(BOOL result, NSString* _Nullable userInfo) {
callback(result, getCString(userInfo));
}];
}

void KakaoUnityPlugin_logout(commonResultDelegate callback)
{
[bridge logoutWithCallback:^(BOOL result) {
callback(result);
}];
}

void KakaoUnityPlugin_unlink(commonResultDelegate callback)
{
[bridge unlinkWithCallback:^(BOOL result) {
callback(result);
}];
}

void KakaoUnityPlugin_login(loginResultDelegate callback)
{
[bridge loginWithCallback:^(BOOL result, NSString* _Nullable error) {
callback(result, getCString(error));
}];
}

}

안녕하세요. iOS SDK 담당자입니다.

제공주신 로그를 확인했을 때 refreshToken 중 appKey가 셋팅되어 있지 않아 크래시가 발생되는 것으로 보입니다.

2.24.0 이후로 내부적으로 토큰 최신화를 하고 있어 앱 초기화 시 KakaoSDK.initSDK가 선제되어야 합니다.

제공주신 KakaoSDKBridge 내의 initSDK()가 AppDelegate나 SceneDelegate 때 초기화가 되는지 확인 부탁드립니다.

빠른 답변 감사합니다.

SDK초기화는 AppDelegate(didFinishLaunchingWithOptions)에 구현되어 있습니다.

앱이 런칭되고 약간의 시간이 지난 후에 crash되는것으로 추정되고 있습니다.

- (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions
{
    //[self registerBackgroundTask];

    [super application:application didFinishLaunchingWithOptions:launchOptions];

    NSString* key = @"LaunchWithRemoteNotification";
    NSDictionary* userInfo = launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey];
    if( userInfo != nil)
    {
        NSError* error = nil;
        NSData* jsonObj = [NSJSONSerialization dataWithJSONObject:userInfo options:0 error:&error];

        if( error)
        {
            [[NSUserDefaults standardUserDefaults] setObject:error.localizedDescription forKey:key];
            [[NSUserDefaults standardUserDefaults] synchronize];
        }
        else
        {
            NSString* str = [[NSString alloc] initWithData:jsonObj encoding:NSUTF8StringEncoding];

            [[NSUserDefaults standardUserDefaults] setObject:str forKey:key];
            [[NSUserDefaults standardUserDefaults] synchronize];
        }
    }
    else
    {
        NSData* data = [[NSUserDefaults standardUserDefaults] objectForKey:key];
        if( data != nil)
        {
            [[NSUserDefaults standardUserDefaults] removeObjectForKey:key];
            [[NSUserDefaults standardUserDefaults] synchronize];
        }
    }

    registerUpdateObserver();
    //[self scheduleBackgroundTask];
    //[self test];

    [bridge initSDK];
    
    return true;
}

제공주신 stackTrace 상에서 확인했을 때, AppLovin SDK가 swizzle 하여 네트워크 요청을 조정한 듯한데요.
AppLovin SDK를 제거하여 시도하여도 동일한 크래시가 발생하는지 확인 부탁드립니다.

라이브에서만 발생하고 있는 이슈이고 AppLovin SDK를 당장제거하긴 곤란하여.
일단 KakaoSDK버전을 2.23.0으로 다운그레이드 해보려고 합니다.
(2.24.0에서는 2.24.1 대비 crash빈도가 낮아서 일단 2.24.0으로 라이브 릴리즈 먼저 진행)

추가로 문의 있으면 댓글 달겠습니다.
도움 주셔서 감사합니다.