리스크립트와 함께 한 1년

Page content

CHANGE LOG

  1. (2022-01-30) 리스크립트 장점으로 패턴매칭 추가

어쩌다 리스크립트

2020년 8월, 당시에는 리스크립트가 존재하지 않았습니다. OCaml의 새로운 문법인 ReasonML(이하 Reason)과 Reason을 자바스크립트로 트랜스파일 해주는 컴파일러인 버클스크립트 뿐이었습니다. 그린랩스에 지원하기 전에 그런 언어가 있다는 것 정도는 알고 있었습니다. 공식 문서를 한 번 읽었고, ‘패턴매칭을 내세우고 있는 언어로구나. 페북에서 개발하는 언어인가?’ 정도의 인상을 받았었습니다. 타입스크립트가 대세였고, 그건 지금도 마찬가지니까요. 페이스북의 Flow처럼 내부에서 사용하려고 만든 언어라는 생각을 언뜻하고 지나쳤습니다.

입사 후 새로운 팀을 빌딩하고, 새로운 기술 스택을 결정하는 과정을 옆에서 지켜볼 수 있었습니다. 이미 면접 중에 CTO님은 새로운 언어를 사용하고 싶다, 그리고 말씀 중에 Reason도 언급하셨기 때문에, 답은 추측할 수 있었습니다. 그렇게 프론트엔드, 백엔드 모두 Reason으로 언어를 결정하고, 개발을 시작했습니다. (현재 그린랩스 백엔드 주 개발 언어는 Clojure로 변경되었습니다.) 지금 가만 생각해보면, CTO님은 꽤나 위험한 결정을 하신 것이죠. 당시 CTO님 포함해봤자 개발자는 5명 뿐이었고, Reason은 다들 경험이 없었으니까요.

함수형 프로그래밍

언어에 익숙해져야만 했습니다. 그래서 팀원들이 다같이 Advent of Code의 2018년도 문제를 같이 풀어보면서 언어에 익숙해지자고 합의하였고, 문제를 풀면서 Reason에 익숙해져보자고 결의를 다졌습니다.

생소한 언어에만 익숙해지면 될 문제가 아니라는 건 금새 알 수 있었습니다. 그보다 더 어려운 건 함수형 프로그래밍이었습니다. 물론 여전히 어렵습니다. 뭔가 알 것 같다는 생각이 들다가도, 뒤돌아서면 또 모르겠고, 말로 설명해보라면 설명을 할 수 없는 그런 존재입니다.

다행히 훌륭한 동료들과의 스터디와 코드 리뷰를 통해 함수형 프로그래밍과 Reason에 익숙해질 수 있었는데요. Reason으로 Gatsby를 이용해서 회사 홈페이지를 만들었고, Reason으로 회사의 웹 서비스에 추가될 새로운 기능을 만들고, 기존 기능을 포팅하기 시작했습니다. 좌충우돌의 연속이었고, 레퍼런스는 찾기 힘들어서 커뮤니티에 가서 도움을 청하거나, 다른 Reason 모듈의 소스를 열어보면서 하나씩 하나씩 우리 것으로 만들어갔습니다.

Reason에서 리스크립트로

버클스크립트가 새로운 이름으로 탈바꿈하기로 결정했습니다. Reason을 트랜스파일하는 컴파일러에서 리스크립트라는 새로운 언어와 컴파일러가 되기로 합니다. 저희 팀은 Reason이냐 리스크립트냐에서 결국 리스크립트로 전환하기로 결정합니다. 당시 저는 Reason에 미련이 남아서, 그리고 뭔가 정통(?)에 가까운 것 아닐까 싶은 마음에 리스크립트로의 전환 결정이 썩 마음에 내키진 않았는데요. 지금은 그 결정이 올바른 결정이었다는 생각이 듭니다. Reason은 개발이 활발히 되지 않고 멈춰진 상태이고, 리스크립트는 뚜렷한 로드맵을 가지고 활발히 개발되고 있는 언어이기 때문입니다. 물론 중위 연산자(infix operator)를 지원하지 않는 점이나, OCaml 최신 버젼을 지원하지 않는 점 등은 아쉽지만, 여전히 장점이 많은 언어라고 생각합니다.

리스크립트의 장점

힌들리-밀너 타입 시스템

리스크립트는 매우 강력한 타입 시스템을 갖고 있습니다. 힌들리-밀너(Hindley-Milner) 타입 시스템이라고 하는데요. 매우 효율적인 타입 추론 기능을 갖고 있습니다. 그래서 특별한 경우가 아니면 타입 어노테이션을 추가하지 않아도 타입을 정확하게 추론해 줍니다. 그리고 타입 안전성(Soundness)를 보장해서, 컴파일이 됐다면 타입간의 논리 명제들이 증명된 것이기 때문에, 타입 레벨에서 안전함이 보장됩니다. 이 타입 시스템은 기대 이상의 효과를 가져다 주었는데요.

우선, 컴파일이 됐는데 의도와 다르게 작동하는 경우, API로부터 받은 데이터가 약속과 다른 형태여서 파싱에 실패했다거나, 바인딩을 한 외부 라이브러리와의 경계에서의 오류와 같은 코드 밖의 오류를 먼저 찾게 됩니다. 즉, 컴파일된 코드 밖의 문제일 가능성이 매우 높아서, 디버깅의 효율이 매우 높아지는 경험을 할 수 있었습니다. 마찬가지로, 동료의 코드 리뷰를 할 때도 동일한 효과를 얻게 되었는데요. 동료의 PR이 컴파일이 된다면, 런타임에서 안전할 것이라는 믿음을 서로 갖고 리뷰를 하는 것은 그렇지 않을 때와 비교했을 때 큰 차이를 가져왔습니다. 리뷰할 때 보다 중요한 부분에 대해 집중할 수 있었습니다.

그리고, 이러한 강력한 정적 타입 시스템 덕분에 코드의 어느 한 곳이 수정되면, 컴파일러가 관련된 모든 곳의 문제를 찾아주기 때문에 두려움 없는 리팩토링이 가능했습니다. 이는 다른 언어에서는 경험해보지 못한 놀라운 경험이었습니다. 컴파일러가 지적하는 부분을 따라가면서 수정하다보면, 1000줄이 넘는 리팩토링도 안전하게 할 수 있었고, 이 리팩토링에 대해 동료들도 런타임에서의 문제를 걱정하지 않고 리뷰를 할 수 있었습니다.

패턴매칭

리스크립트의 장점 중 제가 제일 좋아하고, 매일 경험하는 기능 입니다. 리스크립트 타입 시스템과 패턴매칭의 조합은 강력합니다. 특히, 대수적 데이터 타입 중 하나인 배리언트와 함께 사용하면, 모든 경우를 처리했는지(Exhaustiveness checking)를 컴파일러가 보장해줍니다. 즉, 어떤 경우를 처리하지 않아서 런타임에 발생할 수 있는 오류를 컴파일 타임에 체크할 수가 있습니다. 특히, 리액트 상태 관리에 있어서 패턴매칭은 놀라운 경험을 가져다주었습니다. 관련해서 회사 기술 블로그에 작성한 포스트가 있습니다. (그린랩스 기술블로그 - 대수적 데이터 타입과 리액트 상태 관리)

강력한 포매터

최근 언어들이 포매터와 같은 툴링에도 신경을 많이 쓰는 것 같습니다. 리스크립트도 자체 포매터를 갖고 있는데요. 이 녀석의 성능이 상당히 좋고, 강력합니다. 린트 규칙을 정하고 관리하고, 소모적인 논쟁에 빠질 수 있는 여지를 이 포매터가 없애줍니다. 그리고 코드 리뷰의 효율을 높여주는데 큰 몫을 담당합니다.

빠른 컴파일 속도

정말 빠릅니다. 쓰면 쓸수록 이렇게 타입 어노테이션도 없이 타입을 추론하면서 어떻게 이렇게 빠르게 컴파일할 수 있을까 신기할 정도로 컴파일 속도가 빠릅니다. 같이 사용하는 자바스크립트 툴링 프로그램들이 와치 모드로 돌아가고 있을 때, 리스크립트 컴파일러의 속도를 못 쫓아와서, 기다렸다가 코드를 다시 한 번 저장해서 컴파일을 다시 돌려야할 때가 자주 있을 정도 입니다. 그래서 작업의 리듬이 경쾌하구요. 에러 메세지 또한 정보가 풍부한 점도 놓치지 않았습니다.

함수형 프로그래밍

리스크립트는 함수형 프로그래밍이 가능한 언어입니다. 물론 함수형 프로그래밍만 가능한 것은 아닙니다. 절차적 프로그래밍도 가능한 언어입니다. 하지만 함수형 프로그래밍을 위해 좋은 언어라고 생각합니다. 불변자료구조, 배리언트 등 함수형 프로그래밍을 위한 재료가 충분한 언어입니다. 사내에서 함수형 프로그래밍 스터디를 진행하면서 퓨어스크립트나 스칼라를 이용하기도 했지만, 업무를 하며 늘 사용하는 리스크립트로도 스터디 내용을 표현하는데 부족함이 없었습니다.

OCaml로 이어지는 관문

리스크립트는 오카믈 컴파일러를 이용해서 만들어진 컴파일러이자 언어입니다. 내부에는 여전히 오카믈의 흔적들이 적지 않고, 커뮤니티에도 오카믈, 뤼즌을 같이 하는 개발자들이 많아서 오카믈을 조금씩 알게 되는 기회가 많았습니다. 호기심 반 필요가 반으로 시작한 PPX도 덕분에 오카믈로 만들어 볼 수 있었습니다. 오카믈은 잘 알려지지 않은 언어라서 접할 수 있는 기회가 많지 않은데요. 리스크립트 덕분에 자연스럽게 접할 수 있고, 많이 어렵지 않게 오카믈도 다룰 수 있게 된 점도 리스크립트의 장점이라고 생각합니다.

또, 오카믈 커뮤니티에는 실력있는 개발자들이 많은 것 같아서, 커뮤니티에서 글만 읽어도 배우는 것이 많은 것도 장점이라고 할 수 있습니다.

유연한 인터롭(바인딩)

처음에는 바인딩이 꽤 높은 허들이었습니다. 한글 레퍼런스는 커녕 영어 레퍼런스 조차도 찾기 힘들었고, 2020년 처음 시작할 때는 공식문서에도 내용이 충분치 않았습니다. 그래서 고생을 많이 한 부분이기도 한데, 지금은 이 바인딩이 정말 유연하고 어쩌면 진정한 점진적 타이핑이 이게 아닐까 싶을 정도의 착각에 빠져있습니다. 덕분에 광활한 자바스크립트 생태계를 큰 어려움없이 이용할 수 있구요. 이 강력한 타입 시스템을 어디까지 어느정도까지 적용할 것인지를 정하는 재미(?)가 있습니다.

앞으로

리스크립트를 사용한지 1년이 되는 2021년 8~9월 쯤 이런 글을 하나 써야지 마음만 먹다가, 계속 미루다가 조금씩 쓰고 지우다가, 자칫하면 2년이 되버리겠구나 싶은 마음에 짜임새 없이 생각나는대로 쓴 리스크립트와 함께한 1년이었습니다. 좋은 동료들 덕이 8할은 되는 것 같고, 나머지 2할은 리스크립트라는 언어, 오카믈, 함수형 프로그래밍의 즐거움 덕분에 압축된 경험을 할 수 있었고, 나름 성장했다고 돌아볼 수 있는 1년이었습니다.

리스크립트와 함께한 2년, 3년, … 그 이후로도 계속 쓸 수 있으면 좋겠다는 생각이 가득합니다.