그린랩스가 ReasonML에서 리스크립트로 바꾸는 이유

시작하며

그린랩스에서 리스크립트(ReScript) 공식 문서를 한글로 번역해서 공개합니다.

(https://green-labs.github.io/rescript-in-korean/)

현재 그린랩스에서는 ReasonML로 웹 개발을 하고 있습니다. 하지만 미래에 리스크립트로 넘어가려고 합니다. 웹 개발에 사용하는 경우 ReasonML보다 리스크립트가 더 적합하다고 생각하기 때문입니다. 이번 포스트에서는 리스크립트가 무엇이며, ReasonML 과의 차이점은 어떤 것이 있는지 살펴봅니다. 그리고 그린랩스가 리스크립트로 전환하려는 의사 결정을 하게 된 과정에 대해서 설명하려고 합니다.

ReasonML? 버클스크립트? 리스크립트?

ReasonML로 웹 개발을 하는 과정은 다음과 같습니다.

  1. ReasonML 문법으로 코드 작성
  2. 작성한 ReasonML 코드를 자바스크립트로 변환
  3. 변환된 자바스크립트 코드를 브라우저나 노드 환경에서 실행

위의 과정에서 버클스크립트는 ReasonML 코드를 자바스크립트 코드로 변환하는 핵심 역할을 합니다.

작년 8월, 공식적으로 버클스크립트(BuckleScript)는 리스크립트(ReScript)로 이름을 바꿨습니다. 지난 수 년간 버클스크립트는 분명한 성과가 있었지만, 가지고 있는 문제 또한 명확했는데, 버클스크립트 개발진들은 버클스크립트가 가지고 있는 문제를 해결하고자 이름을 바꾸고 새로운 프로젝트의 시작을 선언했습니다.

버클스크립트의 성과

버클스크립트는 OCaml을 컴파일해서, 빠르고 읽기 좋은 자바스크립트 코드를 생성해보자는 아이디어에서 출발했습니다. 그 이후, 버클스크립트 생태계 위에서 ReasonML이 탄생했습니다. 수년이 지난 지금, 버클스크립트는 웹 생태계가 겪고 있는 다양한 문제들의 해결하고 있습니다. 다음은 버클스크립트가 이룬 성과들입니다.

  • 프론트엔드 개발을 위한 빠르고 믿을만한 빌드 시스템
  • 타입 안정성을 가진 라이브러리(bs-*)를 위한 생태계
  • 믿고 쓸 수 있는(production-ready) 표준 라이브러리 밸트(Belt)

위는 분명히 ReasonML과 버클스크립트를 선택한 개발자들만이 누릴 수 있는 큰 장점인 반면 한계 또한 명확했습니다.

버클스크립트와 ReasonML의 문제

많은 사람들이 버클스크립트에 매력을 느끼고 사용을 시작했지만 문제가 하나 있었습니다. 바로 처음 시작하는 사람들이 너무나 많은 것을 배워야 한다는 점입니다. 그에 따라 중도에 포기하는 사람이 많았습니다.

버클스크립트를 사용하기 위해서는 OCaml의 기본 철학을 개념적으로 이해해야 하고, ReasonML 문법을 알아야 합니다. 또한 자바스크립트 코드를 생성할 때 필요한 버클스크립트 고유의 특징 또한 배워야 합니다. 예를 들어 한 개발자가 ReasonReact 애플리케이션을 만들기 위해서는 다음의 나열된 것들을 두루두루 알고 있어야 합니다.

  • 자바스크립트와 리액트
  • OCaml 언어의 기본 철학
  • ReasonML 문법
  • 버클스크립트의 자바스크립트 호환 문법
  • 버클스크립트의 빌드 시스템
  • ReasonReact만의 특별한 문법

커뮤니티에서도 ReasonML의 진입 장벽이 높다는 이야기가 여러 차례 나왔습니다. Ahrefs에서 Reason 및 ReasonReact로 포팅을 한 후에 1년 반 동안 제품에 ReasonML을 사용한 소감을 팀원들을 대상으로 인터뷰한 적이 있는데, 복수의 팀원들이 ReasonML과 버클스크립트는 정말 훌륭하지만, 배우기가 쉽지 않았다고 언급했습니다.

이런 지적을 수용해 ReasonML과 버클스크립트 팀은 더욱더 문서화를 열심히 했습니다. 심지어 공식 웹사이트에 *새롭게 시작하는 사람들을 위한 예제1*까지 생겼습니다. 이런 노력은 분명히 칭찬받을만한 것이었지만 문제는 쉽게 해결되지 않았습니다. 이런 상황에 대해 버클스크립트 팀은 "이상하게도 문서화를 하면 할수록 사람들은 더욱 힘들어하는 역설적인 상황이 반복되었다"라고 회고했습니다.

리브랜딩: 리스크립트(ReScript)

버클스크립트 팀은 위와 같은 진입 장벽을 인정했고, 문서화로 해결할 수 없는 이 상황을 받아들이기로 했습니다. 그리고 문제를 해결하기로 했습니다. 그 결과 리스크립트가 탄생했습니다. 파편화된 생태계와 문서들을 하나로 통합하여 혼란을 줄이고, 보다 친절한 가이드를 제공하고자 했습니다. 결정적으로 그들이 생각했던 가장 중요한 목표는 바로 개발자가 리스크립트 하나만 알면 되게 하자는 것입니다.

리스크립트 팀에서 공식적으로 언급한 목표는 다음과 같습니다.

  • 컴파일러와 빌드시스템
  • 독자적인 문법(dedicated syntax)
  • 에디터 지원
  • 하나의 문서(https://rescript-lang.org)
  • 하나의 통합된 포럼

여기서 주목해야 할 점은 ReasonML과 다른 독자적인 문법(dedicated syntax)이 생긴다는 것입니다. 이것은 기존에 ReasonML을 사용해 웹 개발을 했던 많은 회사들과 개발자들에게 당황스러운 발표였습니다. 아마도 버클스크립트 팀에 대한 신뢰와는 별개로 새로운 언어 문법을 만든다는 것이 주는 무게감이 남다르기 때문인 것 같습니다. 이 발표 이후 TinyMCE라는 유명한 위지윅 에디터를 만드는 팀에서도 이 부분을 언급했는데, 그들은 리스크립트가 안정적이게 될 때까지, ReasonML로 개발하는 것을 유지하고, 리스크립트의 발전을 지켜보겠다고 이야기했습니다.

사실 리브랜딩 이전에도 버클스크립트는 독자적인 문법을 추가한 적이 있었는데, 아마도 이러한 시도들이 리스크립트의 탄생에 대한 복선이었던 것 같습니다.

to_rescript

*출처: https://rescript-lang.org/blog/new-rescript-logo

리스크립트와 ReasonML을 비교했을 때 다른 점

리스크립트와 ReasonML을 비교했을 때 다른 점은 그린랩스에서 번역한 리스크립트 문법으로 변경하기 페이지를 읽어보면 좋습니다. 주요한 변경 사항만 간단히 살펴보면 다음과 같습니다.

  • 세미 콜론을 찍지 않아도 됩니다.
  • if, switch, try에 괄호가 필요 없습니다.
  • 타입 인자 문법이 option(int)에서 option<int>와 같이 바뀌었습니다.
  • 백틱을 사용하는 문자열이 생겼습니다. 줄바꿈과 유니코드를 지원합니다.
  • 배열 문법이 [|1, 2, 3|]에서 [1, 2, 3]로 바뀌었는데, 자바스크립트에서는 배열이 가장 기본적인 자료 구조이기 때문입니다.
  • 리스트 문법이 [1, 2, 3]에서 list{1, 2, 3}으로 바뀌었습니다.
  • 일급 모듈의 문법이 (module S: Student) 에서 module(S: Student)로 바뀌었습니다.
  • 객체에 접근하는 방법이 settings##visible #= true에서 settings["visible"] = true로 바뀌었습니다.
  • 재귀적인 타입을 선언하려면 이제 명시적으로 작성해주어야 합니다. 타입 선언이 기본적으로 재귀적일 수 없도록 되어있습니다.

원래 ReasonML은 네이티브 환경과 자바스크립트 환경, 두 가지를 모두 지원하는 언어입니다. 각각의 컴파일러가 공유하는 지점이 있고, 백엔드에 따라서 네이티브 빌드 결과물이 나오기도 하고, 자바스크립트 코드가 나오기도 하는 것입니다. 두 개의 플랫폼을 지원한다는 것은 매우 좋은 일이지만 그에 따른 단점도 있었습니다. 두 개의 플랫폼을 고려하다 보면 문법(Syntax)을 보다 중립적으로 선택해야 했고, 호스트에 최적화된 기능을 언어 자체에 녹이기도 힘들었습니다.

반면에 리스크립트는 자바스크립트에서 배열이 가장 기본적인 자료 구조이기 때문에 배열의 문법을 리스트의 문법보다 편하게 만들었고, 객체에 접근하는 방법을 자바스크립트 객체에 접근하는 방법과 비슷하게 바꿨습니다. 이제 더 이상 네이티브 환경을 생각하지 않아도 되기 때문에 보다 적극적으로 자바스크립트 개발자들에게 헌신적인 문법을 제공할 수 있게 된 것입니다.

또한 기존에 불편한 점으로 지적되었던 유니코드를 지원하는 점 등은 개발자들이 매우 환영할만한 일입니다.

[Reason 문법 예]

1module Button = {
2 [@react.component]
3 let make = (~count: int, ~user) =>
4 {
5 let times =
6 switch (count) {
7 | 1 => "once"
8 | n => Belt.Int.toString(n) ++ " times"
9 };
10 let username = user##name;
11 let msg = (username ++ {js|, 클릭해주세요. |js}) ++ times;
12
13 <button> msg->React.string </button>;
14 };
15};

[리스크립트 문법 예]

1module Button = {
2 @react.component
3 let make = (~count: int, ~user) => {
4 let times = switch count {
5 | 1 => "once"
6 | n => Belt.Int.toString(n) ++ " times"
7 }
8 let username = user["name"]
9 let msg = username ++ `님, 클릭해주세요. ` ++ times
10
11 <button> {msg->React.string} </button>
12 }
13}

ReasonML의 미래

그럼 ReasonML은 리스크립트의 독자적인 노선을 어떻게 생각할까요? 그리고 ReasonML의 미래는 어떻게 되는 것일까요? 이에 대한 Jordan Walke를 포함한 ReasonML 팀의 답변을 정리해보면 다음과 같습니다.

  1. 만약 네이티브 애플리케이션을 개발한다면, ReasonML은 좋은 선택지가 될 것입니다. 현재 Jordan Walke를 비롯한 많은 개발자들이 ReasonML이 네이티브 환경에서 실행되는 환경을 개선하는 프로젝트에 집중[^2]하고 있습니다.
  2. 만약 네이티브와 브라우저를 동시에 지원해야 하는 상황이라면, ReasonML은 좋은 선택지가 될 것입니다. 리스크립트가 호환을 약속했고, 또 리스크립트가 없더라도, js_of_ocaml이라는 프로젝트가 있기 때문에, 여러분의 프로젝트가 네이티브와 자바스크립트를 모두 고려한다면, 여전히 ReasonML은 좋은 선택지입니다.
  3. 만약 네이티브 빌드가 필요가 없고, 자바스크립트 환경만 고려한다면 버클스크립트를 사용했듯, 리스크립트를 계속 사용하면 됩니다.

그린랩스의 선택 과정

작년 8월에 팀이 막 꾸려지고 프로젝트를 시작할 때, 리스크립트가 나왔습니다. 그 당시 리스크립트는 에디터 지원이 많이 미숙했고, 특히 언어가 막 나온 상태였기 때문에 레퍼런스가 전무했습니다. 그에 따라 오로지 공식 문서를 참고할 수밖에 없었는데, 그때의 공식 문서는 내용이 많이 부실했습니다.

그래서 우선 ReasonML로 프로젝트를 시작하기로 결정했습니다. 최신 리스크립트 컴파일러를 썼지만 ReasonML 문법을 사용했습니다. ReasonML은 상대적으로 레퍼런스가 많았고, 리스크립트 컴파일러가 ReasonML 문법에 대한 호환이 완벽하게 지켜졌기 때문에 문제가 없었습니다.

6개월 정도가 지난 지금, 리스크립트는 에디터 지원도 충분해졌고, 특히 공식 문서가 굉장히 탄탄해졌습니다. 그래서 최근에 합류하신 분들은 리스크립트로 온보딩을 합니다. 또한 얼마 전에 작은 프로젝트 하나를 리스크립트로 구현하고 배포했습니다. 회사 서비스에 반영했던 첫 번째 리스크립트 프로젝트였습니다.

현재 ReasonML/리스크립트를 모두 사용하고 있습니다. 강조하고 싶은 점은 리스크립트로 온보딩하신 분들이 기존 ReasonML 프로젝트에 기여하시는 것도 큰 장벽이 없었다는 것입니다. 위에 나열한 차이점만 존재할 뿐, 두 언어의 뿌리는 같기 때문입니다. 마찬가지로 기존 구성원들이 새로 입사하신 분들의 리스크립트 코드를 리뷰하는데도 무리가 없었습니다. 그럼에도 불구하고 조만간 전체 프로젝트를 리스크립트로 넘어갈 것입니다. 웹 개발에는 리스크립트가 더 적합하기 때문입니다.

이러한 경험을 바탕으로 이제부터 그린랩스가 국내 리스크립트 생태계에 기여하고자 합니다. 그 첫번째 프로젝트로 공식 문서를 번역해 공개하게 되었습니다.

리스크립트(ReScript) 한글 공식 문서 (https://green-labs.github.io/rescript-in-korean/)

이 문서가 리스크립트를 시작하는 한국 개발자분들께 많은 도움이 되길 바랍니다.



Gravatar for kimchhickey@gmail.com
양성민백엔드 엔지니어
2021. 01. 29.


참고자료


1 현재는 페이지가 리스크립트로 옮겨져서 찾을 수 없습니다. 구글에서 "Newcomers Examples ReasonML"을 검색하시면 그 흔적을 찾을 수 있습니다.

2 현재는 페이지가 리스크립트로 옮겨져서 찾을 수 없습니다. 구글에서 "Newcomers Examples ReasonML"을 검색하시면 그 흔적을 찾을 수 있습니다.


추천 콘텐츠