플러터 IOS 로그인 deep link 에러

kakao_flutter_sdk_user 1.5.0


안녕하세요 플러터로 앱 개발 중 에러가 발생해서 확인 요청드립니다
안드로이드에서는 정상 동작하나 iOS에서는 로그인 이후 아래와 같은 에러가 발생합니다

https://developers.kakao.com/docs/latest/ko/getting-started/sdk-flutter#setup-scheme-ios
링크 가이드에 따라서 설정도 동일하게 했는데 문제가 발생합니다!

1.4.3에서는 정상 동작하는데 1.5.0으로 버전을 올리면 문제가 생기네요 확인 후 답변 부탁드립니다

error

Deep Link does not contain valid required params. URL params: {
    code = "5NTcoXRMt6H4okjZyLn8-7u_qXdVxVPagl3xkHd1M99Dcv0-B8EANQvsz6XiPb1TkKggBgo9dNkAAAGKg8azFg";
}

동일한 문제 발생하여 댓글 남깁니다.
저같은 경우는 ios deep link 사용을 위해

<key>FlutterDeepLinkingEnabled</key>
<false/>

설정 해둔 상태이며, 위 deeplink 설정을 false로 하면 동작에 문제는 없으나, 딥링크가 동작 하지 않아… 해결이 필요한 상태입니다.

1개의 좋아요

@anon61296854 안녕하세요. 플러터에서 딥링크를 구현할 수 있는 방법이 다양하다보니 말씀주신 내용만으로는 정확하게 어떤 상황인지 파악하기가 어렵습니다ㅠㅠ 딥링크 구현부 코드, 사용하는 패키지, 링크 주소, 재현 영상 등을 추가로 알려주시면 이슈파악하는데 큰 도움이 될 것 같습니다. 또한 커스텀 스킴을 사용했는지 애플의 유니버셜 링크를 사용한건지 등의 정보도 같이 전달 부탁드립니다. 그리고 앱이 실행 중인지 여부에 따라 딥링크 동작 방식이 다르기 때문에 어떤 경우에 이슈가 발생하는지도 알려주시면 감사하겠습니다. ex - 앱 종료 상태에서 딥링크를 통해 앱을 실행시키는 경우, 앱이 백그라운드에서 실행 중이고 딥링크를 사용해 앱으로 전환하는 경우

@junddao 안녕하세요 위의 답변에서 말씀드렸듯이 플러터에서 딥링크를 구현할 수 있는 방법이 다양하다보니 말씀주신 내용만으로는 어떤 상황인지 파악하기가 어렵습니다. 위 답변 확인 후 조금 더 구체적으로 설명 부탁드리겠습니다.

확인이 늦었습니다.

flutter deep link 구현 후 kakao에서 넘어오는

kakao64917f18…f2cd31360576b://oauth?code=JctSzqf_sTX83ox5lIb1_hYi …

요녀석을 go_router 에서 받아먹고 있네요.
flutter 코드에서 /?code=JctSzqf_sTX83ox5lIb1_hYiuPz2we … 요녀석을 받아 먹어서 예외처리 해둔 상태입니다.

  • kakao_flutter_sdk: ^1.5.0
  • Flutter 3.13.4

@junddao
go_router에서 kakao${app_key} 스킴을 가로챈다는 현상자체가 잘 이해가 가지 않는데요, 조금 번거로우시더라도 이슈 재현되는 간단한 샘플 프로젝트 만들어서 공유해주실 수 있을까요? (혹은 현재 프로젝트를 저에게 개인메시지로 보내주셔도 좋습니다)

전달해주신 내용을 바탕으로 직접 테스트했을 때는 이슈가 재현되지 않고, 현상에 대해서 잘 이해가 가지 않아서 원인 파악이 어려운 상태입니다ㅠㅠ

안녕하세요 1년이 지난 글이네요.
저희도 현재 동일한 현상이 발생하고 있어 글을 남깁니다.

go_router 패키지를 보면 redirect라는 부분이 있습니다. 보통은 이 부분을 페이지 이동 시 로그인 여부를 측정한다던가의 액션을 취한 뒤 다른 링크로 보내던, 원래 링크로 보내던 하는 역할로 쓰더라고요.
스크린샷 2024-09-11 22.14.40

그런데 카카오 로그인 후 저희 앱을 호출할 때 deeplink를 통해 호출 시, 여기서 일반적인 경우라면 앱의 원래 페이지로 돌아와 이후 액션 처리를 진행해야 하는데, 여기서 go_router의 redirect를 실행해버려서 의도치않게 페이지 이동이 진행되어 버립니다.

테스트로 go_router를 제외하고 해보니, 원래 카카오 로그인 액션대로 작동하는 것을 확인하였습니다.

글을 쓰신 분께도 궁금한게, 해결이 되었으니 더이상 글을 남기지 않으셨을텐데 어떻게 해결하신 것인지 궁금합니다!

감사합니다 :slight_smile:

@geniusk 안녕하세요

사용하는 sdk 버전, 이슈 발생하는 플랫폼 (Android / iOS / Web), 로그인 코드, 이슈 상황에서의 로그 첨부 부탁드리겠습니다.
추가로 GoRouter 설정도 공유해주시면 이슈 확인하는데 도움이 될 것 같아요

안녕하세요

SDK버전: 1.9.5
이슈 발생 플랫폼: Android / iOS
로그인 코드는 예제와 동일합니다.
https://developers.kakao.com/docs/latest/ko/kakaologin/flutter#kakaologin-sample

로그로 보면

  1. UserApi.instance.loginWithKakaoTalk(); 호출
  2. 카카오 측에서 딥링크로 kakaoec…00d86://oauth/?code=b8aS1U…-2W8wW6V7rJg 호출
  3. 자사 앱 실행
  4. 1번 아래 코드 실행하지 않고, GoRouter에 redirect 로직을 타버림 (이때 redirect 설정이 없으면 기본으로 return null을 시켜서 original link인 루트로 가버립니다. 이전 루트는 /abc 였지만 그냥 루트로 가버리는 현상 발생)

위 절차대로 흘러가 4번에서 문제가 발생하고 있습니다.
GoRouter 버전은 14.2.7 이며, 특별히 따로 설정한 부분은 없고, initialLocation이 /abc입니다.

빠른 답변 감사합니다

추석 연휴가 끼어있어서 답변이 조금 늦었습니다

말씀하신 내용으로 아래와 같이 샘플 코드 작성해서 구현해봤는데요, 이슈가 재현되지 않고 정상적으로 동작하는 것을 확인했습니다.

조금 번거로우시더라도 샘플 프로젝트를 만들어서 kakao_flutter_sdk와 go_router 의 의존성만 추가해서 구현했을 때 이슈가 재현되는지 확인부탁드리고, 여전히 이슈가 발생한다면 구현하신 코드 첨부 부탁드리겠습니다.

참고로 제가 테스트한 환경은 kakao_flutter_sdk 1.9.5 버전, go_router 14.2.7 버전입니다.

main.dart

import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:go_router_login_error/test.dart';
import 'package:kakao_flutter_sdk/kakao_flutter_sdk.dart';

void main() {
  KakaoSdk.init(nativeAppKey: 'NATIVE_APP_KEY'); // 실제 앱 키 입력

  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  final _router = GoRouter(
    initialLocation: '/home',
    routes: [
      GoRoute(
        path: '/home',
        builder: (_, __) => const MyHomePage(title: 'Flutter Demo Home Page'),
        routes: [GoRoute(path: 'test', builder: (_, __) => const TestPage())],
        redirect: (BuildContext context, GoRouterState state) {
          if (state.uri.scheme.toString() == 'https' ||
              state.uri.scheme.toString() == 'applinks') {
            print('deepLink O');
          } else {
            print('deepLink X');
          }
          print(state.uri.toString());

          return null;
        },
      )
    ],
  );

  MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp.router(
      routerConfig: _router,
      title: 'Flutter Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: Text(widget.title),
      ),
      body: const Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'Home',
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          context.go("/home/test");
        },
        child: const Icon(Icons.add),
      ),
    );
  }
}

test.dart

import 'package:flutter/material.dart';
import 'package:kakao_flutter_sdk/kakao_flutter_sdk.dart';

class TestPage extends StatelessWidget {
  const TestPage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Test Page')),
      body: const Center(
        child: Text('Test'),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () async {
          try {
            await UserApi.instance.loginWithKakaoTalk();
            ScaffoldMessenger.of(context)
                .showSnackBar(SnackBar(content: Text('Login Success')));
          } catch (e) {
            ScaffoldMessenger.of(context)
                .showSnackBar(SnackBar(content: Text('Login Error: $e')));
          }
        },
        child: const Icon(Icons.add),
      ),
    );
  }
}

안녕하세요.
비슷한 증상을 겪고 있어 댓글 답니다.

아마 위에서 작성하신 샘플 코드에서는 문제없이 동작할 것이라 생각합니다.
기존에 문제 되는 부분은 gorouter current path가 root가 아닌 경우에 발생하는 것이라,
샘플 코드처럼 root path에서 테스트를 하면 정상 동작이 될 것으로보입니다.

login page를 생성해서 gorouter route에 등록 후 root path에서 login page로 push 한 후에 로그인을 시도하면,
위에서 발생하는 root page로 redirect 되는 문제를 확인 하 실 수 있을 것 같네요.

해결을 위해서는 redirect에서 아래와 같이 처리하면 임시방편으로 처리는 가능할 것 같습니다.
(login을 할 수 있는 페이지가 여러군데에 있다면… 골치아플것 같긴하네요)

redirect: (context, state) {
if (state.uri.toString().contains(‘kakao’)) {
print(‘GoRouter it is kakao deeplink’);
return state.namedLocation('‘loginPage’);
}
return null;
}

1개의 좋아요

@savain @junddao @geniusk @anon61296854

안녕하세요

최근 비슷한 이슈 제보가 더 들어와서 조금 더 확인을 해보았는데요, Custom URL Scheme을 사용하는 경우 go_router에서 redirect 처리를 하기 때문에 발생한 이슈인 것으로 파악했습니다.

아래 내용 참고하셔서 코드 수정하시면 이슈 해결될 것으로 보이는데요, 적용해보시고 문제가 있다면 추가로 제보 부탁드리겠습니다.

2개의 좋아요

어머나… 빠른 답변 감사합니다!

1개의 좋아요