[GraphQL-TypeORM] 친구 관계 구현 - GraphQL Schema, Resolver

지난 번에 작성한 TypeORM 코드에 GraphQL을 추가해보자.

프로젝트 구조

프로젝트 구조는 다음과 같다.

├── src
│   ├── entity
│   │   ├── Follow.ts
│   │   └── User.ts
│   ├── graphql
│   ├── repository
│   │   ├── Follower
│   │   │   ├── FollowerRepository.test.ts
│   │   │   └── FollowerRepository.ts
│   │   ├── User
│   │   │   ├── UserRepository.test.ts
│   │   │   ├── UserRepository.ts
│   │   │   └── index.ts
│   │   └── index.ts
│   ├── index.ts
│   └── startServer.ts
├── tsconfig.json
├── yarn.lock
├── README.md
├── jest.config.js
├── ormconfig.json
├── ormconfigSample.json
└── package.json

이번에 작업할 graphql 폴더의 구조는 아래와 같다.

├── follow
│   ├── followResolver.ts
│   ├── followSchema.ts
│   └── index.ts
├── user
│   ├── index.ts
│   ├── userResolver.ts
│   └── userSchema.ts
└── index.ts

GraphQL Schema

먼저 user schema와 follow schema를 정의한다. user, follow schema는 TypeORM에서 정의한 Entity와 유사하다.

User schema

// src/graphql/user/userSchema.ts

import { gql } from 'apollo-server-express';

const userSchema = gql`
  extend type Query {
    signin(email: String!, password: String!): AuthPayload!
    me: User!
    user(id: ID!): User!
    users: [User]!
  }

  extend type Mutation {
    signup(input: signupInput): User!
  }

  type AuthPayload {
    user: User!
    token: String!
  }

  type User {
    id: ID!
    email: String!
    nickname: String!
    following: [Follow]!
    followers: [Follow]!
  }

  input signupInput {
    email: String!
    password: String!
    nickname: String!
  }
`;

export { userSchema };

최소한의 행위만 구현했다.

유저는 로그인을 하고, 자신의 정보를 확인할 수 있고, 다른 사용자의 정보를 확인할 수 있다. (다른 사용자의 정보를 확인하는 것은 나중에 친구만 가능하도록 변경해보자.)

그리고 follower, following의 정보를 확인할 수 있다.

User Type은 TypeORM에서 정의한 Entity와 유사하다.

Follow schema

// src/graphql/follow/followSchema.ts

import { gql } from 'apollo-server-express';

const followSchema = gql`
  extend type Query {
    getFollowers(id: ID!): [Follow]!
    getFollowing(id: ID!): [Follow]!
  }

  extend type Mutation {
    setFollowing(id: ID!): Follow!
    deleteFollowing(id: ID!): Follow!
    deleteFollower(id: ID!): Follow!
    checkFollower(id: ID!): Follow!
  }

  type Follow {
    id: ID!
    following: User!
    follower: User!
    checked: Boolean!
    createdAt: String!
    updatedAt: String!
  }
`;

export { followSchema };

유저는 회원가입을 할 수 있고, 다른 유저를 following 할 수 있다.

자신의 following, follower를 삭제할 수 있고, checkFollower를 이용하여 follower들 중 확인하지 않은 대상을 확인한 대상으로 변경할 수 있다.

GraphQL Resolver

일단 프로그램을 실행하기 위해 schema에 해당하는 resolver signature만을 만들어두자.

user resolver

// src/graphql/user/userResolver.ts

const userResolver = {
  Query: {
    signin: () => {},
    me: () => {},
    user: () => {},
    users: () => {},
  },
  User: {
    following: () => {},
    followers: () => {},
  },
  Mutation: {
    signup: () => {},
  },
};

export { userResolver };

follow resolver

// src/graphql/follow/followResolver.ts

const followResolver = {
  Query: {
    getFollowers: () => {},
    getFollowing: () => {},
  },
  Follow: {
    following: () => {},
    follower: () => {},
  },
  Mutation: {
    setFollowing: () => {},
    deleteFollowing: () => {},
    deleteFollower: () => {},
    checkFollower: () => {},
  },
};

export { followResolver };

마지막으로 schema와 resolver를 각각 하나로 엮어서 Apollo Server에 전달하자.

// src/graphql/user/index.ts

export { userResolver } from './userResolver';
export { userSchema } from './userSchema';
// src/graphql/follow/index.ts

export { followResolver } from './followResolver';
export { followSchema } from './followSchema';
// src/graphql/index.ts

import { gql } from 'apollo-server-express';
import { userResolver, userSchema } from './user';
import { followResolver, followSchema } from './follow';

const linkSchema = gql`
  type Query {
    _: Boolean
  }
  type Mutation {
    _: Boolean
  }
  type Subscription {
    _: Boolean
  }
`;

const schemas = [linkSchema, userSchema, followSchema];

const resolvers = [userResolver, followResolver];

export { resolvers, schemas };
// src/startServer.ts

import 'reflect-metadata';
import express from 'express';
import { ApolloServer } from 'apollo-server-express';
import { schemas, resolvers } from './graphql';
import connectDB from './repository';

export const startServer = async () => {
  try {
    await connectDB();
    const PORT = 9999;
    const app = express();

    const server = new ApolloServer({
      typeDefs: schemas,
      resolvers,
    });

    server.applyMiddleware({ app, cors: false });

    app.listen(PORT, () => {
      console.log(`Server: http://localhost:${PORT}${server.graphqlPath}`);
    });
  } catch (error) {
    console.error(error);
  }
};

이제 yarn dev로 프로그램을 실행할 수 있다.


Written by@[Suho]
뭐든지 만들어보자.