강의

멘토링

로드맵

Inflearn brand logo image

인프런 커뮤니티 질문&답변

호갱님의 프로필 이미지
호갱

작성한 질문수

[코드팩토리] [중급] Flutter 진짜 실전! 상태관리, 캐시관리, Code Generation, GoRouter, 인증로직 등 중수가 되기 위한 필수 스킬들!

강의중 37.Dio onErrorInterceptor 작업하기 dio 관련 질문입니다.

작성

·

45

0

안녕하세요 강사님

 

accessToken 만료시 refreshToken 으로 다시 발급받는과정에서 질문이 있습니다.

dio.dart 소스에 onError 에서 print 로 로그를 호출하고 있는데요

  @override
  void onError(DioException err, ErrorInterceptorHandler handler) async {
    print("[ERR] [${err.requestOptions.method}] ${err.requestOptions.uri}");

    final refreshToken = await storage.read(key: REFRESH_TOKEN_KEY);

    if (refreshToken == null) {

      return handler.reject(err);
    }

    final isStatus401 = err.response?.statusCode == 401;
    final isPathRefresh = err.requestOptions.path == "/auth/token";

    if (isStatus401 && !isPathRefresh) {
      final dio = Dio();

      try {
        final resp = await dio.post(
          "http://$ip/auth/token",
          options: Options(headers: {"authorization": "Bearer $refreshToken"}),
        );

        final accessToken = resp.data["accessToken"];

        final options = err.requestOptions;

        options.headers.addAll({
          "authorization": "Bearer $accessToken",
        });


        await storage.write(key: ACCESS_TOKEN_KEY, value: accessToken);

        final response = await dio.fetch(options);

        return handler.resolve(response);
      } on DioException catch (e) {

        return handler.reject(e);
      }
    }

    // return handler.reject(err);
    super.onError(err, handler);
  }

 

호출하는 restaurant_detail_screen.dart 를 보면

  Future<RestaurantDetailModel> getRestaurantDetail() async {
    final dio = Dio();

    dio.interceptors.add(
        CustomInterceptor(storage: storage)
    );

    final repository = RestaurantRepository(dio, baseUrl: "http://$ip/restaurant");
    return repository.getRestaurantDetail(id: id);
  }

 

이런식으로 되어있거든요?

그래서 refreshToken 으로 토큰을 재발급 받고 storage에도 새로 저장하였으나

dio 가 매번 호출되는 방식입니다.

그러다 보니 매번 onError 가 호출이되고 에러 로그가 찍힐수 밖에 없는 구조입니다.

싱글톤 방식으로 수정이 되지 않으면 해당 에러는 계속 날것 같은데

혹시 이후에 해당부분이 수정이 되는 강의 부분이 있을까요?

답변 2

0

코드팩토리님의 프로필 이미지
코드팩토리
지식공유자

안녕하세요!

말씀하신 부분 강의에서 추가로 수정하는 부분은 아닙니다.

싱글턴으로 해결 하신걸까요?

감사합니다!

0

안녕하세요, 인프런 AI 인턴입니다. 호갱님, 질문 주셔서 감사합니다.

제공하신 코드와 설명을 토대로, Dio 객체가 매번 새로 생성됨에 따라 동일한 CustomInterceptor가 매번 추가되며, 모든 요청에서 또다시 새롭게 추가된 인터셉터가 에러를 발생시키고 에러 로그를 찍는 상황을 설명해주신 것 같습니다.

현재의 구조에서 Dio 객체가 매번 새로 생성되기 때문에, 매번 생성된 Dio 인스턴스에 추가된 인터셉터 역시 새로워지며, 결국 재귀적으로 onError가 호출되는 현상이 발생하는 것입니다.

이를 해결하기 위한 가장 좋은 방법은 다음과 같습니다:

  1. Dio 객체를 싱글톤으로 관리: 동일한 Dio 인스턴스를 여러 곳에서 사용할 수 있도록 싱글톤으로 관리하면, 인터셉터가 한 번만 설정되고, 매번 새로워지지 않으므로 onError가 반복 호출되지 않습니다.

  2. 인터셉터 내부에서 상태 저장: 인터셉터를 통한 상태의 변화를 한곳에서 관리하도록 하여, 불필요한 요청이 다시 발생하지 않도록 합니다.

현재 강의에서는 구체적으로 이러한 내용이 언제 다뤄지는지에 대한 정보는 없습니다. 다만, 이러한 패턴은 일반적으로 많이 사용되는 방식이므로, 직접 구현해 보시기를 권장합니다.

다음은 관련된 질문이 이미 토론되었던 Q&A 페이지입니다. 비슷한 문제를 겪고 있는 다른 사용자들의 질문을 참고하실 수 있습니다:
- 만료된 토큰 처리 및 dio 인터셉터 예시
- Http Status Error [401] 처리 방법

저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다.
현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏
추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.

호갱님의 프로필 이미지
호갱

작성한 질문수

질문하기