<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>Halo World</title>
    <link>https://haloworld.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Tue, 7 Jul 2026 17:23:14 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>_Yeony</managingEditor>
    <image>
      <title>Halo World</title>
      <url>https://tistory1.daumcdn.net/tistory/1948501/attach/acac0bda561b40099873044e9c45b943</url>
      <link>https://haloworld.tistory.com</link>
    </image>
    <item>
      <title>[GraphQL] GraphQL 클라이언트 만들어보기</title>
      <link>https://haloworld.tistory.com/160</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;본 포스팅은 Inflearn 얄코님 강의를 수강하며&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;복습용으로&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;작성하였습니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.inflearn.com/course/%EC%96%84%ED%8C%8D%ED%95%9C-graphql-apollo/dashboard&quot;&gt;https://www.inflearn.com/course/%EC%96%84%ED%8C%8D%ED%95%9C-graphql-apollo/dashboard&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1644759478407&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;[무료] 얄팍한 GraphQL과 Apollo - 인프런 | 강의&quot; data-og-description=&quot;⚡ 짧고 굵은 전체 90분 강좌! 사이트의 코드들을 복붙하며 빠르게 GraphQL을 배우고 아폴로 사용법을 익히세요., - 강의 소개 | 인프런...&quot; data-og-host=&quot;www.inflearn.com&quot; data-og-source-url=&quot;https://www.inflearn.com/course/%EC%96%84%ED%8C%8D%ED%95%9C-graphql-apollo/dashboard&quot; data-og-url=&quot;https://www.inflearn.com/course/%EC%96%84%ED%8C%8D%ED%95%9C-graphql-apollo&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bXhGVA/hyNn2XAfI2/fuVjH0FkU5vfK2bY9FCph0/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500,https://scrap.kakaocdn.net/dn/Q4vJm/hyNpeoAbAS/Kvumili9uFJkYDPNGwBZvk/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500&quot;&gt;&lt;a href=&quot;https://www.inflearn.com/course/%EC%96%84%ED%8C%8D%ED%95%9C-graphql-apollo/dashboard&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.inflearn.com/course/%EC%96%84%ED%8C%8D%ED%95%9C-graphql-apollo/dashboard&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bXhGVA/hyNn2XAfI2/fuVjH0FkU5vfK2bY9FCph0/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500,https://scrap.kakaocdn.net/dn/Q4vJm/hyNpeoAbAS/Kvumili9uFJkYDPNGwBZvk/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[무료] 얄팍한 GraphQL과 Apollo - 인프런 | 강의&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;⚡ 짧고 굵은 전체 90분 강좌! 사이트의 코드들을 복붙하며 빠르게 GraphQL을 배우고 아폴로 사용법을 익히세요., - 강의 소개 | 인프런...&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.inflearn.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;React와 Apollo Client&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실습을 위한&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 백앤드 서버 : &lt;a href=&quot;https://gitlab.com/yalco/yalco-inflearn-graphql-apollo/-/tree/master/1-3-graphql-exp&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://gitlab.com/yalco/yalco-inflearn-graphql-apollo/-/tree/master/1-3-graphql-exp&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 클라이언트 서버 : &lt;a href=&quot;https://gitlab.com/yalco/yalco-inflearn-graphql-apollo/-/tree/master/4-1-react-before-apollo&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://gitlab.com/yalco/yalco-inflearn-graphql-apollo/-/tree/master/4-1-react-before-apollo&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;1. 아폴로 클라이언트 적용&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아폴로 클라이언트 모듈 설치&lt;/p&gt;
&lt;pre id=&quot;code_1644755348936&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;npm install @apollo/client graphql&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설치한 모듈 import&lt;/p&gt;
&lt;pre id=&quot;code_1644755402644&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//app.js

// ...
import { ApolloProvider } from '@apollo/client';
import { ApolloClient, InMemoryCache } from '@apollo/client'
// ...


// ...
  const client = new ApolloClient({
    uri: 'http://localhost:4000',
    cache: new InMemoryCache()
  });
  // ...&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;client : GraphQL 서버와 정보를 주고받을 ApolloClient 객체 (axios 같은 역할)&lt;/li&gt;
&lt;li&gt;url : GraphQL 서버 주소&lt;/li&gt;
&lt;li&gt;cache : &lt;a href=&quot;https://www.apollographql.com/docs/react/caching/cache-configuration/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;InMemoryCache&lt;/a&gt;를 통한 캐시 관리&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1644755639197&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//app.js

//   ...
  return (
    &amp;lt;div className=&quot;App&quot;&amp;gt;
     //랜더링 하는 부분의 안쪽을 ApolloClient로 감싸줌
      &amp;lt;ApolloProvider client={client}&amp;gt;
        &amp;lt;header className=&quot;App-header&quot;&amp;gt;
          &amp;lt;h1&amp;gt;Company Management&amp;lt;/h1&amp;gt;
          &amp;lt;nav&amp;gt;
            &amp;lt;ul&amp;gt;
              {NavMenus()}
            &amp;lt;/ul&amp;gt;
          &amp;lt;/nav&amp;gt;
        &amp;lt;/header&amp;gt;
        &amp;lt;main&amp;gt;
          {mainComp[menu]}
        &amp;lt;/main&amp;gt;
      &amp;lt;/ApolloProvider&amp;gt;
    &amp;lt;/div&amp;gt;
  );
//   ...&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2. GraphQL 서버로부터 목록 받아와 표시하기&lt;/h4&gt;
&lt;pre id=&quot;code_1644755773860&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//roles.js

// ...
import { useState } from 'react';
import { useQuery, gql } from '@apollo/client';
// ...

// ...
const GET_ROLES = gql`  //아래 내용을 바탕으로 graphQL에 보낼 요청 객체를 만듦
  query GetRoles {
    roles {
      id
    }
  }
`;
// ...&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;랜더링될 컨텐츠 id를 저장한 state 지정&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1644755935806&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//role.js

function Roles() {
    // ...
      const [contentId, setContentId] = useState('');
    // ...

}&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;서버로부터 데이터를 받아와서 띄워주기 위한 메소드 작성&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1644756073688&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// ...
  function AsideItems () {
    const roleIcons = {
      developer: ' ',
      designer: ' ',
      planner: ' '
    }
    const { loading, error, data } = useQuery(GET_ROLES);	//위에서 선언한 GraphQL 쿼리 이용
    
    //로딩과 에러 설정
    if (loading) return &amp;lt;p className=&quot;loading&quot;&amp;gt;Loading...&amp;lt;/p&amp;gt;
    if (error) return &amp;lt;p className=&quot;error&quot;&amp;gt;Error :(&amp;lt;/p&amp;gt;
    
    return (
      &amp;lt;ul&amp;gt;
        {data.roles.map(({id}) =&amp;gt; {
          return (
            &amp;lt;li key={id} className={'roleItem ' +  (contentId === 'id' ? 'on' : '')}
            onClick={() =&amp;gt; {setContentId(id)}}&amp;gt;
              &amp;lt;span&amp;gt;{contentId === id ? ' ' : '⬛'}&amp;lt;/span&amp;gt;
              {roleIcons[id]} {id}
            &amp;lt;/li&amp;gt;
          )
        })}
      &amp;lt;/ul&amp;gt;
    );
  }
// ...&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;3. GraphQL 서버로부터&lt;span&gt;&amp;nbsp;&lt;/span&gt;id로 컨텐츠 받아와 표시하기&lt;/h4&gt;
&lt;pre id=&quot;code_1644756274461&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//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
      }
    }
  }
`;
// ...&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1644756446465&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//role.js

  function MainContents () {

//위에서 설정한 id로 특정 role 정보를 가져오는 쿼리 사용
    // id는 contentId state를 전달
    const { loading, error, data } = useQuery(GET_ROLE, {
      variables: {id: contentId}
    })

    if (loading) return &amp;lt;p className=&quot;loading&quot;&amp;gt;Loading...&amp;lt;/p&amp;gt;
    if (error) return &amp;lt;p className=&quot;error&quot;&amp;gt;Error :(&amp;lt;/p&amp;gt;
    if (contentId === '') return (&amp;lt;div className=&quot;roleWrapper&quot;&amp;gt;Select Role&amp;lt;/div&amp;gt;)

    return (
      &amp;lt;div className=&quot;roleWrapper&quot;&amp;gt;
        &amp;lt;h2&amp;gt;{data.role.id}&amp;lt;/h2&amp;gt;
        &amp;lt;div className=&quot;requirement&quot;&amp;gt;&amp;lt;span&amp;gt;{data.role.requirement}&amp;lt;/span&amp;gt; required&amp;lt;/div&amp;gt;
        &amp;lt;h3&amp;gt;Members&amp;lt;/h3&amp;gt;
        //가져온 정보 렌더링 해주기
        &amp;lt;ul&amp;gt;
          {data.role.members.map((member) =&amp;gt; {
            return (&amp;lt;li&amp;gt;{member.last_name}&amp;lt;/li&amp;gt;)
          })}
        &amp;lt;/ul&amp;gt;
        &amp;lt;h3&amp;gt;Equipments&amp;lt;/h3&amp;gt;
        &amp;lt;ul&amp;gt;
          {data.role.equipments.map((equipment) =&amp;gt; {
            return (&amp;lt;li&amp;gt;{equipment.id}&amp;lt;/li&amp;gt;)
          })}
        &amp;lt;/ul&amp;gt;
        &amp;lt;h3&amp;gt;Softwares&amp;lt;/h3&amp;gt;
          {data.role.softwares.map((software) =&amp;gt; {
            return (&amp;lt;li&amp;gt;{software.id}&amp;lt;/li&amp;gt;)
          })}
        &amp;lt;ul&amp;gt;
        &amp;lt;/ul&amp;gt;
      &amp;lt;/div&amp;gt;
    );
  }&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Query와&amp;nbsp;Mutation을&amp;nbsp;사용하여&amp;nbsp;웹페이지&amp;nbsp;만들기&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모듈 로드&lt;/p&gt;
&lt;pre id=&quot;code_1644756893813&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//teams.js

// ...
import { useState } from 'react';
import { useQuery, useMutation, gql } from '@apollo/client'
// ...&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;상태를 저장할 state 준비&lt;/p&gt;
&lt;pre id=&quot;code_1644756915109&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//teams.js

// ...
  const [contentId, setContentId] = useState(0)
  const [inputs, setInputs] = useState({
    manager: '',
    office: '',
    extension_number: '',
    mascot: '',
    cleaning_duty: '',
    project: ''
  })
// ...&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;1. 팀 목록 받아오기&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;쿼리 작성&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1644757012797&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//teams.js

// ...
const GET_TEAMS = gql`
  query GetTeams {
    teams {	//team 스키마에 저장된 id, manager
        id
        manager
        members {	//member 스키마에 저장된 특정 값을 받아옴
          id
          first_name
          last_name
          role
        }
      }
  }
`;
// ...&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;아래처럼 useQeury를 이용해 해당 쿼리를 실행시킬 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1644757217582&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const { loading, error, data, refetch } = useQuery(GET_TEAMS);&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;실행되면 data에 받아온 데이터가 들어오게 되며, 데이터에 접근해 렌더링 시켜줄 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1644758338006&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;return (
      &amp;lt;ul&amp;gt;
        {data.teams.map(({id, manager, members}) =&amp;gt; {
          return (
            &amp;lt;li key={id}&amp;gt;
              &amp;lt;span className=&quot;teamItemTitle&quot; onClick={() =&amp;gt; {setContentId(id)}}&amp;gt;
                Team {id} : {manager}'s
              &amp;lt;/span&amp;gt;
              &amp;lt;ul className=&quot;teamMembers&quot;&amp;gt;
                {members.map(({id, first_name, last_name, role}) =&amp;gt; {
                  return (
                    &amp;lt;li key={id}&amp;gt;
                      {roleIcons[role]} {first_name} {last_name}
                    &amp;lt;/li&amp;gt;
                  )
                })}
              &amp;lt;/ul&amp;gt;
            &amp;lt;/li&amp;gt;
          )
        })}
      &amp;lt;/ul&amp;gt;
    )&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2. Mutation 사용&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;항목 삭제하기&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1644758508130&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// ...
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)
  }
    // ...&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;delete 버튼에 execDeleteTeam를 적용하여 실행&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1644758517031&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// ...
    &amp;lt;button onClick={execDeleteTeam}&amp;gt;Delete&amp;lt;/button&amp;gt;
// ...&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. Fetch 사용&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;항목을 삭제/삽입/수정한 후 리스트를 갱신하기위해서 refetch를 이용할 수 잇다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1644758578081&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// ...
//함수 밖에서 refetch를 넣을 refetchTeams 변수 선언
let refetchTeams


// ...
//useQuery의 매개변수 중 refetch를 위에서 선언한 refetchTeams 변수에 넣어준다.
const { loading, error, data, refetch } = useQuery(GET_TEAMS);
refetchTeams = refetch
// ...
//항목 삭제이후 부분에서 refetchTeams()를 호출해줌으로써 refetch 실행할 수 있다.
alert(`${data.deleteTeam.id} 항목이 삭제되었습니다.`)
refetchTeams()
// ...&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;수정/삽입에 대한 추가적인 쿼리는 아래 사이트에서 참조&lt;br /&gt;&lt;a href=&quot;https://www.yalco.kr/@graphql-apollo/4-2/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://www.yalco.kr/@graphql-apollo/4-2/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Fragment 사용하기&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Fragment&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;여러 쿼리에 사용될 수 있는, 재사용 가능한 필드셋 (반복되는 쿼리를 재사용하여 중복을 줄임)&lt;/li&gt;
&lt;li&gt;중복을 줄임으로써 전체 코드를 간소화&lt;/li&gt;
&lt;li&gt;서버단에서는 유니언, 인터베이스로 쿼리 중복을 간소화했다면 클라이언트에서는 fragment로 간소화&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://graphql-kr.github.io/learn/queries/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://graphql-kr.github.io/learn/queries/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어, 아래와 같은 쿼리는&lt;/p&gt;
&lt;pre id=&quot;code_1644759320119&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;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
        }
      }
    }
  }
`;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래처럼 재사용되는 요소들을 fragment로 분리하여 중복을 제거할 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1644759368273&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;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}
`;&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt; fragment는 선언시 'fragment'로 선언하면 된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>개발 지식/DEVELOPMENT</category>
      <author>_Yeony</author>
      <guid isPermaLink="true">https://haloworld.tistory.com/160</guid>
      <comments>https://haloworld.tistory.com/160#entry160comment</comments>
      <pubDate>Sun, 13 Feb 2022 22:38:12 +0900</pubDate>
    </item>
    <item>
      <title>[GraphQL] GraphQL 서버 깊이 파보기 (2)</title>
      <link>https://haloworld.tistory.com/159</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;본 포스팅은 Inflearn 얄코님 강의를 수강하며 &lt;b&gt;복습용으로 &lt;/b&gt;작성하였습니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.inflearn.com/course/%EC%96%84%ED%8C%8D%ED%95%9C-graphql-apollo/dashboard&quot;&gt;https://www.inflearn.com/course/%EC%96%84%ED%8C%8D%ED%95%9C-graphql-apollo/dashboard&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1644737753407&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;[무료] 얄팍한 GraphQL과 Apollo - 인프런 | 강의&quot; data-og-description=&quot;⚡ 짧고 굵은 전체 90분 강좌! 사이트의 코드들을 복붙하며 빠르게 GraphQL을 배우고 아폴로 사용법을 익히세요., - 강의 소개 | 인프런...&quot; data-og-host=&quot;www.inflearn.com&quot; data-og-source-url=&quot;https://www.inflearn.com/course/%EC%96%84%ED%8C%8D%ED%95%9C-graphql-apollo/dashboard&quot; data-og-url=&quot;https://www.inflearn.com/course/%EC%96%84%ED%8C%8D%ED%95%9C-graphql-apollo&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bXhGVA/hyNn2XAfI2/fuVjH0FkU5vfK2bY9FCph0/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500,https://scrap.kakaocdn.net/dn/Q4vJm/hyNpeoAbAS/Kvumili9uFJkYDPNGwBZvk/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500&quot;&gt;&lt;a href=&quot;https://www.inflearn.com/course/%EC%96%84%ED%8C%8D%ED%95%9C-graphql-apollo/dashboard&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.inflearn.com/course/%EC%96%84%ED%8C%8D%ED%95%9C-graphql-apollo/dashboard&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bXhGVA/hyNn2XAfI2/fuVjH0FkU5vfK2bY9FCph0/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500,https://scrap.kakaocdn.net/dn/Q4vJm/hyNpeoAbAS/Kvumili9uFJkYDPNGwBZvk/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[무료] 얄팍한 GraphQL과 Apollo - 인프런 | 강의&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;⚡ 짧고 굵은 전체 90분 강좌! 사이트의 코드들을 복붙하며 빠르게 GraphQL을 배우고 아폴로 사용법을 익히세요., - 강의 소개 | 인프런...&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.inflearn.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;유니언과 인터페이스&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이전 예제에서는 각각의 배열이 특정 스칼라 타입이나 특정 커스텀 데이터 타입을 반환했지만,&lt;/li&gt;
&lt;li&gt;Union타입은 타입 여럿을 한 배열에 반환이 가능함&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;1. Equipment와 Supply를 함께 반환하기&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt; given 데이터 타입 정의&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1644734753296&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//given.js 
//equipment와 supply를 함께 반환할 데이터 타입

const { gql } = require('apollo-server')
const dbWorks = require('../dbWorks.js')
const typeDefs = gql`
    union Given = Equipment | Supply   //Given 타입에 Equipment 또는 Supply를 받을 수 있음
`
const resolvers = {
    Query: {
    	//한 배열에 equipment와 supply를 둘다 넣어서 반환
        givens: (parent, args) =&amp;gt; {
            return [
                ...dbWorks.getEquipments(args),
                ...dbWorks.getSupplies(args)
            ]
        }
    },
    Given: {
        __resolveType(given, context, info) {
        //해당 부분의 결과로 쿼리시 __typename 지정됨
            if (given.used_by) {
                return 'Equipment'
            }
            if (given.team) {
                return 'Supply'
            }
            return null
        }
    }
}
module.exports = {
    typeDefs: typeDefs,
    resolvers: resolvers
}&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;정의한 resolver를 루트 쿼리에 추가&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1644734891101&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//_queries.js

const typeDefs = gql`
    type Query {
        // ...
        givens: [Given]
    }
`&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;index.js에 given 모듈 추가&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1644734931415&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//index.js

// ...
const givens = require('./typedefs-resolvers/givens')
// ...
const typeDefs = [
    // ...
    givens.typeDefs
]
// ...
const resolvers = [
    // ...
    givens.resolvers
]
// ...&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;playground에서 테스트&amp;nbsp;&lt;/li&gt;
&lt;li&gt;givens 쿼리의 결과로 equipment와 supply 모두 반환&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1644734989610&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;query {
  givens {
    __typename  //해당 데이터가 equipment인지 supply인지 나타내주기 위해 사용
    ... on Equipment {  //해당 데이터가 equipment인 경우 반환할 항목
      id
      used_by
      count
      new_or_used
    }
    ... on Supply {  //해당 데이터가 supply인 경우 반환할 항목
      id
      team
    }
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2. 인터페이스&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;유사한 객체 타입을 만들기 위한 공통 필드 타입&lt;/li&gt;
&lt;li&gt;추상 타입 - 다른 타입에 implement 되기 위한 타입&lt;/li&gt;
&lt;li&gt;Java의 인터페이스와 비슷한 역할&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1644735246844&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//공통으로 갖고있는 필드 : id, user_by

type Equipment {
    id: ID!
    used_by: Role!
    count: Int
    new_or_used: NewOrUsed!
}
...
type Software {
    id: ID!
    used_by: Role!
    developed_by: String!
    description: String
}&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;공통 필드를 갖고있는 tools.js (인터페이스) 정의&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1644735302547&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//tools.js

const { gql } = require('apollo-server')
const typeDefs = gql`
    interface Tool {   //interface 정의
        id: ID!
        used_by: Role!
    }
`
const resolvers = {
    Tool: {
        __resolveType(tool, context, info) {
        //들어온 데이터가 어떤 타입인지 구분
            if (tool.developed_by) {
                return 'Software'
            }
            if (tool.new_or_used) {
                return 'Equipment'
            }
            return null
        }
    }
}
module.exports = {
    typeDefs: typeDefs,
    resolvers: resolvers
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1644735377573&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//Tool을 implement한 Equipment
type Equipment implements Tool {
    id: ID!
    used_by: Role!
    count: Int
    new_or_used: NewOrUsed!
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1644735382570&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//Tool을 implement한 Software
type Software implements Tool {
    id: ID!
    used_by: Role!
    developed_by: String!
    description: String
}&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;index.js에 tools import&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1644735448360&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//index.js

// ...
const tools = require('./typedefs-resolvers/tools')
// ...
const typeDefs = [
    // ...
    tools.typeDefs
]
// ...
const resolvers = [
    // ...
    tools.resolvers
]
// ...&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;People 쿼리에 적용&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1644735660641&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//peopls.js 정의

const { gql } = require('apollo-server')
const dbWorks = require('../dbWorks.js')
const typeDefs = gql`
    type People {
        id: ID!
        first_name: String!
        last_name: String!
        sex: Sex!
        blood_type: BloodType!
        serve_years: Int!
        role: Role!
        team: ID!
        from: String!
        tools: [Tool]  //tool 인터페이스 타입
        givens: [Given] // given 유니언 타입
    }
`
const resolvers = {
    Query: {
        people: (parent, args) =&amp;gt; dbWorks.getPeople(args),
        person: (parent, args) =&amp;gt; dbWorks.getPeople(args)[0]
    }
}
module.exports = {
    typeDefs: typeDefs,
    resolvers: resolvers
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1644735741898&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//_queries.js 루트 쿼리에 추가

const typeDefs = gql`
    type Query {
        people: [People],
        // ...
    }
`&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1644735695521&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//index.js에 모듈 추가

// ...
const people = require('./typedefs-resolvers/people')
// ...
const typeDefs = [
    // ...
    people.typeDefs
]
// ...
const resolvers = [
    // ...
    people.resolvers
]
// ...&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;playground에 쿼리 테스트&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1644735824747&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;query {
  people {
    id
    first_name
    last_name
    givens {	//given 타입 쿼리 
        __typename
    	... on Equipment {
      	id
      	used_by
      	count
      	new_or_used
    	}
    	... on Supply {
      	id
      	team
    	}
  	}	
    tools {	//tools interface 타입에 대한 쿼리 
      __typename
      ... on Equipment {
        id
        used_by
        count
        new_or_used
      }
      ... on Software {
        id
        used_by
        description
        developed_by
      }
    }
  }
}​&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;+ 추가&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;Interface 타입과 Union 타입은 공통 필드를 갖고 있는지 없는지에 차이가 있음&lt;br /&gt;Interface 타입을 구현한 객체는 Interface에 정의된 모든 필드를 갖고 있어야 함.&lt;br /&gt;&lt;br /&gt;또한, 인터페이스 타입은 쿼리시 공통 부분으로 쿼리가 가능하다.&amp;nbsp;&lt;br /&gt;예를 들어, Equipment와 Software이 공통으로 갖고있는 id, used_by를 사용해 특정 쿼리를 만들 수 있음&lt;br /&gt;참고 : https://devport.tistory.com/21&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;인자와 인풋타입&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;People 데이터 조건들로 필터 넣어 받아오기&lt;/h4&gt;
&lt;pre id=&quot;code_1644736223832&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//_queries.js


    type Query {
        ...
        peopleFiltered(
            team: Int, 
            sex: Sex, 
            blood_type: BloodType, 
            from: String
        ): [People]
        ...
    }&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;__queries.js에서 정의한 대로 인자들을 받아와서 args로 인자들을 넘겨줄 수 있음&lt;/li&gt;
&lt;li&gt;받아서&amp;nbsp;처리하는&amp;nbsp;곳에서&amp;nbsp;sql&amp;nbsp;등&amp;nbsp;쿼리문을&amp;nbsp;사용하여&amp;nbsp;args를&amp;nbsp;기반으로한&amp;nbsp;where절&amp;nbsp;구현&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1644736246278&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//people.js

Query: {
    // ...
    peopleFiltered: (parent, args) =&amp;gt; dbWorks.getPeople(args),
  }&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;playground에서 쿼리 호출&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1644736392536&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;query {
  peopleFiltered (
    team: 1	//1 팀에 속하고
    blood_type: B	//b형인
    from: &quot;Texas&quot;	//Texas 출신만 쿼리
  ) {
    id
    first_name
    last_name
    sex
    blood_type
    serve_years
    role
    team
    from
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;데이터를 페이지로 나누어 받아오기&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;paging 처리 방식&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1644736542415&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;    //__queries.js
    
    type Query {
        ...
        peoplePaginated(
            page: Int!,
            per_page: Int!
        ): [People]
        ...
    }&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1644736564645&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//people.js

    Query: {
        // ...
        peoplePaginated: (parent, args) =&amp;gt; dbWorks.getPeople(args), //내부에서 별도로 페이징 쿼리 진행
        // ...
    }&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;playground에서 쿼리 테스트&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1644736627337&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;query {
//첫 페이지를 받아오고, 한 페이지당 7개의 결과를 받아와라
peoplePaginated(page: 1, per_page: 7) {	
    id
    first_name
    last_name
    sex
    blood_type
    serve_years
    role
    team
    from
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;별칭으로 데이터 받아오기&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;한 요청으로 데이터를 받아오는 경우, 데이터를 특정 기준으로 분리해서 받아오고 싶을 때 유용&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1644736829073&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;query {
  badGuys: peopleFiltered(sex: male, blood_type: B) {
    first_name
    last_name
    sex
    blood_type
  }
  newYorkers: peopleFiltered(from: &quot;New York&quot;) {
    first_name
    last_name
    from
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2330&quot; data-origin-height=&quot;1368&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b6Kkh8/btrtajdkleR/gW5A3udH8mCOyjh6WGbkX1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b6Kkh8/btrtajdkleR/gW5A3udH8mCOyjh6WGbkX1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b6Kkh8/btrtajdkleR/gW5A3udH8mCOyjh6WGbkX1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb6Kkh8%2FbtrtajdkleR%2FgW5A3udH8mCOyjh6WGbkX1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2330&quot; height=&quot;1368&quot; data-origin-width=&quot;2330&quot; data-origin-height=&quot;1368&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;인풋 타입&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;mutation에 들어가는 인자들이 많아지는 경우, 이를 보다 깔끔하게 하기 위해 인자들을 묶어서 실어보내는 방식&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1644737348105&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//people.js

const typeDefs = gql`
    ....
    //실제 정보를 입력할 때 요구되는 필드들
    input PostPersonInput {
        first_name: String!
        last_name: String!
        sex: Sex!
        blood_type: BloodType!
        serve_years: Int!
        role: Role!
        team: ID!
        from: String!
    }
`
const resolvers = {
    // ...
    Mutation: {
        postPerson: (parent, args) =&amp;gt; dbWorks.postPerson(args),
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1644737445807&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//_mutation.js

type Mutation {
  //mutation의 postPerson 명령 실행시 들어가는 인자 정의 - 깔끔하게 묶어서 전달할 수 있음!
    postPerson(input: PostPersonInput): People!
    ...
}&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;playground 쿼리 테스트&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1644737473972&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;mutation {
//인자로 input을 전달
//이전에 정의한 postPersonInput 형식으로 서버에 데이터 전송
  postPerson(input: {	
    first_name: &quot;Hanna&quot;
    last_name: &quot;Kim&quot;
    sex: female
    blood_type: O
    serve_years: 3
    role: developer
    team: 1
    from: &quot;Pusan&quot;
  }) {
    id
    first_name
    last_name
    sex
    blood_type
    role
    team
    from
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* Apollo 서버를 사용해 graphQL로 백앤드단을 구현하는 방법 간단 연습 끝&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;추가 정보는 아래 공식 사이트에서 튜토리얼로 배워볼 수 있음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;https://www.apollographql.com/docs/apollo-server/#:~:text=Apollo+Server+is+an+open,use+data+from+any+source.&lt;/p&gt;</description>
      <category>개발 지식/DEVELOPMENT</category>
      <author>_Yeony</author>
      <guid isPermaLink="true">https://haloworld.tistory.com/159</guid>
      <comments>https://haloworld.tistory.com/159#entry159comment</comments>
      <pubDate>Sun, 13 Feb 2022 16:36:21 +0900</pubDate>
    </item>
    <item>
      <title>[GraphQL] GraphQL 서버 깊이 파보기 (1)</title>
      <link>https://haloworld.tistory.com/158</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;본 포스팅은 Inflearn 얄코님 강의를 수강하며 &lt;b&gt;복습용으로 &lt;/b&gt;작성하였습니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.inflearn.com/course/%EC%96%84%ED%8C%8D%ED%95%9C-graphql-apollo/dashboard&quot;&gt;https://www.inflearn.com/course/%EC%96%84%ED%8C%8D%ED%95%9C-graphql-apollo/dashboard&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1644734355950&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;[무료] 얄팍한 GraphQL과 Apollo - 인프런 | 강의&quot; data-og-description=&quot;⚡ 짧고 굵은 전체 90분 강좌! 사이트의 코드들을 복붙하며 빠르게 GraphQL을 배우고 아폴로 사용법을 익히세요., - 강의 소개 | 인프런...&quot; data-og-host=&quot;www.inflearn.com&quot; data-og-source-url=&quot;https://www.inflearn.com/course/%EC%96%84%ED%8C%8D%ED%95%9C-graphql-apollo/dashboard&quot; data-og-url=&quot;https://www.inflearn.com/course/%EC%96%84%ED%8C%8D%ED%95%9C-graphql-apollo&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bXhGVA/hyNn2XAfI2/fuVjH0FkU5vfK2bY9FCph0/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500,https://scrap.kakaocdn.net/dn/Q4vJm/hyNpeoAbAS/Kvumili9uFJkYDPNGwBZvk/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500&quot;&gt;&lt;a href=&quot;https://www.inflearn.com/course/%EC%96%84%ED%8C%8D%ED%95%9C-graphql-apollo/dashboard&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.inflearn.com/course/%EC%96%84%ED%8C%8D%ED%95%9C-graphql-apollo/dashboard&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bXhGVA/hyNn2XAfI2/fuVjH0FkU5vfK2bY9FCph0/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500,https://scrap.kakaocdn.net/dn/Q4vJm/hyNpeoAbAS/Kvumili9uFJkYDPNGwBZvk/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[무료] 얄팍한 GraphQL과 Apollo - 인프런 | 강의&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;⚡ 짧고 굵은 전체 90분 강좌! 사이트의 코드들을 복붙하며 빠르게 GraphQL을 배우고 아폴로 사용법을 익히세요., - 강의 소개 | 인프런...&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.inflearn.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;서버 구성요소 모듈화&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이전 강의에서 살펴본 typeDefs와 Resolver는 모두 index.js 한 파일에 작성을 한 형태였는데,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각각을 모듈별로 쪼개어 파일을 구성하여 사용할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.apollographql.com/docs/apollo-server/api/apollo-server/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://www.apollographql.com/docs/apollo-server/api/apollo-server/&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아폴로 서버 문서를 보면, 배열 형태로 typeDefs와 Resolvers를 구성할 수 있도록 되어있다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;typeDefs : 단일 변수 또는 배열로 지정 가능&lt;/li&gt;
&lt;li&gt;resolvers : 단일 Object 또는 Merge된 배열로 가능&lt;/li&gt;
&lt;li&gt;각각의 파일에 query 및 mutation 루트 타입 정의&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1644723705015&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//typedefs-resolvers/_queries.js

// ...
const typeDefs = gql`
    type Query {
        equipments: [Equipment]
    }
`
// ...&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1644723723464&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//typedefs-resolvers/_mutations.js

// ...
const typeDefs = gql`
    type Mutation {
      deleteEquipment(id: String): Equipment
    }
`
// ...&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;equipments 데이터의 typeDefs와 resolver 별도 정의&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1644723788483&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//typedefs-resolvers/equipments.js

// ...
const typeDefs = gql`
    type Equipment {
        id: String
        used_by: String
        count: Int
        new_or_used: String
    }
`
const resolvers = {
    Query: {
        equipments: (parent, args) =&amp;gt; dbWorks.getEquipments(args),
    },
    Mutation: {
        deleteEquipment: (parent, args) =&amp;gt; dbWorks.deleteItem('equipments', args),
    }
}
// ...&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;index.js에서 각각의 파일들을 import 해준 후, typeDefs와 resolvers 선언 시 배열로 넣어주어 모듈화 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1644723837113&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//typedefs-resolvers/index.js

// ...
const queries = require('./typedefs-resolvers/_queries')
const mutations = require('./typedefs-resolvers/_mutations')
const equipments = require('./typedefs-resolvers/equipments'
// ...
const typeDefs = [
    queries,
    mutations,
    equipments.typeDefs,
]
const resolvers = [
    equipments.resolvers
]
// ...&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;추가로 supply 라는 새로운 모듈을 추가 한다면, Equipment와 동일하게 해당 typeDef와 resolver를 supplies.js 라는 파일에 정의하고, query와 mutation 파일에 해당 쿼리를 정의해주는 방식으로 추가 가능하다.&lt;br /&gt;&lt;a href=&quot;https://www.yalco.kr/@graphql-apollo/3-1/&quot;&gt;https://www.yalco.kr/@graphql-apollo/3-1/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;GraphQL의 기본 타입들&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;1. 스칼라 타입&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;GraphQL 내장 자료형&lt;/p&gt;
&lt;pre id=&quot;code_1644724379708&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;    type EquipmentAdv {
        id: ID!
        used_by: String!
        count: Int!
        use_rate: Float
        is_new: Boolean!
    }&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;ID : 기본적으로는 String이나, 고유 식별자 역할임을 나타냄&lt;/li&gt;
&lt;li&gt;String : UTF-8 문자열&lt;/li&gt;
&lt;li&gt;Int : 부호가 있는 32비트 정수&lt;/li&gt;
&lt;li&gt;Float : 부호가 있는 부동소수점 값&lt;/li&gt;
&lt;li&gt;Boolean : 참/거짓&lt;/li&gt;
&lt;li&gt;! 은 Non null을 의미하며, null인 경우 서버 내부에서 오류 반환&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1644724493173&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//equipment.js 내부에 equipmentAdvs를 위한 resolver 정의
//user_rate, is_new를 해당하는 스칼라 타입으로 변환
const resolvers = {
    Query: {
        // ...
        equipmentAdvs: (parent, args) =&amp;gt; dbWorks.getEquipments(args)
            .map((equipment) =&amp;gt; {
                if (equipment.used_by === 'developer') {
                    equipment.use_rate = Math.random().toFixed(2)
                }
                equipment.is_new = equipment.new_or_used === 'new'
                return equipment
            }),
    },
    // ...
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1644724669080&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//_queries.js
    type Query {
        ...
        equipmentAdvs: [EquipmentAdv]
        ...
    }&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;playground에서 테스트&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1644724706891&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;query {
    equipmentAdvs {
        id
        used_by
        count
        use_rate
        is_new
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2. 열거 타입&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Enum 타입의 데이터인 경우 enum 타입을 생성하여 데이터 타입을 지정해 줄 수 있다.&lt;/li&gt;
&lt;li&gt;객체에 데이터가 Enum 타입에 정의되어 있지 않은 타입으로 지정되는 경우 Error가 발생한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1644733343823&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//_enums.js  enum 예제
//Role 타입으로 설정된 데이터는 developer, desiner, planner로만,
//NewOrUsed 타입으로 설정된 데이터는 new, used 두 가지 값만 가능하다.

const { gql } = require('apollo-server')
const typeDefs = gql`
    enum Role {
        developer
        designer
        planner
    }
    enum NewOrUsed {
        new
        used
    }
`
module.exports = typeDefs&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1644733438726&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//index.js의 typeDefs에 enums 타입 추가

// ...
const enums = require('./typedefs-resolvers/_enums')
// ...
const typeDefs = [
    // ...
    enums,
    // ...
]&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1644733480387&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//equipments.js

const typeDefs = gql`
    type Equipment {
        id: ID!
        used_by: Role! //Role 타입에 설정되어있는 값만 들어갈 수 있다.
        count: Int!
        new_or_used: NewOrUsed! //NewOrUsed 타입에 설정되어있는 값만 들어갈 수 있다.
    }
    type EquipmentAdv {
        id: ID!
        used_by: Role!
        count: Int!
        use_rate: Float
        is_new: Boolean!
    }
`&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;playground에서 쿼리를 실행하여 결과를 확인해 볼 수 있다.&lt;/li&gt;
&lt;li&gt;db에 enums에 설정되어있지 않은 값이 들어있으면 (예를 들어, used_by 값이 manager로 설정되어있으면) 쿼리 실행 중 에러가 발생한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1644733494621&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;query {
  equipments {
    id
    used_by
    count
    new_or_used
  }
equipmentAdvs {
    id
    used_by
    count
    use_rate
    is_new
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;3. 리스트 타입&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;특정 타입의 배열을 반환&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1644734457993&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//equipments.js

const typeDefs = gql`
    // ...
    type EquipmentAdv {
        id: ID!
        used_by: Role!
        count: Int!
        use_rate: Float
        is_new: Boolean!,
        users: [String!]
    }
`
// ...
const resolvers = {
    Query: {
        // ...
        equipmentAdvs: (parent, args) =&amp;gt; dbWorks.getEquipments(args)
            .map((equipment) =&amp;gt; {
                if (equipment.used_by === 'developer') {
                    equipment.use_rate = Math.random().toFixed(2)
                }
                equipment.is_new = equipment.new_or_used === 'new'
                
                // 리스트 예제 
                // equipment 결과값의 1/2을 대상으로 
                // user라는 배열을 추가하고, 
                // db에 저장된 equipment.used_by와 같은 role을 갖고 있는 사람 중 1/5 확률로 
                // user 배열에 추가함
                if (Math.random() &amp;gt; 0.5) {
                    equipment.users = []
                    dbWorks.getPeople(args).forEach((person) =&amp;gt; {
                        if (person.role === equipment.used_by &amp;amp;&amp;amp; Math.random() &amp;lt; 0.2) {
                            equipment.users.push(person.last_name)
                        }
                    })
                }
                return equipment
            }),
    },
    // ...
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 125px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 25px;&quot;&gt;
&lt;td style=&quot;width: 25%; height: 25px;&quot;&gt;선언부&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 25px;&quot;&gt;users: null&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 25px;&quot;&gt;users: []&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 25px;&quot;&gt;users[..., null]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 25px;&quot;&gt;
&lt;td style=&quot;width: 25%; height: 25px;&quot;&gt;[String]&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 25px;&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;가능&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 25px;&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;가능&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 25px;&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;가능&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 25px;&quot;&gt;
&lt;td style=&quot;width: 25%; height: 25px;&quot;&gt;[String!]&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 25px;&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;가능&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 25px;&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;가능&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 25px;&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;불가능&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 25px;&quot;&gt;
&lt;td style=&quot;width: 25%; height: 25px;&quot;&gt;[String]!&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 25px;&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;불가능&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 25px;&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;가능&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 25px;&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;가능&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 25px;&quot;&gt;
&lt;td style=&quot;width: 25%; height: 25px;&quot;&gt;[String!]!&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 25px;&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;불가능&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 25px;&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;가능&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 25px;&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;불가능&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;4. 객체 타입&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;사용자에 의해 정의된 타입들&lt;/li&gt;
&lt;li&gt;ex) typeDefs, equipment 등..&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>개발 지식/DEVELOPMENT</category>
      <author>_Yeony</author>
      <guid isPermaLink="true">https://haloworld.tistory.com/158</guid>
      <comments>https://haloworld.tistory.com/158#entry158comment</comments>
      <pubDate>Sun, 13 Feb 2022 15:39:41 +0900</pubDate>
    </item>
    <item>
      <title>[GraphQL] Apollo-server 셋팅</title>
      <link>https://haloworld.tistory.com/157</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;본 포스팅은 Inflearn 얄코님 강의를 수강하며 복습용으로 작성하였습니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.inflearn.com/course/%EC%96%84%ED%8C%8D%ED%95%9C-graphql-apollo/dashboard&quot;&gt;https://www.inflearn.com/course/%EC%96%84%ED%8C%8D%ED%95%9C-graphql-apollo/dashboard&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1644152923383&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;[무료] 얄팍한 GraphQL과 Apollo - 인프런 | 강의&quot; data-og-description=&quot;⚡ 짧고 굵은 전체 90분 강좌! 사이트의 코드들을 복붙하며 빠르게 GraphQL을 배우고 아폴로 사용법을 익히세요., - 강의 소개 | 인프런...&quot; data-og-host=&quot;www.inflearn.com&quot; data-og-source-url=&quot;https://www.inflearn.com/course/%EC%96%84%ED%8C%8D%ED%95%9C-graphql-apollo/dashboard&quot; data-og-url=&quot;https://www.inflearn.com/course/%EC%96%84%ED%8C%8D%ED%95%9C-graphql-apollo&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cgBXa8/hyNleWbMN2/kVA42CMadCubOBfup6kI1K/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500,https://scrap.kakaocdn.net/dn/BFJg9/hyNlpi6Mod/jfHx7hEGNntLSHwHTdZNxK/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500&quot;&gt;&lt;a href=&quot;https://www.inflearn.com/course/%EC%96%84%ED%8C%8D%ED%95%9C-graphql-apollo/dashboard&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.inflearn.com/course/%EC%96%84%ED%8C%8D%ED%95%9C-graphql-apollo/dashboard&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cgBXa8/hyNleWbMN2/kVA42CMadCubOBfup6kI1K/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500,https://scrap.kakaocdn.net/dn/BFJg9/hyNlpi6Mod/jfHx7hEGNntLSHwHTdZNxK/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[무료] 얄팍한 GraphQL과 Apollo - 인프런 | 강의&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;⚡ 짧고 굵은 전체 90분 강좌! 사이트의 코드들을 복붙하며 빠르게 GraphQL을 배우고 아폴로 사용법을 익히세요., - 강의 소개 | 인프런...&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.inflearn.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;apollo-server 셋팅&lt;/b&gt;&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 프로젝트 생성 및 실행 테스트&lt;/p&gt;
&lt;pre id=&quot;code_1644155023066&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;npm init
npm start // package.json에서 &quot;start&quot; : &quot;nodemon index.js&quot;로 초기 셋팅&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. Mock DB 모듈 삽입&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;mock DB는 &lt;a href=&quot;https://gitlab.com/yalco/yalco-inflearn-graphql-apollo&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://gitlab.com/yalco/yalco-inflearn-graphql-apollo&lt;/a&gt; 의 2-1에 있는 폴더로 이용. 해당 폴더를 프로젝트 내부로 이동&lt;/p&gt;
&lt;pre id=&quot;code_1644155165142&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//필요한 모듈 설치
npm i convert-csv-to-json
npm start&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. Apollo 서버 설치&lt;/p&gt;
&lt;pre id=&quot;code_1644155228044&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;npm i graphql apollo-server //아폴로 서버 모듈 설치&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1644155512634&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const database = require('./database')
const { ApolloServer, gql } = require('apollo-server')

//주고받을 데이터 형식 정의
const typeDefs = gql`
  type Query {
    teams: [Team]
  }
  type Team {
    id: Int
    manager: String
    office: String
    extension_number: String
    mascot: String
    cleaning_duty: String
    project: String
  }
`

//각 요청을 받았을 때 어떤 액션을 할 것인지 정의
const resolvers = {
  Query: {
    teams: () =&amp;gt; database.teams
  }
}

//typeDefs와 resolvers를 인자로 받는 apollo server 생성
const server = new ApolloServer({ typeDefs, resolvers })
server.listen().then(({ url }) =&amp;gt; {
console.log(`   Server ready at ${url}`)
})&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;typeDefs
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;GraphQL 명세에서 사용될 데이터, 요청의 타입 지정&lt;/li&gt;
&lt;li&gt;gql(template literal tag)로 생성됨&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;resolver
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;서비스의 액션들을 함수로 지정&lt;/li&gt;
&lt;li&gt;요청에 따라 데이터를 반환/입력/수정/삭제함&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1644155589536&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//서버 재실행
npm start&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;실행된 http://localhost:4000 에서 로컬 서버에 쿼리 및 테스트 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1644155700093&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//조회 쿼리 테스트
query {
  teams {
    id
    manager
    office
    extension_number
    mascot
    cleaning_duty
    project
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Query 구현하기&lt;/b&gt;&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 모든 team 리스트 받아오기&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;typeDefs에 Query 루트타입 및 teams 명령어 정의&lt;/li&gt;
&lt;li&gt;쿼리 명령문 마다 반환될 데이터 형태를 지정&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;pre id=&quot;code_1644719284324&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;    type Query {
    	//teams라는 명령어는 team 리스트를 반환함
        teams: [Team]
    }&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;tepyDefs에 데이터 형태 정의&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1644719399688&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;    //Teams 명령어에 사용될 team이라는 데이터의 형식 정의
    type Team {
        id: Int
        manager: String
        office: String
        extension_number: String
        mascot: String
        cleaning_duty: String
        project: String
    }&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Resolver에 해당 함수 정의&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1644719477060&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const resolvers = {
  Query: {
  //teams 명령어는 database에 있는 teams를 반환함
  //실제 프로젝트에서는 DB를 조회하는 쿼리(sql, nosql 명령어) 사용
    teams: () =&amp;gt; database.teams
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;로컬 서버 playground에서 쿼리 테스트&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1644719769715&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;query {
  teams{
    id,
    manager,
    office,
    extension_number,
    mascot,
    cleaning_duty,
    project,
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 특정 team만 받아오는 경우&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt; args로 주어진 id에 해당하는 team만 필터링하여 반환&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1644719832329&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Query: {
    //...
    team: (parent, args, context, info) =&amp;gt; database.teams
        .filter((team) =&amp;gt; {
            return team.id === args.id
        })[0],
}&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;id를 인자로 받아 하나의 Team 데이터 반환&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1644719844254&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;type Query {
    ...
    team(id: Int): Team
}&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;쿼리 테스트&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1644719895488&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;query {
//team들 중 id가 1인 team만 반환
team(id: 1) {
    id
    manager
    office
    extension_number
    mascot
    cleaning_duty
    project
}
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 자료 참고하여 equipmets, supplies 등 다양한 추가 쿼리 실습&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.yalco.kr/@graphql-apollo/2-2/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://www.yalco.kr/@graphql-apollo/2-2/&lt;/a&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Mutation 구현하기&lt;/b&gt;&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Query와 Mutation은 개발자들간의 합의된 명세&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 정보들을 받아올때는 쿼리&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 해당 정보를 추가, 수정, 삭제 할때는 Mutation&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. Equipment 데이터 삭제하기&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;typeDefs에 Mutation 정의&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1644717707492&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;type Mutation {
	//Equipment를 삭제하고, 삭제된 Equipment를 반환
    deleteEquipment(id: String): Equipment
  }&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;resolve에 함수 정의&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1644717805760&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Mutation: {
      deleteEquipment: (parent, args, context, info) =&amp;gt; {
      
      	  //실제로는 DB에 필요한 쿼리문 (sql이나 몽고DB 명령어처럼 실제 DB를 위해 필요한 코드
          //해당 실습에서는 mock DB를 활용하는 메소드로 대체
          const deleted = database.equipments
              .filter((equipment) =&amp;gt; {
                  return equipment.id === args.id
              })[0]
          database.equipments = database.equipments
              .filter((equipment) =&amp;gt; {
                  return equipment.id !== args.id
              })
          return deleted
      }
}&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;로컬 서버 playground에서 쿼리 테스트&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1644718340575&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;mutation {
  deleteEquipment(id: &quot;notebook&quot;) {
    id
    used_by
    count
    new_or_used
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; * 해당 항목이 삭제된 것 반환값과 함께 확인 가능&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. Equipment 데이터 추가하기&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;typeDefs에 insert Mutation 정의&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1644718443311&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;type Mutation {
	//insert한 후 해당 Equitment 반환
    insertEquipment(
        id: String,
        used_by: String,
        count: Int,
        new_or_used: String
    ): Equipment
    ...
}&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;resolve에 함수 정의&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1644718631554&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Mutation: {
	//여기서 args는 Equitment와 동일한 데이터 구조를 갖고 있음
    //해당 데이터를 db에 바로 push 
    insertEquipment: (parent, args, context, info) =&amp;gt; {
        database.equipments.push(args)
        return args
    },
    //...
}&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;로컬 서버 playground에서 쿼리 테스트&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1644718846585&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;mutation {
  insertEquipment (
    id: &quot;laptop&quot;,
    used_by: &quot;developer&quot;,
    count: 17,
    new_or_used: &quot;new&quot;
  ) {
    id
    used_by
    count
    new_or_used
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;insert 한 결과 확인 가능 (query시 해당 데이터도 반환되는 것 볼 수 있음)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1986&quot; data-origin-height=&quot;668&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ppX2A/btrs667qZSU/RvMiuBVEUXFyH2KiOwIXU1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ppX2A/btrs667qZSU/RvMiuBVEUXFyH2KiOwIXU1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ppX2A/btrs667qZSU/RvMiuBVEUXFyH2KiOwIXU1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FppX2A%2Fbtrs667qZSU%2FRvMiuBVEUXFyH2KiOwIXU1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1986&quot; height=&quot;668&quot; data-origin-width=&quot;1986&quot; data-origin-height=&quot;668&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3. Equipment 데이터 수정하기&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;typeDefs에 update Mutation 정의&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1644719008004&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;type Mutation {
    editEquipment(
        id: String,
        used_by: String,
        count: Int,
        new_or_used: String
    ): Equipment
    ...
}&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;resolve에 함수 정의&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1644719021721&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Mutation: {
    // ...
    editEquipment: (parent, args, context, info) =&amp;gt; {
        return database.equipments.filter((equipment) =&amp;gt; {
            return equipment.id === args.id
        }).map((equipment) =&amp;gt; {
            Object.assign(equipment, args)
            return equipment
        })[0]
    },
    // ...
}&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;로컬 서버 playground에서 쿼리 테스트&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1644719032394&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;mutation {
  editEquipment (
    id: &quot;pen tablet&quot;,
    new_or_used: &quot;new&quot;,
    count: 30,
    used_by: &quot;designer&quot;
  ) {
    id
    new_or_used
    count
    used_by
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>개발 지식/DEVELOPMENT</category>
      <author>_Yeony</author>
      <guid isPermaLink="true">https://haloworld.tistory.com/157</guid>
      <comments>https://haloworld.tistory.com/157#entry157comment</comments>
      <pubDate>Tue, 8 Feb 2022 00:34:11 +0900</pubDate>
    </item>
    <item>
      <title>[GraphQL] GraphQL 기초 (REST API와 비교, GraphQL 강점, Apollo란?)</title>
      <link>https://haloworld.tistory.com/156</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;본 포스팅은 Inflearn 얄코님 강의를 수강하며 &lt;b&gt;복습용으로 &lt;/b&gt;작성하였습니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.inflearn.com/course/%EC%96%84%ED%8C%8D%ED%95%9C-graphql-apollo/dashboard&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://www.inflearn.com/course/%EC%96%84%ED%8C%8D%ED%95%9C-graphql-apollo/dashboard&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1644050529482&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;[무료] 얄팍한 GraphQL과 Apollo - 인프런 | 강의&quot; data-og-description=&quot;⚡ 짧고 굵은 전체 90분 강좌! 사이트의 코드들을 복붙하며 빠르게 GraphQL을 배우고 아폴로 사용법을 익히세요., - 강의 소개 | 인프런...&quot; data-og-host=&quot;www.inflearn.com&quot; data-og-source-url=&quot;https://www.inflearn.com/course/%EC%96%84%ED%8C%8D%ED%95%9C-graphql-apollo/dashboard&quot; data-og-url=&quot;https://www.inflearn.com/course/%EC%96%84%ED%8C%8D%ED%95%9C-graphql-apollo&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bnuqPs/hyNjRHuIWQ/k6PYIvklRE0HNQeSJfEHWk/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500,https://scrap.kakaocdn.net/dn/mJLNs/hyNjMTHRiw/1FuMJqRJyRqBsMeuIoEGV1/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500&quot;&gt;&lt;a href=&quot;https://www.inflearn.com/course/%EC%96%84%ED%8C%8D%ED%95%9C-graphql-apollo/dashboard&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.inflearn.com/course/%EC%96%84%ED%8C%8D%ED%95%9C-graphql-apollo/dashboard&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bnuqPs/hyNjRHuIWQ/k6PYIvklRE0HNQeSJfEHWk/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500,https://scrap.kakaocdn.net/dn/mJLNs/hyNjMTHRiw/1FuMJqRJyRqBsMeuIoEGV1/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[무료] 얄팍한 GraphQL과 Apollo - 인프런 | 강의&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;⚡ 짧고 굵은 전체 90분 강좌! 사이트의 코드들을 복붙하며 빠르게 GraphQL을 배우고 아폴로 사용법을 익히세요., - 강의 소개 | 인프런...&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.inflearn.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;GraphQL은 Rest API 방식의 단점을 보완할 수 있는 방법&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Rest API 방식의 단점&amp;nbsp;&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래와 같은 경우가 발생하기 쉽다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; - 불필요한 정보까지 받아오는 상황 (OverFetching)&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; - 필요한 정보를 못 받아오는 상황 (UnderFetching)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;ex) OverFetching : 사용자의 이름만 필요한데, 이름 외적인 개인정보도 함께 Response로 받게 됨&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;UnderFetching : 특정 사용자 정보의 response로 또 다시 쿼리를 해야하는 상황.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Response로 1번 사용자가 속한 팀을 알아내고, 그 팀에 속한 팀원들을 알아야 하는 경우 -&amp;gt; 2번 쿼리 필요&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;GraphQL로 CRUD 해보기&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://gitlab.com/yalco/yalco-inflearn-graphql-apollo&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://gitlab.com/yalco/yalco-inflearn-graphql-apollo&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드는 위 얄코님 강의의 1-3으로 사용하였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;1. query&amp;nbsp;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; GraphQL에서 Read에 해당하는 요청으로 REST API와 달리 원하는 정보만 쿼리할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&amp;nbsp; 각 팀 목록에서 manager와 office에 해당하는 정보만 쿼리 (Over fecthing 해결)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;978&quot; data-origin-height=&quot;701&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cb2DeX/btrsysIBtp7/jlnSkXCVHYgb8AD33xPtC1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cb2DeX/btrsysIBtp7/jlnSkXCVHYgb8AD33xPtC1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cb2DeX/btrsysIBtp7/jlnSkXCVHYgb8AD33xPtC1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcb2DeX%2FbtrsysIBtp7%2FjlnSkXCVHYgb8AD33xPtC1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;978&quot; height=&quot;701&quot; data-origin-width=&quot;978&quot; data-origin-height=&quot;701&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;팀 1의 특정 정보와 팀 1에 속하는 팀 멤버의 값 리턴 (Under fetching 해결)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1023&quot; data-origin-height=&quot;750&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dVUTCP/btrsqB1lvTR/XLldBhd22bGoAdy5apQxbK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dVUTCP/btrsqB1lvTR/XLldBhd22bGoAdy5apQxbK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dVUTCP/btrsqB1lvTR/XLldBhd22bGoAdy5apQxbK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdVUTCP%2FbtrsqB1lvTR%2FXLldBhd22bGoAdy5apQxbK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1023&quot; height=&quot;750&quot; data-origin-width=&quot;1023&quot; data-origin-height=&quot;750&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;2. mutation&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; GraphQL에서 생성/수정/삭제 요청 시 사용하는 명령어&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 2-1. 팀 정보 생성 요청&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1016&quot; data-origin-height=&quot;751&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cSuT59/btrsxD4FhYF/GyVPjxyvjQyORmAxTaW9YK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cSuT59/btrsxD4FhYF/GyVPjxyvjQyORmAxTaW9YK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cSuT59/btrsxD4FhYF/GyVPjxyvjQyORmAxTaW9YK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcSuT59%2FbtrsxD4FhYF%2FGyVPjxyvjQyORmAxTaW9YK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1016&quot; height=&quot;751&quot; data-origin-width=&quot;1016&quot; data-origin-height=&quot;751&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;2-2. 팀 정보 수정 요청&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1013&quot; data-origin-height=&quot;748&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/QBwsN/btrsAcysNlm/a4gmH2wTPUw1NeNd09Bhdk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/QBwsN/btrsAcysNlm/a4gmH2wTPUw1NeNd09Bhdk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/QBwsN/btrsAcysNlm/a4gmH2wTPUw1NeNd09Bhdk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FQBwsN%2FbtrsAcysNlm%2Fa4gmH2wTPUw1NeNd09Bhdk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1013&quot; height=&quot;748&quot; data-origin-width=&quot;1013&quot; data-origin-height=&quot;748&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 2-3. 팀 정보 삭제 요청&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1012&quot; data-origin-height=&quot;731&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/1uVoq/btrsxEWO2ZQ/mOpczqlPkzYzBWKeCIkJl0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/1uVoq/btrsxEWO2ZQ/mOpczqlPkzYzBWKeCIkJl0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/1uVoq/btrsxEWO2ZQ/mOpczqlPkzYzBWKeCIkJl0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F1uVoq%2FbtrsxEWO2ZQ%2FmOpczqlPkzYzBWKeCIkJl0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1012&quot; height=&quot;731&quot; data-origin-width=&quot;1012&quot; data-origin-height=&quot;731&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;GraphQL의 강점&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 필요한 정보만 선택하여 받아올 수 있음&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Overfetching 문제 해결&lt;/li&gt;
&lt;li&gt;데이터 전송량 감소&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 여러 계층의 정보를 한꺼번에 받아올 수 있음&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Underfetching 문제 해결&lt;/li&gt;
&lt;li&gt;요청 횟수 감소&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 하나의 endpoint에서 모든 요청을 처리&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt; 하나의 URI에서 POST로 모든 요청을 처리 가능&lt;/li&gt;
&lt;li&gt;query, mutation 모두 POST로 처리됨&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1569&quot; data-origin-height=&quot;546&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/watjg/btrsvdyRBiV/XjTCQNgaxFMVB3RPKsfMTk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/watjg/btrsvdyRBiV/XjTCQNgaxFMVB3RPKsfMTk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/watjg/btrsvdyRBiV/XjTCQNgaxFMVB3RPKsfMTk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fwatjg%2FbtrsvdyRBiV%2FXjTCQNgaxFMVB3RPKsfMTk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1569&quot; height=&quot;546&quot; data-origin-width=&quot;1569&quot; data-origin-height=&quot;546&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러나, REST API의 장점도 충분히 많기 때문에 상황에 따라 적절하게 선택해 사용해야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Apollo 란?&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;GraphQL은 REST API와 마찬가지로 API 요청을 주고받는 명세일 뿐이다.&lt;/li&gt;
&lt;li&gt;이를 사용하려면 GraphQL의 명세대로 백엔드/프론트엔드를 구현하거나, 이를 처리해주는 솔루션을 사용하여야 함&lt;br /&gt;ex) GraphQL.js, GraphQL Yoga, AWS Amplify, Relay 등..&lt;br /&gt;(&lt;a style=&quot;font-family: -apple-system, BlinkMacSystemFont, AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; letter-spacing: 0px;&quot; href=&quot;https://graphql.org/code/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://graphql.org/code/&lt;/a&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; letter-spacing: 0px;&quot;&gt; 에서 GraphQL을 위한 여러 솔루션들을 확인할 수 있다.)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Apollo는 이 솔루션들 중 하나
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;BackEnd, FrontEnd 모두 제공&lt;/li&gt;
&lt;li&gt;설정이 쉽고, 다양한 기능 제공&lt;/li&gt;
&lt;li&gt;Apollo Server 명세 : &lt;a href=&quot;https://www.apollographql.com/docs/apollo-server/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://www.apollographql.com/docs/apollo-server/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Apollo Client 명세 (React) : &lt;a href=&quot;https://www.apollographql.com/docs/react/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://www.apollographql.com/docs/react/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>개발 지식/DEVELOPMENT</category>
      <category>GraphQL</category>
      <author>_Yeony</author>
      <guid isPermaLink="true">https://haloworld.tistory.com/156</guid>
      <comments>https://haloworld.tistory.com/156#entry156comment</comments>
      <pubDate>Sat, 5 Feb 2022 18:13:33 +0900</pubDate>
    </item>
    <item>
      <title>[LeetCode] 617. Merge Two Binary Trees</title>
      <link>https://haloworld.tistory.com/155</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://leetcode.com/problems/merge-two-binary-trees/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://leetcode.com/problems/merge-two-binary-trees/&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1633440338608&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class Solution {
    public TreeNode mergeTrees(TreeNode root1, TreeNode root2) {
        TreeNode head = root1;
        
        if(root1==null &amp;amp;&amp;amp; root2==null) return null;
        if(root1==null &amp;amp;&amp;amp; root2!=null) return root2;
        if(root1!=null &amp;amp;&amp;amp; root2==null) return root1;
        
        root1.val+=root2.val;
        root1.left = mergeTrees(root1.left, root2.left);
        root1.right = mergeTrees(root1.right, root2.right);
        
        return root1;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>스터디/알고리즘 문제풀이</category>
      <category>Easy</category>
      <author>_Yeony</author>
      <guid isPermaLink="true">https://haloworld.tistory.com/155</guid>
      <comments>https://haloworld.tistory.com/155#entry155comment</comments>
      <pubDate>Tue, 5 Oct 2021 22:25:49 +0900</pubDate>
    </item>
    <item>
      <title>[LeetCode] 696. Count Binary Substrings</title>
      <link>https://haloworld.tistory.com/154</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://leetcode.com/problems/count-binary-substrings/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://leetcode.com/problems/count-binary-substrings/&lt;/a&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1633310486151&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//풀이 봄
class Solution {
    /*public int countBinarySubstrings(String s) {
        int[] groups = new int[s.length()];
        int idx = 0;
        groups[0]=1;
        for(int i=1;i&amp;lt;s.length(); i++){
            if(s.charAt(i-1) != s.charAt(i)) {
                groups[++idx]=1;
            } else {
                groups[idx]++;
            }
        }
        
        int ans = 0;
        for(int i=1;i&amp;lt;=idx;i++) {
            ans+=Math.min(groups[i-1], groups[i]);
        }
        return ans;
        
    }*/
    
    public int countBinarySubstrings(String s) {
        int result = 0, prev = 0, cur = 1;
        
        for(int i=1;i&amp;lt;s.length();i++){
            if(s.charAt(i-1)!=s.charAt(i)) {
                result += Math.min(prev, cur);
                prev = cur;
                cur = 1;
            } else {
                cur++;
            }
        }
        return result+Math.min(prev,cur);
        
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>스터디/알고리즘 문제풀이</category>
      <category>Easy</category>
      <author>_Yeony</author>
      <guid isPermaLink="true">https://haloworld.tistory.com/154</guid>
      <comments>https://haloworld.tistory.com/154#entry154comment</comments>
      <pubDate>Mon, 4 Oct 2021 10:22:02 +0900</pubDate>
    </item>
    <item>
      <title>[LeetCode] 101. Symmetric Tree</title>
      <link>https://haloworld.tistory.com/153</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://leetcode.com/problems/symmetric-tree/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://leetcode.com/problems/symmetric-tree/&lt;/a&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1633310429931&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class Solution {
    public boolean isSymmetric(TreeNode root) {
        return isMirror(root.right, root.left);
    }
    
    private boolean isMirror(TreeNode n1, TreeNode n2){
        if(n1==null || n2==null) return n1==n2;
        return (n1.val == n2.val &amp;amp;&amp;amp; isMirror(n1.left, n2.right) &amp;amp;&amp;amp; isMirror(n1.right, n2.left));
    }
}&lt;/code&gt;&lt;/pre&gt;</description>
      <category>스터디/알고리즘 문제풀이</category>
      <category>Easy</category>
      <author>_Yeony</author>
      <guid isPermaLink="true">https://haloworld.tistory.com/153</guid>
      <comments>https://haloworld.tistory.com/153#entry153comment</comments>
      <pubDate>Mon, 4 Oct 2021 10:20:39 +0900</pubDate>
    </item>
    <item>
      <title>[LeetCode] 226. Invert Binary Tree</title>
      <link>https://haloworld.tistory.com/152</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://leetcode.com/problems/invert-binary-tree/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://leetcode.com/problems/invert-binary-tree/&lt;/a&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1633310380436&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class Solution {
    public TreeNode invertTree(TreeNode root) {
        TreeNode head= root;
        
        if(root!=null) invert(root);
        return head;
    }
    
    private void invert(TreeNode n1) {
        if(n1==null) return;  

        invert(n1.right);
        invert(n1.left);
        TreeNode tmp = n1.right;
        n1.right = n1.left;
        n1.left = tmp;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>스터디/알고리즘 문제풀이</category>
      <category>Easy</category>
      <author>_Yeony</author>
      <guid isPermaLink="true">https://haloworld.tistory.com/152</guid>
      <comments>https://haloworld.tistory.com/152#entry152comment</comments>
      <pubDate>Mon, 4 Oct 2021 10:20:04 +0900</pubDate>
    </item>
    <item>
      <title>[LeetCode] 543. Diameter of Binary Tree</title>
      <link>https://haloworld.tistory.com/151</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://leetcode.com/problems/diameter-of-binary-tree/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://leetcode.com/problems/diameter-of-binary-tree/&lt;/a&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1632958198334&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class Solution {
    int max=0;
    public int diameterOfBinaryTree(TreeNode root) {
        int left = findDepth(root.left);
        int right = findDepth(root.right);
        return Math.max(left + right, max);
    }
    
    int findDepth(TreeNode node) {
        if(node==null)    return 0;
        int left = findDepth(node.left);
        int right = findDepth(node.right);
        max = Math.max(left + right, max);
        return Math.max(left, right)+1;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;gt; 시간 복잡도 : O(n)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;gt; 공간 복잡도 : O(n)&lt;/p&gt;</description>
      <category>스터디/알고리즘 문제풀이</category>
      <category>Easy</category>
      <category>leetcode</category>
      <author>_Yeony</author>
      <guid isPermaLink="true">https://haloworld.tistory.com/151</guid>
      <comments>https://haloworld.tistory.com/151#entry151comment</comments>
      <pubDate>Thu, 30 Sep 2021 08:31:36 +0900</pubDate>
    </item>
  </channel>
</rss>