스프링 블로그에 2018년 12월 7일에 쓰인 Reactive Programming and Relational Databases의 요약입니다.

1줄 요약: R2DBC 쓰세요.

  1. Reactive Programming은 scalibility와 stability에 좋습니다.
    1. event-driven non-blocking functional pipeline을 통해서 요청을 처리합니다.
  2. 위 장점은 애플리케이션의 모든 스택이 reactive해야 누릴 수 있습니다.
    1. 여기서 RDB가 문제가 됩니다.
  3. 아직 표준화된 비동기 RDB API가 없습니다.
    1. 오라클이 제안한 ADBA가 있긴 합니다.
    2. Postgres ADBA driver도 있긴 한데...
    3. ADBA가 언제 표준에 포함될지 기약할 수 없습니다.
  4. Pivotal에서 만드는 R2DBC가 있습니다.
    1. 표준 API와 구현체가 없는 마당에 기약없이 기다리기보다 직접 만들었습니다.
    2. PostgreSQL, H2, Microsoft SQL Server를 지원합니다.
    3. 스프링에서 R2DBC를 사용할 수 있는 Spring Data R2DBC라는 프로젝트가 있습니다.
  5. Fibers 위에 JDBC를 올립니다.
    1. Fibers는 blocking-api를 non-blocking으로 바꿔주는 light-weight abstraction입니다.
    2. This is possible by stack switching as soon as an invocation hits a blocking API. So the underlying Fiber attempts to continue on a previous flow that was using a blocking API.
  6. 결론
    1. Fibers위에 JDBC를 올리는 작업은 아직 미완성이지만, potential game changer입니다.
    2. ADBA는 현재 스케쥴이 따르면 Java 17, 2021년쯤 자바 표준 런타임에 포함될 것입니다.
    3. 당장 시도해볼 수 있는 것은 R2DBC입니다.

댓글들이 재밌습니다. 본문 서두에 reactive programming이 readibility를 향상시킬 수 있다고 나오는데, 첫 번째 댓글에서 reactive programming은 절대 readable하지 않다면서 급발진을 합니다. blocking io로 구현하는게 훨씬 깔끔하다고...

글쓴이가 아닌 다른사람이 대댓글로 친절하게 알려줬는데, blocking io 코드가 읽기 쉬운것은 당연한 것이고, non-blocking io를 사용해야만 하는 상황에서 reactive programming을 사용하지 않는다면 코드를 읽기가 훨씬 더 어렵기 때문에 reactive programming이 readibility를 향상시킬 수 있다는 의미라고 합니다.

또 R2DBC가 MySQL을 지원할 계획이 있냐고 물어보니 지원할 계획이 있다고 합니다. 다른 댓글에서는 이미 구현된 r2dbc-mysql 를 소개했습니다. 아직 R2DBC 그룹에 포함된 저장소는 아닙니다.

rxjava2-jdbc를 사용하면 non-blocking으로 RDB와 통신하는게 아니냐는 댓글도 있었습니다. 답변에서는 그저 라이브러리가 jdbc의 wrapper일 뿐이기 때문에 jdbc call을 할 때마다 새로운 스레드를 생성해서 blocking 작업을 처리한다고 합니다. 매번 jdbc call할 때마다 새로운 스레드를 생성하므로 결국 jdbc를 직접 사용할 때와 같은문제에 봉착한다고.... R2DBC(혹은 Fibers) 말고는 답이 없습니다.


2020년 4월 12일 현재 이 블로그는 node 풀스택으로 구현되어 있습니다. 프론트는 Next.js로, 백엔드는 InversifyJS를 사용해서 만들었고, 이 둘을 하나의 node위에서 돌리고 있습니다. 하나의 node위에서 모든걸 처리함에도 불구하고 프론트엔드와 백엔드가 통신할 때 http request를 사용합니다. 즉 이 둘은 node 코드상에서 결합되어있지 않기 때문에 백엔드를 통째로 드러내어 다른 구현체로 갈아끼울 수 있습니다.

node로 어느정도 놀아본 것 같으니, 이제 spring-webflux를 사용해서 NIO(non-blocking input and output)로 구현해보려고 합니다. spring-webflux, spring-r2dbc, r2dbc-mysql를 사용하면 되겠네요. 프론트엔드와 백엔드가 통신할 때는 gRPC를 사용해볼까 합니다. 브라우저에서 돌아가는 구현체가 이미 있어요. 야크 털 깎자~