[serverless] serverless를 이용해 graphQL 사용하기 (feat: postgraphile)

김지원·2021년 9월 21일
3

serverless

목록 보기
2/2
post-thumbnail

🤔 graphql을 사용하려고 하는 이유

api 생성 시간을 줄이기 위해서!

필자는 원래 mariadb를 사용하여 restAPI를 만들어 서버를 운영했었다.
하지만 이번 프로젝트 경우 빠르게 진행하려는 이유도 있고
dynamoDB - AppSync - Lambda - amplify 궁합이 찰떡이며 개발 속도가 빨라진다고 팀원에게 듣게 되었다.

하지만 저 방법을 사용하기 위해서는 지금 DB를 관계형으로 이미 짠 상태이고 dynamoDB처럼 noSQL로 되어있는 DB 설계를 하기에는 시간이 부족했다.
심지어 관계가 상당히 많은 DB라서 다른 방법을 찾아야했다. 😨

📖 DB 후보군 (결국 postgreSQL)

사실 위의 내용과는 별개로 restAPI로 만들어도 된다.
하지만 바꾸려고 한 궁극적인 이유는 서버리스에서 DB의 pool 관리가 안됐기때문이다..😱

1. mysql

상업적으로 이용시 라이센스 비용을 내야하기때문에 지양했다. 그래서 처음 DB는 mariaDB였다!

mysql은 특히나 pool 관리를 해주는 모듈인 serverless-mysql이 있어서 너무 아쉬웠다ㅠㅠㅠ

2. mariaDB

위에서 말했던 이유인 pool관리가 안됐기 때문이다.
lambda안에서 pool의 커넥션을 유지해서 만들어둔 pool의 양을 다 사용하게 됐다..
그래서 api를 2번 돌리면 too many connection error OMG 🤯

3. dynamoDB

관계형이 아니기도 하고 나중에 다룰꺼지만 생각해야하는 조건이 많아 포기하였다
꼭 나중에 도전할 것이다!!

4. postgreSQL

관계형이기도하고 mysql과 문법이 비슷하다. (아니 거의 똑같다)
그리고 postgraphile을 이용해 graphQL을 사용할 수 있다!! (⭐가장 중요)

이 방법을 사용하면 AppSync의 역할을 해줄 수 있을 줄 알았다 (물론 아니였지만)

결론적으론 postgreSQL로 정했다

👨‍💻 serverless로 postgraphile실행하기

1. 준비

일단 rds에 postgreSQL을 만들어주었다.
그리고 필요한 모듈을 설치하였다.

  • pg: postgreSQL 클라이언트
  • pg-pool: pg pool 생성
  • postgraphile: graphQL을 사용하기 위함
  • serverless-dotenv-plugin: dotenv의 내용을 사용을 명시하기 위함
  • @graphile-contrib/pg-simplify-inflector: postgraphile 시 스키마의 필드 이름을 간단하게 바꿔준다.

2. 코딩

config.js

const config = {
  user: process.env.POST_USER,
  password: process.env.PASSWORD,
  host: process.env.HOST,
  port: process.env.PORT,
  database: process.env.DATABASE,
  idleTimeoutMillis: 10,
};

module.exports = config;

postgreSQL 접속하기 위한 데이터 모듈화

다른 데이터는 다 아실꺼같아서 idleTimeoutMillis에 대해서만 설명을 드리면

시간 초과가 연결이 끊어지고 삭제되기 전에 클라이언트가 풀에서 유휴 상태로 있어야 하고 체크아웃되지 않아야 하는 시간입니다.

app.js

const express = require("serverless-express/express");
const { postgraphile } = require("postgraphile");
const Pool = require("pg-pool");
const dotenv = require("dotenv");
const pgConfig = require("./config");
const simple = require("@graphile-contrib/pg-simplify-inflector");

const app = express();
dotenv.config();

const pool = new Pool(pgConfig);
let postgraphileConfig = {
  // options
  // retryOnInitFail: true,
  appendPlugins: [simple],
  dynamicJson: true,
  graphqlRoute: "/",
  extendedErrors: ["hint", "detail", "errcode"],
  legacyRelations: "omit",
  pgDefaultRole: process.env.PG_DEFAULT_ROLE,
};

app.use(postgraphile(pool, process.env.SCHEMA, postgraphileConfig));

module.exports = app;

pool: 위의 config 데이터를 받아와 새로 접속해줍니다.

postgraphileConfig

  • retryOnInitFail: 실패시 다시 시도 할건지 확인 (default: false)
  • appendPlugins: 사용할 plugin, 필자는 스키마의 필드 이름을 간단하게 바꿔주는 플러그인 사용
  • dynamicJson: Json으로 data 주고 받음
  • graphqlRoute: postgraphile의 기본 경로 (default: graphiql)
  • extendedErrors: error시 보여 줄 데이터
  • pgDefaultRole: 필자는 postgres로 하였다. 자신의 default role을 쓰면 될 것 같다.

schema같은 경우는 자신이 사용할 스키마를 쓰면 된다.

이렇게 app.use로 postgraphile을 보내준다.

3. handler.js

"use strict";
const handler = require("serverless-express/handler");
const app = require("./app");

module.exports.handler = handler(app);

핸들러는 restAPI 보낼때와 똑같이 serverless-express/handler에서 받아 모듈화 시키는 방식으로 보내준다.

4. serverless.yml

service: service-name

frameworkVersion: '2'

useDotenv: true

provider:
  name: aws
  runtime: nodejs12.x
  region: ap-northeast-2
  lambdaHashingVersion: 20201221
  versionFunctions: true
  apiGateway:
    apiKeys:
      - postgraphile-dev-apikey


plugins:
  - serverless-offline
  - serverless-express
  - serverless-prune-plugin
  - serverless-dotenv-plugin

functions:
    app:
      memorySize: 3008
      handler: handler.handler
      events:
        - http:
            path: /
            method: POST
            cors: true
            private: true

custom:
    # 배포 이전 버전도 저장 유지 5개까지
    prune:
      automatic: true
      number: 5
  • useDotnev: true을 해줘야 env을 사용할 수 있다. 필수!
  • apiKeys 는 권한이 없는 사람은 사용할 수 없게 하기 위한 x-api-key를 생성하기 위함이다.
  • plugins: 자신이 사용할 plugin을 적어준다.
  • events: 부분에서 POST로 아까 app.use로 부른 postgrapile을 사용한다.
    ⭐ private: true를 해야 api-key가 없을 때 message의 내용이 뜨지 않는다.
  • prune: 배포 후 이전 버전을 5개까지 저장하기 위함.

5. 배포 후 실행

배포를 하게 되면
api keys는 x-api-key로 사용하고
endpoints는 경로로 사용하면 된다!

6. 이제 컴퓨터에 저장되어있는 graphiQL로 실행

  1. Add Header 부분에 x-api-key 입력

입력하지 않았을 경우

EndPoint에 endpoint에서 나온 주소 입력 후 graphiQL를 실행!

serverless에서 이제 graphiQL을 사용하여 API를 설계할 수 있다!

하지만 간과한 점...😱

이 코드는 appSync을 대신할 수 없다.

amplify는 appSync와 아주 제대로 연결되어 있기 때문ㅠㅠㅠ

좀 더 편하게 코딩하려면 appSync와 amplify를 연결하여 사용하는게 빠르다 (왜냐면 얘네가 설정 파일 다 만들어줘요😂)

하지만 마지막 희망!!

appSync에서 Aurora PostgreSQL을 지원한다!!!!!

그래서 다음엔 저 방법을 해보려고 한다..

📚 참고한 블로그

profile
backend-developer

0개의 댓글