파싱이론 이야기 2

앞서의 글에서 파싱에 오토마타 이론을 활용하는 드래곤북의 접근방법은 그 복잡성에도 불구하고 실효성은 되려 낮다고 이야기했다.

그러면 대안은 무엇일까? 그냥 “재귀적 분석 파서(recursive descent parser)” 를 만들어 쓰면 된다. 7년쯤 전에 스스로의 가설을 확인하면서 리서치를 진행하다가 같은 생각을 이미 1973년에 하신 Vaughan Pratt 교수님의 논문을 찾을 수 있었다.

“나는 개인적으로 오토마타 이론 자체는 매혹적이라고 생각하지만, 컴파일러 구현에 있어서 오토마타 이론을 적용한 성과는 현재까지 미미했으며, 이 접근방법의 미래 가능성에 대해서도 회의적이다. 나는 오히려 오토마타 이론이 프로그래밍 언어의 발전에 도움이 될 여러 아이디어들의 발전을 가로막고 있다고 생각한다.”

Pratt 교수님은 이어서 표현식(expression)을 재귀 분석적으로 파싱하는 매우 간단하고 우아한 알고리즘에 대한 설명을 이어나간다. 이미 1973년에. 왜 이 논문이 더 일찍 주목을 받지 못했을까? 1) Pratt 교수님 말씀처럼 사람들이 파싱 문제에 오토마타 이론을 적용하는 것에 너무 매료돼 있었고 2) 논문의 설명은 (이런 종류의 논문들이 늘 그렇듯이) 간단하고 우아하지 못했기 때문이 아닐까 싶다..

다행히 이 논문이 영영 잊혀져 있던 것은 아니고, 자바스크립트 진영에서 유명한 Douglas Crockford 에 의해 2007년에 조명됐고, 2011년에는 Bob Nystrom 이 좀더 친절한 설명을 블로그에 공유했다. 최근 몇 년 사이에는 “Pratt 파서” 라는 이름으로 점차 알려지는 단계에 있다.

3편에서는 Pratt 파서를 구현하는 방식을 코드와 함께 살펴보려고 한다.

궁극의 프로그래밍 언어 1

학부때 컴퓨터 공학과의 리스프 해커 친구들은 “리스프에서는 말이지.. 코드를 데이터로 다룰 수 있지” 라고 심오한 표정을 지으며 거들먹거렸다.

폴 그레이엄은 “왜 리스프는 다른가” 에서 프로그래밍 언어들은 점점 더 리스프에 가까워지는 방향으로 발전하고 있으며, 마침내 “매크로” 를 지원하는 순간 더이상 새로운 언어라고 부를 수 없을 것이라고 농담했다. 적어도 폴 그레이엄은 리스프가 “궁극의 프로그래밍 언어” 라고 말하고 싶은 것 같다.

정말 그럴까? 만약 리스프가 진짜 “궁극의 프로그래밍 언어” 라면, 왜 우리는 더 많은 리스프 개발자들을 주변에서 마주치지 못하는 것일까? 아니 “궁극의 프로그래밍 언어” 라는게 과연 존재할 수나 있는 것일까? 만약 그런 것이 존재한다면, 그런 언어는 어떤 특징을 갖고 있을까?

폴 그레이엄은 “간결성이 곧 강력함이다” 에서 코드로 작업을 얼마나 압축적으로 표현할 수 있는 지가 그 언어의 강력함을 결정한다면서, 개발에 소요되는 시간은 (사용된 언어와 상관없이) 코드 줄수에 비례하기 때문에 언어의 간결성은 곧 해당 언어를 사용하는 개발자의 생산성을 높여준다고 설명한다.

코드를 더 압축적으로 만드는 방법은 추상화 밖에는 없다. 이 점에서 매크로라는 궁극의 추상화 도구를 지원하는 리스프의 생산성이 (그 어떤 언어와 비교해서도) 가장 높다는 주장은 꽤 설득력이 있다.

그런데 왜 리스프는 (최근 10여년간 리스프에 대한 관심이 크게 높아졌음에도 불구하고) 여전히 실무 개발에서 거의 쓰이지 않는 것일까? 리스프 개발자들이 주장하듯, 프로그래밍 언어의 우수성과 인기 사이에는 상관관계가 없으며 현재의 상황은 그저 역사적인 사건들의 우연한 결과에 불과하기 때문일까?

리스프와 비슷한 시기에 등장했으며 오늘날까지도 가장 인기있는 언어 1, 2위를 다투고 있는 C 언어를 살펴보면 무언가 힌트를 얻을 수 있지 않을까? C 언어의 개발 생산성 순위는 현대의 프로그래밍 언어들 중에 최하위에 위치할 것이다. 그럼에도 불구하고 왜 C 언어는 여전한 인기를 누리고 있는 것일까?

그건 C 언어가 아니면 할 수 없는 코딩 작업들이 있기 때문이다. 하드웨어에 직접 접근해야 하거나, 미시적인 성능 최적화가 필요할때 개발자들은 C 언어가 아닌 다른 선택지를 떠올리기 힘들다. 임베디드 시스템 프로그래밍, 3D 그래픽 프로그래밍, 고성능 네트워크 서버 개발 등이 그런 예이다.

바로 이 지점에서 리스프의 한계가 비로소 드러난다. 상상할 수 있는 거의 모든 프로그래밍 작업이 가능하다는 점에서 C 언어는 강력하다. 아무리 높은 추상계층에서 코딩 작업을 한다고 해도 프로그램은 결국 하드웨어 레벨에서 실행된다. 그리고 상위의 추상계층에서 하위의 추상계층을 직접 제어하는 것은 가능하지 않다.

모든 추상화 작업에는 본질적인 한계가 있는데, 조엘 스폴스키가 “구멍이 새는 추상화의 법칙” 에서 설명하듯이 어느 추상계층도 완전하지 못하다는 점이 바로 그것이다. 그래서 개발자들에게는 평소에 작업하는 추상계층 보다 하위의 추상계층으로 내려가야하는 일이 때때로 생겨난다. 이때 프로그래밍 언어가 하위 추상계층에 대한 손쉬운 접근을 허용하지 않는다면, 해당 언어로 코딩할 수 있는 작업의 범주는 큰 제약을 받게 된다.

우리는 이제 궁극의 언어가 갖춰야할 두가지 조건을 찾았다. 바로 1) 코드를 데이터로 다루는 기능과 2) 로우레벨 접근성이다. 그리고 마침, 이 두가지 조건을 완벽하게 갖추고 있는 프로그래밍 언어가 있다. 어떤 언어냐고? 바로 어셈블리어다.

어셈블리어에서 코드를 데이터로 취급할 수 있다고? 당연하다. (기계어로 변환된) 어셈블리어 코드는 그냥 바이너리 데이터이기 때문이다. 예를 들어, 특정 데이터 영역(즉 메모리)에 “기계어” 를 저장하고, PC 레지스터에 해당 영역의 주소를 입력하는 순간, 그 데이터는 이제 CPU 인스트럭션 코드의 나열로 인식되며 순차적으로 IR 레지스터로 카피돼 CPU 에서 실행되기 시작할 것이다.

로우레벨 접근성은 두말할 필요도 없다. 어셈블리어와 로우레벨은 마치 동의어나 다름없기 때문이다. 이제 적어도 리스프 보다는 어셈블리어가 “궁극의 프로그래밍 언어” 에 한발짝 더 가까이 다가서게 되었다. 😉

2편에서 계속.

파싱이론 이야기 1

내 학부 전공은 사실 수학이었는데, 대학교 3학년때 진로를 프로그래밍으로 바꾸었다. 어느날 학교서점에서 컴퓨터 공학 섹션을 지나치다가 우연히 집어든 책이 K&R이었다. 200페이지가 채 안되는 책을 선 자리에서 두어시간만에 다 읽고 책을 사들고 나왔는데, 문득 수학 공부에 회의가 들었다. 수학책은 100페이지짜리 한 권을 읽는데 한학기 내내 끙끙대도 힘든 경우가 많은데, 프로그래밍 책은 왜 이렇게 쉽게 쓰여진 거지?

사실 수학책이라고 해서 꼭 내용이 어려워서 읽기가 힘든게 아니다. 많은 경우 글쓴이의 설명을 해독하는게 어려운 문제가 훨씬 더 크다. 근데 이유는 정확히 알 수 없지만, 컴퓨터 분야에서는 쉽고 명료하게 쓰여진 전문서의 비중이 상당히 높은 편이었다.

대학교 3학년을 마치고 1년 휴학을 하고 여름방학부터 1년 3개월 내내 컴퓨터 책만 읽었다. 물론 컴퓨터 책이라고 항상 다 명료하게 쓰여진건 아니었지만, 나는 다른 어느 과학이나 공학 분야보다 컴퓨터 책들이 잘 쓰여진 편이라고 생각한다. 어떻게 보면 내가 진로를 바꾼 가장 큰 이유가 이런 공부의 ROI 차이 때문이었을 것이다.

개발자들 중에는 종종 프로그래밍 언어를 만들고 싶어하는 경우가 있는데, 그때 첫번째 관문으로 등장하는 것이 바로 파싱이다. 그리고 십중팔구 집어들게 되는 책이 바로 드래곤북이다. 그리고 나는 대부분의 개발자들이 자신만의 프로그래밍 언어를 만드는데 실패하는 가장 큰 이유가 바로 드래곤북 때문이라고 생각한다.

이유는 여러가지로 설명할 수 있겠지만 아주 간단하게 말하면 드래곤북은 사실 수학책에 가깝기 때문이다. 드래곤북의 저자들은 프로그래밍 언어 구현에서의 문법 파싱 문제에 컴퓨터 공학의 오토마타 이론을 접목시켰다. 그건 꽤 흥미로운 접근방법이긴 하지만 1) 이론적으로 지나치게 복잡하고 2) 실효성도 비교적 낮은 방법이다.

나는 전공 덕분에 이런 종류의 이론적 방법론의 실용성에 대해 의심부터 먼저 하는 습관이 있는데, 덕분에 드래곤북을 건너뛸 수 있었다. 아무튼 중요한건 프로그래밍 언어를 만드는데 오토마타 이론은 사실 전혀 필요가 없다..는 사실이다.

다음 이야기는 2편에서.

프로그래밍은 레고 조립이 아니다

프로그래밍은 물론 어렵다. 알고리즘을 익히는 것도, 알고리즘을 구현하는 것도, 컴퓨터 공학의 추상적인 개념들을 이해하는 것도, 프로그래밍 언어 사용에 능숙해지는 것도, 각종 문서를 섭렵하고 다양한 프레임워크와 툴들을 익히는 것도 이미 충분히 어렵다.

그런데 명확한 스펙으로 명시될 수 있는 문제를 기존 툴들의 조합으로 해결하는 일의 부가가치란 생각보다 크지 않다. 레고 조립은 누구나 할 수 있는 일이기에, 이런 방식으로 상상할 수 있는 작업이란 1) 상업적인 가치가 작거나 2) 세상에서 이미 누군가가 해버린 일이기 쉽다. 98% 의 경우가 그렇다.

물론 나머지 2% 의 경우가 아주 없지는 않다. 세상이 갑자기 바뀌어서 일시적인 기회의 문이 열리는 경우, 예를 들어 모바일 인터넷 시대가 열리면서 메신저 앱같은 어떻게 보면 빤히 보이는 기회가 있었다. 근데 이 시장을 선점한 곳들은 아마추어 스타트업들이 아니었다. 야후 출신 베테랑들이 만든 왓츠앱, 네이버 출신 베테랑들이 만든 카카오톡, 네이버가 만든 라인, 페이스북이 만든 페이스북 메신저 등은 개발사들이 이미 시장에서 가장 뛰어난 기성 플레이어들이었다.

이유는 간단하다. 같은 기회를 보고 비슷한 시기에 뛰어들었다면, 같은 툴들을 더 오랫동안 다뤄온 베테랑들의 실력이 한참 더 앞서고 그들에게 훨씬 더 많은 자원이 준비돼 있기 때문이다.

결국 스타트업은 산업의 맹점 영역에서 태동할 수 밖에 없다. 미래를 보는 것만으로는 충분하지 않다. 남들이 보지 못하는 미래를 봐야 한다. 그래서 피터 틸은 “당신과 동의하는 사람들이 거의 없는 중요한 진실을 알고 있는게 있느냐?” 고 질문하는 것이다.

기술적인 관점에서, 엔지니어들은 기존의 것들을 조합하는 경우의 수를 생각하는 종류의 사고에 귀재들이다. 근데 이런 엔지니어적 접근방법은 (내 개인적인 경험상) “해결할만한 가치가 있는 문제” 를 발견하는 방법으로는 그다지 효과적이지 못하다.

해결할만한 가치가 있는 문제란 과연 무엇일가? 내가 사용하는 정의는 “그것을 해결하면 세상이 실제로 바뀌는 문제” 이다. 세상에는 다양한 가치있는 문제들이 많이 있지만, 이 관점에서 해결할만한 가치가 있는 문제는 생각보다 많지 않다.

좀더 구체적으로 이야기하자면, 해결할만한 가치가 있는 문제란 적지 않은 숫자의 사람들이 실제로 가지고 있는 꽤 커다란 개인적인 문제이다. 중요한 것은 1) 문제의 보편성(=문제를 가진 사람들의 숫자) 2) 문제의 시급성(=새로운 제품이나 서비스를 찾는 사람들의 적극성) 3) 문제의 개인성(=사람들이 자신의 문제로 받아들이는가) 등이다.

이 세가지 요건이 모두 충족됐다면, 이제 비로소 해결 방법을 고민하기 시작할 준비가 된 것이다. 이런 문제가 실제로 포착됐을때 개발자(또는 기술자)에게 요구되는 자질은 무엇일까? 그 문제를 해결할 수 있는 기술적 해법을 “어떻게든” 만들어내는 것이다. 문제는 이것이 기존에 나와있는 레고블록(=오픈소스 소프트웨어 등)의 조합만으로 온전히 해결되는 경우란 매우 드물다는 것이다.

모든 가치있는 문제의 해결에는 기존에 없던 새로운 (그것이 꼭 기술적인 요소가 아니더라도) 레고블록이 요구된다. 그리고 그 새로운 블록들을 만드는 데에는 많은 경우 개발자에게 전혀 생소한 전문성이 요구될 것이다.

적어도 스타트업에 참여하고 있는 개발자라면 이삼일 혹은 일주일간의 리서치로 해당 분야의 준전문가가 돼서 한달 혹은 두어달의 기간 내로 해당 블록을 만들어낼 수 있어야 한다.

예를 들어, 우리 회사가 현재 직면한 두가지 기술적 문제가 있는데, 하나는 리액트 네이티브라는 앱 개발 프레임워크의 안정성/성능 문제 때문에 이 문제를 확실히 해결할 수 있는 대체 프레임워크를 만들어야 한다는 것이고, 다른 하나는 구글 지도 sdk 의 API 가 너무 제한적이라 역시 대체 sdk 를 만들어야 한다는 것이다. 두가지 문제 다 우리가 운영하고 있는 서비스가 기성 레고블록을 outgrow 한 경우이다.

스타트업에서 문제해결 능력이 중요하다고 말할 때, 개발자에게 요구되는 문제해결 능력이란 이런 것들이다.

이런 문제들에 대한 해법을 같이 고민해주실 분들은 언제든 제게 메일(daesan@gmail.com)을 주시기 바랍니다. 다른 개발자 분들이나 스타트업들이 가진 기술적인 문제들도 함께 고민하고 싶습니다. :)

Copyright @ 2018 Dae San Hwang (Theme: Doo by ThemeVS)