
AI 시대 이전에는 컴퓨터 관련 매대마다 사람들이 서거나 앉아서 책을 찾아보던 모습이 일상과도 같았다. 그냥, 별다른 이유없이 가는 곳이 서점이었고 혹시라도 내가 모르던 재미난 주제를 담은 책이 나왔을까해서 기웃거렸던 때가 있었다. 이제는, 책도 없고 사람도 없다. 책장에, 매대에 놓여있는 것들은 어쩌면 다 철지난 내용을 담은 것들 뿐인 것 같은건 기분탓이다.
그냥 나오려다 눈이 마주쳤다. “어허,, 컴파일러 개발자가 얘기 해준다고?” 라는 주제를 출판하는 회사는? 역시나 인사이트 출판사. 2016년 이후로 10년만에 다시 Pebble Smartwatch 앱을 만들면서, C에 대한 향수 때문인지 아니면 저물어가는 사람이 코딩하던 시대에 대한 미련 때문인지, 덥썩 주워들고 결재를 해버렸다. 무려 컴파일러 개발자가 얘기해준다는데, 그냥 갈 수는 없지않은가;;
가능한 종이 책을 사지 않겠다고 그렇게 다짐을 했건만 난 어쩔 수 없이 온갖 낙서를 해대면서 봐야한다는 변명으로 날 속이고 말았네. 대신, 이번에는 겉포장을 하지 않을 것이다. 팔지도 않을 것이고, 잃어버리면 잃어버리는대로 더러워지면 더러워지는대로 그냥 둘 예정이다.
2026년 9월 15일, 포인터와 배열의 다름에 대해 쓴 9장 부터 본다. 제목에는 충격적이라고 하지만 뭐 잊어버렸던 내용일 뿐 완전 새로운 건 아니었다. 번역 문체도 나쁘지 않고 내용도 맘에든다. 군더더기가 없어 좋다.
내 Mercury는 정보 그자체를 설명하는 것 보다 뭔가와 비교를 할 때, 그리고 순서와 상관없이 궁금한 내용에 대한 것을 직접 해보면서 생각과 결과의 차이를 통해 이해하는 Venus Driven 구조이다. 어릴 때 이 특성을 미리 알았다면, 나는 그렇게 나를 학대하진 않았을 것이다. 비선형적이면서 엄청난 질문을 쏟아내지만 누구도 답을 해주지도 않았고 답해줄 수도 없었기 때문에 나는 나를 이해가 딸리는, 모자란 놈으로 여겼다. 그러나 남들이 도저히 생각해내지 못하는 것들을 만들어내거나 생각해내는 것이 우연이라고 하기엔 너무 잦았기 때문에 스스로도 이해하기 힘들었다. 아니, 그것보단 도대체 어떻게 해야 항상 그렇게 괜찮을 결과물을 만들어내거나 생각해 낼 수 있을까 그 방법을 찾기 위해 서점을 그렇게 들락거렸는지도 모르겠다.
그런 특성을 가진 내가 C 언어에 대해 벽이 사라짐을 느꼈던 계기는 정확히 기억난다. FreeBSD 기반의 커널 방화벽을 제작하는 회사에서 메모리 누수로 인해 Kernel Panic 버그를 잡는 문제를 해결하면서라고 얘기할 수 있다. 당시 커널 코드는 뭐 암호문이나 다를 바 없게 느껴졌었고 도대체 어떻게 해야 커널 개발자가 되는지 내 주변의 사람들은 내게 제대로 대답을 해주지 못했다. 아뭏튼 기억나는 건 도대체 왜Cast를 그렇게 해대는 걸까 하는 의문이었는데, 정확한 code는 기억나지 않지만 대충 기억나는 건 struct base 구조의 크기가 24 bytes 정도이고 멤버 필드중 하나가 4 바이트 짜리 unsigned int 인데 그걸 전혀 다른 사이즈 타입으로 캐스트를 하는 코드였다. 전혀 사이즈가 맞지 않아서 컴파일도 안될 것 같지만 원래 C 컴파일러 라는 놈은 “네가 뭐 알아서 잘 하겠지, 난 그냥 컴파일만 해줄께” 라는 바이브라서 그런지 왜 그게 컴파일 되는지도 왜 하는지도 도무지 알수가 없었던 기억이 있다. 어쨌든 마침내 그 이유를 알게됐을 때 머리속에 번개 같이 모든 퍼즐이 맞춰졌다고나 할까… struct 타입을 어떻게 정렬했느냐에 따라 다르겠지만 그때 그 Cast 이유는 특정 위치에서 지정된 크기 만큼의 데이터를 원하는 타입으로 읽어와서 변수를 초기화 하기 위해서였다. 당시 그 코드가 남아있다면 더 생생하게 기록할 텐데, 아쉽다.
C언어에서 타입은 크기를 의미하고 모든 것은 그 크기를 맞추는 놀음과 같다 라는 깨달음이라고나 할까… 그때 갑자기 C언어에 대한 막연함과 커널 프로그래밍에 대한 막막함이 한순간에 걷히는 느낌이었다. 그리고 그 Kernel Panic을 일으키던 메모리 조작 오류를 밝혀냈는데 그게 내 첫번째 실전 커널 프로그래밍의 결과였다. 그게 왜 기억에 남느냐면, 글로는 설명할 수 없는 개 무식한 과정을 거치면서 그 오류를 잡아내던 시절이기 때문이다. 그때당시 Kernel 쪽에 문제가 생기면 OS가 그냥 뻗어버린다. 퍽~ 하고 아무것도 남지 않는 그런 현상이 발생하면 그 이유를 명확히 알기위해 한 줄씩, 좁혀 들어가면 죽는지 안 죽는지를 봐야하고, 그 때마다 커널 빌드를 해야한다;;;;ㅎㅎ… 씨발..
그러니까 단어 하나 고치고 퍽~ 하고 죽고, 다시 어찌어찌 부팅해서 몇 줄 고치고 빌드하는데 지금처럼 쓕~ 하고 지나가는게 아니란 말씀. 하염없이 컴파일 로그가 올라가는 걸 보다가 내 청춘이 다 가버린 것은 느낌이랄까… 그때 만약 지금처럼 QEMU 에뮬레이터가 있고 소스레벨로 디버깅이 가능했다면 정말 재밌었을 것이다. 그러나, 그때는 중노동에 가까웠다.
여기서 하고 싶은 얘기는 그것이다: “Threshold to understanding”, 즉 어느정도 차올라야 이해라는 것을 하는가.. 라는 건데, 결론을 먼저 말하자면, 그딴 건 없다. 각 사람이 이해해 도달하는 과정과 방법은 그 사람의 구조에 달려있다. 내 경우는, 이론을 듣고 말하고 보는 것 만으로는 완전한 이해에 도달하기 힘들다. 그런데! 만약 “그냥 궁금한 것을 해보고, 생각과 결과의 차이를 비교하면서 떠오르는 궁금함이 무엇이든 그걸 해결하려고 하면” 어느 순간 한꺼번에 전체를 완벽하게 이해하게 된다. 이게 내가 나를 쓰는 방법이다.
그래서 난 뭔가를 학습할 때는 무조건 소스코드를 따라서 분석하거나 디버거로 코드 흐름을 쫒아가거나 내가 궁금한 것을 해보다가 개구멍을 발견해서 그 영역에 들어가지만 곧 전체를 파악하는 경우가 많았었다. 내가 백엔드 개발자에서 프론트엔드 개발자로 전향했던건 ExtJS 가 버전 1일때, 그 소스를 분석해본 후에 JavaScript의 객게지향 상속 테크닉에 충격받았기 때문이었다.
이제는 내가 학습으로 나를 이해시키는 방법을 알기 때문에 이 책, 컴파일러 제작자가 알려주는 내용을 볼 때 읽고 싶은대로, 흥미가 당기는 대로 이리저리 뛰면서 아무런 계획없이 흥미를 쫒는다. 내가 이 책에서 기대하는 건, 이전에는 몰랐던 C 컴퍼일러의 설계레벨에서의 지식이다. 말 처럼 그렇게 딱딱한게 아니라, 오히려 숨은 비화같은 걸 기대한다고나 할까… 다행히도 그런 얘기가 많다. 함수의 인자로 사용되거나 호출 될 때에만 배열이 포인터로 치환된다는 컴파일러 설계 지침이, C언어 매뉴얼에서 페이지가 나눠지게 됨에 따라 어이없이 모든 배열이 포인터와 같이 취급된다는 내용을 가르치는 엉터리 책이 무수히 쏟아졌다는 얘기 같은 것 말이다. 갑자기 C언어의 창시작인 브라이언 커니핸이 떠오른다. C언어로 만드는 전통적인 예제 “Hello World!”를 만든 분. Mr. 커니핸을 추모할 때 사람들이 남긴 “Good bye, world” 라는 헌사가 떠오른다. 난 이 문구를 생각할 때 마다 그렇게 참,,, 찡하다… C는 내게 그런 감정을 가지게 하는 언어라고나 할까..
언젠간, 아무도 Z80 어셈블리를 코딩하지 않듯이 C를 찾지 않게 되는 시대가 오겠지. 이미 char c[10];으로 선언하고 c[3] 을 쓰던 3[c]를 쓰던 상관없다라는게 아무런 재미나 흥미를 끌지 못하는 것과 같다.
설령 그렇다고 해도 내겐 C언어를 공부하는 건 여전히 흥미롭다. 어린애가 태어나서 철이들자마자 “언젠간 죽을 텐데 , 모든게 쓸모없다“고 우울해 하면, 뒤통수가 마려운 것과 같다. 목적과 쓸모가 모든 것의 잣대는 아니잖는가.