이번에 GraphQL, Axios를 합쳐서 사용해볼 수 있는 기회가 생겼습니다.
이런 좋은 기회를 기록하지않고 넘어가기엔 너무 아까운 것 같아 포스팅을 해보려합니다.
REST API의 단점을 때려잡은 GraphQL을 알아보고 어떻게 Axios와 혼합하여 사용할 수 있는지 알아보겠습니다.
GraphQL
GraphQL을 정리해서 이야기해보면 웹 클라이언트가 서버로부터 데이터를 효율적으로 가져오는 것이 목적인 쿼리 언어입니다.
'REST API랑 뭐가 달라? 정보 가져오는 건 똑같은데?' 라는 질문을 하시는 분들도 있겠죠?
GraphQL은 REST API와는 다르게 클라이언트가 필요한 데이터만 정확하게 요청할 수 있는 유연성을 제공합니다.
REST API는 서버에서 정의한 엔드포인트에 요청을 보내면, 서버는 해당 엔드포인트에서 제공하는 모든 데이터를 반환합니다.
이는 필요한 데이터 외에도 부수적인 다른 데이터까지 모두 받아오는 오버패칭을 유발할 수 있다는 단점을 가지고 있다는 이야기입니다.
하지만 GraphQL은 클라이언트가 필요한 데이터의 구조와 양을 정확하게 지정할 수 있습니다.
이는 네트워크 트래픽을 줄이고 불필요한 데이터를 전송하지 않아 성능을 향상시킬 수 있습니다.
또한 GraphQL은 하나의 엔드포인트로 모든 데이터에 접근할 수 있어서 여러 개의 REST 엔드포인트를 호출할 필요가 없습니다.
REST API로 "새로운 상품", "핫 딜 상품" 두 정보를 수신한다고 한다면, 각각의 정보에 통신을 해야하기 때문에 두개의 api 통신이 생기게 됩니다.
하지만 GraphQL은 한번의 통신(엔드포인트)으로 "필요한 정보"만 골라서 접근할 수 있기때문에 개발자 입장에서 통신 관리를 훨씬 수월하게 할 수 있습니다.
그러나 GraphQL을 사용함에 있어 몇 가지 신경써야하는 부분이 있습니다.
첫째, 서버에서 데이터를 요청하고 응답하는 방식이 REST와 다르기 때문에 서버 측 구현이 조금 더 복잡할 수 있습니다.
둘째, GraphQL 쿼리는 일반적으로 더 많은 작업을 수행하기 때문에 쿼리 성능을 최적화해야 할 수 있습니다.
셋째, 무조건 GraphQL이 좋다고는 이야기할 수 없습니다. 프로덕트에 대한 모든 데이터가 필요한 경우, 모든 데이터가 필요한 경우에도 GraphQL을 사용할 수 있지만, 모든 필요한 데이터를 작성해야 하므로 REST보다 더 많은 작업이 필요할 수 있습니다. REST API는 한 엔드포인트에 모든 정보가 담겨있기 때문에 모든 데이터가 필요한 경우 REST 통신이 더 유리하다고 할 수 있겠습니다.
GraphQL 문법
쿼리 (Query)
- 클라이언트가 서버로 데이터를 요청할 때 사용합니다.
- 필드와 인자를 사용하여 원하는 데이터를 지정할 수 있습니다.
예시 :
query {
user(id: 123) {
name
email
posts {
title
content
}
}
}
뮤테이션 (Mutation)
- 서버의 데이터를 변경하거나 업데이트할 때 사용됩니다.
- 서버에 대한 변경사항을 전달하는데 사용됩니다.
예시:
mutation {
createUser(name: "John", email: "john@example.com") {
id
name
email
}
}
스키마 (Schema)
- GraphQL API에서 사용 가능한 모든 유형과 관계를 정의합니다.
- 객체 유형, 필드, 관계를 포함합니다.
예시:
type User {
id: ID!
name: String!
email: String!
posts: [Post!]!
}
type Post {
id: ID!
title: String!
content: String!
author: User!
}
type Query {
user(id: ID!): User
post(id: ID!): Post
}
type Mutation {
createUser(name: String!, email: String!): User!
createPost(title: String!, content: String!, authorId: ID!): Post!
}
이 외에도 인자, 필드, 별칭 등이 있지만 기본적으로 사용하는 친구들만 알아보고 바로 axios 함께 사용할 수 있는 방법에 대해 알아보도록 하겠습니다!
Axios & GraphQL 함께 사용하기
쿼리 (Query)
실제로 리액트에서 GraphQL API에 axios로 통신하는 코드를 살펴보며 이해해보도록 하겠습니다. GraphQL API에 데이터를 수신발신 하기 위한 메서드는 Post로 고정입니다!
먼저 위 문법에서 보신 것 처럼 쿼리문을 작성해서 데이터 요청을 진행해보도록 하겠습니다.
데이터를 가져오는 코드입니다.
useEffect(()=> {
const fetchData = async () => {
try {
const query = `
query {
posts {
id
title
content
}
}
`;
// 이 부분이 Axios를 사용하여 GraphQL API에 POST 요청 보내기!
const response = await axios.post('http://Dante.com', {
query: query
});
setData(response.data.data.posts);
} catch (err) {
setError(err);
}
}
fetchData();
},[]);
위 코드를 확인해보겠습니다.
쿼리문을 보시면, posts 컬렉션에서 id, title, content 필드를 가져올 수 있도록 쿼리를 구성했습니다.
저희는 이 쿼리문을 axios.post("통신주소", { 쿼리추가!}) 를 통해 원하는 데이터를 가져올 수 있습니다. REST API에선 어려운 원하는 컬렉션의 필드만 가져오기! 굉장한 유연성을 보여주는 대목입니다.
뮤테이션 (Mutation)
이번엔 뮤테이션을 살펴보겠습니다.
뮤테이션은 새로운 데이터를 추가하거나, 업데이트 하거나 삭제할때도 사용할 수 있습니다.
데이터 추가
// GraphQL 뮤테이션 쿼리 - 게시물 생성
const createPostMutation = `
mutation CreatePost($input: PostInput!) {
createPost(input: $input) {
id
title
content
}
}
`;
const performMutation = async (mutationQuery, variables) => {
try {
// GraphQL 서버 엔드포인트 URL
const endpointURL = 'https://your-graphql-api-endpoint.com/graphql';
// Axios를 사용하여 GraphQL 뮤테이션 요청 보내기
const response = await axios.post(endpointURL, {
query: mutationQuery,
variables: variables,
});
// 요청 결과 반환
return response.data.data;
} catch (error) {
// 요청 실패 시 에러 처리
console.error('Mutation error:', error);
throw new Error('Mutation failed.');
}
};
// 게시물 생성 뮤테이션 수행 예시
const createPost = async (postData) => {
try {
const variables = {
input: postData,
};
const result = await performMutation(createPostMutation, variables);
return result.createPost;
} catch (error) {
console.error('Error creating post:', error);
throw error;
}
};
// 새로운 게시물 데이터 예시
const newPostData = {
title: 'New Post Title',
content: 'This is the content of the new post.',
};
// 게시물 생성 예시
createPost(newPostData)
.then((createdPost) => {
console.log('Created post:', createdPost);
})
.catch((error) => {
console.error('Error creating post:', error);
});
데이터를 DB에 추가하는 코드입니다. 뮤테이션 쿼리를 생성하여 게시물을 생성합니다.
axios를 사용하여 데이터를 넘겨줄 performMutation 함수를 제작합니다. 인자로 query와 variables(입력 데이터를 변수로)을 전달해줍니다. 위 코드에서는 newPostData가 인자로 전달되는 모습을 보실 수 있습니다.
이후 과정은 일반 fetch 함수와 동일하게 Promise를 반환받아 응답값을 가지고 원하는 대로 사용할 수 있게 됩니다.
예시코드 하나만 더 살펴보겠습니다. 이번에도 mutation코드로 데이터 업데이트가 구현된 코드를 준비해봤습니다.
// GraphQL 뮤테이션 쿼리 정의
const updatePostMutation = `
mutation UpdatePost($id: ID!, $title: String!, $content: String!) {
updatePost(id: $id, title: $title, content: $content) {
id
title
content
}
}
`;
// 업데이트할 게시물의 ID와 변경될 제목(title) 및 내용(content)
const postId = '게시물의 ID';
const updatedTitle = '변경된 제목';
const updatedContent = '변경된 내용';
// 뮤테이션 실행
axios.post('/graphql', {
query: updatePostMutation,
variables: {
id: postId,
title: updatedTitle,
content: updatedContent,
},
})
.then(response => {
console.log('게시물이 업데이트되었습니다:', response.data.data.updatePost);
})
.catch(error => {
console.error('게시물 업데이트 중 오류가 발생했습니다:', error);
});
위에서 보신대로 코드의 구조는 동일합니다. mutation 쿼리문만 바뀌어 코드가 진행되고 있습니다.
바뀐 mutation 쿼리문을 자세히 살펴보겠습니다.
- mution UpdatePost : 뮤테이션 쿼리의 유형을 나타냅니다. 데이터를 업데이트하는 뮤테이션을 정의하고 있습니다.
- ($id: ID!, $title: String!, $content: String!): 이 부분은 뮤테이션에 전달될 변수를 선언하고 있습니다 각각 밸류는 해당 변수의 유형을 나타내고 느낌표는 해당 변수가 반드시 제공되어야한다는 의미입니다.
- updatePost(id: $id, title: $title, content: $content): 이 부분은 실제로 데이터를 업데이트하는 GraphQL 서버의 뮤테이션을 호출합니다. 여기서 id, title, content는 앞서 선언한 변수를 사용하여 값을 전달합니다.
- { id title content }: 이 부분은 뮤테이션 실행 결과로 반환할 필드를 지정합니다. 여기서는 업데이트된 게시물의 ID, 제목, 내용을 반환하도록 지정되어 있습니다.
GraphQL은
굉장히 유연한 통신이 가능하기 때문에 데이터의 오버패칭을 막을 수 있고,
자연스럽게 더 빠른 데이터 통신이 가능하도록 만들 수 있습니다.
'FE 개발' 카테고리의 다른 글
[FE 개발] 가상 돔과 실제 돔 (0) | 2024.01.18 |
---|---|
[FE 개발] 프레임워크와 라이브러리 (0) | 2024.01.17 |
[FE 개발] 동기와 비동기 (0) | 2024.01.17 |
[Git] commit 이력 대거 수정 (Git filter repo) (3) | 2023.12.06 |
[Git] commit 이력 조회하는 방법 (0) | 2023.10.27 |