2016년 중반 마이크로서비스로의 전환을 결정했습니다. 마이크로서비스는 이론상 다른 서비스에 영향을 주지 않고 내부 기술을 바꿀 수 있습니다. 하지만 마이크로서비스 간의 통신 방법은 한번 결정하면 쉽게 바뀌기 어려울 것 같아서 가장 많이 고민했습니다. 그리고 Thrift를 선택했습니다. 이번 글에서는 그 이유와 이후의 상황에 관해 설명하겠습니다.

마이크로서비스에 대한 글들을 찾아보면 대부분은 통신 방법도 REST API를 많이 얘기하고 있습니다. (예. Introduction to Microservices | NGINX) 그러나 이전 글에서 썼듯이 REST API에 불편함을 느끼고 있었습니다. 특히 마이크로서비스 간에는 REST로 표현하기 어려운 더 다양한 API가 필요해질 것 같았습니다. 그래서 대안을 찾아봤습니다.

그 당시 고려했던 대안은 Thrift, Avro, Protocol Buffers였던 것으로 기억합니다. 지금 시점에 괜찮아 보이는 gRPC는 이상하게 당시 고려대상에서 벗어나 있었던 것 같습니다. 아마 RPC 보다는 데이터 직렬화 쪽을 더 중점적으로 생각했던 것 같습니다. 데이터- 특히 배열 -를 JSON으로 만들면 크기가 매우 크기 때문에 데이터 크기가 줄어드는 게 매력적으로 다가왔습니다.

그중에서 Thrift를 선택한 건 다음과 같은 이유가 있었던 것 같습니다.

  1. Avro 방식보다는 Thrift / Protocol Buffers 방식이 더 작은 사이즈를 만들 것 같았습니다.
  2. Protocol Buffers는 JavaScript를 잘 지원하는 듯이 보이지 않았습니다. (공식 문서의 튜토리얼에 없음)
  3. VCNC에서 Thrift를 쓰고 있다는 글을 봐서 어느 정도 검증이 됐으리라 봤습니다.

그렇게 Thrift를 마이크로서비스 간의 통신에 적용하는 작업을 시작했는데 생각만큼 잘 동작하지는 않았습니다.

  1. JavaScript를 지원하지만, 막상 해보니 클리어언트 JavaScript 용이었고, Node.js에 어울리는 코드를 만들어주지 않았습니다. TypeScript 지원을 포함해 몇 가지 수정을 가해서 사용하고 있습니다. (https://github.com/croquiscom/thrift/tree/croquis-171130)
  2. TCP 소켓 통신을 통해 요청마다 연결을 만들어야 하는 낭비를 없애기를 기대했는데, 오토 스케일링과 어울리지 않아서 결국 HTTP 통신을 했습니다.

몇 가지 문제가 있긴 하지만, 오랜 시간에 걸쳐 안정화되어 현재 수백개의 Thrift API가 존재하고 있습니다.

크로키닷컴만의 특이한 규칙이 하나 있다면 Read API에서 모든 필드 요청을 피하기 위해서 받기를 원하는 필드를 지정할 수 있도록 구성되어 있다는 것입니다. Update API도 하나로 여러 요구 사항에 대응하기 위해 업데이트를 할 필드를 같이 주도록 했습니다.

/// 지그재그 공지사항
struct ZigzagNotice {
  /// 레코드 ID
  1: optional i32 id
  /// 공지사항 내용
  2: optional string contents
  /// 공지 날짜
  3: optional i32 date
  /// 배포 대상 OS 타입 (0:common,1:none,2:iOS,3:Android)
  4: optional i32 os
  /// 공지사항에 필요한 링크 URL
  5: optional string link
}

service ZigzagNoticeService {
  /**
   * 해당 레코드 ID의 공지사항을 반환한다.
   *
   * fields는 ZigzagNotice의 구조체 필드 ID로 빈 경우 레코드 ID만 반환한다.
   */
  ZigzagNotice getZigzagNotice(1: i32 notice_id, 2: list<i32> fields)

  /**
   * 해당 레코드 ID의 공지사항을 업데이트 한다.
   *
   * fields는 ZigzagNotice의 구조체 필드 ID로 정의된 필드의 값만 업데이트 된다.
   */
  void updateZigzagNotice(1: i32 notice_id, 2: ZigzagNotice notice, 3: list<i32> fields)
}

이렇게 1년 이상 Thrift를 사용해왔지만 여러 가지 불편함이 발생했습니다.

  1. 라이브러리가 활발하게 개발되지 않고 있습니다. 특히 JavaScript/Node.js 쪽은 큰 변화가 없습니다.
  2. TypeScript와 잘 어울리지 않았습니다.
  3. API 추가/변경 시마다 코드를 생성해야 하는 것이 생각보다 불편했습니다.

그래서 2017년 말에 GraphQL을 살펴보기 시작해서 현재는 새로 작성하는 모든 API를 GraphQL로 만들고 있습니다. 다음번에는 크로키닷컴에서 GraphQL을 적용하는 과정에 관해서 설명하겠습니다.



comments powered by Disqus