반응형

📝Data Fetch

아폴로 서버에서 데이터를 Fetch할 수 있는 라이브러리를 제공한다

 

const sqlite3 = require("sqlite3").verbose();
const { SQLDataSource } = require("datasource-sql");

class DogsDataSource extends SQLDataSource {
  constructor({ cache, token }) {
    const db = new sqlite3.Database("dogs.db");
    super({ db });
    this.token = token; // 혹은 다른 인증 메커니즘을 사용
  }

  async getDogs() {
    return this.db.all("SELECT * FROM dogs");
  }

  async getDogById(id) {
    return this.db.get("SELECT * FROM dogs WHERE id = ?", id);
  }
}


import { RESTDataSource } from '@apollo/datasource-rest';

class MoviesAPI extends RESTDataSource {
  override baseURL = 'https://movies-api.example.com/';

  async getMovie(id: string): Promise<Movie> {
    return this.get<Movie>(`movies/${encodeURIComponent(id)}`);
  }

  async getMostViewedMovies(limit = '10'): Promise<Movie[]> {
    const data = await this.get('movies', {
      params: {
        per_page: limit.toString(), // all params entries should be strings,
        order_by: 'most_viewed',
      },
    });
    return data.results;
  }
}




//highlight-start
interface ContextValue {
  dataSources: {
    dogsDB: DogsDataSource;
    catsApi: CatsAPI;
  };
  token: string;
}
//highlight-end

const server = new ApolloServer<ContextValue>({
  typeDefs,
  resolvers,
});

const { url } = await startStandaloneServer(server, {
  context: async ({ req }) => {
    const { cache } = server;
    const token = req.headers.token;
    return {
      // We create new instances of our data sources with each request.
      // We can pass in our server's cache, contextValue, or any other
      // info our data sources require.
      
      dataSources: {
        dogsDB: new MoviesAPI({ cache, token }),
        catsApi: new CatsAPI({ cache }),
      },
      //highlight-end
      token,
    };
  },
});

console.log(`🚀  Server ready at ${url}`);

SQLDBSource의 예제이며 Apollo Server에 dataSources에 만들어둔 DB Source를 연결하면 된다

API 또한 비슷한 형식으로 하면 된다

이러한 Source들에게 캐싱 일괄처리 등 다양한 옵션들을 제공한다

 

자세한 사항은 공식 문서를 참고하면 좋다

https://www.apollographql.com/docs/apollo-server/data/fetching-data/

https://www.apollographql.com/docs/apollo-server/data/fetching-rest

 

📝웹 프레임워크

기본적으로 startStandaloneServer와 expressMiddleware를 제공합니다 그리고 기본적으로 Apollo Server4에서는 Express 통합인 startStandaloneServer를 사용합니다

 

다양한 웹 프레임워크에서 사용할 수 있게 제공하는 라이브러리가 있다

 

자세한건 공식 문서를 참고하자

https://www.apollographql.com/docs/apollo-server/integrations/integration-index

 

📝Sandbox Landing Page (개발 / 운영)

프로덕션 환경에서는 다른 랜딩 페이지를 제공한다 이는 부분적으로 프로덕션에서 자체 검사를 비활성화하기 때문이다 이말은 Apollo Sandbox와 같은 도구가 작동하지 않는 걸 의미한다

또한 Landing Page를 커스텀하거나 비활성화 할 수도 있다

 

자세한 건 공식 문서를 참고하자

https://www.apollographql.com/docs/apollo-server/workflow/build-run-queries/#custom-landing-page

 

📝Codegen

# This configuration file tells GraphQL Code Generator how
# to generate types based on our schema.
schema: "./schema.graphql"
generates:
  # Specify where our generated types should live.
  ./src/__generated__/resolvers-types.ts:
    plugins:
      - "typescript"
      - "typescript-resolvers"
    config:
      useIndexSignature: true
      # More on this below!
      contextType: "../index#MyContext"

Codegen은 Schema기반으로 그에 맞는 타입스크립트 코드나 리졸버 등을 자동적으로 만들어주는 역할을 해줍니다

다양한 plugins와 config 설정이 존재합니다

 

자세한 건 공식문서인 Graphql-Codegen을 참고해주세요

https://the-guild.dev/graphql/codegen

 

type User {
   id: ID!
   name: String!
   email: String
}

type Query {
   getUser(id: ID!): User
}

export interface User {
   id: string;
   name: string;
   email?: string;
}

export interface Query {
   getUser: User;
}

위에 코드는 해당 스키마를 기준으로 interface가 나온 형태입니다

 

📝Mocking & 테스트 코드

// For clarity in this example we included our typeDefs and resolvers above our test,
// but in a real world situation you'd be importing these in from different files
const typeDefs = `#graphql
  type Query {
    hello(name: String): String!
  }
`;

const resolvers = {
  Query: {
    hello: (_, { name }) => `Hello ${name}!`,
  },
};

it('returns hello with the provided name', async () => {
  const testServer = new ApolloServer({
    typeDefs,
    resolvers,
  });

  const response = await testServer.executeOperation({
    query: 'query SayHelloWorld($name: String) { hello(name: $name) }',
    variables: { name: 'world' },
  });

  // Note the use of Node's assert rather than Jest's expect; if using
  // TypeScript, `assert`` will appropriately narrow the type of `body`
  // and `expect` will not.
  assert(response.body.kind === 'single');
  expect(response.body.singleResult.errors).toBeUndefined();
  expect(response.body.singleResult.data?.hello).toBe('Hello world!');
});

 

executeOperation을 이용해 해당 쿼리에 어떤 파라미터를 줬을 때 결과값에 대한 테스트 코드를 작성할 수 있습니다

또한 Mocking기능도 지원합니다

 

자세한 건 공식문서 참고 바랍니다

https://www.apollographql.com/docs/apollo-server/testing/testing/

https://www.apollographql.com/docs/apollo-server/testing/mocking/

반응형