Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
Tags
- java
- leetcode
- #파밍
- #크랙미3번
- #보안이슈
- #심플즈 크랙미
- #보안뉴스
- #크랙미 9번
- springframework
- #abex
- #크랙미4번
- java8
- 리버싱
- #크랙미2번
- #심플즈
- #고클린
- GraphQL
- #크랙미
- Easy
- #abex크랙미4번
- #리버싱
- #크랙미 10번
- #크랙미 5번
- #abex크랙미
- Spring
Archives
- Today
- Total
Halo World
[GraphQL] GraphQL 클라이언트 만들어보기 본문
본 포스팅은 Inflearn 얄코님 강의를 수강하며 복습용으로 작성하였습니다.
https://www.inflearn.com/course/%EC%96%84%ED%8C%8D%ED%95%9C-graphql-apollo/dashboard
React와 Apollo Client
실습을 위한
- 백앤드 서버 : https://gitlab.com/yalco/yalco-inflearn-graphql-apollo/-/tree/master/1-3-graphql-exp
- 클라이언트 서버 : https://gitlab.com/yalco/yalco-inflearn-graphql-apollo/-/tree/master/4-1-react-before-apollo
1. 아폴로 클라이언트 적용
아폴로 클라이언트 모듈 설치
npm install @apollo/client graphql
설치한 모듈 import
//app.js
// ...
import { ApolloProvider } from '@apollo/client';
import { ApolloClient, InMemoryCache } from '@apollo/client'
// ...
// ...
const client = new ApolloClient({
uri: 'http://localhost:4000',
cache: new InMemoryCache()
});
// ...
- client : GraphQL 서버와 정보를 주고받을 ApolloClient 객체 (axios 같은 역할)
- url : GraphQL 서버 주소
- cache : InMemoryCache를 통한 캐시 관리
//app.js
// ...
return (
<div className="App">
//랜더링 하는 부분의 안쪽을 ApolloClient로 감싸줌
<ApolloProvider client={client}>
<header className="App-header">
<h1>Company Management</h1>
<nav>
<ul>
{NavMenus()}
</ul>
</nav>
</header>
<main>
{mainComp[menu]}
</main>
</ApolloProvider>
</div>
);
// ...
2. GraphQL 서버로부터 목록 받아와 표시하기
//roles.js
// ...
import { useState } from 'react';
import { useQuery, gql } from '@apollo/client';
// ...
// ...
const GET_ROLES = gql` //아래 내용을 바탕으로 graphQL에 보낼 요청 객체를 만듦
query GetRoles {
roles {
id
}
}
`;
// ...
- 랜더링될 컨텐츠 id를 저장한 state 지정
//role.js
function Roles() {
// ...
const [contentId, setContentId] = useState('');
// ...
}
- 서버로부터 데이터를 받아와서 띄워주기 위한 메소드 작성
// ...
function AsideItems () {
const roleIcons = {
developer: '💻',
designer: '🎨',
planner: '📝'
}
const { loading, error, data } = useQuery(GET_ROLES); //위에서 선언한 GraphQL 쿼리 이용
//로딩과 에러 설정
if (loading) return <p className="loading">Loading...</p>
if (error) return <p className="error">Error :(</p>
return (
<ul>
{data.roles.map(({id}) => {
return (
<li key={id} className={'roleItem ' + (contentId === 'id' ? 'on' : '')}
onClick={() => {setContentId(id)}}>
<span>{contentId === id ? '🔲' : '⬛'}</span>
{roleIcons[id]} {id}
</li>
)
})}
</ul>
);
}
// ...
3. GraphQL 서버로부터 id로 컨텐츠 받아와 표시하기
//roles.js
// ...
const GET_ROLE = gql`
query GetRole($id: ID!) { //특정 Id에 대한 role정보 가져오는 graphQL 쿼리문
role(id: $id) {
id
requirement
members {
id
last_name
serve_years
}
equipments {
id
}
softwares {
id
}
}
}
`;
// ...
//role.js
function MainContents () {
//위에서 설정한 id로 특정 role 정보를 가져오는 쿼리 사용
// id는 contentId state를 전달
const { loading, error, data } = useQuery(GET_ROLE, {
variables: {id: contentId}
})
if (loading) return <p className="loading">Loading...</p>
if (error) return <p className="error">Error :(</p>
if (contentId === '') return (<div className="roleWrapper">Select Role</div>)
return (
<div className="roleWrapper">
<h2>{data.role.id}</h2>
<div className="requirement"><span>{data.role.requirement}</span> required</div>
<h3>Members</h3>
//가져온 정보 렌더링 해주기
<ul>
{data.role.members.map((member) => {
return (<li>{member.last_name}</li>)
})}
</ul>
<h3>Equipments</h3>
<ul>
{data.role.equipments.map((equipment) => {
return (<li>{equipment.id}</li>)
})}
</ul>
<h3>Softwares</h3>
{data.role.softwares.map((software) => {
return (<li>{software.id}</li>)
})}
<ul>
</ul>
</div>
);
}
Query와 Mutation을 사용하여 웹페이지 만들기
모듈 로드
//teams.js
// ...
import { useState } from 'react';
import { useQuery, useMutation, gql } from '@apollo/client'
// ...
상태를 저장할 state 준비
//teams.js
// ...
const [contentId, setContentId] = useState(0)
const [inputs, setInputs] = useState({
manager: '',
office: '',
extension_number: '',
mascot: '',
cleaning_duty: '',
project: ''
})
// ...
1. 팀 목록 받아오기
- 쿼리 작성
//teams.js
// ...
const GET_TEAMS = gql`
query GetTeams {
teams { //team 스키마에 저장된 id, manager
id
manager
members { //member 스키마에 저장된 특정 값을 받아옴
id
first_name
last_name
role
}
}
}
`;
// ...
- 아래처럼 useQeury를 이용해 해당 쿼리를 실행시킬 수 있다.
const { loading, error, data, refetch } = useQuery(GET_TEAMS);
- 실행되면 data에 받아온 데이터가 들어오게 되며, 데이터에 접근해 렌더링 시켜줄 수 있다.
return (
<ul>
{data.teams.map(({id, manager, members}) => {
return (
<li key={id}>
<span className="teamItemTitle" onClick={() => {setContentId(id)}}>
Team {id} : {manager}'s
</span>
<ul className="teamMembers">
{members.map(({id, first_name, last_name, role}) => {
return (
<li key={id}>
{roleIcons[role]} {first_name} {last_name}
</li>
)
})}
</ul>
</li>
)
})}
</ul>
)
2. Mutation 사용
- 항목 삭제하기
// ...
const DELETE_TEAM = gql`
mutation DeleteTeam($id: ID!) {
deleteTeam(id: $id) {
id
}
}
`
// ...
function execDeleteTeam () {
if (window.confirm('이 항목을 삭제하시겠습니까?')) {
deleteTeam({variables: {id: contentId}})
}
}
//작성한 delete 쿼리를 이용해 useMutation으로 쿼리 날림
//쿼리가 실행된 후에는 deleteTeamCompleted 함수를 실행하도록 함
const [deleteTeam] = useMutation(
DELETE_TEAM, { onCompleted: deleteTeamCompleted })
function deleteTeamCompleted (data) {
console.log(data.deleteTeam)
alert(`${data.deleteTeam.id} 항목이 삭제되었습니다.`)
setContentId(0)
}
// ...
- delete 버튼에 execDeleteTeam를 적용하여 실행
// ...
<button onClick={execDeleteTeam}>Delete</button>
// ...
3. Fetch 사용
- 항목을 삭제/삽입/수정한 후 리스트를 갱신하기위해서 refetch를 이용할 수 잇다.
// ...
//함수 밖에서 refetch를 넣을 refetchTeams 변수 선언
let refetchTeams
// ...
//useQuery의 매개변수 중 refetch를 위에서 선언한 refetchTeams 변수에 넣어준다.
const { loading, error, data, refetch } = useQuery(GET_TEAMS);
refetchTeams = refetch
// ...
//항목 삭제이후 부분에서 refetchTeams()를 호출해줌으로써 refetch 실행할 수 있다.
alert(`${data.deleteTeam.id} 항목이 삭제되었습니다.`)
refetchTeams()
// ...
- 수정/삽입에 대한 추가적인 쿼리는 아래 사이트에서 참조
https://www.yalco.kr/@graphql-apollo/4-2/
Fragment 사용하기
Fragment
- 여러 쿼리에 사용될 수 있는, 재사용 가능한 필드셋 (반복되는 쿼리를 재사용하여 중복을 줄임)
- 중복을 줄임으로써 전체 코드를 간소화
- 서버단에서는 유니언, 인터베이스로 쿼리 중복을 간소화했다면 클라이언트에서는 fragment로 간소화
- https://graphql-kr.github.io/learn/queries/
예를 들어, 아래와 같은 쿼리는
const GET_PEOPLE = gql`
query GetPeople {
people {
id
first_name
last_name
sex
blood_type
}
}
`;
const GET_PERSON = gql`
query GetPerson($id: ID!) {
person(id: $id) {
id
first_name
last_name
sex
blood_type
serve_years
role
team
from
tools {
__typename
... on Software {
id
}
... on Equipment {
id
count
}
}
}
}
`;
아래처럼 재사용되는 요소들을 fragment로 분리하여 중복을 제거할 수 있다.
const Names = gql`
fragment names on People {
first_name
last_name
}
`
const HealthInfo = gql`
fragment healthInfo on People {
sex
blood_type
}
`
const WorkInfo = gql`
fragment workInfo on People {
serve_years
role
team
from
}
`
const GET_PEOPLE = gql`
query GetPeople {
people {
id
...names
...healthInfo
}
}
${Names}
${HealthInfo}
`;
- fragment는 선언시 'fragment'로 선언하면 된다.
'개발 지식 > DEVELOPMENT' 카테고리의 다른 글
[GraphQL] GraphQL 서버 깊이 파보기 (2) (0) | 2022.02.13 |
---|---|
[GraphQL] GraphQL 서버 깊이 파보기 (1) (0) | 2022.02.13 |
[GraphQL] Apollo-server 셋팅 (0) | 2022.02.08 |
[GraphQL] GraphQL 기초 (REST API와 비교, GraphQL 강점, Apollo란?) (0) | 2022.02.05 |