LINE 하스켈 부트 캠프

안녕하세요, LINE에서 프론트엔드 개발을 담당하고 있는 Jun입니다.

2016년 10월 24일부터 28일까지, LINE 시부야 오피스에서 ‘LINE 하스켈 부트 캠프’라는 행사가 열렸습니다. 이번 블로그에서는 이 행사의 참가 후기를 공유하고자 합니다.

하스켈이란

하스켈은 유연성, 조합가능성, 안전성을 유지하면서도 고성능의 소프트웨어를 작성하게 해주는 현대적인 애플리케이션 프로그래밍 언어입니다. 최근 페이스북(Facebook), 스탠다드차타드(Standard Chartered) 등 여러 기업에서 하스켈의 상업적 이용 가능성을 성공적으로 검증한 사례가 늘고 있고, 많은 언어와 라이브러리에서 하스켈의 방법론을 차용하여 현장의 주목을 받고 있습니다.

LINE에서도 스터디 그룹을 만들어 하스켈을 공부하거나, 사내 서비스를 하스켈로 개발하는 등 하스켈에 대한 개발자들의 관심이 높아지고 있습니다. ‘LINE 하스켈 부트 캠프’는 하스켈에 관심 있는 엔지니어들이 모여서 하스켈에 입문해 보는 5일간의 모임이었습니다. 하스켈 부트 캠프는 하스켈의 심연과도 같은 학술적 깊이를 탐험하는 모임이 아니라, 하스켈을 누구라도 흥미를 갖고 사용해볼 수 있도록 초보 단계부터 배워보는 것을 목표로 했습니다. 행사의 진행은 하스켈로 사내 서비스를 제작한 경험이 있는 Han님이 담당하셨습니다.

왜 하스켈인가

하스켈로 고성능의 프로그램을 안전하고 간결하게 작성하는 예시를 살펴보겠습니다.

import Data.List (isPrefixOf)
  
appendIfNeeded xs ys =
    if xs `isPrefixOf` ys
        then ys
        else xs ++ ys

위의 appendIfNeeded 함수의 정의에는 어떤 타입도 명시하지 않았습니다. 하지만 하스켈의 타입 추론 덕분에 함수의 인자인 xsys는 비교가 가능한 리스트라는 것이 보장됩니다. 만약 이 함수에 리스트가 아닌 값을 넣거나, 리스트의 인자들이 비교가 불가능한 타입이라면 컴파일러가 오류를 냅니다. 하스켈의 타입 추론은 코드를 간결하게 유지하면서도, 잘못된 코드가 실행 시간에 동작할 위험을 줄여줍니다.

하스켈이 보장하는 안전성은 값의 타입에 그치지 않습니다. 아래와 같은 함수 타입이 있다고 해봅시다.

toString :: Integer -> String

위의 toString 함수는 정수를 인자로 받아 문자열을 반환하는 평범한 함수로, 어느 언어에서나 만들 수 있습니다. 하지만 하스켈은 이 함수에 대해서 ‘같은 정수가 인자로 제공된다면, 언제 어디서 이 함수가 실행되더라도 같은 문자열을 반환한다’라는 사실을 보장합니다. 즉 하스켈의 함수는 입력값이 같으면 출력값이 같다는 것이 보장됩니다. 일반적인 언어들에서는, 어떤 함수를 호출했을 때 무슨 일이 일어날지에 대해서 코드를 확인하지 않고서는 아무것도 알 수가 없습니다. 어떤 함수를 호출함으로써 의도치 않게 파일 시스템의 특정 파일을 서버로 전송하거나, 대륙간탄도미사일을 발사할 수도 있습니다. 하지만 하스켈에서는 함수의 타입만으로도 그런 기대하지 않은 동작이 없을 것을 확신할 수 있습니다.

readFile :: FilePath -> IO ByteString

반면 readFile은 어떤 파일의 경로를 받아 그 파일의 내용을 읽어들이는 함수입니다. 이 함수는 파일 시스템에 접근해야 하고, 파일 시스템은 언제라도 변화할 수 있습니다. 하스켈은 이런 경우 IO라는 타입을 통해서 함수를 액션으로 만들 수 있습니다. 액션은 실제 세계와 의사소통할 수 있으며, 파일 입출력이나 네트워크 통신 등의 유의미한 부작용을 만들어낼 수 있습니다. 중요한 것은, IO 타입에 의해 지정된 액션만이 그러한 부작용을 만들어낼 수 있다는 것입니다. 하스켈에서는 부작용에 대한 예외 처리를 위해 액션 이외의 코드를 볼 필요가 없습니다. 이런 부작용의 분리는 코드 구조를 바람직하게 해줄 뿐 아니라 유지보수에 드는 수고도 줄여줍니다.

이처럼 하스켈은 타입 수준에서 부작용을 관리해 참조투명성(referential transparency)을 확보해주는 언어입니다. 어떤 함수가 어떤 타입의 값을 인자로 받고 반환할 수 있는지, 시공간의 영향을 받지 않고 항상 같은 값을 반환하는지, 부작용을 발생시킬 수 있는지 등을 컴파일 시점에 알 수 있습니다. 이는 필연적으로 동시성과 병렬성의 구현이 쉬워지는 결과를 낳습니다. 동시성과 병렬성은 현대 프로그래밍에서 중요한 주제이자 어려운 주제이기도 합니다. 대부분의 언어에서는 그러한 어려움을 프로그래머들이 더 주의를 기울임으로써 해결합니다. 하지만 하스켈 컴파일러는 충분한 정보를 알고 있기 때문에, 스스로도 동시성 관리를 할 수 있습니다.

f x + g y

이 식은 f라는 함수를 x에 적용한 결과와, g라는 함수를 y에 적용한 결과를 합하는 식입니다. 하스켈의 +IO 액션이 아니므로, fg 역시 액션이 아니라는 것을 컴파일러는 타입을 명시하지 않고도 알 수 있습니다. 이는 f xg y가 시공간에 영향을 받지 않고 동일한 값을 반환한다는 것을 의미합니다. 따라서 f xg y가 동시에 실행되거나, 다른 CPU 코어에서 실행되어도 결과에는 영향을 주지 않습니다. 따라서 컴파일러에게 병렬화에 대한 간단한 힌트를 제공하는 것만으로도 병렬 연산을 수행하는 프로그램을 만들어낼 수 있습니다.

f x `par` g y `pseq` f x + g y  

위 코드에서 par 함수는 f xg y를 동시에 실행하도록 하고, pseq 함수는 좌측의 수행이 완료된 후에 우측의 계산을 수행하도록 합니다. 이제 적절한 컴파일 인자 혹은 실행 인자만 부여하면 f xg y가 자동으로 병렬화됩니다. 동시성·병렬성을 구현하려고 프로세스와 스레드, 스레드 풀 따위를 다루며 씨름할 필요가 없는 것이죠.

이와 같이 하스켈은 간결한 코드로 안전성, 참조투명성, 동시성 등을 확보할 수 있는 합리적이고 혁신적인 설계와 더불어 성능, 조합성, 커뮤니티와 생태계 등 다양한 매력을 지니고 있습니다.

하스켈 부트 캠프

부트 캠프는 월요일부터 금요일까지, 매일 오후 두 시간씩 진행되었습니다. 적지 않은 시간을 투자해야 하는 행사였지만 많은 개발자분들이 모였습니다. 장소가 만원이 될 정도로 LINE 엔지니어들은 하스켈에 뜨거운 관심을 보였습니다.

행사 진행은 먼저 Han님의 발표 자료를 보며 하스켈의 기초적인 개념과 관습을 공부하고, 그 이후 라이브 코딩을 함께 실습하는 방식이었습니다. 하스켈의 문법은 간결하지만, 처음 보는 사람은 낯설다고 느낄 수도 있습니다. 실제로 하스켈을 공부하려는 많은 사람들이 이 단계에서 포기하곤 합니다. 하스켈 부트 캠프는 하스켈을 처음 공부하는 개발자들이 실제 하스켈 코딩에 익숙해지는 것에 중점을 두었습니다.

흥미롭게도 하스켈 부트 캠프에 참여해주신 개발자분들의 주요 분야는 클라이언트, 서버, 프론트엔드 등 다양했습니다. 하스켈은 ‘무슨 수를 써서라도 성공하지 말자(Avoid success at all cost)’라는 비공식 모토 아래에 파괴적이고 실험적인 언어 발전을 시도해왔고, 이런 하스켈의 발전은 다른 언어에도 좋은 영향을 주었습니다. 자바의 람다와 Generics, 스칼라의 Option이나 Future 타입, 스위프트의 Optional chaining, 자바스크립트의 Promises와 async/await 등 수많은 언어의 기능들이 하스켈에서 영향을 받아 만들어졌습니다. 이는 하스켈을 공부하는 것으로 평소에 사용하는 언어에 대한 이해도도 높아진다는 것을 의미합니다. Han님은 하스켈의 개념을 설명하면서 대응되는 다른 언어의 기능들도 함께 설명하였는데, 하스켈에 대한 이해를 도왔을 뿐만 아니라 프로그래밍 언어 세계에서 하스켈의 가치도 전달했다고 생각합니다.

부트 캠프의 내용에서 좋았던 점은 자칫 한없이 어려워질 수 있는 하스켈을 가능한 실용적 측면에서 설명하려 했다는 점입니다. 예를 들어 많은 사람들이 하스켈 하면 떠올리는 것은 람다 대수학, 범주론, 타입 클래스, 모나드 등의 듣기만 해도 어렵고 두려운 개념들입니다. 하지만 Han님은 하스켈을 유연함, 조합 가능함, 안전함 등 실용적 측면에 중점을 두어 설명했습니다. 당연한 얘기지만 하스켈을 사용하기 위해서 범주론 박사학위 따위는 필요 없습니다. 하스켈의 공부 방법 역시 다른 프로그래밍 언어와 크게 다르지 않습니다. 일단 사용이 가능한 수준이 되면, 이것저것 만들어보면서 조금씩 어려운 개념들을 공부해가는 것이죠. 하스켈 부트 캠프는 그 과정의 시작점으로서 훌륭한 역할을 수행했다고 생각합니다.

LINE 하스켈 부트 캠프는 하스켈 모임들에서 사용하는 방법과는 조금 다른 커리큘럼을 택했습니다. 첫날은 하스켈 커뮤니티가 일반적으로 사용하는 프로젝트 관리 도구인 Stack과 패키지 및 문서의 저장소 역할을 하는 Stackage를 설명했습니다. 이를 시작으로 String 타입의 비효율성을 해결하는 Text나 ByteString, 하스켈의 메타프로그래밍 언어 확장인 Template Haskell, 웹 애플리케이션 인터페이스인 WAI 등, 당장 하스켈을 사용해서 무언가 재밌는 것을 만드는 데 필요한 도구들에 대해 다루었습니다. 하스켈 모임은 자칫 학술적인 모임이 되기 쉬운데, LINE 하스켈 부트 캠프는 다양한 분야의 개발자를 위한 실용적인 내용으로 구성했다는 점이 인상 깊었습니다.

물론 5일 내내 코드나 라이브러리에 대한 이야기만 한 것은 아닙니다. 하스켈 부트 캠프의 중요한 목적 중 하나는 하스켈에 대한 흥미와 의욕을 북돋우는 것이었습니다. 이를 위해서 Han님은 하스켈을 사용해야 하는 이유를 여러 가지 예시를 들어가며 설명했습니다. LINE은 많은 엔지니어들이, 그보다 더 많은 장치들을 이용해서, 그보다 훨씬 많은 유저들이 사용하는 서비스를 개발합니다. 이런 환경에서 가장 중요한 것 중 하나는 서비스의 신뢰성(reliability)입니다. 신뢰성을 높이기 위해 많은 언어들이 개발자에게 여러 가지 장치와 관습을 강조하는 반면, 하스켈은 프로그래밍 언어의 수준에서 더 안전한 프로그램을 보장합니다. 신뢰성이 다른 무엇보다 중요한 상황에서는 하스켈은 좋은 선택지가 될 수 있을 것입니다. 또한 하스켈은 프로그래밍 그 자체에 흥미와 열의를 가진 사람들로부터 많은 관심을 받고 있는 언어입니다. 이는 하스켈을 사용함으로써 우수하고 모티베이션이 강한 개발자들과 일할 기회 역시 늘어난다는 것을 의미합니다. LINE처럼 우수한 개발자를 모집하려는 열의가 강한 회사일수록 하스켈의 가치는 높아질 것입니다.

마지막 날의 ‘모나드 괴담’ 발표 역시 상당히 흥미로웠습니다. 모나드는 하스켈을 어렵게 보이게 만들고, 하스켈을 배우고자 하는 사람들을 좌절시키는 개념 중 하나입니다. 실제로 모나드라는 개념은 범주론에서 왔고, 이를 완벽하게 이해하기 위해서는 학술적으로 높은 수준의 지식이 필요합니다. 하지만 Han님은 여기에 대해 “모나드를 이해함으로써 하스켈 프로그래머가 되려는 것은 ‘악기란 무엇인가’를 이해함으로써 악기의 연주자가 되려는 것과 같다”라는 문장을 인용했습니다. 악기 연주자가 되기 위해 악기의 철학적 의미를 알 필요는 없듯이, 하스켈을 실용적 도구로 사용하기 위해 모나드의 학문적 의미를 이해할 필요는 없습니다. 결국 범주론과 모나드라는 단어의 괴기스러움 자체가 하스켈 학습에 있어서 빠지기 쉬운 함정인 것이죠. ‘모나드 괴담’ 발표는 하스켈 공부하는 사람들에게 그런 함정의 존재를 미리 알림으로써, 어려운 단어들에 의해 하스켈에 대한 흥미를 잃지 말 것을 당부했습니다.

마무리하며

하스켈에 관심 있는 분들은 LINE에서 하스켈을 쓰고 있다거나 학습회가 열렸다는 사실에 놀라셨을지도 모릅니다. 저도 오래 전부터 하스켈에 관심을 가져 왔지만, 회사에서 사용할 기회가 있을 것이라고는 생각하지 못했습니다. LINE 하스켈 부트 캠프는 LINE이 IT 기업으로서 기술의 중요성, 도구의 중요성을 간과하지 않는 회사이며 향상심 넘치는 동료들과 함께 일할 수 있는 일터임을 제게 다시금 느끼게 해주었고, 개인적으로도 설레고 즐거운 행사였습니다.

부트 캠프에서 참가자들이 얻을 수 있었던 가장 큰 수확은, 하스켈이 상업적으로 사용하기에 충분한 실용성을 가지고 있다는 사실을 알게 된 것입니다. 하스켈이 학계에서 출발한 언어임은 맞지만, 유수의 기업에서 이미 하스켈을 채택하여 성공을 거두고 있습니다. 이것은 하스켈이 학계의 전유물이 아닌 산업계에서도 쓸모 있는 도구임을 보여주고 있다고 Han님은 강조했습니다. 부트 캠프에서도 하스켈의 여러 실용적인 도구들이 소개되었는데, 그 중에서는 소프트웨어 트랜잭셔널 메모리 등 서비스에서 실제로 사용해도 좋겠다는 생각이 드는 것들이 많이 있었습니다. 시간 관계상 소개된 모든 도구에 대해 자세한 설명을 들을 순 없었지만, 하스켈의 실용적 측면을 체험하고 실제로 느껴볼 수 있었던 자리였습니다.

이번 부트 캠프를 비롯한 여러 노력들이 앞으로 잘 결실을 맺어서, 다음 번에는 더욱 고무적인 소식으로 여러분과 만날 수 있다면 좋겠습니다. 예를 들어, LINE에서 좀 더 본격적으로 하스켈을 소프트웨어 개발에 채택해서, 실제로 하스켈을 도입한 소프트웨어에 대한 기술적이고 상세한 소개를 드릴 수 있다면 좋겠죠. 캠프에서 사용된 슬라이드 자료 중 마지막 날의 “모나드 괴담”을 아래에 게재합니다.