📝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/