본문으로 바로가기

Apollo-server에서 context는 무엇인가

 

apollo-server에서 contructor에 지정해주는 context란 다음과 같습니다. 일종의 전역 변수 같은 개념이죠.

 

An object (or a function that creates an object) that's passed to every resolver that executes for a particular operation. This enables resolvers to share helpful context, such as a database connection.

Certain fields are added to this object automatically, depending on which Node.js middleware your server uses.

For more details, see The context argument.

출처 - www.apollographql.com/docs/apollo-server/api/apollo-server/#constructor

 

 

한가지 더 중요한 사실은 첫번째 인자로 Request 객체를 자동으로 가져온다는 겁니다.

 

미들웨어

=> gql context

=> context를 @Context를 통해 resolver에서 사용하거나 ExecutionContext를 통해CustomDecorator, Guard 등에서 활용합니다.

 

 

미들웨어를 통해 req 객체에 원하는 정보를 달아서 전달하면 gql context에서 적당히 정제한 후에 넘겨주는 방식으로 자주 사용합니다.

 

A request context is available for each request. When context is defined as a function, it will be called on each request and will receive an object containing a req property, which represents the request itself.

By returning an object from the context function, it will be available as the third positional parameter of the resolvers:

new ApolloServer({
  typeDefs,
  resolvers: {
    Query: {
      books: (parent, args, context, info) => {
        console.log(context.myProperty); // Will be `true`!
        return books;
      },
    }
  },
  context: async ({ req }) => {
    return {
      myProperty: true
    };
  },
})

 

출처 - github.com/apollographql/apollo-server#context

 

 

 

Nest에서 context를 통해 resolver에서 사용하자

 

우선 미들웨어를 통해 req 객체에 사용할 정보를 추가해줘야 합니다. 이 부분은 Middleware를 다룬 제 포스트를 참고하시면 됩니다.

 

darrengwon.tistory.com/980

 

Nest Middleware

docs.nestjs.com/middleware Documentation | NestJS - A progressive Node.js framework Nest is a framework for building efficient, scalable Node.js server-side applications. It uses progressive JavaScr..

darrengwon.tistory.com

 

어쨋거나 JwtMiddleware를 달아주었고, req.user에 정보를 추가해줬습니다. 이 request 객체는 context의 첫번째 인자로 들어가니 여기서 빼내 사용하면 되겠죠

@Injectable()
export class JwtMiddleWare implements NestMiddleware {
  constructor(private readonly jwtService: JwtService, private readonly usersService: UsersService) {}

  ... 생략
  req['user'] = user;
  
  next();
  
}
export class AppModule implements NestModule {
  configure(consumer: MiddlewareConsumer) {
    consumer.apply(JwtMiddleWare).forRoutes({
      path: '/graphql',
      method: RequestMethod.ALL,
    });
  }
}

 

context를 사용할 수 있게 GraphQLModule을 구성해봅시다.

GraphQLModule은 apollo-server-core를 연장한 겁니다. 내부 정의 부분을 참고해보면 ApolloServerBase를 받아 사용한 부분이 보입니다. 이 말은, Apollo에서 제공하는 내용을 통해 gql 서버를 구성할 수 있다는 것입니다.

import { ApolloServerBase } from 'apollo-server-core';

줄 수 있는 속성이 많네요. 각 속성이 무엇을 의미하는지는 공식문서를 참고합시다.

 

export interface Config extends BaseConfig {
  modules?: GraphQLSchemaModule[];
  typeDefs?: DocumentNode | Array<DocumentNode> | string | Array<string>;
  parseOptions?: GraphQLParseOptions;
  resolvers?: IResolvers | Array<IResolvers>;
  schema?: GraphQLSchema;
  schemaDirectives?: Record<string, typeof SchemaDirectiveVisitor>;
  context?: Context | ContextFunction;
  ... 중략
}

 

다음과 같이 구성해봅시다.

GraphQLModule.forRoot({
  autoSchemaFile: join(process.cwd(), 'src/schema.gql'), // set true if you want to use in memory gql
  debug: true,
  playground: true,
  context: ({ req }) => ({ user: req['user'] }),
}),

 

일반적으로 resolver에서 (root, args, context, info) => ... 상태로 들어가서 여기에서 사용했습니다만 nest에서는 조금 다릅니다. @nest/graphql에서 @Context를 이용해야 합니다.

 

@Query(() => User)
getMyProfile(@Context() context) {
  if (!context.user) {
    return;
  } else {
    return context.user;
  }
}

 

 

darren, dev blog
블로그 이미지 DarrenKwonDev 님의 블로그
VISITOR 오늘 / 전체