프론트엔드 데브코스 5기 TIL 59 - GraphQL, Apollo

김영현·2023년 12월 19일
0

TIL

목록 보기
68/129

GraphQL

Rest API vs GraphQL API

둘 다 인터넷을 통한 데이터 교환을 위한 API를 설계하는 두 가지 접근 방식이지만, 방법과 반환 데이터가 다르다.

예를들어, 사람의 전화번호와 마지막 구매내역이 필요하다고 하자.
REST API/person이라는 URL로 요청하여 사람의 전화번호를 반환받고 /purchase라는 URL로 요청하여 구매내역을 반환받는다.
GraphQL은 그저 person이라는 데이터를 요청할때 필요한 phone-number, purchase프로퍼티를 요청하면 된다.

또한 REST APIGET, POST, PUT, DELETE같은 HTTP 동사를 적극적으로 사용하지만, GraphQLPOST만 사용한다.

차이점, 장 단점을 살펴보면 더욱 많지만 여기서 생략하고 실전으로 가보겠다. 한번 겪어보고 다시 공부하는게 더 잘된다!

용법

  • POST/graphql로만 요청해야함
  • 백엔드에서 미리 타입을 정의해야함
  • 요청은 query 변경은 mutation을 사용

=> 백엔드 개발자가 귀찮아진다 ㅋㅋ

단점

러닝커브가 높다
HTTP캐싱이 어렵다
필요한 필드를 모두 작성해야함
파일 업로드에 대한 명쾌한 방법x

예시

https://graphql-kr.github.io/learn/queries/#


strapi를 이용하여 GraphQL서버 만들기!

서버 킨담에 좌측 MaketPlace들어가서 graphql검색후 설치
이후 http://localhost:1337/graphql 로 접속하면된다.

짜좐.

쿼리

한번 쿼리를 해보자! Docs를 열어보면 내가 만든 컬렉션과 필드에 대해 계단식으로 잘 나와있다.

띠용. 권한이 없어서 그랬다.
좌측 하단 Http 헤더 설정부분에 Bear토큰 추가함.
{ "Authorization": "Bearer <token>" }
이렇게 추가하면된다. 여기서 token은 strapi에서 발급받은 API토큰이다


여기서 발급받은거!

짜잔 잘 쿼리됐다.

실제로 요청할때마다 POST메서드로 동작한다.

문서 추가하기

강의에서는 그냥 user필드를 사용했지만 내 환경에서는 user_permission_user필드로 되어있다.

strapi들어가보면 실제로 추가된 데이터가...! 혼자 프로젝트 할때 정말 요긴하게 사용할 것 같다.

문서 변경하기

잘 작동한다!

문서 삭제하기

잘 삭제되었다. 한번 더 누르면 문서가 없다고 나온다

CRUD를 이리 간단히 구현할수 있다니 놀랍다!


Apollo Client

리액트에서 GraphQL을 쉽게 사용할 수 있게 도와주는 라이브러리다.

https://www.apollographql.com/docs/

사용방법은 다음과 같다.

//App.js
const client = new ApolloClient({
  uri: "http://localhost:1337/graphql",
  cache: new InMemoryCache(),
});

const Container = styled.div`
  width: 400px;
  margin: 0 auto;
`;

function App() {
  return (
    <ApolloProvider client={client}>
      <Container>
        <Header>Todo</Header>
        <NewTasForm />
        <TaskList />
      </Container>
    </ApolloProvider>
  );
}

ApolloClient의 인스턴스를 생성하여 ApolloProvider의 프롭스로 넣어준다.

  • new ApolloClient({...}) : uri로 GQL서버의 주소를 넣어준다. cache로컬에 저장하기위한 말 그대로의 캐시다. 즉, 이미 캐시된 결과는 바로 리턴해준다.
    Apollo 캐시에 관하여 자세한 설명은 여기에...
    결국 스토어라고 생각하면 된다.

쿼리(뮤테이션)는 아래와 같이 하면된다.

//NewTaskForm.js

const CREATE_TASK = gql`
  mutation CreateTask($content: String!) {
    createTask(data: { content: $content, complete: false }) {
      data {
        id
      }
    }
  }
`;

export const NewTasForm = () => {
  const [task, setTask] = useState("");
  const [createTask, { data, loading, error }] = useMutation(CREATE_TASK);

  const client = useApolloClient();

  const handleSubmit = useCallback(
    (e) => {
      e.preventDefault();
      createTask({ variables: { content: task } });
      setTask("");
      client.refetchQueries({ include: ["GetTasks"] });
    },
    [createTask, task, client]
  );

  return (
    <Form onSubmit={handleSubmit}>
      <Input
        placeholder="Add Task"
        value={task}
        onChange={(e) => setTask(e.target.value)}
      />
      <SubmitButton>Add</SubmitButton>
    </Form>
  );
};
  • useMutation() : apollo-client에서 제공하는 훅으로 GraphQL을 도와준다.(쿼리)
    상수화해놓은 CREATE_TASK를 자세히 보면 GQL mutations문이다.

  • useApolloClient() : apollo-client의 기능을 끌어다 사용할 수 있다. 여기서는 refetch때문에 불러와 사용했다. 이때 캐시를 업데이트한다.

Vs Redux

리덕스는 불필요한 액션, 리듀서 등을 생성하지만 Apollo는 gql과 그냥 소통만 슥슥하여 데이터를 던져준다(더 선언적임).

하지만 로컬상태(UI)등은 어떻게하지?
놀랍게도 로컬 상태도 지원함...!

이 부분은 자세히 알아봐야겠지만, 만약 서버측에서 GQL을 지원한다면 apollo-client+gql기반으로 작업하는게 restAPI+redux보다 훨씬 빠를 수도 있겠다는 생각이듬...


느낀점

NextJs, GQL, Apollo 등 새로운 기술을 배우니 재밌기도 하면서 기본기에 대한 불안감이 다시 스멀스멀 올라온다. 새것도 좋지만 결국 기초가 짱짱해야 새로운 기술의 펀더멘탈을 잘 흡수할 수 있다...!

profile
모르는 것을 모른다고 하기

0개의 댓글