graphql 헤더에 토큰추가

이진희·2022년 2월 12일
1

graphql-challenge

목록 보기
2/2

로그인/로그아웃

  • 로그인/로그아웃 기능은 RESTapi를 사용하는게 맞다고 판단되어 authToken과 refreshToken을 받는 건 RESTapi 서버를 만들어 사용하기로 했다.
  • 인증과정
    1) 로그인 요청
    2) authToken/refreshToken 발급
    3) authToken은 리덕스에 저장, refreshToken은 cookie에 저장
    4) 인증이 필요한 요청의 헤더에 Authorization : `Bearer ${token}`형태로 토큰 넣어서 보내주기
    5) 주기적으로 authToken확인해서 만료되었는지 확인하고, 만료되었다면 refreshToken을 다시 서버에 보내 새로운 authToken로 갱신
  • graphql 요청을 보낼 때 포스팅, 파일업로드, 카테고리 생성 뮤테이션은 인증이 필요했기에 graphql 요청을 보낼 때 헤더에 토큰을 넣어서 보내주어야 했다.

헤더에 token 추가하기

  • 해당 방법은 "일회성" 으로 헤더에 토큰을 추가하는 방법이다. 요청을 보낼 때마다 기본적으로 헤더에 토큰을 넣어 보내고 싶다면 https://www.apollographql.com/docs/react/networking/authentication/ 의 Header파트를 참조!
  • 또한 훅(hook) 을 사용하는 경우에 적용가능한 방법. hook을 사용하지 않는 경우 setContext로 설정하는 것으로 알고 있음.
  1. Client 생성 시 credentials 설정 추가(CORS 에러때문에)

    import React from "react";
    import { render } from "react-dom";
    import { BrowserRouter } from "react-router-dom";
    import App from "./src/App";
    import {
      ApolloClient,
      ApolloProvider,
      HttpLink,
      InMemoryCache,
    } from "@apollo/client"; 
    
    import { createUploadLink } from "apollo-upload-client";
    // 파일 업로드를 해야해서 createUploadLink 사용.
    const httpLink = createUploadLink({
      uri: "graphql 주소",
      credentials: "same-origin", //CORS에러 처리하기 위해 추가
    });
    
    const client = new ApolloClient({
      link: httpLink,
      cache: new InMemoryCache(),
    });// 클라이언트 인스턴스 생성
    
    render(
      <ApolloProvider client={client}>//프로바이더에 클라이언트 제공
        <BrowserRouter>
          <App />
        </BrowserRouter>
      </ApolloProvider>,
      document.querySelector("#root")
    );
  2. graphql 요청보내는 곳에서 header 설정(context->headers-> [keyname] : token)

const [posting, { loading, error, data }] = useMutation(POSTING, {
    context: {
      headers: {
        authorization: `Bearer ${window.localStorage.getItem("authToken")}`,
        "Content-Type": "application/json",
      },
    },
  });

추가 보완점(여러 뮤테이션/쿼리 한번에 요청하기) -아직 미해결 참조 XXX

  • 현재는 포스팅을 할 때 썸네일을 먼저 업로드하고=> (Upload 뮤테이션), 올라간 파일의 fildId를 받아서 posting뮤테이션의 variable로 넘기는 방식으로 하고 있다.
  • 이것보다는 upload 뮤테이션과 posting 뮤테이션을 한꺼번에 묶어서 request하는 방식을 사용하는 편이 좋다고 생각했다.

1. @export decorator

  • 내가 원한 형태 : 1.Upload 뮤테이션(결과 : fileId) -> 2. Posting 뮤테이션(변수로 fileId 사용) 단, 하나의 요청에 두개의 뮤테이션이 다 실행되어야 한다.
  • 그럼 Upload 뮤테이션의 결과물을 Posting 뮤테이션의 변수로 사용해야 하는데, 이걸 어떻게 해야 할지 몰랐다.
  • @export 데코레이터를 사용하면 될 것 같다.
    ( field @export(as: "variable name") 형태)(https://github.com/apollographql/apollo-client/issues/6634)
const UPLOAD = gql`
    mutation upload($file: Upload!) {
      upload(file: $file) {
        realName
        fileId @export(as: "thumbnail")
        originalName
      }
    }
  `;
  
 const POSTING = gql`
    mutation createPost(
      $title: String!
      $tags: [String]!
      $content: String
      $thumbnail: ID
    ) {
      createPost(
        input: {
          title: $title
          tags: $tags
          content: $content
          thumbnail: $thumbnail
        }
      ) {
        postId
        tags
      }
    }
  `;

2. 여러개의 쿼리/뮤테이션 동시에 실행

이제 gql안에 두 개의 뮤테이션을 넣어서 request를 보내면 된다.
gql구문에 두개의 뮤테이션을 한꺼번에 넣어서 실행하려고 했으나, 아래와 같은 에러가 뜨면서 실행되지 않았다.

react-apollo only supports a query, subscription, or a mutation per HOC. [object Object] had 0 queries, 0 subscriptions and 2 mutations. You can use 'compose' to join multiple operation types to a component

react-apollo 는 HOC 하나 당 하나의 뮤테이션/쿼리/서브스크립션 을 지원한다는 것이다. 그 다음에 친절하게도 여러개를 한꺼번에 실행하고 싶다면 여러 쿼리/뮤테이션/서브스크립션을 합쳐주는 'compose'를 사용하면 된다고 되어 있다.

-그래서 compose를 찾아보고 있는데,,아직은 정확히 어떻게 사용하는지 모르겠다. 보완해서 처리하기!

해결책

  • 좀 허무한데,, 그냥 내가 gql을 이상하게 사용해서 그런거였다ㅠ
mutaion MUTAIONNAME($variableA:typeA,$varibleB:typeB){
	A(variable:$variableA){
    	data
    }
    B(variable:$variableB){
    	data
    }
}

위와 같은 형식으로 요청하면 잘만 실행된다. 내가 한 실수는 A와 B앞에도 mutation을 붙여버린 것,,!
원래 내부에선 mutation/query 안 붙이는데 무슨 정신으로 붙인건지 모르겠다.

profile
슬로우 스타터

0개의 댓글