[코드팩토리] [중급] Flutter 진짜 실전! 상태관리, 캐시관리, Code Generation, GoRouter, 인증로직 등 중수가 되기 위한 필수 스킬들!
안녕하세요 코팩님! 이제 드디어 GoRouter에 대한 강의를 들으려고 합니다. 그런데 지금 GoRouter가 v13까지 업데이트 되어있네요 ㄷㄷ 혹시 GoRouter v13 추가로 강의하실 계획 있으신가요?? 그리고 제가 v13으로 강의를 듣고 코딩을 해도 크게 문제 없을까요?
[코드팩토리] [중급] Flutter 진짜 실전! 상태관리, 캐시관리, Code Generation, GoRouter, 인증로직 등 중수가 되기 위한 필수 스킬들!
[ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: type 'List<IModelWithId>' is not a subtype of type 'List<RatingModel>?' of 'data' #0 CursorPagination.copyWith (package:codefactory_lecture/common/model/cursor_pagination_model.dart:28:14) #1 Pagination.paginate (package:codefactory_lecture/common/provider/pagination_provider.dart:91:22) <asynchronous suspension> 이건 디테일 스크린에서 rating을 fetchmore로 더 불러올때 나는 에러입니다. [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: type 'List<IModelWithId>' is not a subtype of type 'List<RestaurantModel>?' of 'data' #0 CursorPagination.copyWith (package:codefactory_lecture/common/model/cursor_pagination_model.dart:28:14) #1 Pagination.paginate (package:codefactory_lecture/common/provider/pagination_provider.dart:91:22) <asynchronous suspension> 그리고 이건 restaurant_screen.dart에서 쭉 내려서 데이터를 더 불러오려고 할 때 에러입니다. 둘 다 비슷한 에러입니다. state = resp.copyWith(data: [ ...pState.data, ...resp.data, ]); 페이지네이션 코드 중 이 부분에 문제가 있었고, CursorPagination copyWith({ CursorPaginationMeta? meta, List<T>? data, }) { return CursorPagination<T>( meta: meta ?? this.meta, data: data ?? this.data); } 여기서 List<T>? data의 타입이 맞지 않는 것 같습니다. 데이터 타입이 알맞게 각각 들어가야 할텐데, 자꾸 List<IModelWithId> 타입이 들어가는 거 같아요... 어느 부분을 고쳐야 할까요?
[코드팩토리] [중급] Flutter 진짜 실전! 상태관리, 캐시관리, Code Generation, GoRouter, 인증로직 등 중수가 되기 위한 필수 스킬들!
결론적으로 JWT토큰도 서버측 페이지(예, index.php)에 하드코딩해서 클라인언트 앱으로 전송할 수 있네요... 문제의 핵심은 제가 임시로 구축한 서버(아파치 웹서버)로 요청하는 주소 끝에 정확한 페이지 주소를 붙이든(예,http://제 도메인 주소/auth/token/index.php) 아니면 http://제 도메인 주소/auth/token/와 같은식으로 끝에 "/"는 꼭 붙여야지 응답을 받을 수 있는데, 제가 강의를 따라서 그대로 요청하는 주소를 아래와 같이 끝에 "/"를 붙이지 않고 Dio 요청을 했기 때문에 생기는 문제였습니다. http://제 도메인 주소/auth/token http://제 도메인 주소/auth/login 여전히 POSTMAN으로 요청을 테스트해보면, POSTMAN에서는 요청하는 주소 끝에 "/"붙이지 않더라도 정상적으로 응답을 받을 수 있는데, 왜 Dio로 요청했을 때는 응답을 받을 수가 없는지는 알수가 없지만 혹시라도 저하고 똑같은 문제를 겪으시는 분이 계실까봐 글남깁니다...^^;; ................................ 이하 기존 작성했 던 글....................... 안녕하세요? 너무 초보적인 질문같아서 좀 창피하기도 한데, 다름이 아니고, 중급강의 최종 소스를 바탕으로 제가 예전에 만들어 보고 싶었던 앱을 만들려고 하고 있습니다. 백엔드는 예전에 PHP를 좀 다뤄본적이 있어서 일단은, 그래도 친숙한 PHP로 백엔드를 만들어볼려고 하는데,로그인 단계부터 잘 진행이 안되네요..ㅠㅠ 강사님 강의 덕분에 JWT 및 토큰 관리 개념을 배워서 이걸 나중에 PHP로 구현해볼려고는 하고 있기는 한데, 우선 flutter로 앱 만드는 것에 집중하고 싶어서, 일단은 앱에서 로그인 요청을 하면 서버측 페이지에 "하드코딩"한 JWT 토큰 정보를 사용자측 앱으로 전달되게해서 로그인을 할 수 있게 하고 싶은데, 아무리 해도 로그인이 안되네요. 제가 임시로 구축한 사이트에 강의에 맞춰서 아래 경로를 맞췄고 http://제 도메인 주소/auth/login 이 페이지를 호출하면 POSTMAN에서 로그인 후 응답받았던 아래 토큰을 복사해서 페이지에 담은 후 클라이언트 앱으로 전달되게 했는데 아무리 해도 로그인이 안되고 에러가 뜹니다. { "refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InRlc3RAY29kZWZhY3RvcnkuYWkiLCJzdWIiOiJmNTViMzJkMi00ZDY4LTRjMWUtYTNjYS1kYTlkN2QwZDkyZTUiLCJ0eXBlIjoicmVmcmVzaCIsImlhdCI6MTcwNjI1ODYwMCwiZXhwIjoxNzA2MzQ1MDAwfQ.dvMz8WgEk-28q3F2J4E5CLLUURO1w8S7MlgqGje5ils", "accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InRlc3RAY29kZWZhY3RvcnkuYWkiLCJzdWIiOiJmNTViMzJkMi00ZDY4LTRjMWUtYTNjYS1kYTlkN2QwZDkyZTUiLCJ0eXBlIjoiYWNjZXNzIiwiaWF0IjoxNzA2MjU4NjAwLCJleHAiOjE3MDYyNTg5MDB9.lnCJ7Okwvk1xh2WNz8n4oXbHWczy1H72sVb4znOXWUs" } 제 짧은 소견으로는 어찌되었건 클라이언트앱으로 토큰 정보가 전송되면 로그인이 진행되어야 할 텐데 안되는 이유가 무엇인지 모르겠습니다... ........................ ....................... 위의 질문을 쓰고, 몇가지 더 테스트를 해본 결과를 종합하면, Dio에서 JWT형식으로 된 토큰(하드코딩한 토큰)이 담긴 응답은 내부적으로 어떤 검증 절차를 거쳐서 오류를 일으키는 것 같습니다. 오류는 다음과 같은 오류가 뜨는데, 다른 페이지는 아래와 같은 오류가 뜨지 않고 제대로 정보를 수신합니다. I/flutter (22276): Dio 에러 상세정보: I/flutter (22276): 타입: DioErrorType.response I/flutter (22276): 메시지: Http status error [301] I/flutter (22276): 에러: Http status error [301] I/flutter (22276): 응답: <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN"> I/flutter (22276): <html><head> I/flutter (22276): <title>301 Moved Permanently</title> I/flutter (22276): </head><body> I/flutter (22276): <h1>Moved Permanently</h1> I/flutter (22276): <p>The document has moved <a href="http://제 도메인 주소/auth/token/">here</a>.</p> I/flutter (22276): </body></html> 결론적으로 하드코딩된 JWT 토큰 은 Dio 패키지를 통해서 정상적으로 응답을 수신할 수 없으며, JWT 토큰을 제대로 서버측에서 수신하려면 서버측에 JWT 토큰을 제대로 인증하고 발급할 수 있게 구축을 해야한다로 귀결되는 것 같습니다. 이러한 결론이 맞을까요? 이 /auth/login/auth/login
[코드팩토리] [중급] Flutter 진짜 실전! 상태관리, 캐시관리, Code Generation, GoRouter, 인증로직 등 중수가 되기 위한 필수 스킬들!
Restaurant_screen.dart에서 스크롤시 type 'CursorPagination<dynamic>' is not a subtype of type 'CursorPagination<RestaurantModel>' in type cast 오류나시는 분들 다다음 강의에서 오류 해결 방법 나옵니당
[코드팩토리] [중급] Flutter 진짜 실전! 상태관리, 캐시관리, Code Generation, GoRouter, 인증로직 등 중수가 되기 위한 필수 스킬들!
E/flutter ( 9967): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: DioException [bad response]: This exception was thrown because the response has a status code of 403 and RequestOptions.validateStatus was configured to throw for this status code. E/flutter ( 9967): The status code of 403 has the following meaning: "Client error - the request contains bad syntax or cannot be fulfilled" E/flutter ( 9967): Read more about status codes at https://developer.mozilla.org/en-US/docs/Web/HTTP/Status E/flutter ( 9967): In order to resolve this exception you typically have either to verify and fix your request code or you have to fix the server code. E/flutter ( 9967): E/flutter ( 9967): #0 DioMixin.fetch.<anonymous closure> (package:dio/src/dio_mixin.dart:507:7) E/flutter ( 9967): #1 _FutureListener.handleError (dart:async/future_impl.dart:180:22) E/flutter ( 9967): #2 Future._propagateToListeners.handleError (dart:async/future_impl.dart:858:47) E/flutter ( 9967): #3 Future._propagateToListeners (dart:async/future_impl.dart:879:13) E/flutter ( 9967): #4 Future._completeError (dart:async/future_impl.dart:655:5) E/flutter ( 9967): #5 _SyncCompleter._completeError (dart:async/future_impl.dart:63:12) E/flutter ( 9967): #6 _Completer.completeError (dart:async/future_impl.dart:27:5) E/flutter ( 9967): #7 Future.any.onError (dart:async/future.dart:618:45) E/flutter ( 9967): #8 _RootZone.runBinary (dart:async/zone.dart:1666:54) E/flutter ( 9967): #9 _FutureListener.handleError (dart:async/future_impl.dart:177:22) E/flutter ( 9967): #10 Future._propagateToListeners.handleError (dart:async/future_impl.dart:858:47) E/flutter ( 9967): #11 Future._propagateToListeners (dart:async/future_impl.dart:879:13) E/flutter ( 9967): #12 Future._completeError (dart:async/future_impl.dart:655:5) E/flutter ( 9967): #13 Future._asyncCompleteError.<anonymous closure> (dart:async/future_impl.dart:745:7) E/flutter ( 9967): #14 _microtaskLoop (dart:async/schedule_microtask.dart:40:21) E/flutter ( 9967): #15 _startMicrotaskLoop (dart:async/schedule_microtask.dart:49:5) IOS 시뮬레이터로 잘만 해왔다가, 안드로이드 에뮬로도 잘 되는지 확인해보려고 했는데 로그인 할 때 403에러가 뜨네요... 어떻게 해결해야 할까요? // localhost const emulatorIP = '10.0.2.2:3000'; const simulatorIP = '127.0.0.1:3000'; final ip = Platform.isAndroid ? emulatorIP : simulatorIP;
[코드팩토리] [중급] Flutter 진짜 실전! 상태관리, 캐시관리, Code Generation, GoRouter, 인증로직 등 중수가 되기 위한 필수 스킬들!
안녕하세요! provider적용하기 강의 듣고 있습니다. 궁금한게, 프로젝트를 진행할 수 록 여러개의 provider를 생성하게 되는데 그럼 이 모든 provider의 인스턴스가 사용하지 않아도 무조건 앱 실행시 다 인스턴스화 되어 메모리에 올라가게 되나요? 제가 객체지향관련 개념이 플러터하면서 처음이라 조금 헷갈립니다. 감사합니다.
[코드팩토리] [중급] Flutter 진짜 실전! 상태관리, 캐시관리, Code Generation, GoRouter, 인증로직 등 중수가 되기 위한 필수 스킬들!
안녕하세요! 코드팩토리님 현재 장바구니 관련 강의를 듣고 있습니다만, 「RefreshToken 만료되면 로그아웃」 강의까지가 토큰 처리 관련해서 질문이 있습니다. lib/dio/dio.dart 파일에서 토큰 관련 처리를 하는걸로 알고있습니다. accessToken이 만료되면 onError 메소드가 실행되고 accessToken이 재발급되는 구조로 이해하고 있는데 맞나요..?? 제가 이해하고 있는게 맞는거라면 onError라는 메소드가 실행이 되어야 하는데 onError메소드는 실행이 안되고 401에러(잘못된 토큰입니다.)가 난 상태에서 멈춰버리더라구요.. (vscode로 공부중입니다.) 코드팩토리님의 소스( https://github.com/codefactory-co/flutter-lv2-rest-api )도 받아서 실행해보았습니다만, 저하고 똑같은 에러가 발생되고 앱이 멈췄습니다. onError메소드가 실행이 안되는 이유를 잘모르겠습니다..ㅠ 혹시 몰라 저의 깃허브도 올립니다. (dev브랜치로 봐주시면 감사하겠습니다.) https://github.com/limchangmin95/flutter_delivery/tree/dev
[코드팩토리] [중급] Flutter 진짜 실전! 상태관리, 캐시관리, Code Generation, GoRouter, 인증로직 등 중수가 되기 위한 필수 스킬들!
- 학습 관련 질문을 남겨주세요. 상세히 작성하면 더 좋아요! - 먼저 유사한 질문이 있었는지 검색해보세요. - 서로 예의를 지키며 존중하는 문화를 만들어가요. - 잠깐! 인프런 서비스 운영 관련 문의는 1:1 문의하기를 이용해주세요. 코드팩토리 디스코드 https://bit.ly/3HzRzUM Flutter 강의를 구매하시면 코드팩토리 디스코드 서버 플러터 프리미엄 채널에 들어오실 수 있습니다! 디스코드 서버에 들어오시고 저에게 메세지로 강의를 구매하신 이메일을 보내주시면 프리미엄 채널에 등록해드려요! 프리미엄 채널에 들어오시면 모든 질의응답 최우선으로 답변해드립니다! provider를 사용할 때 ref.read 는 on click 함수처럼 이벤트있는 곳에서 한번만 사용할 때 쓴다고 이해했는데,splashScreen의 checkToken함수 내부에서는 ref.read (secureStorageProvider)로 사용하고restaurantDetailScreen의 getRestaurantDetail 함수 내부에서는 ref.watch (dioProvider)로 사용한 이유가 뭘까요? 그리고 ref.listen은 이것들과 어떻게 다른 상황에서 쓰이는지 헷갈립니다.
[코드팩토리] [중급] Flutter 진짜 실전! 상태관리, 캐시관리, Code Generation, GoRouter, 인증로직 등 중수가 되기 위한 필수 스킬들!
- 학습 관련 질문을 남겨주세요. 상세히 작성하면 더 좋아요! - 먼저 유사한 질문이 있었는지 검색해보세요. - 서로 예의를 지키며 존중하는 문화를 만들어가요. - 잠깐! 인프런 서비스 운영 관련 문의는 1:1 문의하기를 이용해주세요. 코드팩토리 디스코드 https://bit.ly/3HzRzUM Flutter 강의를 구매하시면 코드팩토리 디스코드 서버 플러터 프리미엄 채널에 들어오실 수 있습니다! 디스코드 서버에 들어오시고 저에게 메세지로 강의를 구매하신 이메일을 보내주시면 프리미엄 채널에 등록해드려요! 프리미엄 채널에 들어오시면 모든 질의응답 최우선으로 답변해드립니다! 플러터 시뮬레이터로 로그인을 시도하는데 아래와 같은 오류가 나요..[VERBOSE-2:dart_vm_ initializer.cc (41)] Unhandled Exception: DioException [connection error]: The connection errored: Connection refused This indicates an error which most likely cannot be solved by the library. Error: SocketException: Connection refused (OS Error: Connection refused, errno = 61), address = 127.0.0.1, port = 534693000번 포트가 아니라 53469로 사용하고 있어서 나는 오류인 것은 알겠는데,어떻게 시뮬레이터를 3000번 포트에서 실행할 수 있을지 모르겠어요.
[코드팩토리] [중급] Flutter 진짜 실전! 상태관리, 캐시관리, Code Generation, GoRouter, 인증로직 등 중수가 되기 위한 필수 스킬들!
type 'CursorPaginationLoading' is not a subtype of type 'CursorPagination<dynamic>' in type cast pagination-1 까지 잘 진행했는데 2~4까지 묶어서 실습하는 중 위와 같은 오류 때문에 계속 loading 바가 나옵니다. 다시 한번 소스코드를 강사님 강의를 보며 점검해 봤는데, 찾을 수가 없어 도움을 청합니다.
[코드팩토리] [중급] Flutter 진짜 실전! 상태관리, 캐시관리, Code Generation, GoRouter, 인증로직 등 중수가 되기 위한 필수 스킬들!
강사님 강의를 쭉 보고, 앱을 개발 해보고 있는데요. 모델에 List<String>이 있고, toJson으로 생성해서 GET 형태로 서버로 보냈는데, List<String>에 'aaaa', 'bbbb'라는 값이 있을때, name=aaaa&name=bbbb 라고, 중복된 변수명을 가지고 생성이 되어서 서버로 전송하더군요. 이렇게 생성되는게 정상적인 형태인가요? 아니면, 옵션 같은걸 넣어야하는건지, 몰라서 문의드립니다.
[코드팩토리] [중급] Flutter 진짜 실전! 상태관리, 캐시관리, Code Generation, GoRouter, 인증로직 등 중수가 되기 위한 필수 스킬들!
이미지 서버로 firebase를 선택했는데 업로드 속도가 많이 느려 로글르 살펴보니 error getting token java.util.concurrent.ExecutionException: com.googl e.firebase.internal.api.FirebaseNoSignedInUserException: Please sign in before trying to get a token. ' 'Error getting App Check token; using placeholder token instead. Error: com.google.firebase.FirebaseException: No AppCheckProvider installed. W/NetworkRequest(16203): no auth token for request' 위와 같은 두 에러가 뜨네요.. 구글에 검색해도 잘 안나와서 질문 남깁니다. 위와 같은 에러를 마주친 경험이 있을까요??