스칼라의 도입을 회고하며

안녕하세요, 레이니스트 제품 개발팀에서 소프트웨어 엔지니어로 일하고 있는 최현민입니다. 레이니스트 기술 블로그에 어떤 글을 올리면 좋을까 고민하던 찰나에, 작년 중순부터 레이니스트 기술 스택의 일부로 함께하게된 스칼라에 대해 얘기하고자 합니다. 특히, 레이니스트에서 스칼라를 도입하게 되면서 느낀 점들을 공유하고자 합니다.

스칼라는 어떤 프로그래밍 언어인가?

스칼라(Scala)라는 이름엔 스칼라의 확장 가능성(Scala = Sca(lable) + la(nguage))이 내포되어 있습니다.

스칼라는

  • 간결하고 정확한 문법을 가진 덕에 스크립트 언어로도 충분히 쓰일 수 있으며,
  • 견고한 타입 시스템을 지녔기 때문에 중간 이상의 규모를 가진 프로젝트에서도 개발, 리팩토링, 테스트 과정에 많은 편의를 제공합니다.

이뿐만 아니라, JVM 기반으로 실행된다는 이점을 갖고 있습니다. 스칼라 프로젝트에서는 Java 라이브러리를 매우 간편하게 사용할 수 있으며, 개발 후에도 JVM의 완성도를 믿고 안심하고 배포를 할 수 있습니다.


사용 배경

레이니스트에서 처음으로 스칼라가 개발 언어로 사용된 프로젝트는 ‘셰프 알프레드’입니다. (레이니스트 서버 개발팀은 뱅크샐러드와 관련된 서버를 뱅크샐러드 세계관의 셰프라고 생각하고, 이에 맞춰 각 프로젝트의 명명을 사람 이름으로 하는 독특한 문화가 있습니다. 카드 추천 서버는 뱅크샐러드 세계관의 셰프 알프레드인 셈입니다.) 알프레드는 기존에 존재하던 카드 추천 서버보다 더욱 가용성 있고, 더욱 표현력이 좋은 카드 추천 서버를 개발하는 것을 목표로 시작된 프로젝트입니다.

스칼라가 뱅크샐러드의 새로운 카드 추천 서버의 개발 언어로 결정된 배경에는 당시 개발팀이 프로그래밍 언어로서의 스칼라의 모습에 대한 신뢰가 있었기 때문입니다. 당시 개발팀은 뱅크샐러드 웹을 개발하면서 파이썬의 list comprehension과 풍부한 리터럴이 금융 상품 추천 엔진 코드의 표현력과 가독성을 높인다는 것을 깨달았기 때문에, 견고하게 설계된 스칼라 컬렉션 라이브러리의 사용이 금융 상품 추천 엔진을 구현하는 데 있어서 도움이 될 것이라고 믿게 되었습니다. 이 뿐만 아니라 스칼라에 내장된 Future/Promise를 이용해 손쉽게 비동기 프로그래밍을 할 수 있을 것 같은 점, akka와 같은 외부 라이브러리를 이용해 쉽게 scale out할 수 있을 것 같은 점 등이 스칼라가 알프레드를 개발하는 데 있어 최적일 것이라 믿게 해줬습니다.


스칼라 첫 한 달, 수행자의 고통

스칼라를 사용하기 시작한 이후의 한 달은 고통의 연속이었습니다. 사내에서 스칼라를 처음 사용하는 것은 제가 처음이었기 때문에 제가 직접 스칼라와 부딪쳐보는 수 밖에 없었습니다.

스칼라 첫 걸음

당연히 스칼라로 개발을 하기 위해서는 스칼라를 어느정도 익숙하게 사용할 수 있어야겠지만… 스칼라를 직접 사용하기 전의 저는 어마어마한 용기와 자신감을 가지고 있었기 때문에, 99 Scala Problems에 있는 문제들을 풀다 보면 어느 순간 카드 추천 서버를 만들 정도의 스칼라 실력이 뚝딱 생겨날 것이라 믿었습니다. 그래서 다음과 같은 문제들을 하나 둘씩 풀게 되었는데…

4. 리스트에 있는 원소의 수를 구하라.

“생각보다 할만한 걸?”

풀다 보니 점점 스칼라를 잘 쓸 수 있을 것 같다는 막연한 자신감이 생기게 되었습니다. 애초에 스칼라의 교과서적인 책인 Programming in Scala가 위협적일 정도로 두껍기 때문에(1000페이지에 육박하는 분량의 책), 모든 기능들을 하나하나씩 배운 뒤 개발을 하는 것보다는 개발을 하면서 차근차근 배워나가는 것이 훨씬 효율적일 것이라 생각했습니다. 게다가, implicit 키워드나, 복잡한 제네릭 프로그래밍은 카드 추천을 구현하는 데 있어서 크게 필요하지 않을 것이라 판단했습니다.

어떤 프레임워크 / 라이브러리를 써야 하는가?

스칼라는 다양한 라이브러리를 가진 편이고, 각 라이브러리가 비교적 견고하게 설계되고 구현된 편이 많기 때문에, 초기에 프로젝트의 프레임워크나 라이브러리를 정하는 것은 쉽지 않았습니다. 스칼라 사용 경험이 없기 때문에 어떤 것이 더 좋을지 판단할 방법이 없었기 때문입니다.

결과적으로, HTTP 프레임워크로 akka-http, Play, Finch 중에서 akka-http를 채택하게 되었습니다. Play는 사용자 층이 두터워 보이긴 했지만, 카드 추천 엔진 서버와 같은 마이크로서비스를 구현하는 것보다는 웹앱을 만드는데 더 좋아 보였습니다. 트위터의 Finch는 매우 좋아보였지만, Finch의 사용이 자연스럽게 트위터 스타일의 스칼라 스택을 사용하도록 유도하는 것이 염려되었습니다. 결과적으로, akka-http가 가장 무난하게 원하는 HTTP 서버를 커스터마이징하는데 좋을 것이라 판단되었습니다.

Persistence를 위해서는 사실 고민도 없이 자연스럽게 Slick을 사용하게 되었습니다. 설치하자마자 손쉽게 기존의 MySQL 스키마를 자동으로 스칼라 코드로 변환할 수 있었고, type safety를 해치지 않고 데이터베이스 쿼리를 실행할 수 있다는 점이 굉장히 매력적으로 보였습니다.

기초는 중요하다

사용할 라이브러리를 정하고 난 뒤에, 제 부족한 스칼라 실력이 개발 속도의 발목을 잡는다는 것을 깨달았습니다. 어떻게든 부족한 능력으로 개발을 진행하려고 노력했지만, 결국 뒤늦게 스칼라 문법을 제대로 공부하지 않으면 계속 제자리 걸음을 할 것 같다는 결론을 내렸습니다.

사실 글에 적고 싶은 기능들이 매우 많지만, 가장 많이 쓰임에도 불구하고 초기에 상당히 어려울 수도 있는 요소들인 for comprehension과 Future에 대해 소개해드리겠습니다.

For Comprehension

스칼라의 for comprehension은 굉장히 강력한 기능 중 하나입니다. for comprehension을 이용하면 다른 C/C++ 스타일의 for 문을 간결하게 표현할 수 있으며, 복잡하게 중첩된 자료들을 손쉽게 풀어낼 수도 있습니다. for comprehension 자체만 심도 있게 다뤄도 될 주제라서 자세히 설명하기는 어려우므로, 몇 가지 예시들로 for comprehension의 강력함과 어려움을 살펴보겠습니다.

예시로 3중 중첩된 정수형 리스트의 정수 원소들을 일렬로 나열하는 작업을 수행하는 스칼라와 파이썬 코드를 보겠습니다.

이처럼 스칼라의 for comprehension은 이처럼 파이썬의 list comprehension이 해주는 많은 일들을 가능케 합니다.

사실 위의 예시만 봐서는 스칼라의 for comprehension이 파이썬의 list comprehension이랑 별반 다를 것이 없는 것처럼 보일 수도 있습니다.

위의 예시를 살짝 변형해서, List[List[List[Int]]]의 타입을, List[List[Option[Int]]] 타입의 값으로 바꿔봅시다.

분명히 다른 타입의 값이지만, for comprehension은 기존과 마찬가지로 잘 작동합니다. 큰 고민 없이 이 코드를 본다면 잘 작동한다는 점만 두고 마냥 행복할 수도 있겠습니다만, 잘 생각해보면 도대체 이게 왜 동작하는 코드인지는 동작 여부와는 별개로 미스테리로 남게 됩니다.

스칼라를 처음 접했을 당시의 저에겐 위의 for comprehension이 굉장히 어렵게 다가왔습니다. 실제로 공부를 해보니 for comprehension은 단순히 for 문의 역할을 하는 것뿐만 아니라, map, flatMap의 멤버 메소드를 가진 모나드스러운 타입에 대해서 일반적으로 작동함을 알게 되었고, 저를 다시 고통의 소용돌이에 몰아넣었습니다.

Future/Promise를 통한 비동기 프로그래밍

Future/Promise는 스칼라를 통해 개발을 하다보면 절대로 지나칠 수 없는 기능 중 하나입니다. 물론, 이는 스칼라에만 존재하는 개념은 아니고, for comprehension만큼 일반적이지도 않지만, 스칼라를 통해 서버 개발을 하다 보면 필연적으로 맞닥뜨릴 수 밖에 없는 기능이기 때문에 이에 대해 설명을 드리고 싶습니다.

Future는 비동기적으로 작업을 수행할 수 있게 해주는 매우 유용한 도구입니다. Future[T] 타입의 값은 T 타입을 가진 값이 ‘언젠가' 비동기적으로 돌아올 것을 의미합니다.

비동기적으로 어떤 값이 성공적으로 돌아올 때, 이 값을 이용해 새로운 값을 만들고 싶다면, map과 flatMap을 이용하면 됩니다. 비동기적으로 작동하는 피보나치 함수를 통해 어떻게 Future를 활용할 수 있는지 살펴보겠습니다.

우선 간단하게 흐름을 설명드리자면,

  • Future { expression } 의 형태로 새로운 Future를 만들 수 있습니다. 이를 통해, 100ms 동안 슬립한 뒤 3이 돌아오게 되는 Future[Int] 타입의 f1을 만들었습니다.
  • f1의 값이 돌아오게 되면, 그 값을 변형하고 싶을 수 있습니다. 단, f1은 비동기적으로 동작하고 있기 때문에, 새로운 값의 변형 결과 또한 Future로 남아야 합니다. 이를 위해 map을 사용할 수 있습니다. f1의 결과를 2배 곱한 값이 비동기적으로 계산되는 f2라는 Future를 만들었습니다.
  • f2에서 계산되는 값을 n이라 할때, 피보나치 수열의 n번째 값으로 변형하고 싶습니다. 단, fibonacci 함수는 Future[Int] 타입의 결과를 가집니다. 이럴 경우에는 flatMap을 사용해서, Future[Int] 타입을 가진 f3를 만들 수 있습니다.
  • “Futures are fun!”의 출력이 피보나치 계산보다 코드 상에서 나중에 명시되었음에도 불과하고 “Futures are fun!”이 먼저 출력된 뒤에 피보나치 수열의 값이 출력됨을 알 수 있습니다. 메인 쓰레드를 블락하지 않고 비동기적으로 작업을 수행한 셈입니다.

스칼라의 Future/Promise를 이용하면 비교적 ‘손쉽게’ 비동기적 프로그래밍을 할 수 있습니다. Future[T] 타입의 값에 map, flatMap을 능숙할 줄 안다면 말입니다………….

물론 지금은 Future를 사용하는데 큰 어려움을 겪고 있지 않습니다만, 개발 초기에 Future를 사용하는 것은 굉장히 큰 고역이었습니다. 지금 현재 코드 베이스 중에서 Future를 사용하는 코드의 일부를 보자면,

아, 정신이 혼미해진다…

당시 스칼라를 사용한 지 채 한달도 안 된 저에게는 위와 같은 코드를 구현할 능력은 고사하고, 완전히 이해하기 힘들었습니다. 물론, 단편적인 구문이 어떻게 실행될 지에 대해서는 스칼라의 타입 체킹 기능을 이용해 유추할 수는 있었지만(타입 시스템의 힘), 당시 최대한 빠르게 개발을 하고 싶었던 입장에선 자유자재로 Future를 사용하지 못하는 점이 답답할 수 밖에 없었습니다.

일단 버텨보자

스칼라 개발 첫 달 홀로 알프레드를 개발하던 저는 스칼라의 장벽에 의해 개발에 큰 어려움을 겪고 있었습니다. 다행히, 스칼라를 개발 언어로 채택하는 기업이 많다는 것을 알았기 때문에, 개발하면서 어려움을 겪을때마다 ‘이 또한 지나가리라', ‘다 내 내공이 부족하기 때문이다…’ 이 두 생각을 속으로 되뇌면서 스칼라의 어려워보이는 기능들을 최대한 이해하고 사용하기로 결심했습니다.


고통 이후, 깨달음의 시기

다행히 개발 초기의 고통이 영원히 지속되지는 않았습니다. 첫 달에 스칼라를 공부하는 과정을 거치면서 스칼라의 철학을 자연스럽게 조금씩 이해하게 되었고, 스칼라를 사용하는 것의 장점이 무엇인지 직접적으로 느끼기 시작했습니다.

견고한 타입 시스템의 편리함

가장 먼저 깨달은 것은, 스칼라의 견고한 타입 시스템은 개발 및 배포 프로세스에서 발생할 수 있는 불안 요소를 상당히 완화해준다는 점입니다. 스칼라 컴파일러는 코드를 컴파일하는 과정에서 작성된 코드가 스칼라 타입 시스템의 규칙에 부합하는 지 검사하는데, 이 과정을 통과한 코드의 실행 도중에 타입 에러는 실질적으로 거의 발생하지 않는다고 봐도 무방합니다. 예를 들어,

  1. 스칼라의 Option 타입을 적재적소에 잘 사용한다면, 프로그램을 실행하는데 있어서 Null Pointer Exception의 발생을 사실상 원천 차단해줍니다. (물론, Option의 get 메소드와 같이 예상치 못하게 Exception을 발생시킬 수 있는 요소들을 최대한 지양해야겠지요.)
  2. 비동기적 프로그래밍은 근본적으로 굉장히 어렵기 때문에, 개발을 하는 과정에서 실수를 할 여지가 수도 없이 많이 있습니다. 하지만, Future/Promise와 같은 스칼라 비동기 프로그래밍 라이브러리들은 스칼라의 정적 타입 시스템에 기반해 만들어졌기 때문에, 이런 라이브러리를 통해 비동기 프로그래밍을 한다면, 타입 체킹을 통과했다는 전제 하에 개발자가 할 수 있는 실수를 미연에 검사해줍니다.

새로운 카드 추천 서버를 개발하는데 있어서도 비교적 짧은 시간에 적은 인원으로 프로젝트를 배포 준비 단계까지 끌고 갈 수 있었던 것은 타입 시스템의 위력에 있습니다. 각자 맡은 기능이 컴파일이라도 성공한다면, 높은 확률로 테스트를 통과할 것이라는 것이 보장이 되었고, 초기 작업물을 구현하고 난 뒤에는 디버깅에 시간을 거의 쏟지 않아도 되게 되었습니다.

막강한 표현력

이뿐만 아니라, 스칼라의 막강한 표현력이 개발에 굉장히 도움이 됨을 깨달았습니다. 개인적으로 map, flatMap, filter, sum, maxBy 등의 사용에 익숙해지니 이 메소드들이 기본으로 제공되지 않던 시절에는 어떻게 코딩을 했었는지 아리송할 정도입니다.

간단한 예시를 들어보겠습니다. 소비자들과 각 소비자들의 소비 내역이 주어질때, 어떤 소비자가 가장 많은 소비를 했는지 판단하는 코드를 작성한다고 가정합시다.

위의 컬렉션을 적극 활용하지 않는다면, 약간의 명령형 프로그래밍을 통해 구현을 해야 합니다.

이 코드가 사실 그렇게 표현력이 나쁜 편은 아닙니다만, 컬렉션 라이브러리를 적극 응용한 예시를 보면 개선할 점이 많았다는 것을 알 수 있습니다.

map, sum, maxBy의 사용을 통해 더욱 코드가 간결하고 깔끔해짐을 알 수 있습니다.


뒤늦게 깨달은 것들

결국 개발 3개월 만에 새로운 카드 추천 서버인 알프레드의 개발을 마칠 수 있었습니다. 첫 1개월을 저 혼자서 진행했고, 그 이후의 2개월을 새롭게 들어온 팀원이 도와줬다는 점을 고려하면 꽤나 성공적으로 개발이 이루어졌다고 평가합니다.

하지만, 시간이 지나면서 모든 면에서 개발이 성공적이진 않았다고 판단하게 되었습니다. 알프레드를 개발한 뒤 많은 시간이 지난 뒤에야만 깨달을 수 있었던 점들을 적어봅니다.

선택지가 많아진다고 답이 명쾌해지진 않는다

예전에 심리학 개론 수업에서 선택의 역설에 대해 배운적이 있습니다. 선택의 역설을 간단하게 이야기하면, ‘선택지가 많아진다고 행복해지진 않는다’는 것입니다.

스칼라는 선택의 역설의 좋은 예라고 생각합니다. 스칼라는 여러가지 패러다임을 온전하게 지원하기 위해 다양한 기능들을 프로그래머에게 제공합니다. 이 기능들을 전부 이해하는 숙련된 사람이라면, 어떤 기능들을 어느 시기에 써야 하는지 명백할 수 있지만, 그렇지 못한 사람에겐 한 문제를 해결하는데 너무나 해결책이 많음으로 인해 오히려 혼란을 야기할 수도 있습니다.

레이니스트 내에서도 스칼라를 새롭게 도입해보면서 이런 혼란을 겪었습니다. 작게는, sum 타입(enum과 같은 Algebraic Data Type)을 sealed trait으로 선언할 것인지 sealed abstract class로 선언할 것인지, trait을 선언할 때 정적인 값을 val, lazy val, def 중 어떤 것으로 선언해야 하는지 고민하는 과정을 겪었습니다. 아키텍쳐 단위의 고민에 있어서는 DI를 어떤 방식으로 할 것인지 고민이 됐습니다. 스칼라에서는 디펜던시를 클래스 생성 당시에 주입할 수도 있고, implicit하게 주입할 수도 있으며, trait을 잘 응용해서 케이크 패턴을 기반으로 주입할 수도 있으며, 자바 기반의 DI 라이브러리를 사용해도 됩니다. 이 와중에 가장 힘들었던 점은 팀내에서 스칼라로 작업한 경험이 많은 사람이 전혀 없었기 때문에, 어떤 방식을 취하는 것이 팀에 가장 도움이 될 지 몰랐다는 점입니다.

스칼라를 직접 사용해보기 전에는 스칼라의 풍부한 기능들이 무조건적으로 팀의 효율성 향상에 도움이 될 수 있을 것이라 생각했습니다. 이건 잘못된 생각이었습니다. 특정 기능을 어떤 방식으로 활용할 것인지 명확한 합의가 이루어지지 않으면, 개발을 하는 과정 내에서 혼란이 발생할 수 밖에 없고, 작업에 대한 확신이 생기지 않기 때문에 효율성의 증진을 이룰 수가 없습니다. 그렇기 때문에, 스칼라의 풍부함이 팀의 효율성을 높이기 위해선, 팀 차원에서도 다양한 기능들을 잘 숙지하고, 일관성 있는 스타일 가이드를 만들어 나가려는 노력을 취해야 합니다.

어떠한 기술도 만능은 아니다

한창 카드 추천 서버를 개발할 당시 저의 개발 최우선 원칙은 스칼라를 되도록이면 함수형 프로그래밍 언어로써 사용해야 된다는 것이었습니다. 당시의 저는 함수형 프로그래밍의 세계에 깊이 도취되어 있었고, 모든 문제를 함수형 패러다임에 알맞게 해결하고자 했습니다.

물론, 함수형 프로그래밍은 많은 장점을 지니고 있지만, 모든 상황에서 능사는 아닙니다. 다음 간단한 예시를 살펴봅시다.

두 코드 모두 동일한 작업을 수행하는 코드입니다. 그렇기 때문에 나이브하게 생각하면 둘의 실행 시간은 크게 다르지 않아야 합니다.

기이하게도, FunctionalSum.scala의 수행 시간은 제 컴퓨터에서 1분에 육박하는 반면에, ImperativeSum.scala의 수행 시간은 0.5초 정도에 불과합니다. 이 차이는 FunctionalSum.scala의 for comprehension에서, sum += 1이 실행될 때마다, JVM 내에서 하나의 익명 클래스가 생성되기 때문에 발생합니다. (스칼라가 JVM과의 호환성을 높이면서 성능 면에서의 트레이드오프가 있었던 셈입니다.)

물론, 실제 프로그램이 구동될때는 이처럼 극단적인 성능 차이가 발생하진 않습니다. 그럼에도 불구하고 이 두 코드의 성능 차이가 시사하는 바는, 아무리 일반적으로 좋아보이는 추상화의 결과물도 모든 상황에서 만능일 수는 없다는 점입니다.

심리학자 매슬로우는 다음과 같은 말을 했습니다.

당신이 갖고 있는 유일한 장비가 망치라면, 당신은 모든 문제를 못으로 본다. — 매슬로우

작년의 카드 추천 서버 개발팀은 오직 함수형 프로그래밍이라는 망치만을 도구로 사용하고 싶었습니다. 그렇기 때문에 개발하면서 맞닥뜨린 모든 문제가 함수형 프로그래밍을 통해 해결되어야 할 것 같았습니다. 일종의 강박 관념이 있었던 셈입니다.

이 강박 관념이 비합리적인 가장 큰 이유는, 모든 문제를 함수적으로 해결하는 것은 성공적으로 카드 추천 서버를 개발하는 것과 직접적인 상관 관계가 없기 때문입니다. 물론, 함수형 패러다임에 알맞게 프로그래밍을 하다 보면, 논증이 손쉬운 소프트웨어를 개발할 수는 있습니다. 하지만, 좋은 추천 카드 서버의 더욱 핵심적인 본질은 계산의 정확도와 속도에 있습니다. 함수형 패러다임이 정확도와 속도를 향상시키는 데 도움을 줄 수 있다면, 운이 좋게도 눈 앞의 문제가 우리 망치에 알맞은 못인 것이지요. 단, 눈 앞의 있는 무언가가 못이 아니라 나사나 볼트임을 알았다면 드라이버나 렌치를 꺼내는 것이 훨씬 합리적이듯이, 어떤 기능을 함수형으로 구현하는 것이 최적이 아닐땐 유연하게 다른 방법을 모색해야 합니다.

실제로, 최근에 들어서 기존에 고수했던 개발 방법론이 뱅크샐러드가 제공하는 카드 추천의 품질을 높이는데 도움이 되지 않는다고 결론을 내렸습니다. 그에 따라, 기존 코드 중에서 퍼포먼스에 큰 영향을 줄 수 있는 요소들은 함수형 스타일에서 명령형 스타일로 수정하는 작업을 진행하고 있습니다. 이 과정에서 코드의 간결함이나 표현력은 잃겠지만, 카드 추천 서버의 본질 중 하나인 퍼포먼스 측면에서의 상당한 향상을 이룰 수 있다는 점이 더욱 중요하다는 판단을 내린 셈입니다.

노하우는 제때 팀에 공유되어야 한다

스칼라는 상당히 가파른 러닝 커브를 가진 편입니다. 스칼라의 다양한 키워드와 추상적 기능들은 새로 스칼라 코딩을 시작해보는 개발자에게 큰 혼란을 불러일으키곤 합니다(물론, 하스켈이나 ML류의 언어에 익숙하면 그 혼란은 훨씬 덜한 편입니다). 그렇기 때문에 사실 개발팀내에 스칼라의 사용을 환영하기만 하는 분위기는 아닙니다.

이에 대해서는 스칼라를 도입하는 과정에서 쌓아온 노하우를 팀에 공유하고자 하는 노력이 부족했다고 개인적으로 회고합니다. 스칼라는 배울 것이 많은 언어입니다. 그렇기 때문에 개인이 시간을 쏟아 터득하는 노하우를 팀에 빠르게 공유하지 않음은 분명 나중에 누군가가 같은 것을 터득하는데 많은 시간을 할애할 것임을 의미합니다.

레이니스트처럼 개발팀이 작은 경우(10 ~ 20명)에는 개개인이 쌓아온 노하우를 서로 공유하는 자리를 중간 이상의 규모의 개발팀보다 비교적 쉽게 마련할 수 있습니다. 이런 이점을 활용해 개발팀 전체의 노하우를 적극적으로 공유하면서 위에 언급된 비효율을 미연에 방지했어야 된다고 회고합니다.

실제로, 2016년 레이니스트의 개발팀 중 안드로이드 팀은 RxJava를 도입했고, iOS 팀은 RxSwift를 개발 초기부터 스택의 일부로 채택했으며, 서버팀은 스칼라를 사용하면서 Future/Promise를 도입했습니다. 서버팀과 iOS팀 모두에 조금씩 몸을 담근 입장에서 말하자면, Rx를 잘 사용하는 노하우와 Future/Promise를 잘 사용하는 노하우는 상당히 흡사합니다. 이런 상황에서 Future/Promise를 공부하는 입장에서 제가 터득한 노하우를 팀에 공유하는 시간을 가졌으면 새로운 것을 학습하는 데 있어서 비효율을 줄일 수 있을것이고, 개발팀 전체에 장기적으로 이득이 되었을 것입니다.


맺음말

스칼라를 배우면서 뱅크샐러드의 새로운 카드 추천 서버인 알프레드를 개발하는 과정을 통해 스칼라가 가진 단점과 장점을 모두 살펴봤습니다. 스칼라는 다양한 프로그래밍 패러다임을 굉장히 유연하게 잘 흡수한, 아주 견고하게 잘 설계된 범용 프로그래밍 언어입니다. 다만, 이런 스칼라의 치밀하고 방대한 구조는 스칼라의 철학에 익숙하지 않은 개발자들에게 공포로 다가올 수는 있습니다.

그렇기 때문에 당장 일/주의 시간 단위로 프로토타입을 빠르게 개발하고자 하는 팀에게 스칼라를 도입하는 것은 굉장히 비합리적인 결정일 것입니다. 스칼라의 사용에 익숙하지 않은 팀은 스칼라를 통해 업무를 효율적으로 처리해내는데까지도 적어도 몇 주는 소모할 것이기 때문입니다. 반면에, 기존의 프로토타입보다 견고하고 완성도 있는 프로젝트를 개발하는 데 시간을 쏟을 의지가 있는 개발팀에게는 스칼라는 정말 나쁘지 않을 선택이 될 것입니다. 앞서 말했듯이 스칼라의 견고한 정적 타입 시스템과 간결하고 명료한 표현력은 프로그램의 정확성과 안정성을 향상시킬 수 있기 때문입니다.

팀 차원에서 스칼라는 개발팀 자체적으로 노하우를 쌓고자 하는 의지가 있는 소규모의 팀일수록 도입하기 좋은 프로그래밍 언어라고 생각합니다. 스칼라의 여러가지 기능들을 어떤 식으로 사용할 것인지 개발팀이 자체적으로 합의해나가는 과정을 통해 결국 이 강력한 도구들을 유연하게 활용할 방법을 빠르게 찾아나갈 수 있을 것입니다.

레이니스트 또한 스칼라를 도입하는 과정엔 많은 굴곡이 있었지만, 과거로 돌아가 다시 카드 추천 서버의 개발 언어를 선택할 기회가 저에게 주어진다면 주저하지 않고 스칼라를 선택할 것입니다.

스칼라는 정확도와 속도를 모두 보장하는 금융 상품 추천 엔진을 개발해야 된다는 레이니스트 개발팀의 니즈에 어울리는 성격을 갖고 있기 때문입니다. 정확도를 극대화하는 것이 핵심이라면, 함수형 프로그래밍 패러다임에 알맞게 코드를 작성할 수도 있으며, 최대한 빠르게 작동하는 코드를 작성하고 싶을 땐, 정확도를 조금 희생하면서 Java에 필적하는 속도로 동작하는 코드를 작성할 수 있습니다.

레이니스트 슬랙 채널 #xyz_scala에 올라온 메세지

그 외에도, 스칼라를 사용하는 것이 업무의 즐거움과 효율성을 동시에 제고해주었기 때문입니다. 여태껏 레이니스트 내에서 스칼라로 개발을 했던 엔지니어들이 공통적으로 한 말은 스칼라를 통해 일을 하는 과정 자체가 너무 즐거웠다는 것입니다. 스칼라를 사용하기 위해 익혀야 하는 패러다임과 개념을 터득하는 과정 자체가 너무 즐거울 뿐만 아니라, 이런 새로운 패러다임과 개념을 올바르게 습득하는 것이 개발자로서 하여금 더욱 간결하고 정확한 코드를 빠른 시간 내에 작성하도록 도와주면서 결과적으로 개발자 효율성과 유지/보수의 용이성의 놀라운 향상에 이르게 하는 과정을 봐왔기 때문입니다.

앞서 말했듯이, 어떠한 기술도 만능이 될 수는 없으며, 이는 프로그래밍 언어에서도 마찬가지라고 생각합니다. 스칼라를 도입하고자 한다면, 스칼라가 지닌 강점과 약점이 무엇인지 명확하게 이해하고, 현재 개발팀의 상황과 진행하려는 프로젝트의 성격을 정확하게 이해해 스칼라를 도입하는 것이 합리적인지 판단하고자 하는 노력이 필요하다고 생각합니다.

긴 글 읽어주셔서 감사합니다.