Prisma로 GraphQL을 쉽게 도입하기

Jade Yeom
LABELSTORE ENGINEERING
12 min readJul 9, 2019

--

안녕하세요. 블랭크코퍼레이션에서 인플루언서 공동구매 플랫폼 레이블스토어의 개발팀을 이끌고있는 염승우 입니다! 🚀

급속도로 성장중인 레이블스토어의 새로운 버전을 개발하면서 Prisma로 GraphQL을 도입 할 수 있었던 경험을 공유해보려고 합니다.

우리는 왜 Prisma를 선택했는가?

Prisma 랜딩페이지의 메인 화면

Prisma를 도입하기 전, 레이블스토어 개발팀은 Sequelize ORM을 사용했었습니다. Sequelize는 Node.js 개발 진영에서는 다른 ORM 보다 뛰어난 성능, 간편한 마이그레이션 및 모델 작성 등으로 독보적으로 유명합니다.

변경점마다 관리해야하는 Sequelize의 마이그레이션과 모델들

하지만 변경점이 생길 때 마다 모델과 마이그레이션을 따로 관리해야 한다는 점이 매우 불편했습니다. 얼리스테이지 제품 개발의 특성상 테이블과 컬럼 그리고 그것들의 관계(Relationship)에 대한 추가와 수정이 잦았는데, 이에 대응하는것이 많이 불편했죠.

또한 단순히 모델과 마이그레이션을 관리하는 것이 아니라, RESTful API 에서의 추가적인 대응 작업마저 번거롭기 일쑤였습니다. API가 추가될 때는 Endpoint를 계속해서 만들어 주어야 하고, 그것들을 별개로 관리하기란 참으로 불편했죠.

저희 개발팀은 이런 불편에 대안을 찾던 중 Prisma를 찾게되었습니다. Prisma는 앞서 말했던 불편한 점을 개선했음은 물론, 아래와 같은 강력한 기능을 제공하고 있었어요.

  1. GraphQL 형식의 데이터모델만 작성하면 사용하는 언어와 DBMS에 구애받지 않고, ORM 클라이언트와 모델, 그리고 Data Schema 가 자동으로 생성된다.
  2. GraphQL, REST API의 구현체를 제공해준다.
  3. 자체 어드민 페이지를 제공하여 쉬운 데이터 운용이 가능하다. (비개발자도 손쉽게 쓸 수 있을 정도.)

이런 장점들 외에도 ZEIT, GraphQL, Heroku, Netlify 등과 같은 유명한 회사나 기술창립자 분들, 그리고 스탠포드 대학교, 클라이너 퍼킨스 와 같은 대규모 단체의 투자도 함께 받았다는 점이 저희에게 신뢰감을 주었습니다.

Prisma는 어떻게 동작하는가?

Prisma는 기존 ORM의 동작방식과는 조금 다릅니다. Sequelize나 TypeORM과 같은 기존 ORM은 DB 호스트에 직접적인 Connection을 이루어 트랜잭션을 수행하는데요. Prisma 같은 경우는 Scala로 작성된 Prisma의 서버가 DB 호스트를 앞단에서 관리합니다.

이 후 GraphQL 형식의 DataModel을 정의하면 Prisma가 알아서 사용하고있는 DBMS와 언어의 종류에 맞게 실제 DB 배포부터, 클라이언트와 모델 그리고 타입정의까지 자동으로 만들어 제공해 줍니다. 또한 GraphQL의 구현체까지 모두 정의되어있죠.

글 작성 날짜를 기준으로, 현재 지원하고 있는 언어는 JavaScript, TypeScript, Go 이며, DBMS는 Postgres, MySQL, mongoDB을 지원하고 있습니다. (추후에는 Elastic Search와 Oracle을 지원할 예정이라고 합니다.)

만들어진 클라이언트와 모델 그리고 구현체 등을 바탕으로 실제 서버에 적용하면 끝입니다. 주로 apollo-server을 이용하여 구현체(Resolvers)를 그대로 활용합니다.

한 번 사용해볼까요?

Prisma를 사용하기 위해선 일단 CLI 애플리케이션을 설치해야합니다. 사용하시는 패키지 매니저로 아래와 같이 설치해주세요.

// Yarn을 사용한다면
$ yarn global add prisma
// NPM을 사용한다면
$ npm i -g prisma

Prisma CLI를 통해 로컬환경에서 설정하기

$ prisma init

방법은 정말 간단합니다. 위 커맨드를 실행하시고 원하는 DBMS와 Client 언어를 선택하면 되는데요. 저는 MySQL과 TypeScript의 Prisma 클라이언트를 선택했습니다.

그러면 Prisma CLI는 그에 맞게 Prisma Server를 컨테이너 형태로 올릴 수 있는 docker-compose 파일, prisma 설정 파일인 prisma.yml, 그리고 GraphQL 형태로 데이터 모델링을 할 수 있는 datamodel.prisma 파일을 자동으로 생성합니다. 우린 이 세가지 파일들로 Prisma를 사용해볼겁니다.

Prisma Server 구동

$ docker-compose up -d

이렇게 Docker 이미지를 받고, 컨테이너로써 실행되면 localhost:4466 으로 prisma 서버가 실행됩니다. 우린 이제 이 엔드포인트로써 Prisma 서버를 사용할 수 있습니다.

이제 기본 설정은 끝났습니다! 🙆‍♂️

해당 과정이 번거롭다면 AWS Cloudformation를 통해 쉽게 구축할 수 있으니 이 방법을 시도해보는것도 좋습니다. (튜토리얼 링크)

데이터 모델 작성

데이터 모델은 GraphQL 형식의 작성 방식과 거의 동일합니다. 예시로 계정과 프로필 그리고 그 계정으로 글을 쓴다는 시나리오를 가정하고 Account, Profile, Post 각각 1:1:N 관계에 있는 타입을 간단히 정의해보겠습니다. datamodel.prisma 파일을 아래와 같이 작성해주세요.

type Account {
id: ID! @id
email: String!
profile: Profile!
posts: [Post!]!
createdAt: DateTime! @createdAt
updatedAt: DateTime! @updatedAt
}
type Profile {
id: ID! @id
account: Account! @relation(link: INLINE)
bio: String
websiteURL: String
createdAt: DateTime! @createdAt
updatedAt: DateTime! @updatedAt
}
type Post {
id: ID! @id
content: String!
author: Account! @relation(link: INLINE)
createdAt: DateTime! @createdAt
updatedAt: DateTime! @updatedAt
}

기존 데이터베이스에서 데이터 모델 작성

Prisma에는 Introspect라는 기능이 있습니다. 이 기능은 Prisma에서 해당 데이터베이스의 정보를 읽고 자동으로 DataModel 을 작성해주는데요. 기존 데이터베이스를 그대로 Prisma 에서 사용하려면 아래와 같이 입력 후 데이터베이스 서버 정보를 입력합니다. 이 후 Prisma에서 기존 데이터베이스 정보들을 바탕으로 DataModel을 자동으로 작성해줍니다.

Prisma 서버에 변경점 적용

$ prisma deploy

이제 위와 같이 입력해주세요. 모든 변경점이 실제 데이터베이스에 적용되며, 모델과 클라이언트들이 자동으로 변경점에 대한 업데이트를 진행할겁니다.

위처럼 변경점이 적용되었다는 결과가 뜨면 성공적으로 서버에 적용되었다는 뜻입니다. 이제 http://localhost:4466 으로 접속해볼게요.

지금 보시는 화면은 GraphQL Playground 인데요. Prisma 서버에 직접적으로 질의(Query, Mutation, Subscription)을 요청할 수 있으며, 응답 결과를 보여주고, Schema와 Docs를 제공해주는 역할을 합니다. 여기에 GraphQL 문법을 사용해서 간단히 계정을 생성하고, 자기소개를 적고, 글도 같이 한 번 써보는 질의를 던져볼게요.

GraphQL 질의 문법은 여기를 참고하세요.

요청된 Query

mutation {
createAccount(
// 생성될 계정의 데이터
data :{
email : "jade@yeom.me",
profile :{
create : {
bio : "I'm Jade"
}
}
posts : {
create : {
content : "이렇게 GraphQL Mutation으로 계정을 만들 수 있네요."
}
}
}
){
// Response로 받을 Account의 Fields를 명세
profile {
id
bio
createdAt
updatedAt
}
posts {
content
createdAt
updatedAt
}
}
}

응답된 Response

{
"data": {
"createAccount": {
"profile": {
"id": "cjxudbg9d00680937b5ihuyb1",
"bio": "I'm Jade",
"createdAt": "2019-07-08T12:34:49.481Z",
"updatedAt": "2019-07-08T12:34:49.481Z"
},
"posts": [
{
"content": "이렇게 GraphQL Mutation으로 계정을 만들 수 있네요.",
"createdAt": "2019-07-08T12:34:49.482Z",
"updatedAt": "2019-07-08T12:34:49.482Z"
}
]
}
}
}

어떤가요? 정말 간단하죠! 기존의 고전적인 ORM을 사용해서 만들었으면, Relation 신경써야하고, JOIN 걸어야 하고, 트랜잭션 하나하나 일일이 신경쓸게 많아서 정말 시간이 들었을거예요.

Prisma가 자동으로 만들어준 Resolvers

이런 기본적인 CRUD 형태의 간단한 질의 말고도 Sorting, Filtering, Subscription의 Resolvers는 Prisma가 모두 자동으로 만들어 제공합니다.

실 운영 환경에서는 Prisma GraphQL 서버를 그대로 사용해서는 안되며, Apollo Server와 같은 GraphQL Server의 Resolver를 Prisma에서 제공해준 구현체와 연결하여 사용하는 것이 좋습니다.

레이블스토어 ❤️ Prisma

레이블스토어는 Sequelize를 사용하던 모든 애플리케이션들을 Prisma로 대체하였습니다.

레이블스토어의 백오피스B2C 애플리케이션 모두 Prisma의 GraphQL로 개발되었습니다. 프론트엔드는 React, Next.js와 apollo-client를 사용하여 대부분의 애플리케이션을 개발하고 있으며, 백엔드는 Express기반의 apollo-server를 사용하고 있습니다. 아직까지는 저희 Prisma 서버의 다운타임은 발생하지 않았습니다. 비교적 Stable 하게 Production 환경에서 운용되고 있고, 혹여 모를 대규모 트래픽에 대비하기 위해 ECS 위에서 운용되고 있는 모든 클러스터는 Auto Scaling 설정이 되어있습니다.

레이블스토어의 Prisma 개발서버 어드민

Prisma에서 기본적으로 제공하는 어드민 페이지도 적극 활용하고 있습니다. 이 덕분에 비개발 영역에 있으신 분들이지만, 운영업무를 보시는 분들께서 백오피스에서 건들기 힘든 세세한 부분들도 쉽게 수정할 수 있으며, 퍼포먼스 마케터 분들과 같이 날 것의 데이터를 원하시는 분들도 손쉽게 데이터를 뽑아서 볼 수 있도록 열어드리고 있습니다.

정말 초고속으로 만든 유저간 채팅기능 with Prisma

Prisma로 정의한 모든 타입들은 Subscription을 지원합니다. Subscription은 Pubsub 패턴의 실시간성 API로써 데이터의 Created, Updated, Deleted에 대한 모든 이벤트를 WebSocket을 통해 받아볼 수 있는데요. 이번 레이블스토어 개발팀은 유저간의 채팅을 구현하기 위해 Subscription 기능을 통해 채널톡과 유사하지만 유저들 간의 채팅이 가능한 기능을 단 이틀 만에 만들었습니다! 😊

WebSocket을 통한 실시간 트랜잭션

Prisma 2 is Coming

Prisma의 새로운 버전의 RFC가 작성된 이후 새로운 버전 개발에 박차를 가하고 있습니다. 주요 변경점은 별도로 운용해야했던 Prisma Server의 의존성을 없애고 자체 쿼리 엔진과 마이그레이션 엔진을 Standalone 형태로 사용할 수 있다는 점이 크며, 기존 버전의 알려진 많은 이슈들을 해결했다고 합니다. 로드맵 상으로는 올해 안으로는 나올 것 같고, 이번에 열린 GraphQL Conf Berlin 2019 행사 이후 Prisma2의 Preview를 공개했다고 하니 체험해보셔도 좋을 것 같습니다.

레이블스토어를 이루는 기술들

끝 마치며

레이블스토어는 날마다 성장하고 있고, 이에 빠르게 변화하는 모든 상황에 준비하고 있습니다. 다음은 레이블스토어의 시스템 아키텍쳐에 대해 공유해보려고 합니다.

읽어주셔서 감사합니다!

우리는 더 빠르게 달리기 위해 뜻을 같이 할 동료를 찾고있습니다. 혹시나 저희 팀에 관심이 있으시면 아래 채용공고도 함께 둘러봐주세요. 🙏

레이블스토어 개발자 채용공고 🚀

블랭크코퍼레이션 채용공고 🙌

--

--