[GraphQL][React] apollo-client에 Header 설정하기 - JWT

koline·2023년 11월 24일
0

GraphQL

목록 보기
7/8

앞선 apollo-client 세팅 방법 포스팅에서 클라이언트 서버를 생성하고 React 앱과 연동하였다.

개발을 하다보면 여기 구조를 바꿔야할 때가 있는데, 그 중 하나가 JsonWebToken (JWT)를 사용할 때 로그인 후 토큰을 발급 받고 이후 요청을 보낼 때 요청 해더에 authorization 정보를 헤더에 포함해 주는게 일반적인데, 이를 위해서는 main.ts 구조를 변경해야 한다.

1. main.ts에 context 설정 추가

import { setContext } from "@apollo/client/link/context";

const authLink = setContext((_, { headers }) => {
  // server로 부터 발급 받은 토큰 가져오기
  const accessToken = store.getState().authToken.accessToken;
  return {
    headers: {
      ...headers,
      authorization: accessToken ? `Bearer ${accessToken}` : "",
    }
  }
});

apollo-client에 내부적으로 요청의 context를 수정할 수 있는 setContext 함수를 제공한다.

이 함수를 사용하여 헤더를 설정해주면 된다. 위에서 store.getState() 부분은 redux에 토큰을 저장해 두었을 때를 예시로 든 것이고 토큰을 가져와서 헤더에 설정만 해주면 된다.

2. context 설정을 httpLink에 적용

const authLink = setContext((_, { headers }) => {
  // server로 부터 발급 받은 토큰 가져오기
  const accessToken = store.getState().authToken.accessToken;
  return {
    headers: {
      ...headers,
      authorization: accessToken ? `Bearer ${accessToken}` : "",
    }
  }
});

// Apollo의 concat 기능으로 합쳐준다
const link = ApolloLink.from([authLink.concat(httpLink)])

const client = new ApolloClient({
  link: link,
  cache: new InMemoryCache(),
  defaultOptions: {
    watchQuery: {
      fetchPolicy: 'cache-and-network',
    },
  },
});

const rootElement = document.getElementById('root');
if (!rootElement) throw new Error('Failed to find the root element');
const root = ReactDOM.createRoot(rootElement);

root.render(
  <Provider store={store}>
    <ApolloProvider client={client}>
      <BrowserRouter>
        <App />
      </BrowserRouter>
    </ApolloProvider>
  </Provider>
)

이렇게 설정을 해두면 httpLink에 위의 setContext 함수를 통해 추가한 헤더 설정을 적용이 된다. 위 설정을 적용하면 useQueryuseMutation을 사용할 때마다 일괄적으로 헤더설정이 추가된다. 만약 특정 쿼리에만 헤더설정을 하고 싶다면 해당 useQuery 또는 useMutation 에 헤더설정을 추가해야 한다.

또한 위 설정은 일괄적으로 쿼리에 적용된다는 점에서 middleware 같은 역할을 할 수도 있는데 예를 들어 쿼리에 어떤 응답이 왔을 때의 동작을 정의하여 적용하고 싶다면 아래와 같이 추가해 줄수 있다.

import { onError } from "@apollo/client/link/error";
import { handleGraphQLError } from './handlers/GraphQLErrorHandlers.tsx';

// 에러 발생시 동작 정의
const errorLink = onError((err: any) => {
  if (err.graphQLErrors) {
    handleGraphQLError(err);
  }
})

const link = ApolloLink.from([errorLink, authLink.concat(httpLink)])



참조


[GraphQL][React] apollo-client 세팅하기 - React, Typescript

profile
개발공부를해보자

0개의 댓글

관련 채용 정보