파싱이론 이야기 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편에서 계속.

지금이 아니면 안돼 (Now or Never)

사람을 행동하게 만드는 주 동인은 무엇일까.

물론 사람은 스스로 생각해서 자신에게 필요한 여러가지 행동을 한다. 하지만 24시간 중 대부분의 시간에는 이미 어떤 루틴들이 할당돼 있다. 8시간 잠을 자고, 씻고, 먹고, 회사 또는 학교에서 일과시간을 보내고, 의무적인 소셜활동과 청소/빨래, 은행업무, 이메일 확인 등 여러 일상적인 잡무까지 마치고 나면 남는 시간은 생각보다 많지 않다.

그리고 많은 사람들은 그 남는 시간에 신문을 읽거나, TV를 보거나, 트위터/페이스북을 하거나, 독서를 하거나, 음악을 듣거나, 쇼핑 사이트를 둘러본다. 일상에 필수적이진 않지만 사람들이 자유의지로 (정말?) 선택한 활동들이다.

결국 사람들이 원래 하지 않았던 어떤 새로운 활동을 하게 만든다는 것은 그 사람이 기존에 하고 있던 TV/트위터/독서/음악/쇼핑 중 무엇 하나를 (일시적으로라도) 포기시키는 일인 셈이다.

수많은 광고들과 백화점 세일 전단지들과 SNS 움짤들은 우리의 일상에 끼어들어 사람들이 현재 하고 있는 그 무언가를 멈추게 하고 주의를 끌려고 한다. 그 찰나의 순간 사람들이 하던 일을 멈추고 광고를 클릭하고 결제 버튼을 누르게 만드는 것은 과연 무엇일까?

나름대로 고민한 결과 나는 그것이 “지금이 아니면 안돼” 즉 “Now or Never” 의 상황이라는 결론을 내렸다.

사람은 일반적으로 “Now or Never” 의 상황이 아니라면, 행동이나 결정을 미룬다. 왜냐면.. 음.. 그럴 수 있기 때문이다. A 라는 제품을 지금이 아니라도 다음에 살 수 있다면 “살지 말지를 판단하는 일” 은 나중에 해도 된다. 지금 내가 꽤 한가한게 아니라면 그런 판단은 대개 나중으로 미뤄진다. 하지만 B 라는 제품은 지금 20% 할인행사 중이다. 그리고 이 제품은 지금까지 할인을 한 적이 한번도 없고 아마 앞으로도 없을 것이다. 그렇다면 B 라는 제품에 대한 구매 결정은 반드시 할인행사 마지막 날인 오늘 내려야만 한다. B 제품을 꼭 산다는 것은 아니다. 하지만 살지 말지를 (나중으로 미루지 못하고) 꼭 오늘 결정해야만 하는 것이다.

결국 물건을 팔기 위해서는 고객을 물건을 살지 말지를 반드시 결정해야만 하는 상황으로 내몰아야 한다. 다시 말하면 고객에게 “Now or Never” 를 작동시켜야 한다. 그렇게 하지 못하면 최악의 상황이 발생하고 만다. 바로 고객이 결정을 나중으로 미루는 것이다.

“아직은 확신이 들지 않는군요. 좀더 생각해 볼게요.”

고객이 사지 않겠다고 결정한 것은 아니지만, 이제 물건을 파는 일은 십중팔구 물건너간 셈이나 다름 없다. 이제 그가 결정을 미뤄둔 수십가지의 다른 상품들과 경쟁을 해야 하기 때문이다. 어떻게 하면 이런 최악의 상황을 막을 수 있을까?

“이게 마지막 재고입니다. 아마 내일 오시면 이미 누군가에게 팔렸을 겁니다.”

(고객이 당신의 말을 믿는다면) 이제 고객은 그 물건을 지금 사지 않으면 영영 살 수 없다는 것을 안다. 그래서 당장 결정을 내려야만 한다. 당장 돈을 지불하고 그 물건을 소유할 것인지, 아니면 영영 가지지 못하게 될 것인지를.

이런 상황이라고 해서 고객이 항상 물건을 사는 것은 물론 아니다. 하지만 구매를 결정할 확률이 이제 10배 이상은 높아졌다.

파싱이론 이야기 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)을 주시기 바랍니다. 다른 개발자 분들이나 스타트업들이 가진 기술적인 문제들도 함께 고민하고 싶습니다. :)

객관을 지향하는 주관적인 이야기들

한동안 미뤄두었던 블로그 글쓰기를 시작해볼까 합니다.

첫 글의 제목을 “객관을 지향하는 주관적인 이야기들”로 정해 보았습니다. “객관을 지향한다”는 말의 의미는 틀린 이야기를 쓰지 않으려 노력한다는 의미입니다. 그리고 당연하지만 틀린 줄 아는 이야기를 적지 않겠습니다. 행여 이미 한 이야기가 틀린 것을 나중에 알았다면, 그것 또한 적도록 하겠습니다.

하지만 제가 블로그에 쓰는 내용은 대부분 “주관적인 이야기들”이 될 것입니다. 온전히 객관적인 글이란 사실 누구나 아는 이야기이거나, 아니면 해당 분야 내에서 통설에 가까운 다소 뻔한 내용들이겠지요. 그런 글은 쓰는 재미도 없거니와 사회적 효용도 크지 않다는 생각입니다. 아마도 결과적으로 정리되는 이야기들은 (공개적으로 처음 게시되는) 새로운 생각들이거나, 분야 내 소수 의견이거나, 아니면 아직 널리 퍼지지 않은 내용들이 될 것 같습니다.

주제에는 딱히 제한을 두지 않으려고 합니다. 제가 IT 분야에서 일하고 있다보니, 프로그래밍과 수학, 그리고 기술 이야기가 자주 나올 것 같고, 인간, 사회, 경제 등 좀더 보편적인 주제도 종종 다루지 않을까 싶습니다. 음.. 소재가 궁해지면 온갖 잡설들이 등장하게 될지도 모르겠습니다. 😅

프로그래밍 이야기는 튜링 기계나 파싱이론 등 컴퓨터 과학의 이론적인 이야기부터 UI 설계와 행동경제학 등 프론트엔드 개발의 기획적인 고민까지 다방면으로 다뤄보려고 합니다. 다만 모든 주제는 B2C 개발의 관점에서만 다룰 예정입니다.

어떤 분들은 도대체 파싱이론을 이야기하는데 B2C 개발이냐, B2B 개발이냐가 무슨 관련이 있냐고 물을 지도 모르겠습니다. 그런데 제가 막상 어떤 분야를 공부하고 그것을 활용해 여러 작업들을 진행하다 보니 모든 연구개발에서 가장 중요한 요소는 “동기”더군요. 그런데 산업적인 관점에서 B2C 개발과 B2B 개발은 개인에게 전혀 다른 동기 구조를 갖게 만든다고 생각합니다. 그런 측면에서 제 생각과 사고의 전개는 늘상 B2C 개발의 관점으로 편향적일 수 있음을 밝혀둡니다.

누군가에게 참고나 도움이 되는 내용들이었으면 합니다. 어쩌면 사람들을 더 많이 만나고 싶어서 시작하는 프로젝트일지도 모르겠거든요. 😉

마지막으로 이 블로그에 적히는 글들은 제 개인적이고 자유로운 생각들에 불과하며 제가 속한 조직의 정책이나 입장을 대변하지 않음을 분명히 밝혀둡니다. (저도 이런 문장을 언젠가 한 번 써보고 싶었.. ㅎ)

그럼 앞으로 한달에 두어 차례씩 지난 십수년간 고민해온 주제들을 하나씩 풀어보도록 하겠습니다. 트위터(@daesanhwang) DM 이나 메일(daesan@gmail.com) 등을 통해 많은 분들과 이야기 나눌 수 있다면 더없이 즐거울 것 같습니다. :)

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