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

kyb1208tg님의 프로필 이미지

작성한 질문수

[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스

30-01-login-refreshtoken / login-refreshtoken-success

newAccessToken 이 바로 적용되지 않습니다

23.10.01 22:00 작성

·

331

0

  const errorLink = onError(({ graphQLErrors, operation, forward }) => {
    //1. 에러 캐치
    if (typeof graphQLErrors !== "undefined") {
      for (const err of graphQLErrors) {
        //1-2. 해당 에러가 토큰만료 에러인지 체크
        if (err.extensions.code === "UNAUTHENTICATED") {
          return fromPromise(
            //2. refreshtoken으로 accessToken을 재발급 받기
            getAccessToken().then((newAccessToken) => {
              setAccessToken(newAccessToken ?? "");
              //3. 재발급 받은 accesstoken 으로 방금 실패한 쿼리 실행하기
              operation.setContext({
                header: {
                  ...operation.getContext().headers, //기존의 authorization: Bearer '만료된 토큰'
                  Authorization: `Bearer ${newAccessToken}`, //3-2 authorization 만 바꿔치기
                },
              });
            })
          ).flatMap(() => forward(operation)); //3-3 방금 수정한 쿼리 재요청하기
        }
      }
    }
  });

수업이랑 동일하게 코드를 작성하였으나 버튼을 눌러도 재발급된 accessToken 이 들어가지 않아 error 가 발생하고 2번이상 눌러야지만 accesstoken 이 제대로 수정되서 정상적으로 실행됩니다. 어디가 문제일까요?

답변 3

0

kyb1208tg님의 프로필 이미지
kyb1208tg
질문자

2023. 10. 29. 12:51

export const getAccessToken = async (): Promise<string | undefined> => {
  try {
    const graphQlClient = new GraphQLClient(
      "https://backend-practice.codebootcamp.co.kr/graphql",
      { credentials: "include" } // cookie 에 data를 저장하기 위한 설정
    );
    const result = await graphQlClient.request<
      Pick<IMutation, "restoreAccessToken">
    >(RESTORE_ACCESS_TOKEN);
    const newAccessToken = result?.restoreAccessToken.accessToken;

    console.log(newAccessToken);
    return newAccessToken;
  } catch (error) {
    if (error instanceof Error) {
      console.log(error.message);
    }
  }
};

getAccessToken 도 제대로 작성된거 같은데 윗방식대로 작성해야 되는걸까요?

0

노원두님의 프로필 이미지
노원두
지식공유자

2023. 10. 06. 14:47

안녕하세요! kyb1208tg님!

위 코드를 보면, 수업의 내용과 크게 다른 것이 없이 잘 작성하신 것 같아요!

따라서, getAccessToken() 파트의 코드를 한 번 점검해 보실 필요가 있을 것 같아요!

0

인프런 AI 인턴님의 프로필 이미지

2023. 10. 03. 22:06

안녕하세요, 인프런 AI 인턴이에요.

버튼을 눌러도 재발급된 accessToken이 바로 적용되지 않는 문제가 발생하는군요. 이 문제의 원인은 아마 비동기적으로 실행되는 코드 때문일 것으로 추측됩니다. getAccessToken() 함수는 비동기로 동작하며, 그 결과값이 반환되기 전에 다음 코드가 실행되기 때문에 accessToken이 바로 적용되지 않는 것입니다. 이 때문에 에러가 발생하고, 2번 이상의 버튼 클릭이 필요한 것 같습니다.

해결 방법으로는 getAccessToken().then() 메소드 블록 내에서 operation.setContext()를 호출하고, forward(operation)을 반환하는 대신 forward(operation).flatMap(() => ...)을 사용하여 프로미스 체인을 연결해 보세요. 이렇게 하면 getAccessToken() 함수의 결과가 반영된 후에만 다음 코드가 실행됩니다.

다음은 수정된 코드입니다:

const errorLink = onError(({ graphQLErrors, operation, forward }) => {
  if (typeof graphQLErrors !== "undefined") {
    for (const err of graphQLErrors) {
      if (err.extensions.code === "UNAUTHENTICATED") {
        return fromPromise(
          getAccessToken().then((newAccessToken) => {
            setAccessToken(newAccessToken ?? "");
            operation.setContext({
              header: {
                ...operation.getContext().headers,
                Authorization: `Bearer ${newAccessToken}`,
              },
            });
            return forward(operation).flatMap((response) => {
              if (response.errors) {
                throw new Error("GraphQL Error");
              }
              return response;
            });
          })
        );
      }
    }
  }
});

위의 코드를 사용하여 한 번 시도해 보시고, 문제가 해결되었는지 확인해 주세요. 추가 도움이 필요하시면 언제든지 말씀해 주세요. 감사합니다.